Implment #define

By using the recently-imported hash_table implementation.
diff --git a/glcpp-lex.l b/glcpp-lex.l
index 747e240..a220fef 100644
--- a/glcpp-lex.l
+++ b/glcpp-lex.l
@@ -31,12 +31,27 @@
 
 %option reentrant noyywrap
 
+%x ST_DEFINE
+%x ST_DEFVAL
+
+SPACE		[[:space:]]
+NONSPACE	[^[:space:]]
+NOTNEWLINE	[^\n]
+HSPACE		[ \t]
+HASH		^{HSPACE}*#
+IDENTIFIER	[_a-zA-Z][_a-zA-Z0-9]*
+DEFVAL		{NONSPACE}{NOTNEWLINE}*
 %%
 
-	/* Silently eat all whitespace. */
-[[:space:]]+
+{HASH}define		{ BEGIN ST_DEFINE; return DEFINE; }
 
-	/* Any non-whitespace is a token. */
-[^[:space:]]+			{ return TOKEN; }
+<ST_DEFINE>{HSPACE}+
+<ST_DEFINE>{IDENTIFIER}	{ BEGIN ST_DEFVAL; yylval = strdup (yytext); return IDENTIFIER; }
+
+<ST_DEFVAL>{SPACE}+
+<ST_DEFVAL>{DEFVAL}	{ BEGIN INITIAL; yylval = strdup (yytext); return DEFVAL; }
+
+	/* Anything we don't specifically recognize is a stream of tokens */
+{NONSPACE}+		{ yylval = strdup (yytext); return TOKEN; }
 
 %%
diff --git a/glcpp-parse.y b/glcpp-parse.y
index a2d1094..89dc464 100644
--- a/glcpp-parse.y
+++ b/glcpp-parse.y
@@ -27,30 +27,46 @@
 
 #include "glcpp.h"
 
-#define YYSTYPE int
+#define YYLEX_PARAM parser->scanner
 
 void
 yyerror (void *scanner, const char *error);
 
 %}
 
-%parse-param {void *scanner}
+%parse-param {glcpp_parser_t *parser}
 %lex-param {void *scanner}
 
+%token DEFINE
+%token DEFVAL
+%token IDENTIFIER
 %token TOKEN
 
 %%
 
 input:		/* empty */
-	|	tokens
+	|	content
 ;
 
-
-tokens:		token
-	|	tokens token
+content:	token
+	|	directive
+	|	content token
+	|	content directive
 ;
 
-token:		TOKEN
+directive:	DEFINE IDENTIFIER DEFVAL {
+	hash_table_insert (parser->defines, $3, $2);
+}
+;
+
+token:		TOKEN {
+	char *value = hash_table_find (parser->defines, $1);
+	if (value)
+		printf ("%s", value);
+	else
+		printf ("%s", $1);
+	free ($1);
+}
 ;
 
 %%
@@ -60,3 +76,24 @@
 {
 	fprintf (stderr, "Parse error: %s\n", error);
 }
+
+void
+glcpp_parser_init (glcpp_parser_t *parser)
+{
+	yylex_init (&parser->scanner);
+	parser->defines = hash_table_ctor (32, hash_table_string_hash,
+					   hash_table_string_compare);
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+	return yyparse (parser);
+}
+
+void
+glcpp_parser_fini (glcpp_parser_t *parser)
+{
+	yylex_destroy (parser->scanner);
+	hash_table_dtor (parser->defines);
+}
diff --git a/glcpp.c b/glcpp.c
index eefac74..d6c89df 100644
--- a/glcpp.c
+++ b/glcpp.c
@@ -26,12 +26,14 @@
 int
 main (void)
 {
+	glcpp_parser_t parser;
 	int ret;
-	void *scanner;
 
-	yylex_init (&scanner);
-	ret = yyparse (scanner);
-	yylex_destroy (scanner);
+	glcpp_parser_init (&parser);
+
+	ret = glcpp_parser_parse (&parser);
+
+	glcpp_parser_fini (&parser);
 
 	return ret;
 }
diff --git a/glcpp.h b/glcpp.h
index 485387b..5278e1b 100644
--- a/glcpp.h
+++ b/glcpp.h
@@ -24,10 +24,27 @@
 #ifndef GLCPP_H
 #define GLCPP_H
 
-/* Generated by glcpp-lex.l to glcpp-lex.c */
+#include "hash_table.h"
 
+#define YYSTYPE char *
 #define yyscan_t void*
 
+typedef struct {
+	yyscan_t scanner;
+	struct hash_table *defines;
+} glcpp_parser_t;
+
+void
+glcpp_parser_init (glcpp_parser_t *parser);
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser);
+
+void
+glcpp_parser_fini (glcpp_parser_t *parser);
+
+/* Generated by glcpp-lex.l to glcpp-lex.c */
+
 int
 yylex_init (yyscan_t *scanner);
 
@@ -40,6 +57,6 @@
 /* Generated by glcpp-parse.y to glcpp-parse.c */
 
 int
-yyparse (void *scanner);
+yyparse (glcpp_parser_t *parser);
 
 #endif