Add support (and test) for an object-to-function chain with the parens in the content.
authorCarl Worth <cworth@cworth.org>
Thu, 27 May 2010 00:01:57 +0000 (17:01 -0700)
committerCarl Worth <cworth@cworth.org>
Thu, 27 May 2010 00:01:57 +0000 (17:01 -0700)
That is, the following case:

#define foo(x) (x)
#define bar
bar(baz)

which now works with this (ugly) commit.

I definitely want to come up with something cleaner than this.

glcpp-parse.y
tests/055-define-chain-obj-to-func-parens-in-text.c [new file with mode: 0644]

index 1346b65aff6196a1b471158ade777688a2c3072f..abdcd1ed5d84368f5fb0a013922c7d961b388ac7 100644 (file)
@@ -926,9 +926,9 @@ _glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
  * needs further expansion.
  */
 static int
-_glcpp_parser_expand_token_onto (glcpp_parser_t *parser,
-                                token_t *token,
-                                token_list_t *result)
+_expand_token_onto (glcpp_parser_t *parser,
+                   token_t *token,
+                   token_list_t *result)
 {
        const char *identifier;
        macro_t *macro;
@@ -1075,10 +1075,10 @@ _arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
 /* Prints the expansion of *node (consuming further tokens from the
  * list as necessary). Upon return *node will be the last consumed
  * node, such that further processing can continue with node->next. */
-static void
-_glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
-                                   token_node_t **node_ret,
-                                   token_list_t *result)
+static function_status_t
+_expand_function_onto (glcpp_parser_t *parser,
+                      token_node_t **node_ret,
+                      token_list_t *result)
 {
        macro_t *macro;
        token_node_t *node;
@@ -1103,7 +1103,7 @@ _glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
                break;
        case FUNCTION_NOT_A_FUNCTION:
                _token_list_append (result, node->token);
-               return;
+               return FUNCTION_NOT_A_FUNCTION;
        case FUNCTION_UNBALANCED_PARENTHESES:
                fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
                         identifier);
@@ -1112,7 +1112,7 @@ _glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
 
        if (macro->replacements == NULL) {
                talloc_free (arguments);
-               return;
+               return FUNCTION_STATUS_SUCCESS;
        }
 
        if (_argument_list_length (arguments) !=
@@ -1123,7 +1123,7 @@ _glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
                         identifier,
                         _argument_list_length (arguments),
                         _string_list_length (macro->parameters));
-               return;
+               exit (1);
        }
 
        /* Perform argument substitution on the replacement list. */
@@ -1191,6 +1191,8 @@ _glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
        _string_list_pop (parser->active);
 
        talloc_free (arguments);
+
+       return FUNCTION_STATUS_SUCCESS;
 }
 
 static void
@@ -1199,19 +1201,50 @@ _glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
                                      token_list_t *result)
 {
        token_node_t *node;
+       token_list_t *intermediate, *list_orig = list;
+       int i, need_rescan = 0;
 
        if (list == NULL)
                return;
 
-       for (node = list->head; node; node = node->next)
-       {
-               if (_glcpp_parser_expand_token_onto (parser, node->token,
-                                                    result))
+       intermediate = _token_list_create (parser);
+
+       /* XXX: The two-pass expansion here is really ugly. The
+        * problem this is solving is that we can expand a macro into
+        * a function-like macro name, and then we need to recognize
+        * that as a function-like macro, but perhaps the parentheses
+        * and arguments aren't on the token list yet, (since they are
+        * in the actual content so they are part of what we are
+        * expanding.
+        *
+        * This ugly hack works, but is messy, fragile, and hard to
+        * maintain. I think a cleaner solution would separate the
+        * notions of expanding and appending and avoid this problem
+        * altogether.
+        */
+
+       for (i = 0; i < 2; i++) {
+               if (i == 1) {
+                       list = intermediate;
+                       intermediate = _token_list_create (parser);
+               }
+               for (node = list->head; node; node = node->next)
                {
-                       _glcpp_parser_expand_function_onto (parser, &node,
-                                                           result);
+                       if (_expand_token_onto (parser, node->token,
+                                               intermediate))
+                       {       
+                               if (_expand_function_onto (parser, &node,
+                                                          intermediate))
+                               {
+                                       need_rescan = 1;
+                               }
+                       }
                }
+               if (list != list_orig)
+                       talloc_free (list);
        }
+
+       _token_list_append_list (result, intermediate);
 }
 
 void
diff --git a/tests/055-define-chain-obj-to-func-parens-in-text.c b/tests/055-define-chain-obj-to-func-parens-in-text.c
new file mode 100644 (file)
index 0000000..00f2c23
--- /dev/null
@@ -0,0 +1,3 @@
+#define failure() success
+#define foo failure
+foo()