diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | glcpp-lex.l | 20 | ||||
-rw-r--r-- | glcpp-parse.y | 214 | ||||
-rw-r--r-- | glcpp.h | 12 |
4 files changed, 214 insertions, 34 deletions
@@ -22,4 +22,4 @@ test: clean: rm -f glcpp-lex.c glcpp-parse.c *.o *~ - rm -f tests/*.out tests/*.gcc tests/*.expected + rm -f tests/*.out tests/*.gcc tests/*.expected tests/*~ diff --git a/glcpp-lex.l b/glcpp-lex.l index 3622db939e..c6e545aa8e 100644 --- a/glcpp-lex.l +++ b/glcpp-lex.l @@ -38,7 +38,7 @@ NEWLINE [\n] HSPACE [ \t] HASH ^{HSPACE}*# IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* -TOKEN {NONSPACE}+ +TOKEN [^[:space:](),]+ %% @@ -53,12 +53,22 @@ TOKEN {NONSPACE}+ {IDENTIFIER} { yylval.str = xtalloc_strdup (yyextra, yytext); - if (glcpp_parser_macro_defined (yyextra, yylval.str)) - return MACRO; - else - return IDENTIFIER; + switch (glcpp_parser_macro_type (yyextra, yylval.str)) + { + case MACRO_TYPE_UNDEFINED: + return IDENTIFIER; + break; + case MACRO_TYPE_OBJECT: + return OBJ_MACRO; + break; + case MACRO_TYPE_FUNCTION: + return FUNC_MACRO; + break; + } } +[(),] { return yytext[0]; } + {TOKEN} { yylval.str = xtalloc_strdup (yyextra, yytext); return TOKEN; diff --git a/glcpp-parse.y b/glcpp-parse.y index 4d6475497b..2e40db525b 100644 --- a/glcpp-parse.y +++ b/glcpp-parse.y @@ -24,12 +24,19 @@ #include <stdio.h> #include <stdlib.h> +#include <assert.h> #include <talloc.h> #include "glcpp.h" #define YYLEX_PARAM parser->scanner +typedef struct { + int is_function; + list_t *parameter_list; + list_t *replacement_list; +} macro_t; + struct glcpp_parser { yyscan_t scanner; struct hash_table *defines; @@ -39,13 +46,32 @@ void yyerror (void *scanner, const char *error); void -_print_expanded_macro (glcpp_parser_t *parser, const char *macro); +_define_object_macro (glcpp_parser_t *parser, + const char *macro, + list_t *replacement_list); + +void +_define_function_macro (glcpp_parser_t *parser, + const char *macro, + list_t *parameter_list, + list_t *replacement_list); + +void +_print_expanded_object_macro (glcpp_parser_t *parser, const char *macro); + +void +_print_expanded_function_macro (glcpp_parser_t *parser, + const char *macro, + list_t *arguments); list_t * _list_create (void *ctx); void -_list_append (list_t *list, const char *str); +_list_append_item (list_t *list, const char *str); + +void +_list_append_list (list_t *list, list_t *tail); %} @@ -57,9 +83,9 @@ _list_append (list_t *list, const char *str); %parse-param {glcpp_parser_t *parser} %lex-param {void *scanner} -%token DEFINE IDENTIFIER MACRO NEWLINE TOKEN UNDEF -%type <str> IDENTIFIER MACRO TOKEN string -%type <list> replacement_list +%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO TOKEN UNDEF +%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN string +%type <list> argument argument_list parameter_list replacement_list %% @@ -77,16 +103,48 @@ content: printf ("%s", $1); talloc_free ($1); } -| MACRO { - _print_expanded_macro (parser, $1); - talloc_free ($1); - } +| macro | directive_with_newline | NEWLINE { printf ("\n"); } ; +macro: + FUNC_MACRO '(' argument_list ')' { + _print_expanded_function_macro (parser, $1, $3); + } +| OBJ_MACRO { + _print_expanded_object_macro (parser, $1); + talloc_free ($1); + } +; + +argument_list: + /* empty */ { + $$ = _list_create (parser); + } +| argument { + $$ = _list_create (parser); + _list_append_list ($$, $1); + } +| argument_list ',' argument { + _list_append_list ($1, $3); + $$ = $1; + } +; + +argument: + /* empty */ { + $$ = _list_create (parser); + } +| argument string { + _list_append_item ($1, $2); + talloc_free ($2); + } +| argument '(' argument ')' +; + directive_with_newline: directive NEWLINE { printf ("\n"); @@ -95,10 +153,23 @@ directive_with_newline: directive: DEFINE IDENTIFIER replacement_list { - talloc_steal ($3, $2); - hash_table_insert (parser->defines, $3, $2); + _define_object_macro (parser, $2, $3); + } +| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list { + _define_function_macro (parser, $2, $4, $6); + } +| UNDEF FUNC_MACRO { + 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); } -| UNDEF MACRO { +| UNDEF OBJ_MACRO { list_t *replacement = hash_table_find (parser->defines, $2); if (replacement) { /* XXX: Need hash table to support a real way @@ -115,17 +186,33 @@ replacement_list: /* empty */ { $$ = _list_create (parser); } - | replacement_list string { - _list_append ($1, $2); + _list_append_item ($1, $2); talloc_free ($2); $$ = $1; } ; +parameter_list: + /* empty */ { + $$ = _list_create (parser); + } +| IDENTIFIER { + $$ = _list_create (parser); + _list_append_item ($$, $1); + talloc_free ($1); + } +| parameter_list ',' IDENTIFIER { + _list_append_item ($1, $3); + talloc_free ($3); + $$ = $1; + } +; + string: IDENTIFIER { $$ = $1; } -| MACRO { $$ = $1; } +| FUNC_MACRO { $$ = $1; } +| OBJ_MACRO { $$ = $1; } | TOKEN { $$ = $1; } ; @@ -144,7 +231,19 @@ _list_create (void *ctx) } void -_list_append (list_t *list, const char *str) +_list_append_list (list_t *list, list_t *tail) +{ + if (list->head == NULL) { + list->head = tail->head; + } else { + list->tail->next = tail->head; + } + + list->tail = tail->tail; +} + +void +_list_append_item (list_t *list, const char *str) { node_t *node; @@ -196,10 +295,20 @@ glcpp_parser_destroy (glcpp_parser_t *parser) talloc_free (parser); } -int -glcpp_parser_macro_defined (glcpp_parser_t *parser, const char *identifier) +macro_type_t +glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier) { - return (hash_table_find (parser->defines, identifier) != NULL); + macro_t *macro; + + macro = hash_table_find (parser->defines, identifier); + + if (macro == NULL) + return MACRO_TYPE_UNDEFINED; + + if (macro->is_function) + return MACRO_TYPE_FUNCTION; + else + return MACRO_TYPE_OBJECT; } static void @@ -208,15 +317,17 @@ _print_expanded_macro_recursive (glcpp_parser_t *parser, const char *orig, int *first) { - list_t *replacement; + macro_t *macro; node_t *node; - replacement = hash_table_find (parser->defines, token); - if (replacement == NULL) { + macro = hash_table_find (parser->defines, token); + if (macro == NULL) { printf ("%s%s", *first ? "" : " ", token); *first = 0; } else { - for (node = replacement->head ; node ; node = node->next) { + list_t *replacement_list = macro->replacement_list; + + for (node = replacement_list->head ; node ; node = node->next) { token = node->str; if (strcmp (token, orig) == 0) { printf ("%s%s", *first ? "" : " ", token); @@ -231,9 +342,62 @@ _print_expanded_macro_recursive (glcpp_parser_t *parser, } void -_print_expanded_macro (glcpp_parser_t *parser, const char *macro) +_define_object_macro (glcpp_parser_t *parser, + const char *identifier, + list_t *replacement_list) +{ + macro_t *macro; + + macro = xtalloc (parser, macro_t); + + macro->is_function = 0; + macro->parameter_list = NULL; + macro->replacement_list = talloc_steal (macro, replacement_list); + + hash_table_insert (parser->defines, macro, identifier); +} + +void +_define_function_macro (glcpp_parser_t *parser, + const char *identifier, + list_t *parameter_list, + list_t *replacement_list) +{ + macro_t *macro; + + macro = xtalloc (parser, macro_t); + + macro->is_function = 1; + macro->parameter_list = talloc_steal (macro, parameter_list); + macro->replacement_list = talloc_steal (macro, replacement_list); + + hash_table_insert (parser->defines, macro, identifier); +} + +void +_print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier) { int first = 1; + macro_t *macro; + + macro = hash_table_find (parser->defines, identifier); + assert (! macro->is_function); + + _print_expanded_macro_recursive (parser, identifier, identifier, &first); +} + +void +_print_expanded_function_macro (glcpp_parser_t *parser, + const char *identifier, + list_t *arguments) +{ + int first = 1; + macro_t *macro; + + macro = hash_table_find (parser->defines, identifier); + assert (macro->is_function); + + /* XXX: Need to use argument list here in the expansion. */ - _print_expanded_macro_recursive (parser, macro, macro, &first); + _print_expanded_macro_recursive (parser, identifier, identifier, &first); } @@ -52,9 +52,15 @@ glcpp_parser_parse (glcpp_parser_t *parser); void glcpp_parser_destroy (glcpp_parser_t *parser); -int -glcpp_parser_macro_defined (glcpp_parser_t *parser, - const char *identifier); +typedef enum { + MACRO_TYPE_UNDEFINED, + MACRO_TYPE_OBJECT, + MACRO_TYPE_FUNCTION +} macro_type_t; + +macro_type_t +glcpp_parser_macro_type (glcpp_parser_t *parser, + const char *identifier); /* Generated by glcpp-lex.l to glcpp-lex.c */ |