diff options
author | Carl Worth <[email protected]> | 2011-09-29 17:04:47 -0700 |
---|---|---|
committer | Carl Worth <[email protected]> | 2011-09-30 11:44:10 -0700 |
commit | 28842c2331e6df2cbe18c0be3487ece93680075d (patch) | |
tree | 33bf0f64352bdad368f12bb823262fdd11deabbf | |
parent | 7bb3403e0172a440b8100bcf1db8462f50a254cc (diff) |
glcpp: Implement token pasting for non-function-like macros
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 <[email protected]>
Signed-off-by: Carl Worth <[email protected]>
-rw-r--r-- | src/glsl/glcpp/glcpp-parse.y | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index d547ecf6ff3..ff9fa7a49b4 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -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); |