Free up some special bits in modifiers. This change using symbol_op to contain the specifier parsing function. It is easier to add new specifiers. We don't need special bits any more. Index: sparse/parse.h =================================================================== --- sparse.orig/parse.h 2007-02-03 03:38:31.000000000 -0800 +++ sparse/parse.h 2007-02-03 03:38:56.000000000 -0800 @@ -133,5 +133,6 @@ extern struct symbol *ctype_fp(unsigned extern void copy_statement(struct statement *src, struct statement *dst); extern int inline_function(struct expression *expr, struct symbol *sym); extern void uninline(struct symbol *sym); +extern void init_parser(int); #endif /* PARSE_H */ Index: sparse/symbol.c =================================================================== --- sparse.orig/symbol.c 2007-02-03 02:53:50.000000000 -0800 +++ sparse/symbol.c 2007-02-03 03:38:56.000000000 -0800 @@ -678,43 +678,9 @@ static struct sym_init { { "__label__", &label_ctype, MOD_LABEL | MOD_UNSIGNED }, { "_Bool", &bool_ctype, MOD_UNSIGNED }, - /* Type qualifiers */ - { "const", NULL, MOD_CONST }, - { "__const", NULL, MOD_CONST }, - { "__const__", NULL, MOD_CONST }, - { "volatile", NULL, MOD_VOLATILE }, - { "__volatile", NULL, MOD_VOLATILE }, - { "__volatile__", NULL, MOD_VOLATILE }, - /* Predeclared types */ { "__builtin_va_list", &int_type, 0 }, - /* Typedef.. */ - { "typedef", NULL, MOD_TYPEDEF }, - - /* Extended types */ - { "typeof", NULL, MOD_TYPEOF }, - { "__typeof", NULL, MOD_TYPEOF }, - { "__typeof__", NULL, MOD_TYPEOF }, - -#if 0 - { "attribute", NULL, MOD_ATTRIBUTE }, -#endif - { "__attribute", NULL, MOD_ATTRIBUTE }, - { "__attribute__", NULL, MOD_ATTRIBUTE }, - - { "struct", NULL, MOD_STRUCTOF }, - { "union", NULL, MOD_UNIONOF }, - { "enum", NULL, MOD_ENUMOF }, - - { "inline", NULL, MOD_INLINE }, - { "__inline", NULL, MOD_INLINE }, - { "__inline__", NULL, MOD_INLINE }, - - /* Ignored for now.. */ - { "restrict", NULL, 0 }, - { "__restrict", NULL, 0 }, - { NULL, NULL, 0 } }; @@ -794,6 +760,7 @@ void init_symbols(void) hash_ident(&n) #include "ident-list.h" + init_parser(stream); for (ptr = symbol_init_table; ptr->name; ptr++) { struct symbol *sym; sym = create_symbol(stream, ptr->name, SYM_NODE, NS_TYPEDEF); Index: sparse/parse.c =================================================================== --- sparse.orig/parse.c 2007-02-03 03:37:57.000000000 -0800 +++ sparse/parse.c 2007-02-03 14:23:12.000000000 -0800 @@ -35,6 +35,90 @@ struct statement_list *function_computed static struct token *statement(struct token *token, struct statement **tree); +static struct token *struct_specifier(struct token *token, struct ctype *ctype); +static struct token *union_specifier(struct token *token, struct ctype *ctype); +static struct token *enum_specifier(struct token *token, struct ctype *ctype); +static struct token *attribute_specifier(struct token *token, struct ctype *ctype); +static struct token *typeof_specifier(struct token *token, struct ctype *ctype); + +static struct symbol_op typeof_op = { + S_OP_TYPEOF, + .specifier = typeof_specifier, +}; + +static struct symbol_op attribute_op = { + S_OP_ATTRIBUTE, + .specifier = attribute_specifier, +}; + +static struct symbol_op struct_op = { + S_OP_TYPE_SPECIFIER, + .specifier = struct_specifier, +}; + +static struct symbol_op union_op = { + S_OP_TYPE_SPECIFIER, + .specifier = union_specifier, +}; + +static struct symbol_op enum_op = { + S_OP_TYPE_SPECIFIER, + .specifier = enum_specifier, +}; + +static struct keyword { + const char *name; + unsigned long modifiers; + struct symbol_op *op; +} keyword_init_table[] = { + /* Type qualifiers */ + { "const", MOD_CONST }, + { "__const", MOD_CONST }, + { "__const__", MOD_CONST }, + { "volatile", MOD_VOLATILE }, + { "__volatile", MOD_VOLATILE }, + { "__volatile__", MOD_VOLATILE }, + + /* Typedef.. */ + { "typedef", MOD_TYPEDEF }, + + /* Extended types */ + { "typeof", .op = &typeof_op }, + { "__typeof", .op = &typeof_op }, + { "__typeof__", .op = &typeof_op }, + +#if 0 + { "attribute", 0, &attribute_op }, +#endif + { "__attribute", .op = &attribute_op }, + { "__attribute__", .op = &attribute_op }, + + + { "struct", .op = &struct_op }, + { "union", .op = &union_op }, + { "enum", .op = &enum_op }, + + { "inline", MOD_INLINE }, + { "__inline", MOD_INLINE }, + { "__inline__", MOD_INLINE }, + + /* Ignored for now.. */ + { "restrict", }, + { "__restrict", }, +}; + +void init_parser(int stream) +{ + int i; + for (i = 0; i < sizeof keyword_init_table/sizeof keyword_init_table[0]; i++) { + struct keyword *ptr = keyword_init_table + i; + struct symbol *sym = create_symbol(stream, ptr->name, SYM_NODE, NS_TYPEDEF); + sym->ident->reserved = 1; + sym->ctype.modifiers = ptr->modifiers; + sym->op = ptr->op; + } +} + // Add a symbol to the list of function-local symbols static void fn_local_symbol(struct symbol *sym) { @@ -114,7 +198,7 @@ static int apply_modifiers(struct positi return 0; } -static struct symbol * indirect(struct position pos, struct ctype *ctype, int type) +static struct symbol * alloc_indirect_symbol(struct position pos, struct ctype *ctype, int type) { struct symbol *sym = alloc_symbol(pos, type); @@ -205,11 +289,17 @@ static struct token *parse_struct_declar return struct_declaration_list(token, &sym->symbol_list); } -static struct token *struct_or_union_specifier(enum type type, struct token *token, struct ctype *ctype) +static struct token *struct_specifier(struct token *token, struct ctype *ctype) { - return struct_union_enum_specifier(type, token, ctype, parse_struct_declaration); + return struct_union_enum_specifier(SYM_STRUCT, token, ctype, parse_struct_declaration); } +static struct token *union_specifier(struct token *token, struct ctype *ctype) +{ + return struct_union_enum_specifier(SYM_UNION, token, ctype, parse_struct_declaration); +} + + typedef struct { int x; unsigned long long y; @@ -742,13 +832,13 @@ static void apply_ctype(struct position static void check_modifiers(struct position *pos, struct symbol *s, unsigned long mod) { unsigned long banned, wrong; - unsigned long this_mod = s->ctype.modifiers; const unsigned long BANNED_SIZE = MOD_LONG | MOD_LONGLONG | MOD_SHORT; const unsigned long BANNED_SIGN = MOD_SIGNED | MOD_UNSIGNED; + unsigned int type = s->op ? s->op->type : 0; - if (this_mod & (MOD_STRUCTOF | MOD_UNIONOF | MOD_ENUMOF)) + if (type & S_OP_TYPE_SPECIFIER) banned = BANNED_SIZE | BANNED_SIGN; - else if (this_mod & MOD_SPECIALBITS) + else if (type) banned = 0; else if (s->ctype.base_type == &fp_type) banned = BANNED_SIGN; @@ -777,6 +867,7 @@ static struct token *declaration_specifi struct ident *ident; struct symbol *s, *type; unsigned long mod; + unsigned int optype; next = token->next; if (token_type(token) != TOKEN_IDENT) @@ -788,19 +879,11 @@ static struct token *declaration_specifi break; thistype = s->ctype; mod = thistype.modifiers; - if (qual && (mod & ~(MOD_ATTRIBUTE | MOD_CONST | MOD_VOLATILE))) + optype = s->op ? s->op->type : 0; + if (qual && (optype & (S_OP_TYPE_SPECIFIER | S_OP_TYPEOF))) break; - if (mod & MOD_SPECIALBITS) { - if (mod & MOD_STRUCTOF) - next = struct_or_union_specifier(SYM_STRUCT, next, &thistype); - else if (mod & MOD_UNIONOF) - next = struct_or_union_specifier(SYM_UNION, next, &thistype); - else if (mod & MOD_ENUMOF) - next = enum_specifier(next, &thistype); - else if (mod & MOD_ATTRIBUTE) - next = attribute_specifier(next, &thistype); - else if (mod & MOD_TYPEOF) - next = typeof_specifier(next, &thistype); + if (s->op && s->op->specifier) { + next = s->op->specifier(next, &thistype); mod = thistype.modifiers; } type = thistype.base_type; @@ -908,13 +991,13 @@ static struct token *direct_declarator(s continue; } - sym = indirect(token->pos, ctype, SYM_FN); + sym = alloc_indirect_symbol(token->pos, ctype, SYM_FN); token = parameter_type_list(next, sym, p); token = expect(token, ')', "in function declarator"); continue; } if (token->special == '[') { - struct symbol *array = indirect(token->pos, ctype, SYM_ARRAY); + struct symbol *array = alloc_indirect_symbol(token->pos, ctype, SYM_ARRAY); token = abstract_array_declarator(token->next, array); token = expect(token, ']', "in abstract_array_declarator"); ctype = &array->ctype; @@ -930,7 +1013,7 @@ static struct token *pointer(struct toke unsigned long modifiers; struct symbol *base_type; - modifiers = ctype->modifiers & ~(MOD_TYPEDEF | MOD_ATTRIBUTE); + modifiers = ctype->modifiers & ~MOD_TYPEDEF; base_type = ctype->base_type; ctype->modifiers = modifiers; @@ -974,7 +1057,7 @@ static struct token *handle_bitfield(str return conditional_expression(token->next, &expr); } - bitfield = indirect(token->pos, ctype, SYM_BITFIELD); + bitfield = alloc_indirect_symbol(token->pos, ctype, SYM_BITFIELD); token = conditional_expression(token->next, &expr); width = get_expression_value(expr); bitfield->bit_size = width; @@ -1766,6 +1849,21 @@ static struct token *parse_k_r_arguments return parse_function_body(token, decl, list); } +static struct token *toplevel_asm_declaration(struct token *token, struct symbol_list **list) +{ + struct symbol *anon = alloc_symbol(token->pos, SYM_NODE); + struct symbol *fn = alloc_symbol(token->pos, SYM_FN); + struct statement *stmt; + + anon->ctype.base_type = fn; + stmt = alloc_statement(token->pos, STMT_NONE); + fn->stmt = stmt; + + token = parse_asm(token->next, stmt); + + add_symbol(list, anon); + return token; +} struct token *external_declaration(struct token *token, struct symbol_list **list) { @@ -1776,20 +1874,8 @@ struct token *external_declaration(struc int is_typedef; /* Top-level inline asm? */ - if (match_idents(token, &asm_ident, &__asm___ident, &__asm_ident, NULL)) { - struct symbol *anon = alloc_symbol(token->pos, SYM_NODE); - struct symbol *fn = alloc_symbol(token->pos, SYM_FN); - struct statement *stmt; - - anon->ctype.base_type = fn; - stmt = alloc_statement(token->pos, STMT_NONE); - fn->stmt = stmt; - - token = parse_asm(token->next, stmt); - - add_symbol(list, anon); - return token; - } + if (match_idents(token, &asm_ident, &__asm___ident, &__asm_ident, NULL)) + return toplevel_asm_declaration(token, list); /* Parse declaration-specifiers, if any */ token = declaration_specifiers(token, &ctype, 0); Index: sparse/symbol.h =================================================================== --- sparse.orig/symbol.h 2007-02-03 02:53:50.000000000 -0800 +++ sparse/symbol.h 2007-02-03 14:22:03.000000000 -0800 @@ -73,10 +73,16 @@ struct ctype { struct symbol *base_type; }; +#define S_OP_TYPE_SPECIFIER 0x0001 +#define S_OP_ATTRIBUTE 0x0002 +#define S_OP_TYPEOF 0x0004 + struct symbol_op { + unsigned long type; int (*evaluate)(struct expression *); int (*expand)(struct expression *, int); int (*args)(struct expression *); + struct token *(*specifier)(struct token *token, struct ctype *ctype); }; extern int expand_safe_p(struct expression *expr, int cost); @@ -159,12 +165,7 @@ struct symbol { #define MOD_LONGLONG 0x0800 #define MOD_TYPEDEF 0x1000 -#define MOD_STRUCTOF 0x2000 -#define MOD_UNIONOF 0x4000 -#define MOD_ENUMOF 0x8000 -#define MOD_TYPEOF 0x10000 -#define MOD_ATTRIBUTE 0x20000 #define MOD_INLINE 0x40000 #define MOD_ADDRESSABLE 0x80000 @@ -185,7 +186,6 @@ struct symbol { #define MOD_NONLOCAL (MOD_EXTERN | MOD_TOPLEVEL) #define MOD_STORAGE (MOD_AUTO | MOD_REGISTER | MOD_STATIC | MOD_EXTERN | MOD_INLINE | MOD_TOPLEVEL) -#define MOD_SPECIALBITS (MOD_STRUCTOF | MOD_UNIONOF | MOD_ENUMOF | MOD_ATTRIBUTE | MOD_TYPEOF) #define MOD_SIGNEDNESS (MOD_SIGNED | MOD_UNSIGNED | MOD_EXPLICITLY_SIGNED) #define MOD_SPECIFIER (MOD_CHAR | MOD_SHORT | MOD_LONG | MOD_LONGLONG | MOD_SIGNEDNESS) #define MOD_SIZE (MOD_CHAR | MOD_SHORT | MOD_LONG | MOD_LONGLONG) Index: sparse/lib.c ===================================================================