diff options
author | Josh Triplett <josh@freedesktop.org> | 2007-03-07 21:40:15 -0800 |
---|---|---|
committer | Josh Triplett <josh@freedesktop.org> | 2007-03-07 21:40:15 -0800 |
commit | af30c6df74f01db10fa78ac0cbdb5c3c40b5c73f (patch) | |
tree | 32983dd28adb96057d7e84dcbca727c62dea9235 | |
parent | Moving statement parsing into smaller functions. (diff) | |
download | sparse-af30c6df74f01db10fa78ac0cbdb5c3c40b5c73f.tar.gz sparse-af30c6df74f01db10fa78ac0cbdb5c3c40b5c73f.tar.bz2 sparse-af30c6df74f01db10fa78ac0cbdb5c3c40b5c73f.zip |
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.
Signed-Off-By: Christopher Li <sparse@chrisli.org>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Josh Triplett <josh@freedesktop.org>
-rw-r--r-- | parse.c | 141 | ||||
-rw-r--r-- | parse.h | 1 | ||||
-rw-r--r-- | symbol.c | 35 | ||||
-rw-r--r-- | symbol.h | 24 | ||||
-rw-r--r-- | token.h | 3 |
5 files changed, 135 insertions, 69 deletions
@@ -5,6 +5,7 @@ * * Copyright (C) 2003 Transmeta Corp. * 2003-2004 Linus Torvalds + * Copyright (C) 2004 Christopher Li * * Licensed under the Open Software License version 1.1 */ @@ -36,6 +37,96 @@ struct statement_list *function_computed_goto_list; static struct token *statement(struct token *token, struct statement **tree); static struct token *handle_attributes(struct token *token, struct ctype *ctype); +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 modifier_op = { + .type = KW_MODIFIER, +}; + +static struct symbol_op qualifier_op = { + .type = KW_QUALIFIER, +}; + +static struct symbol_op typeof_op = { + .type = KW_TYPEOF, + .declarator = typeof_specifier, +}; + +static struct symbol_op attribute_op = { + .type = KW_ATTRIBUTE, + .declarator = attribute_specifier, +}; + +static struct symbol_op struct_op = { + .type = KW_SPECIFIER, + .declarator = struct_specifier, +}; + +static struct symbol_op union_op = { + .type = KW_SPECIFIER, + .declarator = union_specifier, +}; + +static struct symbol_op enum_op = { + .type = KW_SPECIFIER, + .declarator = enum_specifier, +}; + +static struct init_keyword { + const char *name; + enum namespace ns; + unsigned long modifiers; + struct symbol_op *op; +} keyword_table[] = { + /* Type qualifiers */ + { "const", NS_TYPEDEF, MOD_CONST, .op = &qualifier_op }, + { "__const", NS_TYPEDEF, MOD_CONST, .op = &qualifier_op }, + { "__const__", NS_TYPEDEF, MOD_CONST, .op = &qualifier_op }, + { "volatile", NS_TYPEDEF, MOD_VOLATILE, .op = &qualifier_op }, + { "__volatile", NS_TYPEDEF, MOD_VOLATILE, .op = &qualifier_op }, + { "__volatile__", NS_TYPEDEF, MOD_VOLATILE, .op = &qualifier_op }, + + /* Typedef.. */ + { "typedef", NS_TYPEDEF, MOD_TYPEDEF, .op = &modifier_op }, + + /* Extended types */ + { "typeof", NS_TYPEDEF, .op = &typeof_op }, + { "__typeof", NS_TYPEDEF, .op = &typeof_op }, + { "__typeof__", NS_TYPEDEF, .op = &typeof_op }, + + { "__attribute", NS_TYPEDEF, .op = &attribute_op }, + { "__attribute__", NS_TYPEDEF, .op = &attribute_op }, + + { "struct", NS_TYPEDEF, .op = &struct_op }, + { "union", NS_TYPEDEF, .op = &union_op }, + { "enum", NS_TYPEDEF, .op = &enum_op }, + + { "inline", NS_TYPEDEF, MOD_INLINE, .op = &modifier_op }, + { "__inline", NS_TYPEDEF, MOD_INLINE, .op = &modifier_op }, + { "__inline__", NS_TYPEDEF, MOD_INLINE, .op = &modifier_op }, + + /* Ignored for now.. */ + { "restrict", NS_TYPEDEF, .op = &qualifier_op}, + { "__restrict", NS_TYPEDEF, .op = &qualifier_op}, +}; + +void init_parser(int stream) +{ + int i; + for (i = 0; i < sizeof keyword_table/sizeof keyword_table[0]; i++) { + struct init_keyword *ptr = keyword_table + i; + struct symbol *sym = create_symbol(stream, ptr->name, SYM_KEYWORD, ptr->ns); + sym->ident->keyword = 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) { @@ -115,7 +206,7 @@ static int apply_modifiers(struct position pos, struct ctype *ctype) 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); @@ -207,11 +298,17 @@ static struct token *parse_struct_declaration(struct token *token, struct symbol 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; @@ -744,14 +841,11 @@ static void apply_ctype(struct position pos, struct ctype *thistype, struct ctyp 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; - if (this_mod & (MOD_STRUCTOF | MOD_UNIONOF | MOD_ENUMOF)) - banned = BANNED_SIZE | BANNED_SIGN; - else if (this_mod & MOD_SPECIALBITS) - banned = 0; + if (s->type == SYM_KEYWORD) + banned = s->op->type == KW_SPECIFIER ? (BANNED_SIZE | BANNED_SIGN) : 0; else if (s->ctype.base_type == &fp_type) banned = BANNED_SIGN; else if (s->ctype.base_type == &int_type || !s->ctype.base_type || is_int_type (s)) @@ -790,19 +884,14 @@ static struct token *declaration_specifiers(struct token *next, struct ctype *ct break; thistype = s->ctype; mod = thistype.modifiers; - if (qual && (mod & ~(MOD_ATTRIBUTE | MOD_CONST | MOD_VOLATILE))) - 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 (qual) { + if (s->type != SYM_KEYWORD) + break; + if (!(s->op->type & (KW_ATTRIBUTE | KW_QUALIFIER))) + break; + } + if (s->type == SYM_KEYWORD && s->op->declarator) { + next = s->op->declarator(next, &thistype); mod = thistype.modifiers; } type = thistype.base_type; @@ -910,13 +999,13 @@ static struct token *direct_declarator(struct token *token, struct symbol *decl, 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; @@ -932,10 +1021,10 @@ static struct token *pointer(struct token *token, struct ctype *ctype) 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; - + while (match_op(token,'*')) { struct symbol *ptr = alloc_symbol(token->pos, SYM_PTR); ptr->ctype.modifiers = modifiers & ~MOD_STORAGE; @@ -976,7 +1065,7 @@ static struct token *handle_bitfield(struct token *token, struct symbol *decl) 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; @@ -133,5 +133,6 @@ extern struct symbol *ctype_fp(unsigned long spec); 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 */ @@ -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); @@ -33,6 +33,7 @@ enum namespace { NS_ITERATOR = 32, NS_PREPROCESSOR = 64, NS_UNDEF = 128, + NS_KEYWORD = 256, }; enum type { @@ -53,9 +54,18 @@ enum type { SYM_LABEL, SYM_RESTRICT, SYM_FOULED, + SYM_KEYWORD, SYM_BAD, }; +enum keyword { + KW_SPECIFIER = 1 << 0, + KW_MODIFIER = 1 << 1, + KW_QUALIFIER = 1 << 2, + KW_ATTRIBUTE = 1 << 3, + KW_TYPEOF = 1 << 4, +}; + struct context { struct expression *context; unsigned int in, out; @@ -74,10 +84,14 @@ struct ctype { }; struct symbol_op { + enum keyword type; int (*evaluate)(struct expression *); int (*expand)(struct expression *, int); int (*args)(struct expression *); -}; + + /* keywrods */ + struct token *(*declarator)(struct token *token, struct ctype *ctype); +}; extern int expand_safe_p(struct expression *expr, int cost); extern int expand_constant_p(struct expression *expr, int cost); @@ -87,8 +101,8 @@ extern int expand_constant_p(struct expression *expr, int cost); #define SYM_ATTR_STRONG 2 struct symbol { - enum namespace namespace:8; enum type type:8; + enum namespace namespace:9; unsigned char used:1, attr:2; struct position pos; /* Where this symbol was declared */ struct ident *ident; /* What identifier this symbol is associated with */ @@ -159,12 +173,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 +194,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) @@ -54,7 +54,8 @@ struct ident { struct symbol *symbols; /* Pointer to semantic meaning list */ unsigned char len; /* Length of identifier name */ unsigned char tainted:1, - reserved:1; + reserved:1, + keyword:1; char name[]; /* Actual identifier */ }; |