Fix parsing of object-like macro with a definition that begins with '('.
authorCarl Worth <cworth@cworth.org>
Thu, 13 May 2010 17:29:07 +0000 (10:29 -0700)
committerCarl Worth <cworth@cworth.org>
Fri, 14 May 2010 16:20:13 +0000 (09:20 -0700)
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
glcpp-parse.y

index c6e545aa8ed2802d92794d16f2529d8fdf96ee7a..3c9dda46d4790a75d3820917babce99649846855 100644 (file)
@@ -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;
+<ST_DEFINE>{IDENTIFIER}        {
+       BEGIN ST_DEFVAL;
+       yylval.str = xtalloc_strdup (yyextra, yytext);
+       return IDENTIFIER;
 }
 
+<ST_DEFVAL>\n {
+       BEGIN INITIAL;
+       return NEWLINE;
+}
+
+<ST_DEFVAL>{HSPACE}+ {
+       BEGIN INITIAL;
+       return SPACE;
+}
 
-{IDENTIFIER}   {
+<ST_DEFVAL>"(" {
+       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);
index 66725db69edf50e71f0baed5507970a91ced2d17..dc352de55b65a218bb8b1aa1b9f250eb01afb7ac 100644 (file)
@@ -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 <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN string
+%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF
+%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN word word_or_symbol
 %type <list> 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; }