Pre-expand macro arguments at time of invocation.
authorCarl Worth <cworth@cworth.org>
Thu, 20 May 2010 22:15:26 +0000 (15:15 -0700)
committerCarl Worth <cworth@cworth.org>
Thu, 20 May 2010 22:15:26 +0000 (15:15 -0700)
Previously, we were using the same lexing stack as we use for macro
expansion to also expand macro arguments. Instead, we now do this
earlier by simply recursing over the macro-invocations replacement
list and constructing a new expanded list, (and pushing only *that*
onto the stack).

This is simpler, and also allows us to more easily implement token
pasting in the future.

glcpp-lex.l
glcpp-parse.y
glcpp.h

index 114b59f04567a074ca875ad4601046b05bc3ed53..6138a9de12ef48b94062e9454036d8e8a826486c 100644 (file)
@@ -138,14 +138,6 @@ TOKEN              [^[:space:](),]+
        switch (glcpp_parser_classify_token (yyextra, yylval.str,
                                             &parameter_index))
        {
-               case TOKEN_CLASS_ARGUMENT:
-                       talloc_free (yylval.str);
-                       /* We don't return a value here since the
-                        * current token will be replaced by new
-                        * tokens. */
-                       glcpp_parser_push_expansion_argument (yyextra,
-                                                             parameter_index);
-               break;
                case TOKEN_CLASS_IDENTIFIER:
                        return IDENTIFIER;
                break;
index ddc2a258cd8736c9b2c8392520c6f76239735f8e..0691619acf4b936d7b3345f09db8d4280de0c987 100644 (file)
@@ -86,11 +86,6 @@ _token_list_append (token_list_t *list, int type, const char *value);
 void
 _token_list_append_list (token_list_t *list, token_list_t *tail);
 
-static void
-glcpp_parser_push_expansion_macro (glcpp_parser_t *parser,
-                                  macro_t *macro,
-                                  argument_list_t *arguments);
-
 static void
 glcpp_parser_pop_expansion (glcpp_parser_t *parser);
 
@@ -614,24 +609,7 @@ glcpp_parser_classify_token (glcpp_parser_t *parser,
 {
        macro_t *macro;
 
-       /* First we check if we are currently expanding a
-        * function-like macro, and if so, whether the parameter list
-        * contains a parameter matching this token name. */
-       if (parser->expansions &&
-           parser->expansions->macro &&
-           parser->expansions->macro->parameters)
-       {
-               string_list_t *list;
-
-               list = parser->expansions->macro->parameters;
-
-               if (_string_list_contains (list, identifier, parameter_index))
-                   return TOKEN_CLASS_ARGUMENT;
-       }
-
-       /* If not a function-like macro parameter, we next check if
-        * this token is a macro itself. */
-
+       /* Is this token a defined macro? */
        macro = hash_table_find (parser->defines, identifier);
 
        if (macro == NULL)
@@ -685,47 +663,21 @@ _define_function_macro (glcpp_parser_t *parser,
 }
 
 static void
-_glcpp_parser_push_expansion_internal (glcpp_parser_t *parser,
-                                      macro_t *macro,
-                                      argument_list_t *arguments,
-                                      token_node_t *replacements)
+_glcpp_parser_push_expansion (glcpp_parser_t *parser,
+                             macro_t *macro,
+                             token_node_t *replacements)
 {
        expansion_node_t *node;
 
        node = xtalloc (parser, expansion_node_t);
 
        node->macro = macro;
-       node->arguments = arguments;
        node->replacements = replacements;
 
        node->next = parser->expansions;
        parser->expansions = node;
 }
 
-static void
-glcpp_parser_push_expansion_macro (glcpp_parser_t *parser,
-                                  macro_t *macro,
-                                  argument_list_t *arguments)
-{
-       _glcpp_parser_push_expansion_internal (parser, macro, arguments,
-                                              macro->replacements->head);
-}
-
-void
-glcpp_parser_push_expansion_argument (glcpp_parser_t *parser,
-                                     int argument_index)
-{
-       argument_list_t *arguments;
-       token_list_t *argument;
-
-       arguments = parser->expansions->arguments;
-
-       argument = _argument_list_member_at (arguments, argument_index);
-
-       _glcpp_parser_push_expansion_internal (parser, NULL, NULL,
-                                              argument->head);
-}
-
 static void
 glcpp_parser_pop_expansion (glcpp_parser_t *parser)
 {
@@ -752,7 +704,7 @@ _expand_object_macro (glcpp_parser_t *parser, const char *identifier)
        assert (! macro->is_function);
        assert (! glcpp_parser_is_expanding (parser, identifier));
 
-       glcpp_parser_push_expansion_macro (parser, macro, NULL);
+       _glcpp_parser_push_expansion (parser, macro, macro->replacements->head);
 }
 
 void
@@ -761,6 +713,9 @@ _expand_function_macro (glcpp_parser_t *parser,
                        argument_list_t *arguments)
 {
        macro_t *macro;
+       token_list_t *expanded;
+       token_node_t *i, *j;
+       int parameter_index;
 
        macro = hash_table_find (parser->defines, identifier);
        assert (macro->is_function);
@@ -777,7 +732,26 @@ _expand_function_macro (glcpp_parser_t *parser,
                return;
        }
 
-       glcpp_parser_push_expansion_macro (parser, macro, arguments);
+       expanded = _token_list_create (macro);
+
+       for (i = macro->replacements->head; i; i = i->next) {
+               if (_string_list_contains (macro->parameters, i->value,
+                                          &parameter_index))
+               {
+                       token_list_t *argument;
+                       argument = _argument_list_member_at (arguments,
+                                                            parameter_index);
+                       for (j = argument->head; j; j = j->next)
+                       {
+                               _token_list_append (expanded, j->type,
+                                                   j->value);
+                       }
+               } else {
+                       _token_list_append (expanded, i->type, i->value);
+               }
+       }
+
+       _glcpp_parser_push_expansion (parser, macro, expanded->head);
 }
 
 static int
@@ -819,12 +793,6 @@ glcpp_parser_lex (glcpp_parser_t *parser)
        switch (glcpp_parser_classify_token (parser, yylval.str,
                                             &parameter_index))
        {
-       case TOKEN_CLASS_ARGUMENT:
-               talloc_free (yylval.str);
-               glcpp_parser_push_expansion_argument (parser,
-                                                     parameter_index);
-               goto RECURSE;
-               break;
        case TOKEN_CLASS_IDENTIFIER:
                return IDENTIFIER;
                break;
diff --git a/glcpp.h b/glcpp.h
index 048a9be76bb4b2ef5013d63fd119f254236b4025..1537109ada6a449f6695a43cfc1f66f771102d5b 100644 (file)
--- a/glcpp.h
+++ b/glcpp.h
@@ -71,7 +71,6 @@ typedef struct argument_list {
 typedef struct glcpp_parser glcpp_parser_t;
 
 typedef enum {
-       TOKEN_CLASS_ARGUMENT,
        TOKEN_CLASS_IDENTIFIER,
        TOKEN_CLASS_IDENTIFIER_FINALIZED,
        TOKEN_CLASS_FUNC_MACRO,
@@ -92,7 +91,6 @@ typedef struct {
 
 typedef struct expansion_node {
        macro_t *macro;
-       argument_list_t *arguments;
        token_node_t *replacements;
        struct expansion_node *next;
 } expansion_node_t;