3 * Copyright © 2010 Intel Corporation
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
32 #define YYLEX_PARAM parser->scanner
36 list_t *parameter_list;
37 list_t *replacement_list;
42 struct hash_table *defines;
46 yyerror (void *scanner, const char *error);
49 _define_object_macro (glcpp_parser_t *parser,
51 list_t *replacement_list);
54 _define_function_macro (glcpp_parser_t *parser,
56 list_t *parameter_list,
57 list_t *replacement_list);
60 _print_expanded_object_macro (glcpp_parser_t *parser, const char *macro);
63 _print_expanded_function_macro (glcpp_parser_t *parser,
68 _list_create (void *ctx);
71 _list_append_item (list_t *list, const char *str);
74 _list_append_list (list_t *list, list_t *tail);
83 %parse-param {glcpp_parser_t *parser}
84 %lex-param {void *scanner}
86 %token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO TOKEN UNDEF
87 %type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN string
88 %type <list> argument argument_list parameter_list replacement_list
107 | directive_with_newline
114 FUNC_MACRO '(' argument_list ')' {
115 _print_expanded_function_macro (parser, $1, $3);
118 _print_expanded_object_macro (parser, $1);
125 $$ = _list_create (parser);
128 $$ = _list_create (parser);
129 _list_append_list ($$, $1);
131 | argument_list ',' argument {
132 _list_append_list ($1, $3);
139 $$ = _list_create (parser);
142 _list_append_item ($1, $2);
145 | argument '(' argument ')'
148 directive_with_newline:
155 DEFINE IDENTIFIER replacement_list {
156 _define_object_macro (parser, $2, $3);
158 | DEFINE IDENTIFIER '(' parameter_list ')' replacement_list {
159 _define_function_macro (parser, $2, $4, $6);
162 list_t *replacement = hash_table_find (parser->defines, $2);
164 /* XXX: Need hash table to support a real way
165 * to remove an element rather than prefixing
166 * a new node with data of NULL like this. */
167 hash_table_insert (parser->defines, NULL, $2);
168 talloc_free (replacement);
173 list_t *replacement = hash_table_find (parser->defines, $2);
175 /* XXX: Need hash table to support a real way
176 * to remove an element rather than prefixing
177 * a new node with data of NULL like this. */
178 hash_table_insert (parser->defines, NULL, $2);
179 talloc_free (replacement);
187 $$ = _list_create (parser);
189 | replacement_list string {
190 _list_append_item ($1, $2);
198 $$ = _list_create (parser);
201 $$ = _list_create (parser);
202 _list_append_item ($$, $1);
205 | parameter_list ',' IDENTIFIER {
206 _list_append_item ($1, $3);
213 IDENTIFIER { $$ = $1; }
214 | FUNC_MACRO { $$ = $1; }
215 | OBJ_MACRO { $$ = $1; }
222 _list_create (void *ctx)
226 list = xtalloc (ctx, list_t);
234 _list_append_list (list_t *list, list_t *tail)
236 if (list->head == NULL) {
237 list->head = tail->head;
239 list->tail->next = tail->head;
242 list->tail = tail->tail;
246 _list_append_item (list_t *list, const char *str)
250 node = xtalloc (list, node_t);
251 node->str = xtalloc_strdup (node, str);
255 if (list->head == NULL) {
258 list->tail->next = node;
265 yyerror (void *scanner, const char *error)
267 fprintf (stderr, "Parse error: %s\n", error);
271 glcpp_parser_create (void)
273 glcpp_parser_t *parser;
275 parser = xtalloc (NULL, glcpp_parser_t);
277 yylex_init_extra (parser, &parser->scanner);
278 parser->defines = hash_table_ctor (32, hash_table_string_hash,
279 hash_table_string_compare);
285 glcpp_parser_parse (glcpp_parser_t *parser)
287 return yyparse (parser);
291 glcpp_parser_destroy (glcpp_parser_t *parser)
293 yylex_destroy (parser->scanner);
294 hash_table_dtor (parser->defines);
295 talloc_free (parser);
299 glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
303 macro = hash_table_find (parser->defines, identifier);
306 return MACRO_TYPE_UNDEFINED;
308 if (macro->is_function)
309 return MACRO_TYPE_FUNCTION;
311 return MACRO_TYPE_OBJECT;
315 _print_expanded_macro_recursive (glcpp_parser_t *parser,
323 macro = hash_table_find (parser->defines, token);
325 printf ("%s%s", *first ? "" : " ", token);
328 list_t *replacement_list = macro->replacement_list;
330 for (node = replacement_list->head ; node ; node = node->next) {
332 if (strcmp (token, orig) == 0) {
333 printf ("%s%s", *first ? "" : " ", token);
336 _print_expanded_macro_recursive (parser,
345 _define_object_macro (glcpp_parser_t *parser,
346 const char *identifier,
347 list_t *replacement_list)
351 macro = xtalloc (parser, macro_t);
353 macro->is_function = 0;
354 macro->parameter_list = NULL;
355 macro->replacement_list = talloc_steal (macro, replacement_list);
357 hash_table_insert (parser->defines, macro, identifier);
361 _define_function_macro (glcpp_parser_t *parser,
362 const char *identifier,
363 list_t *parameter_list,
364 list_t *replacement_list)
368 macro = xtalloc (parser, macro_t);
370 macro->is_function = 1;
371 macro->parameter_list = talloc_steal (macro, parameter_list);
372 macro->replacement_list = talloc_steal (macro, replacement_list);
374 hash_table_insert (parser->defines, macro, identifier);
378 _print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier)
383 macro = hash_table_find (parser->defines, identifier);
384 assert (! macro->is_function);
386 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
390 _print_expanded_function_macro (glcpp_parser_t *parser,
391 const char *identifier,
397 macro = hash_table_find (parser->defines, identifier);
398 assert (macro->is_function);
400 /* XXX: Need to use argument list here in the expansion. */
402 _print_expanded_macro_recursive (parser, identifier, identifier, &first);