glcpp: Implement token pasting for non-function-like macros
authorCarl Worth <cworth@cworth.org>
Fri, 30 Sep 2011 00:04:47 +0000 (17:04 -0700)
committerCarl Worth <cworth@cworth.org>
Fri, 30 Sep 2011 18:44:10 +0000 (11:44 -0700)
This is as simple as abstracting one existing block of code into a
function call and then adding a single call to that function for the
case of a non-function-like macro.

This fixes the recently-added 097-paste-with-non-function-macro test
as well as the following piglit tests:

spec/glsl-1.30/preprocessor/concat/concat-01.frag
spec/glsl-1.30/preprocessor/concat/concat-02.frag

Also, the concat-04.frag test now passes for the right reason. The
test is intended to fail the compilation, but before this commit it
was failing compilation (and hence passing the test) for the wrong
reason.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Carl Worth <cworth@cworth.org>
src/glsl/glcpp/glcpp-parse.y

index d547ecf6ff38e10f1fd44ca890cc107c2434321b..ff9fa7a49b44d7a74cbe60b97e305a81bbf162be 100644 (file)
@@ -1275,6 +1275,48 @@ _glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
        glcpp_parser_lex_from (parser, expanded);
 }
 
+static void
+_glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list)
+{
+       token_node_t *node;
+
+       node = list->head;
+       while (node)
+       {
+               token_node_t *next_non_space;
+
+               /* Look ahead for a PASTE token, skipping space. */
+               next_non_space = node->next;
+               while (next_non_space && next_non_space->token->type == SPACE)
+                       next_non_space = next_non_space->next;
+
+               if (next_non_space == NULL)
+                       break;
+
+               if (next_non_space->token->type != PASTE) {
+                       node = next_non_space;
+                       continue;
+               }
+
+               /* Now find the next non-space token after the PASTE. */
+               next_non_space = next_non_space->next;
+               while (next_non_space && next_non_space->token->type == SPACE)
+                       next_non_space = next_non_space->next;
+
+               if (next_non_space == NULL) {
+                       yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+                       return;
+               }
+
+               node->token = _token_paste (parser, node->token, next_non_space->token);
+               node->next = next_non_space->next;
+               if (next_non_space == list->tail)
+                       list->tail = node;
+       }
+
+       list->non_space_tail = list->tail;
+}
+
 /* This is a helper function that's essentially part of the
  * implementation of _glcpp_parser_expand_node. It shouldn't be called
  * except for by that function.
@@ -1386,41 +1428,7 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser,
 
        _token_list_trim_trailing_space (substituted);
 
-       node = substituted->head;
-       while (node)
-       {
-               token_node_t *next_non_space;
-
-               /* Look ahead for a PASTE token, skipping space. */
-               next_non_space = node->next;
-               while (next_non_space && next_non_space->token->type == SPACE)
-                       next_non_space = next_non_space->next;
-
-               if (next_non_space == NULL)
-                       break;
-
-               if (next_non_space->token->type != PASTE) {
-                       node = next_non_space;
-                       continue;
-               }
-
-               /* Now find the next non-space token after the PASTE. */
-               next_non_space = next_non_space->next;
-               while (next_non_space && next_non_space->token->type == SPACE)
-                       next_non_space = next_non_space->next;
-
-               if (next_non_space == NULL) {
-                       yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
-                       return NULL;
-               }
-
-               node->token = _token_paste (parser, node->token, next_non_space->token);
-               node->next = next_non_space->next;
-               if (next_non_space == substituted->tail)
-                       substituted->tail = node;
-       }
-
-       substituted->non_space_tail = substituted->tail;
+       _glcpp_parser_apply_pastes (parser, substituted);
 
        return substituted;
 }
@@ -1490,13 +1498,16 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
 
        if (! macro->is_function)
        {
+               token_list_t *replacement;
                *last = node;
 
                /* Replace a macro defined as empty with a SPACE token. */
                if (macro->replacements == NULL)
                        return _token_list_create_with_one_space (parser);
 
-               return _token_list_copy (parser, macro->replacements);
+               replacement = _token_list_copy (parser, macro->replacements);
+               _glcpp_parser_apply_pastes (parser, replacement);
+               return replacement;
        }
 
        return _glcpp_parser_expand_function (parser, node, last);