Fix defines involving both literals and other defined macros.

We now store a list of tokens in our hash-table rather than a single
string. This lets us replace each macro in the value as necessary.

This code adds a link dependency on talloc which does exactly what we
want in terms of memory management for a parser.

The 3 tests added in the previous commit now pass.
diff --git a/glcpp-parse.y b/glcpp-parse.y
index a3a661b..eae96ef 100644
--- a/glcpp-parse.y
+++ b/glcpp-parse.y
@@ -24,61 +24,158 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <talloc.h>
 
 #include "glcpp.h"
 
 #define YYLEX_PARAM parser->scanner
 
+struct glcpp_parser {
+	yyscan_t scanner;
+	struct hash_table *defines;
+};
+
 void
 yyerror (void *scanner, const char *error);
 
-const char *
-_resolve_token (glcpp_parser_t *parser, const char *token);
+void
+_print_resolved_token (glcpp_parser_t *parser, const char *token);
+
+list_t *
+_list_create (void *ctx);
+
+void
+_list_append (list_t *list, const char *str);
 
 %}
 
+%union {
+	char *str;
+	list_t *list;
+}
+
 %parse-param {glcpp_parser_t *parser}
 %lex-param {void *scanner}
 
-%token DEFINE
-%token DEFVAL
-%token IDENTIFIER
-%token TOKEN
+%token DEFINE IDENTIFIER NEWLINE TOKEN
+%type <str> token IDENTIFIER TOKEN
+%type <list> replacement_list
 
 %%
 
-input:		/* empty */
-	|	content
+input:
+	/* empty */
+|	content
 ;
 
-content:	token
-	|	directive
-	|	content token
-	|	content directive
+content:
+	token {
+		_print_resolved_token (parser, $1);
+		free ($1);
+	}
+|	directive
+|	content token {
+		_print_resolved_token (parser, $2);
+		free ($2);
+	}
+|	content directive
 ;
 
-directive:	DEFINE IDENTIFIER DEFVAL {
-	hash_table_insert (parser->defines, $3, $2);
+directive:
+	DEFINE IDENTIFIER replacement_list NEWLINE {
+		char *key = talloc_strdup ($3, $2);
+		free ($2);
+		hash_table_insert (parser->defines, $3, key);
+		printf ("\n");
+	}
+;
+
+replacement_list:
+	/* empty */ {
+		$$ = _list_create (parser);
+	}
+
+|	replacement_list token {
+		_list_append ($1, $2);
+		free ($2);
+		$$ = $1;
+	}
+;
+
+token:
+	TOKEN { $$ = $1; }
+|	IDENTIFIER { $$ = $1; }
+;
+
+%%
+
+list_t *
+_list_create (void *ctx)
+{
+	list_t *list;
+
+	list = talloc (ctx, list_t);
+	if (list == NULL) {
+		fprintf (stderr, "Out of memory.\n");
+		exit (1);
+	}
+
+	list->head = NULL;
+	list->tail = NULL;
+
+	return list;
 }
-;
 
-token:		TOKEN { printf ("%s", _resolve_token (parser, $1)); free ($1); }
-;
+void
+_list_append (list_t *list, const char *str)
+{
+	node_t *node;
 
-%%
+	node = talloc (list, node_t);
+	if (node == NULL) {
+		fprintf (stderr, "Out of memory.\n");
+		exit (1);
+	}
 
+	node->str = talloc_strdup (node, str);
+	if (node->str == NULL) {
+		fprintf (stderr, "Out of memory.\n");
+		exit (1);
+	}
+		
+	node->next = NULL;
+
+	if (list->head == NULL) {
+		list->head = node;
+	} else {
+		list->tail->next = node;
+	}
+
+	list->tail = node;
+}
+		
 void
 yyerror (void *scanner, const char *error)
 {
 	fprintf (stderr, "Parse error: %s\n", error);
 }
 
-void
-glcpp_parser_init (glcpp_parser_t *parser)
+glcpp_parser_t *
+glcpp_parser_create (void)
 {
+	glcpp_parser_t *parser;
+
+	parser = talloc (NULL, glcpp_parser_t);
+	if (parser == NULL) {
+		fprintf (stderr, "Out of memory.\n");
+		exit (1);
+	}
+
 	yylex_init (&parser->scanner);
 	parser->defines = hash_table_ctor (32, hash_table_string_hash,
 					   hash_table_string_compare);
+
+	return parser;
 }
 
 int
@@ -88,27 +185,43 @@
 }
 
 void
-glcpp_parser_fini (glcpp_parser_t *parser)
+glcpp_parser_destroy (glcpp_parser_t *parser)
 {
 	yylex_destroy (parser->scanner);
 	hash_table_dtor (parser->defines);
+	talloc_free (parser);
 }
 
-const char *
-_resolve_token (glcpp_parser_t *parser, const char *token)
+static void
+_print_resolved_recursive (glcpp_parser_t *parser,
+			   const char *token,
+			   const char *orig,
+			   int *first)
 {
-	const char *orig = token;
-	const char *replacement;
+	list_t *replacement;
+	node_t *node;
 
-	while (1) {
-		replacement = hash_table_find (parser->defines, token);
-		if (replacement == NULL)
-			break;
-		token = replacement;
-		if (strcmp (token, orig) == 0)
-			break;
+	replacement = hash_table_find (parser->defines, token);
+	if (replacement == NULL) {
+		printf ("%s%s", *first ? "" : " ", token);
+		*first = 0;
+	} else {
+		for (node = replacement->head ; node ; node = node->next) {
+			token = node->str;
+			if (strcmp (token, orig) == 0) {
+				printf ("%s%s", *first ? "" : " ", token);
+				*first = 0;
+			} else {
+				_print_resolved_recursive (parser, token, orig, first);
+			}
+		}
 	}
-
-	return token;
 }
 
+void
+_print_resolved_token (glcpp_parser_t *parser, const char *token)
+{
+	int first = 1;
+
+	_print_resolved_recursive (parser, token, token, &first);
+}