From 7db2402a8009772a3f10d19cfc7f30be9ee79295 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 26 May 2010 17:01:57 -0700 Subject: [PATCH] Add support (and test) for an object-to-function chain with the parens in the content. 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 | 65 ++++++++++++++----- ...-define-chain-obj-to-func-parens-in-text.c | 3 + 2 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 tests/055-define-chain-obj-to-func-parens-in-text.c diff --git a/glcpp-parse.y b/glcpp-parse.y index 1346b65aff6..abdcd1ed5d8 100644 --- a/glcpp-parse.y +++ b/glcpp-parse.y @@ -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 index 00000000000..00f2c2346d6 --- /dev/null +++ b/tests/055-define-chain-obj-to-func-parens-in-text.c @@ -0,0 +1,3 @@ +#define failure() success +#define foo failure +foo() -- 2.30.2