Support macro invocations with multiple tokens for a single argument.

We provide for this by changing the value of the argument-list
production from a list of strings (string_list_t) to a new
data-structure that holds a list of lists of strings
(argument_list_t).
This commit is contained in:
Carl Worth 2010-05-14 10:44:19 -07:00
parent db272e6e6f
commit 8f6a828e4a
2 changed files with 102 additions and 24 deletions

View file

@ -62,7 +62,7 @@ _expand_object_macro (glcpp_parser_t *parser, const char *identifier);
string_list_t *
_expand_function_macro (glcpp_parser_t *parser,
const char *identifier,
string_list_t *arguments);
argument_list_t *arguments);
void
_print_string_list (string_list_t *list);
@ -79,17 +79,27 @@ _string_list_append_list (string_list_t *list, string_list_t *tail);
int
_string_list_contains (string_list_t *list, const char *member, int *index);
const char *
_string_list_member_at (string_list_t *list, int index);
int
_string_list_length (string_list_t *list);
argument_list_t *
_argument_list_create (void *ctx);
void
_argument_list_append (argument_list_t *list, string_list_t *argument);
int
_argument_list_length (argument_list_t *list);
string_list_t *
_argument_list_member_at (argument_list_t *list, int index);
%}
%union {
char *str;
string_list_t *list;
string_list_t *string_list;
argument_list_t *argument_list;
}
%parse-param {glcpp_parser_t *parser}
@ -97,7 +107,8 @@ _string_list_length (string_list_t *list);
%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF
%type <str> FUNC_MACRO IDENTIFIER identifier_perhaps_macro OBJ_MACRO TOKEN word word_or_symbol
%type <list> argument argument_list macro parameter_list replacement_list
%type <string_list> argument macro parameter_list replacement_list
%type <argument_list> argument_list
%%
@ -139,11 +150,15 @@ macro:
argument_list:
argument {
$$ = _string_list_create (parser);
_string_list_append_list ($$, $1);
$$ = _argument_list_create (parser);
_argument_list_append ($$, $1);
}
| argument_list ',' SPACE argument {
_argument_list_append ($1, $4);
$$ = $1;
}
| argument_list ',' argument {
_string_list_append_list ($1, $3);
_argument_list_append ($1, $3);
$$ = $1;
}
;
@ -156,6 +171,11 @@ argument:
_string_list_append_item ($1, $2);
talloc_free ($2);
}
| argument SPACE word {
_string_list_append_item ($1, " ");
_string_list_append_item ($1, $3);
talloc_free ($3);
}
| argument '(' argument ')'
;
@ -343,10 +363,59 @@ _print_string_list (string_list_t *list)
printf ("%s", node->str);
}
const char *
_string_list_member_at (string_list_t *list, int index)
argument_list_t *
_argument_list_create (void *ctx)
{
string_node_t *node;
argument_list_t *list;
list = xtalloc (ctx, argument_list_t);
list->head = NULL;
list->tail = NULL;
return list;
}
void
_argument_list_append (argument_list_t *list, string_list_t *argument)
{
argument_node_t *node;
if (argument == NULL || argument->head == NULL)
return;
node = xtalloc (list, argument_node_t);
node->argument = argument;
node->next = NULL;
if (list->head == NULL) {
list->head = node;
} else {
list->tail->next = node;
}
list->tail = node;
}
int
_argument_list_length (argument_list_t *list)
{
int length = 0;
argument_node_t *node;
if (list == NULL)
return 0;
for (node = list->head; node; node = node->next)
length++;
return length;
}
string_list_t *
_argument_list_member_at (argument_list_t *list, int index)
{
argument_node_t *node;
int i;
if (list == NULL)
@ -360,7 +429,7 @@ _string_list_member_at (string_list_t *list, int index)
}
if (node)
return node->str;
return node->argument;
return NULL;
}
@ -453,14 +522,14 @@ _expand_macro_recursive (glcpp_parser_t *parser,
const char *token,
const char *orig,
string_list_t *parameters,
string_list_t *arguments);
argument_list_t *arguments);
static string_list_t *
_expand_string_list_recursive (glcpp_parser_t *parser,
string_list_t *list,
const char *orig,
string_list_t *parameters,
string_list_t *arguments)
argument_list_t *arguments)
{
string_list_t *result;
string_list_t *child;
@ -479,11 +548,11 @@ _expand_string_list_recursive (glcpp_parser_t *parser,
}
if (_string_list_contains (parameters, token, &index)) {
const char *argument;
string_list_t *argument;
argument = _string_list_member_at (arguments, index);
child = _expand_macro_recursive (parser, argument,
orig, NULL, NULL);
argument = _argument_list_member_at (arguments, index);
child = _expand_string_list_recursive (parser, argument,
orig, NULL, NULL);
_string_list_append_list (result, child);
} else {
child = _expand_macro_recursive (parser, token,
@ -502,7 +571,7 @@ _expand_macro_recursive (glcpp_parser_t *parser,
const char *token,
const char *orig,
string_list_t *parameters,
string_list_t *arguments)
argument_list_t *arguments)
{
macro_t *macro;
string_list_t *replacements;
@ -537,7 +606,7 @@ _expand_object_macro (glcpp_parser_t *parser, const char *identifier)
string_list_t *
_expand_function_macro (glcpp_parser_t *parser,
const char *identifier,
string_list_t *arguments)
argument_list_t *arguments)
{
string_list_t *result;
macro_t *macro;
@ -547,13 +616,13 @@ _expand_function_macro (glcpp_parser_t *parser,
macro = hash_table_find (parser->defines, identifier);
assert (macro->is_function);
if (_string_list_length (arguments) !=
if (_argument_list_length (arguments) !=
_string_list_length (macro->parameters))
{
fprintf (stderr,
"Error: macro %s invoked with %d arguments (expected %d)\n",
identifier,
_string_list_length (arguments),
_argument_list_length (arguments),
_string_list_length (macro->parameters));
return NULL;
}

11
glcpp.h
View file

@ -30,7 +30,6 @@
/* Some data types used for parser value. */
typedef struct string_node {
const char *str;
struct string_node *next;
@ -41,6 +40,16 @@ typedef struct string_list {
string_node_t *tail;
} string_list_t;
typedef struct argument_node {
string_list_t *argument;
struct argument_node *next;
} argument_node_t;
typedef struct argument_list {
argument_node_t *head;
argument_node_t *tail;
} argument_list_t;
typedef struct glcpp_parser glcpp_parser_t;
glcpp_parser_t *