summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2010-05-12 13:11:50 -0700
committerCarl Worth <cworth@cworth.org>2010-05-12 13:11:50 -0700
commitcd27e6413a683d3ba1763ec68edfb1ff13193fc3 (patch)
tree0d331b3446bc56f18f4003e90e8657fcc8b73dbe
parent7bdd1f36d9f238e6af4846d46b9dd30fffc772a5 (diff)
Add support for the #undef macro.
This isn't ideal for two reasons: 1. There's a bunch of stateful redundancy in the lexer that should be cleaned up. 2. The hash table does not provide a mechanism to delete an entry, so we waste memory to add a new NULL entry in front of the existing entry with the same key. But this does at least work, (it passes the recently added undef test case).
-rw-r--r--glcpp-lex.l19
-rw-r--r--glcpp-parse.y26
2 files changed, 39 insertions, 6 deletions
diff --git a/glcpp-lex.l b/glcpp-lex.l
index ec91538a73..9ec4deb718 100644
--- a/glcpp-lex.l
+++ b/glcpp-lex.l
@@ -33,7 +33,7 @@
%option extra-type="glcpp_parser_t *"
%x ST_DEFINE
-%x ST_DEFVAL
+%x ST_UNDEF
SPACE [[:space:]]
NONSPACE [^[:space:]]
@@ -67,6 +67,23 @@ TOKEN {NONSPACE}+
<ST_DEFINE>{SPACE}+
+{HASH}undef{HSPACE}* {
+ BEGIN ST_UNDEF;
+ return UNDEF;
+}
+
+<ST_UNDEF>{IDENTIFIER} {
+ yylval.str = xtalloc_strdup (yyextra, yytext);
+ return IDENTIFIER;
+}
+
+<ST_UNDEF>\n {
+ BEGIN INITIAL;
+ return NEWLINE;
+}
+
+<ST_UNDEF>{SPACE}+
+
/* Anything we don't specifically recognize is a stream of tokens */
{NONSPACE}+ {
yylval.str = xtalloc_strdup (yyextra, yytext);
diff --git a/glcpp-parse.y b/glcpp-parse.y
index 1a7ec4970d..29614fb1a4 100644
--- a/glcpp-parse.y
+++ b/glcpp-parse.y
@@ -57,7 +57,7 @@ _list_append (list_t *list, const char *str);
%parse-param {glcpp_parser_t *parser}
%lex-param {void *scanner}
-%token DEFINE IDENTIFIER NEWLINE TOKEN
+%token DEFINE IDENTIFIER NEWLINE TOKEN UNDEF
%type <str> token IDENTIFIER TOKEN
%type <list> replacement_list
@@ -73,19 +73,35 @@ content:
_print_resolved_token (parser, $1);
talloc_free ($1);
}
-| directive
+| directive_with_newline
| content token {
_print_resolved_token (parser, $2);
talloc_free ($2);
}
-| content directive
+| content directive_with_newline
+;
+
+directive_with_newline:
+ directive NEWLINE {
+ printf ("\n");
+ }
;
directive:
- DEFINE IDENTIFIER replacement_list NEWLINE {
+ DEFINE IDENTIFIER replacement_list {
talloc_steal ($3, $2);
hash_table_insert (parser->defines, $3, $2);
- printf ("\n");
+ }
+| UNDEF IDENTIFIER {
+ list_t *replacement = hash_table_find (parser->defines, $2);
+ if (replacement) {
+ /* XXX: Need hash table to support a real way
+ * to remove an element rather than prefixing
+ * a new node with data of NULL like this. */
+ hash_table_insert (parser->defines, NULL, $2);
+ talloc_free (replacement);
+ }
+ talloc_free ($2);
}
;