OSDN Git Service

Fix defines involving both literals and other defined macros.
[android-x86/external-mesa.git] / glcpp-parse.y
index a3a661b..eae96ef 100644 (file)
 
 #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");
+       }
 ;
 
-token:         TOKEN { printf ("%s", _resolve_token (parser, $1)); free ($1); }
+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;
+}
+
+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 @@ glcpp_parser_parse (glcpp_parser_t *parser)
 }
 
 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;
-
-       while (1) {
-               replacement = hash_table_find (parser->defines, token);
-               if (replacement == NULL)
-                       break;
-               token = replacement;
-               if (strcmp (token, orig) == 0)
-                       break;
+       list_t *replacement;
+       node_t *node;
+
+       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);
+}