aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Triplett <josh@freedesktop.org>2007-03-07 21:40:15 -0800
committerJosh Triplett <josh@freedesktop.org>2007-03-07 21:40:15 -0800
commitaf30c6df74f01db10fa78ac0cbdb5c3c40b5c73f (patch)
tree32983dd28adb96057d7e84dcbca727c62dea9235
parentMoving statement parsing into smaller functions. (diff)
downloadsparse-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.c141
-rw-r--r--parse.h1
-rw-r--r--symbol.c35
-rw-r--r--symbol.h24
-rw-r--r--token.h3
5 files changed, 135 insertions, 69 deletions
diff --git a/parse.c b/parse.c
index b5876a7..4a4b419 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/parse.h b/parse.h
index 98c33bc..609910f 100644
--- a/parse.h
+++ b/parse.h
@@ -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 */
diff --git a/symbol.c b/symbol.c
index 1a3f594..bad05fd 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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);
diff --git a/symbol.h b/symbol.h
index e6081e6..e530ff8 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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)
diff --git a/token.h b/token.h
index d60bb46..4c71dbd 100644
--- a/token.h
+++ b/token.h
@@ -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 */
};