#include #include #include "cdecl.h" #include "parse.h" #include "scan.h" #define PASTE(a, b) a ## b #define PASTE2(a, b) PASTE(a, b) #define BIT1(a) ((1ul<<(CDECL_TYPE_ ## a))) #define BIT2(a, b) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))) #define BIT3(a, b, c) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))|(1ul<<(CDECL_TYPE_ ## c))) #define BIT4(a, b, c, d) ((1ul<<(CDECL_TYPE_ ## a))|(1ul<<(CDECL_TYPE_ ## b))|(1ul<<(CDECL_TYPE_ ## c))|(1ul<<(CDECL_TYPE_ ## d))) #define NARG_(_4, _3, _2, _1, n, ...) n #define NARG(...) NARG_(__VA_ARGS__, 4, 3, 2, 1) #define BITS(...) PASTE2(BIT, NARG(__VA_ARGS__))(__VA_ARGS__) /* * We can represent type specifiers as a bitmap, which gives us a finite * list of acceptable bitmap values according to the C standard. However, * the "long" specifier is allowed to occur more than once, but only at most * 2 times. Treat it as a special case, assigning an unused bit to represent * the second long. */ #define CDECL_TYPE_LLONG 32 static int typemap_verify(unsigned long map) { /* * This is the complete list of valid type specifiers from C99ยง6.7.2#2 */ switch (map) { case BITS(VOID): case BITS(CHAR): case BITS(SIGNED, CHAR): case BITS(UNSIGNED, CHAR): case BITS(SHORT): case BITS(SIGNED, SHORT): case BITS(SHORT, INT): case BITS(SIGNED, SHORT, INT): case BITS(UNSIGNED, SHORT): case BITS(UNSIGNED, SHORT, INT): case BITS(INT): case BITS(SIGNED): case BITS(SIGNED, INT): case BITS(UNSIGNED): case BITS(UNSIGNED, INT): case BITS(LONG): case BITS(SIGNED, LONG): case BITS(SIGNED, LONG, INT): case BITS(UNSIGNED, LONG): case BITS(UNSIGNED, LONG, INT): case BITS(LLONG, LONG): case BITS(SIGNED, LLONG, LONG): case BITS(SIGNED, LLONG, LONG, INT): case BITS(UNSIGNED, LLONG, LONG): case BITS(UNSIGNED, LLONG, LONG, INT): case BITS(BOOL): case BITS(FLOAT): case BITS(DOUBLE): case BITS(LONG, DOUBLE): case BITS(FLOAT, COMPLEX): case BITS(DOUBLE, COMPLEX): case BITS(LONG, DOUBLE, COMPLEX): case BITS(STRUCT): case BITS(UNION): case BITS(ENUM): case BITS(IDENT): return 0; } return -1; } static unsigned long typemap_add_typespec(unsigned long map, struct cdecl_declspec *s) { assert(s->type < CDECL_TYPE_LLONG); if (s->type == CDECL_TYPE_LONG) { if (map & BITS(LLONG)) { fprintf(stderr, "too many long specifiers\n"); return -1; } else if (map & BITS(LONG)) { return map | BITS(LLONG); } } if (map & (1ul<type)) { fprintf(stderr, "duplicate type specifier\n"); return -1; } return map | (1<type); } static int verify_specs(struct cdecl_declspec *s) { unsigned long typemap = 0; unsigned num_storage = 0; for (struct cdecl_declspec *c = s; c; c = c->next) { switch (cdecl_spec_kind(c)) { case CDECL_SPEC_TYPE: typemap = typemap_add_typespec(typemap, c); if (typemap == -1) { return -1; } break; case CDECL_SPEC_STOR: if (++num_storage > 1) { fprintf(stderr, "too many storage-class specifiers\n"); return -1; } break; case CDECL_SPEC_QUAL: /* * Since we don't support pointer types yet, all * restrict qualifiers are invalid. Other qualifiers * are always valid. */ if (c->type == CDECL_QUAL_RESTRICT) { fprintf(stderr, "only pointer types can be restrict-qualified.\n"); return -1; } break; case CDECL_SPEC_FUNC: /* * Likewise for function specifiers. */ fprintf(stderr, "only function declarations may have function specifiers.\n"); return -1; default: abort(); } } if (typemap_verify(typemap) == -1) { fprintf(stderr, "conflicting type specifiers\n"); return -1; } return 0; } static int verify_decl(struct cdecl *decl) { return verify_specs(decl->specifiers); } struct cdecl *cdecl_parse_decl(const char *declstr) { YY_BUFFER_STATE state; struct cdecl *decl; int rc; state = yy_scan_string(declstr); rc = yyparse(&decl); yy_delete_buffer(state); if (rc != 0) return NULL; rc = verify_decl(decl); if (rc != 0) { cdecl_free(decl); return NULL; } return decl; }