[Mesa-dev] [PATCH 4/6] glcpp: Implement token pasting for non-function-like macros

Carl Worth cworth at cworth.org
Thu Sep 29 23:00:28 PDT 2011


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.
---
 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 d547ecf..ff9fa7a 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);
-- 
1.7.6.3



More information about the mesa-dev mailing list