aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/genksyms/parse.y
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2011-02-03 17:57:09 -0500
committerMichal Marek <mmarek@suse.cz>2011-03-17 10:13:56 -0400
commite37ddb82500393cb417c3ab0fe0726d9a8652372 (patch)
tree6ecc94992cb5affad4fe438d9b586a61b803f928 /scripts/genksyms/parse.y
parent01762c4ec5f6f62c550304b9c70e824293cefdd0 (diff)
genksyms: Track changes to enum constants
Enum constants can be used as array sizes; if the enum itself does not appear in the symbol expansion, a change in the enum constant will go unnoticed. Example patch that changes the ABI but does not change the checksum with current genksyms: | enum e { | E1, | E2, |+ E3, | E_MAX | }; | | struct s { | int a[E_MAX]; | } | | int f(struct s *s) { ... } | EXPORT_SYMBOL(f) Therefore, remember the value of each enum constant and expand each occurence to <constant> <value>. The value is not actually computed, but instead an expression in the form (last explicitly assigned value) + N is used. This avoids having to parse and semantically understand whole of C. Note: The changes won't take effect until the lexer and parser are rebuilt by the next patch. Signed-off-by: Michal Marek <mmarek@suse.cz> Acked-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts/genksyms/parse.y')
-rw-r--r--scripts/genksyms/parse.y34
1 files changed, 30 insertions, 4 deletions
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index 09a265cd719..ba5c242866c 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -25,6 +25,7 @@
25 25
26#include <assert.h> 26#include <assert.h>
27#include <stdlib.h> 27#include <stdlib.h>
28#include <string.h>
28#include "genksyms.h" 29#include "genksyms.h"
29 30
30static int is_typedef; 31static int is_typedef;
@@ -227,16 +228,19 @@ type_specifier:
227 add_symbol(i->string, SYM_UNION, s, is_extern); 228 add_symbol(i->string, SYM_UNION, s, is_extern);
228 $$ = $3; 229 $$ = $3;
229 } 230 }
230 | ENUM_KEYW IDENT BRACE_PHRASE 231 | ENUM_KEYW IDENT enum_body
231 { struct string_list *s = *$3, *i = *$2, *r; 232 { struct string_list *s = *$3, *i = *$2, *r;
232 r = copy_node(i); r->tag = SYM_ENUM; 233 r = copy_node(i); r->tag = SYM_ENUM;
233 r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; 234 r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;
234 add_symbol(i->string, SYM_ENUM, s, is_extern); 235 add_symbol(i->string, SYM_ENUM, s, is_extern);
235 $$ = $3; 236 $$ = $3;
236 } 237 }
237 238 /*
238 /* Anonymous s/u/e definitions. Nothing needs doing. */ 239 * Anonymous enum definition. Tell add_symbol() to restart its counter.
239 | ENUM_KEYW BRACE_PHRASE { $$ = $2; } 240 */
241 | ENUM_KEYW enum_body
242 { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
243 /* Anonymous s/u definitions. Nothing needs doing. */
240 | STRUCT_KEYW class_body { $$ = $2; } 244 | STRUCT_KEYW class_body { $$ = $2; }
241 | UNION_KEYW class_body { $$ = $2; } 245 | UNION_KEYW class_body { $$ = $2; }
242 ; 246 ;
@@ -449,6 +453,28 @@ attribute_opt:
449 | attribute_opt ATTRIBUTE_PHRASE 453 | attribute_opt ATTRIBUTE_PHRASE
450 ; 454 ;
451 455
456enum_body:
457 '{' enumerator_list '}' { $$ = $3; }
458 | '{' enumerator_list ',' '}' { $$ = $4; }
459 ;
460
461enumerator_list:
462 enumerator
463 | enumerator_list ',' enumerator
464
465enumerator:
466 IDENT
467 {
468 const char *name = strdup((*$1)->string);
469 add_symbol(name, SYM_ENUM_CONST, NULL, 0);
470 }
471 | IDENT '=' EXPRESSION_PHRASE
472 {
473 const char *name = strdup((*$1)->string);
474 struct string_list *expr = copy_list_range(*$3, *$2);
475 add_symbol(name, SYM_ENUM_CONST, expr, 0);
476 }
477
452asm_definition: 478asm_definition:
453 ASM_PHRASE ';' { $$ = $2; } 479 ASM_PHRASE ';' { $$ = $2; }
454 ; 480 ;