void
_string_list_append_list (string_list_t *list, string_list_t *tail);
+void
+_string_list_push (string_list_t *list, const char *str);
+
+void
+_string_list_pop (string_list_t *list);
+
int
_string_list_contains (string_list_t *list, const char *member, int *index);
list->tail = node;
}
+void
+_string_list_push (string_list_t *list, const char *str)
+{
+ string_node_t *node;
+
+ node = xtalloc (list, string_node_t);
+ node->str = xtalloc_strdup (node, str);
+
+ node->next = list->head;
+
+ if (list->tail == NULL) {
+ list->tail = node;
+ }
+
+ list->head = node;
+}
+
+void
+_string_list_pop (string_list_t *list)
+{
+ string_node_t *node;
+
+ node = list->head;
+
+ if (node == NULL) {
+ fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
+ exit (1);
+ }
+
+ list->head = node->next;
+
+ if (list->tail == node) {
+ assert (node->next == NULL);
+ list->tail = NULL;
+ }
+
+ talloc_free (node);
+}
+
int
_string_list_contains (string_list_t *list, const char *member, int *index)
{
for (i = 0, node = list->head; node; i++, node = node->next) {
if (strcmp (node->str, member) == 0) {
- *index = i;
+ if (index)
+ *index = i;
return 1;
}
}
static string_list_t *
_expand_macro_recursive (glcpp_parser_t *parser,
const char *token,
- const char *orig,
+ string_list_t *active,
string_list_t *parameters,
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 *active,
string_list_t *parameters,
argument_list_t *arguments)
{
for (node = list->head ; node ; node = node->next) {
token = node->str;
- if (strcmp (token, orig) == 0) {
+ /* Don't expand this macro if it's on the active
+ * stack, (meaning we're already in the process of
+ * expanding it). */
+ if (_string_list_contains (active, token, NULL)) {
_string_list_append_item (result, token);
continue;
}
argument = _argument_list_member_at (arguments, index);
child = _expand_string_list_recursive (parser, argument,
- orig, NULL, NULL);
+ active, NULL, NULL);
_string_list_append_list (result, child);
} else {
child = _expand_macro_recursive (parser, token,
- orig, parameters,
+ active, parameters,
arguments);
_string_list_append_list (result, child);
}
static string_list_t *
_expand_macro_recursive (glcpp_parser_t *parser,
const char *token,
- const char *orig,
+ string_list_t *active,
string_list_t *parameters,
argument_list_t *arguments)
{
macro_t *macro;
string_list_t *replacements;
+ string_list_t *result;
+
+ if (active == NULL)
+ active = _string_list_create (NULL);
+
+ _string_list_push (active, token);
macro = hash_table_find (parser->defines, token);
if (macro == NULL) {
replacements = macro->replacements;
- return _expand_string_list_recursive (parser, replacements,
- orig, parameters, arguments);
+ result = _expand_string_list_recursive (parser, replacements,
+ active, parameters, arguments);
+
+ _string_list_pop (active);
+ if (_string_list_length (active) == 0)
+ talloc_free (active);
+
+ return result;
}
string_list_t *
macro = hash_table_find (parser->defines, identifier);
assert (! macro->is_function);
- return _expand_macro_recursive (parser, identifier, identifier,
+ return _expand_macro_recursive (parser, identifier, NULL,
NULL, NULL);
}
const char *identifier,
argument_list_t *arguments)
{
- string_list_t *result;
-
macro_t *macro;
- result = _string_list_create (parser);
-
macro = hash_table_find (parser->defines, identifier);
assert (macro->is_function);
return NULL;
}
- return _expand_macro_recursive (parser, identifier, identifier,
+ return _expand_macro_recursive (parser, identifier, NULL,
macro->parameters, arguments);
}