diff options
Diffstat (limited to 'scripts/genksyms/parse.y')
| -rw-r--r-- | scripts/genksyms/parse.y | 81 | 
1 files changed, 56 insertions, 25 deletions
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y index 10d7dc724b6..b9f4cf20230 100644 --- a/scripts/genksyms/parse.y +++ b/scripts/genksyms/parse.y @@ -24,7 +24,8 @@  %{  #include <assert.h> -#include <malloc.h> +#include <stdlib.h> +#include <string.h>  #include "genksyms.h"  static int is_typedef; @@ -50,6 +51,25 @@ remove_list(struct string_list **pb, struct string_list **pe)    free_list(b, e);  } +/* Record definition of a struct/union/enum */ +static void record_compound(struct string_list **keyw, +		       struct string_list **ident, +		       struct string_list **body, +		       enum symbol_type type) +{ +	struct string_list *b = *body, *i = *ident, *r; + +	if (i->in_source_file) { +		remove_node(keyw); +		(*ident)->tag = type; +		remove_list(body, ident); +		return; +	} +	r = copy_node(i); r->tag = type; +	r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL; +	add_symbol(i->string, type, b, is_extern); +} +  %}  %token ASM_KEYW @@ -83,6 +103,7 @@ remove_list(struct string_list **pb, struct string_list **pe)  %token ASM_PHRASE  %token ATTRIBUTE_PHRASE +%token TYPEOF_PHRASE  %token BRACE_PHRASE  %token BRACKET_PHRASE  %token EXPRESSION_PHRASE @@ -200,8 +221,8 @@ storage_class_specifier:  type_specifier:  	simple_type_specifier  	| cvar_qualifier -	| TYPEOF_KEYW '(' decl_specifier_seq '*' ')' -	| TYPEOF_KEYW '(' decl_specifier_seq ')' +	| TYPEOF_KEYW '(' parameter_declaration ')' +	| TYPEOF_PHRASE  	/* References to s/u/e's defined elsewhere.  Rearrange things  	   so that it is easier to expand the definition fully later.  */ @@ -214,29 +235,17 @@ type_specifier:  	/* Full definitions of an s/u/e.  Record it.  */  	| STRUCT_KEYW IDENT class_body -		{ struct string_list *s = *$3, *i = *$2, *r; -		  r = copy_node(i); r->tag = SYM_STRUCT; -		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; -		  add_symbol(i->string, SYM_STRUCT, s, is_extern); -		  $$ = $3; -		} +		{ record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; }  	| UNION_KEYW IDENT class_body -		{ struct string_list *s = *$3, *i = *$2, *r; -		  r = copy_node(i); r->tag = SYM_UNION; -		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; -		  add_symbol(i->string, SYM_UNION, s, is_extern); -		  $$ = $3; -		} -	| ENUM_KEYW IDENT BRACE_PHRASE -		{ struct string_list *s = *$3, *i = *$2, *r; -		  r = copy_node(i); r->tag = SYM_ENUM; -		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; -		  add_symbol(i->string, SYM_ENUM, s, is_extern); -		  $$ = $3; -		} - -	/* Anonymous s/u/e definitions.  Nothing needs doing.  */ -	| ENUM_KEYW BRACE_PHRASE			{ $$ = $2; } +		{ record_compound($1, $2, $3, SYM_UNION); $$ = $3; } +	| ENUM_KEYW IDENT enum_body +		{ record_compound($1, $2, $3, SYM_ENUM); $$ = $3; } +	/* +	 * Anonymous enum definition. Tell add_symbol() to restart its counter. +	 */ +	| ENUM_KEYW enum_body +		{ add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; } +	/* Anonymous s/u definitions.  Nothing needs doing.  */  	| STRUCT_KEYW class_body			{ $$ = $2; }  	| UNION_KEYW class_body				{ $$ = $2; }  	; @@ -449,6 +458,28 @@ attribute_opt:  	| attribute_opt ATTRIBUTE_PHRASE  	; +enum_body: +	'{' enumerator_list '}'				{ $$ = $3; } +	| '{' enumerator_list ',' '}'			{ $$ = $4; } +	 ; + +enumerator_list: +	enumerator +	| enumerator_list ',' enumerator + +enumerator: +	IDENT +		{ +			const char *name = strdup((*$1)->string); +			add_symbol(name, SYM_ENUM_CONST, NULL, 0); +		} +	| IDENT '=' EXPRESSION_PHRASE +		{ +			const char *name = strdup((*$1)->string); +			struct string_list *expr = copy_list_range(*$3, *$2); +			add_symbol(name, SYM_ENUM_CONST, expr, 0); +		} +  asm_definition:  	ASM_PHRASE ';'					{ $$ = $2; }  	;  | 
