From 0a93cbbe4f00e0bdd0c61119d3598e3a98a37505 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 13 May 2010 10:29:07 -0700 Subject: [PATCH] Fix parsing of object-like macro with a definition that begins with '('. Previously our parser was incorrectly treating this case as a function-like macro. We fix this by conditionally passing a SPACE token from the lexer, (but only immediately after the identifier immediately after #define). --- glcpp-lex.l | 41 ++++++++++++++++++++++++++++++++++++----- glcpp-parse.y | 32 ++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/glcpp-lex.l b/glcpp-lex.l index c6e545a..3c9dda4 100644 --- a/glcpp-lex.l +++ b/glcpp-lex.l @@ -32,6 +32,9 @@ %option reentrant noyywrap %option extra-type="glcpp_parser_t *" +%x ST_DEFINE +%x ST_DEFVAL + SPACE [[:space:]] NONSPACE [^[:space:]] NEWLINE [\n] @@ -42,16 +45,42 @@ TOKEN [^[:space:](),]+ %% -{HASH}define{HSPACE}* { +{HASH}undef{HSPACE}* { + return UNDEF; +} + + /* We use the ST_DEFINE and ST_DEFVAL states so that we can + * pass a space token, (yes, a token for whitespace!), since + * the preprocessor specification requires distinguishing + * "#define foo()" from "#define foo ()". + */ +{HASH}define{HSPACE}* { + BEGIN ST_DEFINE; return DEFINE; } -{HASH}undef{HSPACE}* { - return UNDEF; +{IDENTIFIER} { + BEGIN ST_DEFVAL; + yylval.str = xtalloc_strdup (yyextra, yytext); + return IDENTIFIER; } +\n { + BEGIN INITIAL; + return NEWLINE; +} + +{HSPACE}+ { + BEGIN INITIAL; + return SPACE; +} -{IDENTIFIER} { +"(" { + BEGIN INITIAL; + return '('; +} + +{IDENTIFIER} { yylval.str = xtalloc_strdup (yyextra, yytext); switch (glcpp_parser_macro_type (yyextra, yylval.str)) { @@ -67,7 +96,9 @@ TOKEN [^[:space:](),]+ } } -[(),] { return yytext[0]; } +[(),] { + return yytext[0]; +} {TOKEN} { yylval.str = xtalloc_strdup (yyextra, yytext); diff --git a/glcpp-parse.y b/glcpp-parse.y index 66725db..dc352de 100644 --- a/glcpp-parse.y +++ b/glcpp-parse.y @@ -83,8 +83,8 @@ _list_append_list (list_t *list, list_t *tail); %parse-param {glcpp_parser_t *parser} %lex-param {void *scanner} -%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO TOKEN UNDEF -%type FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN string +%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF +%type FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN word word_or_symbol %type argument argument_list parameter_list replacement_list %% @@ -105,9 +105,10 @@ content: } | macro | directive_with_newline -| NEWLINE { - printf ("\n"); - } +| NEWLINE { printf ("\n"); } +| '(' { printf ("("); } +| ')' { printf (")"); } +| ',' { printf (","); } ; macro: @@ -135,7 +136,7 @@ argument: /* empty */ { $$ = _list_create (parser); } -| argument string { +| argument word { _list_append_item ($1, $2); talloc_free ($2); } @@ -149,8 +150,12 @@ directive_with_newline: ; directive: - DEFINE IDENTIFIER replacement_list { - _define_object_macro (parser, $2, $3); + DEFINE IDENTIFIER { + list_t *list = _list_create (parser); + _define_object_macro (parser, $2, list); + } +| DEFINE IDENTIFIER SPACE replacement_list { + _define_object_macro (parser, $2, $4); } | DEFINE IDENTIFIER '(' parameter_list ')' replacement_list { _define_function_macro (parser, $2, $4, $6); @@ -183,7 +188,7 @@ replacement_list: /* empty */ { $$ = _list_create (parser); } -| replacement_list string { +| replacement_list word_or_symbol { _list_append_item ($1, $2); talloc_free ($2); $$ = $1; @@ -206,7 +211,14 @@ parameter_list: } ; -string: +word_or_symbol: + word { $$ = $1; } +| '(' { $$ = xtalloc_strdup (parser, "("); } +| ')' { $$ = xtalloc_strdup (parser, ")"); } +| ',' { $$ = xtalloc_strdup (parser, ","); } +; + +word: IDENTIFIER { $$ = $1; } | FUNC_MACRO { $$ = $1; } | OBJ_MACRO { $$ = $1; } -- 2.7.4