Implement substitution of function parameters in macro calls.

This makes tests 16 - 19 pass.
This commit is contained in:
Carl Worth 2010-05-25 17:32:21 -07:00
parent e9397867dd
commit 9ce18cf983

View file

@ -405,9 +405,6 @@ _argument_list_append (argument_list_t *list, token_list_t *argument)
{ {
argument_node_t *node; argument_node_t *node;
if (argument == NULL || argument->head == NULL)
return;
node = xtalloc (list, argument_node_t); node = xtalloc (list, argument_node_t);
node->argument = argument; node->argument = argument;
@ -741,8 +738,9 @@ typedef enum function_status
* Macro name is not followed by a balanced set of parentheses. * Macro name is not followed by a balanced set of parentheses.
*/ */
static function_status_t 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; token_node_t *node = *node_ret, *last;
int paren_count; int paren_count;
int arg_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 != '(') if (node == NULL || node->token->type != '(')
return FUNCTION_NOT_A_FUNCTION; return FUNCTION_NOT_A_FUNCTION;
argument = NULL;
paren_count = 0; paren_count = 0;
arg_count = 0; arg_count = 0;
do { do {
@ -771,7 +771,14 @@ _find_arguments (token_node_t **node_ret, argument_list_t **arguments)
else if (node->token->type == ',' && else if (node->token->type == ',' &&
paren_count == 1) 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; last = node;
@ -799,6 +806,9 @@ _glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
const char *identifier; const char *identifier;
argument_list_t *arguments; argument_list_t *arguments;
function_status_t status; function_status_t status;
token_list_t *expanded;
token_node_t *i, *j;
int parameter_index;
node = *node_ret; node = *node_ret;
identifier = node->token->value.str; identifier = node->token->value.str;
@ -807,7 +817,8 @@ _glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
assert (macro->is_function); assert (macro->is_function);
status = _find_arguments (node_ret, &arguments); arguments = _argument_list_create (parser);
status = _arguments_parse (arguments, node_ret);
switch (status) { switch (status) {
case FUNCTION_STATUS_SUCCESS: case FUNCTION_STATUS_SUCCESS:
@ -821,10 +832,48 @@ _glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
exit (1); 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); _string_list_push (parser->active, identifier);
_glcpp_parser_print_expanded_token_list (parser, _glcpp_parser_print_expanded_token_list (parser, expanded);
macro->replacements);
_string_list_pop (parser->active); _string_list_pop (parser->active);
talloc_free (arguments);
} }
void void