summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2010-05-25 17:32:21 -0700
committerCarl Worth <cworth@cworth.org>2010-05-25 17:32:21 -0700
commit9ce18cf9837bee379dfd0f52a3df005c1797e544 (patch)
tree74df61b2c9c328e8d9d2ba8e5d0b2c725984f01f
parente9397867ddce20a4263949f4b3a488fa99af3041 (diff)
Implement substitution of function parameters in macro calls.
This makes tests 16 - 19 pass.
-rw-r--r--glcpp-parse.y65
1 files changed, 57 insertions, 8 deletions
diff --git a/glcpp-parse.y b/glcpp-parse.y
index 0460f71..eb93bad 100644
--- a/glcpp-parse.y
+++ b/glcpp-parse.y
@@ -405,9 +405,6 @@ _argument_list_append (argument_list_t *list, token_list_t *argument)
{
argument_node_t *node;
- if (argument == NULL || argument->head == NULL)
- return;
-
node = xtalloc (list, argument_node_t);
node->argument = argument;
@@ -741,8 +738,9 @@ typedef enum function_status
* Macro name is not followed by a balanced set of parentheses.
*/
static function_status_t
-_find_arguments (token_node_t **node_ret, argument_list_t **arguments)
+_arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
{
+ token_list_t *argument;
token_node_t *node = *node_ret, *last;
int paren_count;
int arg_count;
@@ -757,6 +755,8 @@ _find_arguments (token_node_t **node_ret, argument_list_t **arguments)
if (node == NULL || node->token->type != '(')
return FUNCTION_NOT_A_FUNCTION;
+ argument = NULL;
+
paren_count = 0;
arg_count = 0;
do {
@@ -771,7 +771,14 @@ _find_arguments (token_node_t **node_ret, argument_list_t **arguments)
else if (node->token->type == ',' &&
paren_count == 1)
{
- arg_count++;
+ argument = NULL;
+ }
+ else {
+ if (argument == NULL) {
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+ }
+ _token_list_append (argument, node->token);
}
last = node;
@@ -799,6 +806,9 @@ _glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
const char *identifier;
argument_list_t *arguments;
function_status_t status;
+ token_list_t *expanded;
+ token_node_t *i, *j;
+ int parameter_index;
node = *node_ret;
identifier = node->token->value.str;
@@ -807,7 +817,8 @@ _glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
assert (macro->is_function);
- status = _find_arguments (node_ret, &arguments);
+ arguments = _argument_list_create (parser);
+ status = _arguments_parse (arguments, node_ret);
switch (status) {
case FUNCTION_STATUS_SUCCESS:
@@ -821,10 +832,48 @@ _glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
exit (1);
}
+ if (macro->replacements == NULL) {
+ talloc_free (arguments);
+ return;
+ }
+
+
+ if (_argument_list_length (arguments) !=
+ _string_list_length (macro->parameters))
+ {
+ fprintf (stderr,
+ "Error: macro %s invoked with %d arguments (expected %d)\n",
+ identifier,
+ _argument_list_length (arguments),
+ _string_list_length (macro->parameters));
+ return;
+ }
+
+ expanded = _token_list_create (arguments);
+
+ for (i = macro->replacements->head; i; i = i->next) {
+ if (i->token->type == IDENTIFIER &&
+ _string_list_contains (macro->parameters,
+ i->token->value.str,
+ &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->token);
+ }
+ } else {
+ _token_list_append (expanded, i->token);
+ }
+ }
+
_string_list_push (parser->active, identifier);
- _glcpp_parser_print_expanded_token_list (parser,
- macro->replacements);
+ _glcpp_parser_print_expanded_token_list (parser, expanded);
_string_list_pop (parser->active);
+
+ talloc_free (arguments);
}
void