summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--glcpp-lex.l20
-rw-r--r--glcpp-parse.y214
-rw-r--r--glcpp.h12
4 files changed, 214 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 7233150a80..c5472a86b3 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
}
diff --git a/glcpp.h b/glcpp.h
index 39d6d5d0eb..69b3b840ae 100644
--- a/glcpp.h
+++ b/glcpp.h
@@ -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 */