xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/glcpp/glcpp-parse.y (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 %{
2 /*
3  * Copyright © 2010 Intel Corporation
4  *
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:
11  *
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
14  * Software.
15  *
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.
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <inttypes.h>
30 
31 #include "glcpp.h"
32 #include "main/mtypes.h"
33 #include "util/strndup.h"
34 
35 const char *
36 _mesa_lookup_shader_include(struct gl_context *ctx, char *path,
37                             bool error_check);
38 
39 size_t
40 _mesa_get_shader_include_cursor(struct gl_shared_state *shared);
41 
42 void
43 _mesa_set_shader_include_cursor(struct gl_shared_state *shared, size_t cursor);
44 
45 static void
46 yyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
47 
48 static void
49 _define_object_macro(glcpp_parser_t *parser,
50                      YYLTYPE *loc,
51                      const char *macro,
52                      token_list_t *replacements);
53 
54 static void
55 _define_function_macro(glcpp_parser_t *parser,
56                        YYLTYPE *loc,
57                        const char *macro,
58                        string_list_t *parameters,
59                        token_list_t *replacements);
60 
61 static string_list_t *
62 _string_list_create(glcpp_parser_t *parser);
63 
64 static void
65 _string_list_append_item(glcpp_parser_t *parser, string_list_t *list,
66                          const char *str);
67 
68 static int
69 _string_list_contains(string_list_t *list, const char *member, int *index);
70 
71 static const char *
72 _string_list_has_duplicate(string_list_t *list);
73 
74 static int
75 _string_list_length(string_list_t *list);
76 
77 static int
78 _string_list_equal(string_list_t *a, string_list_t *b);
79 
80 static argument_list_t *
81 _argument_list_create(glcpp_parser_t *parser);
82 
83 static void
84 _argument_list_append(glcpp_parser_t *parser, argument_list_t *list,
85                       token_list_t *argument);
86 
87 static int
88 _argument_list_length(argument_list_t *list);
89 
90 static token_list_t *
91 _argument_list_member_at(argument_list_t *list, int index);
92 
93 static token_t *
94 _token_create_str(glcpp_parser_t *parser, int type, char *str);
95 
96 static token_t *
97 _token_create_ival(glcpp_parser_t *parser, int type, int ival);
98 
99 static token_list_t *
100 _token_list_create(glcpp_parser_t *parser);
101 
102 static void
103 _token_list_prepend(glcpp_parser_t *parser, token_list_t *list, token_t *token);
104 
105 static void
106 _token_list_append(glcpp_parser_t *parser, token_list_t *list, token_t *token);
107 
108 static void
109 _token_list_append_list(token_list_t *list, token_list_t *tail);
110 
111 static int
112 _token_list_equal_ignoring_space(token_list_t *a, token_list_t *b);
113 
114 static void
115 _parser_active_list_push(glcpp_parser_t *parser, const char *identifier,
116                          token_node_t *marker);
117 
118 static void
119 _parser_active_list_pop(glcpp_parser_t *parser);
120 
121 static int
122 _parser_active_list_contains(glcpp_parser_t *parser, const char *identifier);
123 
124 typedef enum {
125    EXPANSION_MODE_IGNORE_DEFINED,
126    EXPANSION_MODE_EVALUATE_DEFINED
127 } expansion_mode_t;
128 
129 /* Expand list, and begin lexing from the result (after first
130  * prefixing a token of type 'head_token_type').
131  */
132 static void
133 _glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type,
134                                   token_list_t *list, expansion_mode_t mode);
135 
136 /* Perform macro expansion in-place on the given list. */
137 static void
138 _glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list,
139                                 expansion_mode_t mode);
140 
141 static void
142 _glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser,
143                                         token_list_t *list);
144 
145 static void
146 _glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc,
147                                  int condition);
148 
149 static void
150 _glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc,
151                                    const char *type, int condition);
152 
153 static void
154 _glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc);
155 
156 static void
157 _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
158                                          const char *ident, bool explicitly_set);
159 
160 static int
161 glcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
162 
163 static void
164 glcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list);
165 
166 struct define_include {
167    glcpp_parser_t *parser;
168    YYLTYPE *loc;
169 };
170 
171 static void
172 glcpp_parser_copy_defines(const void *key, void *data, void *closure);
173 
174 static void
175 add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
176 
177 %}
178 
179 %pure-parser
180 %error-verbose
181 
182 %locations
183 %initial-action {
184    @$.first_line = 1;
185    @$.first_column = 1;
186    @$.last_line = 1;
187    @$.last_column = 1;
188    @$.source = 0;
189 }
190 
191 %parse-param {glcpp_parser_t *parser}
192 %lex-param {glcpp_parser_t *parser}
193 
194 %expect 0
195 
196         /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to
197          * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols,
198          * (such as the <HASH> and <DEFINE> start conditions in the lexer). */
199 %token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS PATH INCLUDE
200 %token PASTE
201 %type <ival> INTEGER operator SPACE integer_constant version_constant
202 %type <expression_value> expression
203 %type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA PATH INCLUDE
204 %type <string_list> identifier_list
205 %type <token> preprocessing_token
206 %type <token_list> pp_tokens replacement_list text_line
207 %left OR
208 %left AND
209 %left '|'
210 %left '^'
211 %left '&'
212 %left EQUAL NOT_EQUAL
213 %left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
214 %left LEFT_SHIFT RIGHT_SHIFT
215 %left '+' '-'
216 %left '*' '/' '%'
217 %right UNARY
218 
219 %debug
220 
221 %%
222 
223 input:
224    /* empty */
225 |  input line
226 ;
227 
228 line:
229    control_line
230 |  SPACE control_line
231 |  text_line {
232       _glcpp_parser_print_expanded_token_list (parser, $1);
233       _mesa_string_buffer_append_char(parser->output, '\n');
234    }
235 |  expanded_line
236 ;
237 
238 expanded_line:
239    IF_EXPANDED expression NEWLINE {
240       if (parser->is_gles && $2.undefined_macro)
241          glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
242       _glcpp_parser_skip_stack_push_if (parser, & @1, $2.value);
243    }
244 |  ELIF_EXPANDED expression NEWLINE {
245       if (parser->is_gles && $2.undefined_macro)
246          glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
247       _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2.value);
248    }
249 |  LINE_EXPANDED integer_constant NEWLINE {
250       parser->has_new_line_number = 1;
251       parser->new_line_number = $2;
252       _mesa_string_buffer_printf(parser->output, "#line %" PRIiMAX "\n", $2);
253    }
254 |  LINE_EXPANDED integer_constant integer_constant NEWLINE {
255       parser->has_new_line_number = 1;
256       parser->new_line_number = $2;
257       parser->has_new_source_number = 1;
258       parser->new_source_number = $3;
259       _mesa_string_buffer_printf(parser->output,
260                   "#line %" PRIiMAX " %" PRIiMAX "\n",
261                    $2, $3);
262    }
263 |  LINE_EXPANDED integer_constant PATH NEWLINE {
264       parser->has_new_line_number = 1;
265       parser->new_line_number = $2;
266       _mesa_string_buffer_printf(parser->output,
267                   "#line %" PRIiMAX " %s\n",
268                    $2, $3);
269    }
270 ;
271 
272 define:
273    OBJ_IDENTIFIER replacement_list NEWLINE {
274       _define_object_macro (parser, & @1, $1, $2);
275    }
276 |  FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE {
277       _define_function_macro (parser, & @1, $1, NULL, $4);
278    }
279 |  FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
280       _define_function_macro (parser, & @1, $1, $3, $5);
281    }
282 ;
283 
284 control_line:
285    control_line_success {
286       _mesa_string_buffer_append_char(parser->output, '\n');
287    }
288 |  control_line_error
289 |  HASH_TOKEN LINE pp_tokens NEWLINE {
290 
291       if (parser->skip_stack == NULL ||
292           parser->skip_stack->type == SKIP_NO_SKIP)
293       {
294          _glcpp_parser_expand_and_lex_from (parser,
295                         LINE_EXPANDED, $3,
296                         EXPANSION_MODE_IGNORE_DEFINED);
297       }
298    }
299 ;
300 
301 control_line_success:
302    HASH_TOKEN DEFINE_TOKEN define
303 |  HASH_TOKEN UNDEF IDENTIFIER NEWLINE {
304       struct hash_entry *entry;
305 
306       /* Section 3.4 (Preprocessor) of the GLSL ES 3.00 spec says:
307        *
308        *    It is an error to undefine or to redefine a built-in
309        *    (pre-defined) macro name.
310        *
311        * The GLSL ES 1.00 spec does not contain this text, but
312        * dEQP's preprocess test in GLES2 checks for it.
313        *
314        * Section 3.3 (Preprocessor) revision 7, of the GLSL 4.50
315        * spec says:
316        *
317        *    By convention, all macro names containing two consecutive
318        *    underscores ( __ ) are reserved for use by underlying
319        *    software layers. Defining or undefining such a name
320        *    in a shader does not itself result in an error, but may
321        *    result in unintended behaviors that stem from having
322        *    multiple definitions of the same name. All macro names
323        *    prefixed with "GL_" (...) are also reseved, and defining
324        *    such a name results in a compile-time error.
325        *
326        * The code below implements the same checks as GLSLang.
327        */
328       if (strncmp("GL_", $3, 3) == 0)
329          glcpp_error(& @1, parser, "Built-in (pre-defined)"
330                 " names beginning with GL_ cannot be undefined.");
331       else if (strstr($3, "__") != NULL) {
332          if (parser->is_gles
333              && parser->version >= 300
334              && (strcmp("__LINE__", $3) == 0
335             || strcmp("__FILE__", $3) == 0
336             || strcmp("__VERSION__", $3) == 0)) {
337             glcpp_error(& @1, parser, "Built-in (pre-defined)"
338                    " names cannot be undefined.");
339          } else if (parser->is_gles && parser->version <= 300) {
340             glcpp_error(& @1, parser,
341                    " names containing consecutive underscores"
342                    " are reserved.");
343          } else {
344             glcpp_warning(& @1, parser,
345                      " names containing consecutive underscores"
346                      " are reserved.");
347          }
348       }
349 
350       entry = _mesa_hash_table_search (parser->defines, $3);
351       if (entry) {
352          _mesa_hash_table_remove (parser->defines, entry);
353       }
354    }
355 |  HASH_TOKEN INCLUDE NEWLINE {
356       size_t include_cursor = _mesa_get_shader_include_cursor(parser->gl_ctx->Shared);
357 
358       /* Remove leading and trailing "" or <> */
359       char *start = strchr($2, '"');
360       if (!start) {
361          _mesa_set_shader_include_cursor(parser->gl_ctx->Shared, 0);
362          start = strchr($2, '<');
363       }
364       char *path = strndup(start + 1, strlen(start + 1) - 1);
365 
366       const char *shader =
367          _mesa_lookup_shader_include(parser->gl_ctx, path, false);
368       free(path);
369 
370       if (!shader)
371          glcpp_error(&@1, parser, "%s not found", $2);
372       else {
373          /* Create a temporary parser with the same settings */
374          glcpp_parser_t *tmp_parser =
375             glcpp_parser_create(parser->gl_ctx, parser->extensions, parser->state);
376          tmp_parser->version_set = true;
377          tmp_parser->version = parser->version;
378 
379          /* Set the shader source and run the lexer */
380          glcpp_lex_set_source_string(tmp_parser, shader);
381 
382          /* Copy any existing define macros to the temporary
383           * shade include parser.
384           */
385          struct define_include di;
386          di.parser = tmp_parser;
387          di.loc = &@1;
388 
389          hash_table_call_foreach(parser->defines,
390                   glcpp_parser_copy_defines,
391                   &di);
392 
393          /* Print out '#include' to the glsl parser. We do this
394           * so that it can do the error checking require to
395           * make sure the ARB_shading_language_include
396           * extension is enabled.
397           */
398          _mesa_string_buffer_printf(parser->output, "#include\n");
399 
400          /* Parse the include string before adding to the
401           * preprocessor output.
402           */
403          glcpp_parser_parse(tmp_parser);
404          _mesa_string_buffer_printf(parser->info_log, "%s",
405                      tmp_parser->info_log->buf);
406          _mesa_string_buffer_printf(parser->output, "%s",
407                      tmp_parser->output->buf);
408 
409          /* Copy any new define macros to the parent parser
410           * and steal the memory of our temp parser so we don't
411           * free these new defines before they are no longer
412           * needed.
413           */
414          di.parser = parser;
415          di.loc = &@1;
416          ralloc_steal(parser, tmp_parser);
417 
418          hash_table_call_foreach(tmp_parser->defines,
419                   glcpp_parser_copy_defines,
420                   &di);
421 
422          /* Destroy tmp parser memory we no longer need */
423          glcpp_lex_destroy(tmp_parser->scanner);
424          _mesa_hash_table_destroy(tmp_parser->defines, NULL);
425       }
426 
427       _mesa_set_shader_include_cursor(parser->gl_ctx->Shared, include_cursor);
428    }
429 |  HASH_TOKEN IF pp_tokens NEWLINE {
430       /* Be careful to only evaluate the 'if' expression if
431        * we are not skipping. When we are skipping, we
432        * simply push a new 0-valued 'if' onto the skip
433        * stack.
434        *
435        * This avoids generating diagnostics for invalid
436        * expressions that are being skipped. */
437       if (parser->skip_stack == NULL ||
438           parser->skip_stack->type == SKIP_NO_SKIP)
439       {
440          _glcpp_parser_expand_and_lex_from (parser,
441                         IF_EXPANDED, $3,
442                         EXPANSION_MODE_EVALUATE_DEFINED);
443       }
444       else
445       {
446          _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
447          parser->skip_stack->type = SKIP_TO_ENDIF;
448       }
449    }
450 |  HASH_TOKEN IF NEWLINE {
451       /* #if without an expression is only an error if we
452        *  are not skipping */
453       if (parser->skip_stack == NULL ||
454           parser->skip_stack->type == SKIP_NO_SKIP)
455       {
456          glcpp_error(& @1, parser, "#if with no expression");
457       }
458       _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
459    }
460 |  HASH_TOKEN IFDEF IDENTIFIER junk NEWLINE {
461       struct hash_entry *entry =
462             _mesa_hash_table_search(parser->defines, $3);
463       macro_t *macro = entry ? entry->data : NULL;
464       _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
465    }
466 |  HASH_TOKEN IFNDEF IDENTIFIER junk NEWLINE {
467       struct hash_entry *entry =
468             _mesa_hash_table_search(parser->defines, $3);
469       macro_t *macro = entry ? entry->data : NULL;
470       _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL);
471    }
472 |  HASH_TOKEN ELIF pp_tokens NEWLINE {
473       /* Be careful to only evaluate the 'elif' expression
474        * if we are not skipping. When we are skipping, we
475        * simply change to a 0-valued 'elif' on the skip
476        * stack.
477        *
478        * This avoids generating diagnostics for invalid
479        * expressions that are being skipped. */
480       if (parser->skip_stack &&
481           parser->skip_stack->type == SKIP_TO_ELSE)
482       {
483          _glcpp_parser_expand_and_lex_from (parser,
484                         ELIF_EXPANDED, $3,
485                         EXPANSION_MODE_EVALUATE_DEFINED);
486       }
487       else if (parser->skip_stack &&
488           parser->skip_stack->has_else)
489       {
490          glcpp_error(& @1, parser, "#elif after #else");
491       }
492       else
493       {
494          _glcpp_parser_skip_stack_change_if (parser, & @1,
495                          "elif", 0);
496       }
497    }
498 |  HASH_TOKEN ELIF NEWLINE {
499       /* #elif without an expression is an error unless we
500        * are skipping. */
501       if (parser->skip_stack &&
502           parser->skip_stack->type == SKIP_TO_ELSE)
503       {
504          glcpp_error(& @1, parser, "#elif with no expression");
505       }
506       else if (parser->skip_stack &&
507           parser->skip_stack->has_else)
508       {
509          glcpp_error(& @1, parser, "#elif after #else");
510       }
511       else
512       {
513          _glcpp_parser_skip_stack_change_if (parser, & @1,
514                          "elif", 0);
515          glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
516       }
517    }
518 |  HASH_TOKEN ELSE { parser->lexing_directive = 1; } NEWLINE {
519       if (parser->skip_stack &&
520           parser->skip_stack->has_else)
521       {
522          glcpp_error(& @1, parser, "multiple #else");
523       }
524       else
525       {
526          _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
527          if (parser->skip_stack)
528             parser->skip_stack->has_else = true;
529       }
530    }
531 |  HASH_TOKEN ENDIF {
532       _glcpp_parser_skip_stack_pop (parser, & @1);
533    } NEWLINE
534 |  HASH_TOKEN VERSION_TOKEN version_constant NEWLINE {
535       if (parser->version_set) {
536          glcpp_error(& @1, parser, "#version must appear on the first line");
537       }
538       _glcpp_parser_handle_version_declaration(parser, $3, NULL, true);
539    }
540 |  HASH_TOKEN VERSION_TOKEN version_constant IDENTIFIER NEWLINE {
541       if (parser->version_set) {
542          glcpp_error(& @1, parser, "#version must appear on the first line");
543       }
544       _glcpp_parser_handle_version_declaration(parser, $3, $4, true);
545    }
546 |  HASH_TOKEN NEWLINE {
547       glcpp_parser_resolve_implicit_version(parser);
548    }
549 |  HASH_TOKEN PRAGMA NEWLINE {
550       _mesa_string_buffer_printf(parser->output, "#%s", $2);
551    }
552 ;
553 
554 control_line_error:
555    HASH_TOKEN ERROR_TOKEN NEWLINE {
556       glcpp_error(& @1, parser, "#%s", $2);
557    }
558 |  HASH_TOKEN DEFINE_TOKEN NEWLINE {
559       glcpp_error (& @1, parser, "#define without macro name");
560    }
561 |  HASH_TOKEN GARBAGE pp_tokens NEWLINE  {
562       glcpp_error (& @1, parser, "Illegal non-directive after #");
563    }
564 ;
565 
566 integer_constant:
567    INTEGER_STRING {
568       /* let strtoll detect the base */
569       $$ = strtoll ($1, NULL, 0);
570    }
571 |  INTEGER {
572       $$ = $1;
573    }
574 
575 version_constant:
576    INTEGER_STRING {
577       /* Both octal and hexadecimal constants begin with 0. */
578       if ($1[0] == '0' && $1[1] != '\0') {
579       glcpp_error(&@1, parser, "invalid #version \"%s\" (not a decimal constant)", $1);
580       $$ = 0;
581       } else {
582       $$ = strtoll($1, NULL, 10);
583       }
584    }
585 
586 expression:
587    integer_constant {
588       $$.value = $1;
589       $$.undefined_macro = NULL;
590    }
591 |  IDENTIFIER {
592       $$.value = 0;
593       if (parser->is_gles)
594          $$.undefined_macro = linear_strdup(parser->linalloc, $1);
595       else
596          $$.undefined_macro = NULL;
597    }
598 |  expression OR expression {
599       $$.value = $1.value || $3.value;
600 
601       /* Short-circuit: Only flag undefined from right side
602        * if left side evaluates to false.
603        */
604       if ($1.undefined_macro)
605          $$.undefined_macro = $1.undefined_macro;
606                 else if (! $1.value)
607          $$.undefined_macro = $3.undefined_macro;
608    }
609 |  expression AND expression {
610       $$.value = $1.value && $3.value;
611 
612       /* Short-circuit: Only flag undefined from right-side
613        * if left side evaluates to true.
614        */
615       if ($1.undefined_macro)
616          $$.undefined_macro = $1.undefined_macro;
617                 else if ($1.value)
618          $$.undefined_macro = $3.undefined_macro;
619    }
620 |  expression '|' expression {
621       $$.value = $1.value | $3.value;
622       if ($1.undefined_macro)
623          $$.undefined_macro = $1.undefined_macro;
624                 else
625          $$.undefined_macro = $3.undefined_macro;
626    }
627 |  expression '^' expression {
628       $$.value = $1.value ^ $3.value;
629       if ($1.undefined_macro)
630          $$.undefined_macro = $1.undefined_macro;
631                 else
632          $$.undefined_macro = $3.undefined_macro;
633    }
634 |  expression '&' expression {
635       $$.value = $1.value & $3.value;
636       if ($1.undefined_macro)
637          $$.undefined_macro = $1.undefined_macro;
638                 else
639          $$.undefined_macro = $3.undefined_macro;
640    }
641 |  expression NOT_EQUAL expression {
642       $$.value = $1.value != $3.value;
643       if ($1.undefined_macro)
644          $$.undefined_macro = $1.undefined_macro;
645                 else
646          $$.undefined_macro = $3.undefined_macro;
647    }
648 |  expression EQUAL expression {
649       $$.value = $1.value == $3.value;
650       if ($1.undefined_macro)
651          $$.undefined_macro = $1.undefined_macro;
652                 else
653          $$.undefined_macro = $3.undefined_macro;
654    }
655 |  expression GREATER_OR_EQUAL expression {
656       $$.value = $1.value >= $3.value;
657       if ($1.undefined_macro)
658          $$.undefined_macro = $1.undefined_macro;
659                 else
660          $$.undefined_macro = $3.undefined_macro;
661    }
662 |  expression LESS_OR_EQUAL expression {
663       $$.value = $1.value <= $3.value;
664       if ($1.undefined_macro)
665          $$.undefined_macro = $1.undefined_macro;
666                 else
667          $$.undefined_macro = $3.undefined_macro;
668    }
669 |  expression '>' expression {
670       $$.value = $1.value > $3.value;
671       if ($1.undefined_macro)
672          $$.undefined_macro = $1.undefined_macro;
673                 else
674          $$.undefined_macro = $3.undefined_macro;
675    }
676 |  expression '<' expression {
677       $$.value = $1.value < $3.value;
678       if ($1.undefined_macro)
679          $$.undefined_macro = $1.undefined_macro;
680                 else
681          $$.undefined_macro = $3.undefined_macro;
682    }
683 |  expression RIGHT_SHIFT expression {
684       $$.value = $1.value >> $3.value;
685       if ($1.undefined_macro)
686          $$.undefined_macro = $1.undefined_macro;
687                 else
688          $$.undefined_macro = $3.undefined_macro;
689    }
690 |  expression LEFT_SHIFT expression {
691       $$.value = $1.value << $3.value;
692       if ($1.undefined_macro)
693          $$.undefined_macro = $1.undefined_macro;
694                 else
695          $$.undefined_macro = $3.undefined_macro;
696    }
697 |  expression '-' expression {
698       $$.value = $1.value - $3.value;
699       if ($1.undefined_macro)
700          $$.undefined_macro = $1.undefined_macro;
701                 else
702          $$.undefined_macro = $3.undefined_macro;
703    }
704 |  expression '+' expression {
705       $$.value = $1.value + $3.value;
706       if ($1.undefined_macro)
707          $$.undefined_macro = $1.undefined_macro;
708                 else
709          $$.undefined_macro = $3.undefined_macro;
710    }
711 |  expression '%' expression {
712       if ($3.value == 0) {
713          yyerror (& @1, parser,
714              "zero modulus in preprocessor directive");
715       } else {
716          $$.value = $1.value % $3.value;
717       }
718       if ($1.undefined_macro)
719          $$.undefined_macro = $1.undefined_macro;
720                 else
721          $$.undefined_macro = $3.undefined_macro;
722    }
723 |  expression '/' expression {
724       if ($3.value == 0) {
725          yyerror (& @1, parser,
726              "division by 0 in preprocessor directive");
727       } else {
728          $$.value = $1.value / $3.value;
729       }
730       if ($1.undefined_macro)
731          $$.undefined_macro = $1.undefined_macro;
732                 else
733          $$.undefined_macro = $3.undefined_macro;
734    }
735 |  expression '*' expression {
736       $$.value = $1.value * $3.value;
737       if ($1.undefined_macro)
738          $$.undefined_macro = $1.undefined_macro;
739                 else
740          $$.undefined_macro = $3.undefined_macro;
741    }
742 |  '!' expression %prec UNARY {
743       $$.value = ! $2.value;
744       $$.undefined_macro = $2.undefined_macro;
745    }
746 |  '~' expression %prec UNARY {
747       $$.value = ~ $2.value;
748       $$.undefined_macro = $2.undefined_macro;
749    }
750 |  '-' expression %prec UNARY {
751       $$.value = - $2.value;
752       $$.undefined_macro = $2.undefined_macro;
753    }
754 |  '+' expression %prec UNARY {
755       $$.value = + $2.value;
756       $$.undefined_macro = $2.undefined_macro;
757    }
758 |  '(' expression ')' {
759       $$ = $2;
760    }
761 ;
762 
763 identifier_list:
764    IDENTIFIER {
765       $$ = _string_list_create (parser);
766       _string_list_append_item (parser, $$, $1);
767    }
768 |  identifier_list ',' IDENTIFIER {
769       $$ = $1;
770       _string_list_append_item (parser, $$, $3);
771    }
772 ;
773 
774 text_line:
775    NEWLINE { $$ = NULL; }
776 |  pp_tokens NEWLINE
777 ;
778 
779 replacement_list:
780    /* empty */ { $$ = NULL; }
781 |  pp_tokens
782 ;
783 
784 junk:
785    /* empty */
786 |  pp_tokens {
787       if (parser->gl_ctx->Const.AllowExtraPPTokens)
788          glcpp_warning(&@1, parser, "extra tokens at end of directive");
789       else
790          glcpp_error(&@1, parser, "extra tokens at end of directive");
791 
792       (void)yynerrs;
793    }
794 ;
795 
796 pp_tokens:
797    preprocessing_token {
798       parser->space_tokens = 1;
799       $$ = _token_list_create (parser);
800       _token_list_append (parser, $$, $1);
801    }
802 |  pp_tokens preprocessing_token {
803       $$ = $1;
804       _token_list_append (parser, $$, $2);
805    }
806 ;
807 
808 preprocessing_token:
809    IDENTIFIER {
810       $$ = _token_create_str (parser, IDENTIFIER, $1);
811       $$->location = yylloc;
812    }
813 |  INTEGER_STRING {
814       $$ = _token_create_str (parser, INTEGER_STRING, $1);
815       $$->location = yylloc;
816    }
817 |  PATH {
818       $$ = _token_create_str (parser, PATH, $1);
819       $$->location = yylloc;
820    }
821 |  operator {
822       $$ = _token_create_ival (parser, $1, $1);
823       $$->location = yylloc;
824    }
825 |  DEFINED {
826       $$ = _token_create_ival (parser, DEFINED, DEFINED);
827       $$->location = yylloc;
828    }
829 |  OTHER {
830       $$ = _token_create_str (parser, OTHER, $1);
831       $$->location = yylloc;
832    }
833 |  SPACE {
834       $$ = _token_create_ival (parser, SPACE, SPACE);
835       $$->location = yylloc;
836    }
837 ;
838 
839 operator:
840    '['               { $$ = '['; }
841 |  ']'               { $$ = ']'; }
842 |  '('               { $$ = '('; }
843 |  ')'               { $$ = ')'; }
844 |  '{'               { $$ = '{'; }
845 |  '}'               { $$ = '}'; }
846 |  '.'               { $$ = '.'; }
847 |  '&'               { $$ = '&'; }
848 |  '*'               { $$ = '*'; }
849 |  '+'               { $$ = '+'; }
850 |  '-'               { $$ = '-'; }
851 |  '~'               { $$ = '~'; }
852 |  '!'               { $$ = '!'; }
853 |  '/'               { $$ = '/'; }
854 |  '%'               { $$ = '%'; }
855 |  LEFT_SHIFT        { $$ = LEFT_SHIFT; }
856 |  RIGHT_SHIFT       { $$ = RIGHT_SHIFT; }
857 |  '<'               { $$ = '<'; }
858 |  '>'               { $$ = '>'; }
859 |  LESS_OR_EQUAL     { $$ = LESS_OR_EQUAL; }
860 |  GREATER_OR_EQUAL  { $$ = GREATER_OR_EQUAL; }
861 |  EQUAL             { $$ = EQUAL; }
862 |  NOT_EQUAL         { $$ = NOT_EQUAL; }
863 |  '^'               { $$ = '^'; }
864 |  '|'               { $$ = '|'; }
865 |  AND               { $$ = AND; }
866 |  OR                { $$ = OR; }
867 |  ';'               { $$ = ';'; }
868 |  ','               { $$ = ','; }
869 |  '='               { $$ = '='; }
870 |  PASTE             { $$ = PASTE; }
871 |  PLUS_PLUS         { $$ = PLUS_PLUS; }
872 |  MINUS_MINUS       { $$ = MINUS_MINUS; }
873 ;
874 
875 %%
876 
877 string_list_t *
878 _string_list_create(glcpp_parser_t *parser)
879 {
880    string_list_t *list;
881 
882    list = linear_alloc_child(parser->linalloc, sizeof(string_list_t));
883    list->head = NULL;
884    list->tail = NULL;
885 
886    return list;
887 }
888 
889 void
_string_list_append_item(glcpp_parser_t * parser,string_list_t * list,const char * str)890 _string_list_append_item(glcpp_parser_t *parser, string_list_t *list,
891                          const char *str)
892 {
893    string_node_t *node;
894 
895    node = linear_alloc_child(parser->linalloc, sizeof(string_node_t));
896    node->str = linear_strdup(parser->linalloc, str);
897 
898    node->next = NULL;
899 
900    if (list->head == NULL) {
901       list->head = node;
902    } else {
903       list->tail->next = node;
904    }
905 
906    list->tail = node;
907 }
908 
909 int
_string_list_contains(string_list_t * list,const char * member,int * index)910 _string_list_contains(string_list_t *list, const char *member, int *index)
911 {
912    string_node_t *node;
913    int i;
914 
915    if (list == NULL)
916       return 0;
917 
918    for (i = 0, node = list->head; node; i++, node = node->next) {
919       if (strcmp (node->str, member) == 0) {
920          if (index)
921             *index = i;
922          return 1;
923       }
924    }
925 
926    return 0;
927 }
928 
929 /* Return duplicate string in list (if any), NULL otherwise. */
930 const char *
_string_list_has_duplicate(string_list_t * list)931 _string_list_has_duplicate(string_list_t *list)
932 {
933    string_node_t *node, *dup;
934 
935    if (list == NULL)
936       return NULL;
937 
938    for (node = list->head; node; node = node->next) {
939       for (dup = node->next; dup; dup = dup->next) {
940          if (strcmp (node->str, dup->str) == 0)
941             return node->str;
942       }
943    }
944 
945    return NULL;
946 }
947 
948 int
_string_list_length(string_list_t * list)949 _string_list_length(string_list_t *list)
950 {
951    int length = 0;
952    string_node_t *node;
953 
954    if (list == NULL)
955       return 0;
956 
957    for (node = list->head; node; node = node->next)
958       length++;
959 
960    return length;
961 }
962 
963 int
_string_list_equal(string_list_t * a,string_list_t * b)964 _string_list_equal(string_list_t *a, string_list_t *b)
965 {
966    string_node_t *node_a, *node_b;
967 
968    if (a == NULL && b == NULL)
969       return 1;
970 
971    if (a == NULL || b == NULL)
972       return 0;
973 
974    for (node_a = a->head, node_b = b->head;
975         node_a && node_b;
976         node_a = node_a->next, node_b = node_b->next)
977    {
978       if (strcmp (node_a->str, node_b->str))
979          return 0;
980    }
981 
982    /* Catch the case of lists being different lengths, (which
983     * would cause the loop above to terminate after the shorter
984     * list). */
985    return node_a == node_b;
986 }
987 
988 argument_list_t *
_argument_list_create(glcpp_parser_t * parser)989 _argument_list_create(glcpp_parser_t *parser)
990 {
991    argument_list_t *list;
992 
993    list = linear_alloc_child(parser->linalloc, sizeof(argument_list_t));
994    list->head = NULL;
995    list->tail = NULL;
996 
997    return list;
998 }
999 
1000 void
_argument_list_append(glcpp_parser_t * parser,argument_list_t * list,token_list_t * argument)1001 _argument_list_append(glcpp_parser_t *parser,
1002                       argument_list_t *list, token_list_t *argument)
1003 {
1004    argument_node_t *node;
1005 
1006    node = linear_alloc_child(parser->linalloc, sizeof(argument_node_t));
1007    node->argument = argument;
1008 
1009    node->next = NULL;
1010 
1011    if (list->head == NULL) {
1012       list->head = node;
1013    } else {
1014       list->tail->next = node;
1015    }
1016 
1017    list->tail = node;
1018 }
1019 
1020 int
_argument_list_length(argument_list_t * list)1021 _argument_list_length(argument_list_t *list)
1022 {
1023    int length = 0;
1024    argument_node_t *node;
1025 
1026    if (list == NULL)
1027       return 0;
1028 
1029    for (node = list->head; node; node = node->next)
1030       length++;
1031 
1032    return length;
1033 }
1034 
1035 token_list_t *
_argument_list_member_at(argument_list_t * list,int index)1036 _argument_list_member_at(argument_list_t *list, int index)
1037 {
1038    argument_node_t *node;
1039    int i;
1040 
1041    if (list == NULL)
1042       return NULL;
1043 
1044    node = list->head;
1045    for (i = 0; i < index; i++) {
1046       node = node->next;
1047       if (node == NULL)
1048          break;
1049    }
1050 
1051    if (node)
1052       return node->argument;
1053 
1054    return NULL;
1055 }
1056 
1057 token_t *
_token_create_str(glcpp_parser_t * parser,int type,char * str)1058 _token_create_str(glcpp_parser_t *parser, int type, char *str)
1059 {
1060    token_t *token;
1061 
1062    token = linear_alloc_child(parser->linalloc, sizeof(token_t));
1063    token->type = type;
1064    token->value.str = str;
1065    token->expanding = false;
1066 
1067    return token;
1068 }
1069 
1070 token_t *
_token_create_ival(glcpp_parser_t * parser,int type,int ival)1071 _token_create_ival(glcpp_parser_t *parser, int type, int ival)
1072 {
1073    token_t *token;
1074 
1075    token = linear_alloc_child(parser->linalloc, sizeof(token_t));
1076    token->type = type;
1077    token->value.ival = ival;
1078    token->expanding = false;
1079 
1080    return token;
1081 }
1082 
1083 token_list_t *
_token_list_create(glcpp_parser_t * parser)1084 _token_list_create(glcpp_parser_t *parser)
1085 {
1086    token_list_t *list;
1087 
1088    list = linear_alloc_child(parser->linalloc, sizeof(token_list_t));
1089    list->head = NULL;
1090    list->tail = NULL;
1091    list->non_space_tail = NULL;
1092 
1093    return list;
1094 }
1095 
1096 void
_token_list_prepend(glcpp_parser_t * parser,token_list_t * list,token_t * token)1097 _token_list_prepend(glcpp_parser_t *parser, token_list_t *list, token_t *token)
1098 {
1099    token_node_t *node;
1100 
1101    node = linear_alloc_child(parser->linalloc, sizeof(token_node_t));
1102    node->token = token;
1103    node->next = list->head;
1104 
1105    list->head = node;
1106 }
1107 
1108 void
_token_list_append(glcpp_parser_t * parser,token_list_t * list,token_t * token)1109 _token_list_append(glcpp_parser_t *parser, token_list_t *list, token_t *token)
1110 {
1111    token_node_t *node;
1112 
1113    node = linear_alloc_child(parser->linalloc, sizeof(token_node_t));
1114    node->token = token;
1115    node->next = NULL;
1116 
1117    if (list->head == NULL) {
1118       list->head = node;
1119    } else {
1120       list->tail->next = node;
1121    }
1122 
1123    list->tail = node;
1124    if (token->type != SPACE)
1125       list->non_space_tail = node;
1126 }
1127 
1128 void
_token_list_append_list(token_list_t * list,token_list_t * tail)1129 _token_list_append_list(token_list_t *list, token_list_t *tail)
1130 {
1131    if (tail == NULL || tail->head == NULL)
1132       return;
1133 
1134    if (list->head == NULL) {
1135       list->head = tail->head;
1136    } else {
1137       list->tail->next = tail->head;
1138    }
1139 
1140    list->tail = tail->tail;
1141    list->non_space_tail = tail->non_space_tail;
1142 }
1143 
1144 static token_list_t *
_token_list_copy(glcpp_parser_t * parser,token_list_t * other)1145 _token_list_copy(glcpp_parser_t *parser, token_list_t *other)
1146 {
1147    token_list_t *copy;
1148    token_node_t *node;
1149 
1150    if (other == NULL)
1151       return NULL;
1152 
1153    copy = _token_list_create (parser);
1154    for (node = other->head; node; node = node->next) {
1155       token_t *new_token = linear_alloc_child(parser->linalloc, sizeof(token_t));
1156       *new_token = *node->token;
1157       _token_list_append (parser, copy, new_token);
1158    }
1159 
1160    return copy;
1161 }
1162 
1163 static void
_token_list_trim_trailing_space(token_list_t * list)1164 _token_list_trim_trailing_space(token_list_t *list)
1165 {
1166    if (list->non_space_tail) {
1167       list->non_space_tail->next = NULL;
1168       list->tail = list->non_space_tail;
1169    }
1170 }
1171 
1172 static int
_token_list_is_empty_ignoring_space(token_list_t * l)1173 _token_list_is_empty_ignoring_space(token_list_t *l)
1174 {
1175    token_node_t *n;
1176 
1177    if (l == NULL)
1178       return 1;
1179 
1180    n = l->head;
1181    while (n != NULL && n->token->type == SPACE)
1182       n = n->next;
1183 
1184    return n == NULL;
1185 }
1186 
1187 int
_token_list_equal_ignoring_space(token_list_t * a,token_list_t * b)1188 _token_list_equal_ignoring_space(token_list_t *a, token_list_t *b)
1189 {
1190    token_node_t *node_a, *node_b;
1191 
1192    if (a == NULL || b == NULL) {
1193       int a_empty = _token_list_is_empty_ignoring_space(a);
1194       int b_empty = _token_list_is_empty_ignoring_space(b);
1195       return a_empty == b_empty;
1196    }
1197 
1198    node_a = a->head;
1199    node_b = b->head;
1200 
1201    while (1)
1202    {
1203       if (node_a == NULL && node_b == NULL)
1204          break;
1205 
1206       /* Ignore trailing whitespace */
1207       if (node_a == NULL && node_b->token->type == SPACE) {
1208          while (node_b && node_b->token->type == SPACE)
1209             node_b = node_b->next;
1210       }
1211 
1212       if (node_a == NULL && node_b == NULL)
1213          break;
1214 
1215       if (node_b == NULL && node_a->token->type == SPACE) {
1216          while (node_a && node_a->token->type == SPACE)
1217             node_a = node_a->next;
1218       }
1219 
1220       if (node_a == NULL && node_b == NULL)
1221          break;
1222 
1223       if (node_a == NULL || node_b == NULL)
1224          return 0;
1225       /* Make sure whitespace appears in the same places in both.
1226        * It need not be exactly the same amount of whitespace,
1227        * though.
1228        */
1229       if (node_a->token->type == SPACE && node_b->token->type == SPACE) {
1230          while (node_a && node_a->token->type == SPACE)
1231             node_a = node_a->next;
1232          while (node_b && node_b->token->type == SPACE)
1233             node_b = node_b->next;
1234          continue;
1235       }
1236 
1237       if (node_a->token->type != node_b->token->type)
1238          return 0;
1239 
1240       switch (node_a->token->type) {
1241       case INTEGER:
1242          if (node_a->token->value.ival !=  node_b->token->value.ival) {
1243             return 0;
1244          }
1245          break;
1246       case IDENTIFIER:
1247       case INTEGER_STRING:
1248       case OTHER:
1249          if (strcmp(node_a->token->value.str, node_b->token->value.str)) {
1250             return 0;
1251          }
1252          break;
1253       }
1254 
1255       node_a = node_a->next;
1256       node_b = node_b->next;
1257    }
1258 
1259    return 1;
1260 }
1261 
1262 static void
_token_print(struct _mesa_string_buffer * out,token_t * token)1263 _token_print(struct _mesa_string_buffer *out, token_t *token)
1264 {
1265    if (token->type < 256) {
1266       _mesa_string_buffer_append_char(out, token->type);
1267       return;
1268    }
1269 
1270    switch (token->type) {
1271    case INTEGER:
1272       _mesa_string_buffer_printf(out, "%" PRIiMAX, token->value.ival);
1273       break;
1274    case IDENTIFIER:
1275    case INTEGER_STRING:
1276    case PATH:
1277    case OTHER:
1278       _mesa_string_buffer_append(out, token->value.str);
1279       break;
1280    case SPACE:
1281       _mesa_string_buffer_append_char(out, ' ');
1282       break;
1283    case LEFT_SHIFT:
1284       _mesa_string_buffer_append(out, "<<");
1285       break;
1286    case RIGHT_SHIFT:
1287       _mesa_string_buffer_append(out, ">>");
1288       break;
1289    case LESS_OR_EQUAL:
1290       _mesa_string_buffer_append(out, "<=");
1291       break;
1292    case GREATER_OR_EQUAL:
1293       _mesa_string_buffer_append(out, ">=");
1294       break;
1295    case EQUAL:
1296       _mesa_string_buffer_append(out, "==");
1297       break;
1298    case NOT_EQUAL:
1299       _mesa_string_buffer_append(out, "!=");
1300       break;
1301    case AND:
1302       _mesa_string_buffer_append(out, "&&");
1303       break;
1304    case OR:
1305       _mesa_string_buffer_append(out, "||");
1306       break;
1307    case PASTE:
1308       _mesa_string_buffer_append(out, "##");
1309       break;
1310    case PLUS_PLUS:
1311       _mesa_string_buffer_append(out, "++");
1312       break;
1313    case MINUS_MINUS:
1314       _mesa_string_buffer_append(out, "--");
1315       break;
1316    case DEFINED:
1317       _mesa_string_buffer_append(out, "defined");
1318       break;
1319    case PLACEHOLDER:
1320       /* Nothing to print. */
1321       break;
1322    default:
1323       assert(!"Error: Don't know how to print token.");
1324 
1325       break;
1326    }
1327 }
1328 
1329 /* Return a new token formed by pasting 'token' and 'other'. Note that this
1330  * function may return 'token' or 'other' directly rather than allocating
1331  * anything new.
1332  *
1333  * Caution: Only very cursory error-checking is performed to see if
1334  * the final result is a valid single token. */
1335 static token_t *
_token_paste(glcpp_parser_t * parser,token_t * token,token_t * other)1336 _token_paste(glcpp_parser_t *parser, token_t *token, token_t *other)
1337 {
1338    token_t *combined = NULL;
1339 
1340    /* Pasting a placeholder onto anything makes no change. */
1341    if (other->type == PLACEHOLDER)
1342       return token;
1343 
1344    /* When 'token' is a placeholder, just return 'other'. */
1345    if (token->type == PLACEHOLDER)
1346       return other;
1347 
1348    /* A very few single-character punctuators can be combined
1349     * with another to form a multi-character punctuator. */
1350    switch (token->type) {
1351    case '<':
1352       if (other->type == '<')
1353          combined = _token_create_ival (parser, LEFT_SHIFT, LEFT_SHIFT);
1354       else if (other->type == '=')
1355          combined = _token_create_ival (parser, LESS_OR_EQUAL, LESS_OR_EQUAL);
1356       break;
1357    case '>':
1358       if (other->type == '>')
1359          combined = _token_create_ival (parser, RIGHT_SHIFT, RIGHT_SHIFT);
1360       else if (other->type == '=')
1361          combined = _token_create_ival (parser, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
1362       break;
1363    case '=':
1364       if (other->type == '=')
1365          combined = _token_create_ival (parser, EQUAL, EQUAL);
1366       break;
1367    case '!':
1368       if (other->type == '=')
1369          combined = _token_create_ival (parser, NOT_EQUAL, NOT_EQUAL);
1370       break;
1371    case '&':
1372       if (other->type == '&')
1373          combined = _token_create_ival (parser, AND, AND);
1374       break;
1375    case '|':
1376       if (other->type == '|')
1377          combined = _token_create_ival (parser, OR, OR);
1378       break;
1379    }
1380 
1381    if (combined != NULL) {
1382       /* Inherit the location from the first token */
1383       combined->location = token->location;
1384       return combined;
1385    }
1386 
1387    /* Two string-valued (or integer) tokens can usually just be
1388     * mashed together. (We also handle a string followed by an
1389     * integer here as well.)
1390     *
1391     * There are some exceptions here. Notably, if the first token
1392     * is an integer (or a string representing an integer), then
1393     * the second token must also be an integer or must be a
1394     * string representing an integer that begins with a digit.
1395     */
1396    if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) &&
1397        (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER))
1398    {
1399       char *str;
1400       int combined_type;
1401 
1402       /* Check that pasting onto an integer doesn't create a
1403        * non-integer, (that is, only digits can be
1404        * pasted. */
1405       if (token->type == INTEGER_STRING || token->type == INTEGER) {
1406          switch (other->type) {
1407          case INTEGER_STRING:
1408             if (other->value.str[0] < '0' || other->value.str[0] > '9')
1409                goto FAIL;
1410             break;
1411          case INTEGER:
1412             if (other->value.ival < 0)
1413                goto FAIL;
1414             break;
1415          default:
1416             goto FAIL;
1417          }
1418       }
1419 
1420       if (token->type == INTEGER)
1421          str = linear_asprintf(parser->linalloc, "%" PRIiMAX, token->value.ival);
1422       else
1423          str = linear_strdup(parser->linalloc, token->value.str);
1424 
1425       if (other->type == INTEGER)
1426          linear_asprintf_append(parser->linalloc, &str, "%" PRIiMAX, other->value.ival);
1427       else
1428          linear_strcat(parser->linalloc, &str, other->value.str);
1429 
1430       /* New token is same type as original token, unless we
1431        * started with an integer, in which case we will be
1432        * creating an integer-string. */
1433       combined_type = token->type;
1434       if (combined_type == INTEGER)
1435          combined_type = INTEGER_STRING;
1436 
1437       combined = _token_create_str (parser, combined_type, str);
1438       combined->location = token->location;
1439       return combined;
1440    }
1441 
1442     FAIL:
1443    glcpp_error (&token->location, parser, "");
1444    _mesa_string_buffer_append(parser->info_log, "Pasting \"");
1445    _token_print(parser->info_log, token);
1446    _mesa_string_buffer_append(parser->info_log, "\" and \"");
1447    _token_print(parser->info_log, other);
1448    _mesa_string_buffer_append(parser->info_log, "\" does not give a valid preprocessing token.\n");
1449 
1450    return token;
1451 }
1452 
1453 static void
_token_list_print(glcpp_parser_t * parser,token_list_t * list)1454 _token_list_print(glcpp_parser_t *parser, token_list_t *list)
1455 {
1456    token_node_t *node;
1457 
1458    if (list == NULL)
1459       return;
1460 
1461    for (node = list->head; node; node = node->next)
1462       _token_print(parser->output, node->token);
1463 }
1464 
1465 void
yyerror(YYLTYPE * locp,glcpp_parser_t * parser,const char * error)1466 yyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
1467 {
1468    glcpp_error(locp, parser, "%s", error);
1469 }
1470 
1471 static void
add_builtin_define(glcpp_parser_t * parser,const char * name,int value)1472 add_builtin_define(glcpp_parser_t *parser, const char *name, int value)
1473 {
1474    token_t *tok;
1475    token_list_t *list;
1476 
1477    tok = _token_create_ival (parser, INTEGER, value);
1478 
1479    list = _token_list_create(parser);
1480    _token_list_append(parser, list, tok);
1481    _define_object_macro(parser, NULL, name, list);
1482 }
1483 
1484 /* Initial output buffer size, 4096 minus ralloc() overhead. It was selected
1485  * to minimize total amount of allocated memory during shader-db run.
1486  */
1487 #define INITIAL_PP_OUTPUT_BUF_SIZE 4048
1488 
1489 glcpp_parser_t *
glcpp_parser_create(struct gl_context * gl_ctx,glcpp_extension_iterator extensions,void * state)1490 glcpp_parser_create(struct gl_context *gl_ctx,
1491                     glcpp_extension_iterator extensions, void *state)
1492 {
1493    glcpp_parser_t *parser;
1494 
1495    parser = ralloc (NULL, glcpp_parser_t);
1496 
1497    glcpp_lex_init_extra (parser, &parser->scanner);
1498    parser->defines = _mesa_hash_table_create(NULL, _mesa_hash_string,
1499                                              _mesa_key_string_equal);
1500    parser->linalloc = linear_context(parser);
1501    parser->active = NULL;
1502    parser->lexing_directive = 0;
1503    parser->lexing_version_directive = 0;
1504    parser->space_tokens = 1;
1505    parser->last_token_was_newline = 0;
1506    parser->last_token_was_space = 0;
1507    parser->first_non_space_token_this_line = 1;
1508    parser->newline_as_space = 0;
1509    parser->in_control_line = 0;
1510    parser->paren_count = 0;
1511    parser->commented_newlines = 0;
1512 
1513    parser->skip_stack = NULL;
1514    parser->skipping = 0;
1515 
1516    parser->lex_from_list = NULL;
1517    parser->lex_from_node = NULL;
1518 
1519    parser->output = _mesa_string_buffer_create(parser,
1520                                                INITIAL_PP_OUTPUT_BUF_SIZE);
1521    parser->info_log = _mesa_string_buffer_create(parser,
1522                                                  INITIAL_PP_OUTPUT_BUF_SIZE);
1523    parser->error = 0;
1524 
1525    parser->gl_ctx = gl_ctx;
1526    parser->extensions = extensions;
1527    parser->extension_list = &gl_ctx->Extensions;
1528    parser->state = state;
1529    parser->api = gl_ctx->API;
1530    parser->version = 0;
1531    parser->version_set = false;
1532 
1533    parser->has_new_line_number = 0;
1534    parser->new_line_number = 1;
1535    parser->has_new_source_number = 0;
1536    parser->new_source_number = 0;
1537 
1538    parser->is_gles = false;
1539 
1540    return parser;
1541 }
1542 
1543 void
glcpp_parser_destroy(glcpp_parser_t * parser)1544 glcpp_parser_destroy(glcpp_parser_t *parser)
1545 {
1546    glcpp_lex_destroy (parser->scanner);
1547    _mesa_hash_table_destroy(parser->defines, NULL);
1548    ralloc_free (parser);
1549 }
1550 
1551 typedef enum function_status
1552 {
1553    FUNCTION_STATUS_SUCCESS,
1554    FUNCTION_NOT_A_FUNCTION,
1555    FUNCTION_UNBALANCED_PARENTHESES
1556 } function_status_t;
1557 
1558 /* Find a set of function-like macro arguments by looking for a
1559  * balanced set of parentheses.
1560  *
1561  * When called, 'node' should be the opening-parenthesis token, (or
1562  * perhaps preceeding SPACE tokens). Upon successful return *last will
1563  * be the last consumed node, (corresponding to the closing right
1564  * parenthesis).
1565  *
1566  * Return values:
1567  *
1568  *   FUNCTION_STATUS_SUCCESS:
1569  *
1570  *      Successfully parsed a set of function arguments.
1571  *
1572  *   FUNCTION_NOT_A_FUNCTION:
1573  *
1574  *      Macro name not followed by a '('. This is not an error, but
1575  *      simply that the macro name should be treated as a non-macro.
1576  *
1577  *   FUNCTION_UNBALANCED_PARENTHESES
1578  *
1579  *      Macro name is not followed by a balanced set of parentheses.
1580  */
1581 static function_status_t
_arguments_parse(glcpp_parser_t * parser,argument_list_t * arguments,token_node_t * node,token_node_t ** last)1582 _arguments_parse(glcpp_parser_t *parser,
1583                  argument_list_t *arguments, token_node_t *node,
1584                  token_node_t **last)
1585 {
1586    token_list_t *argument;
1587    int paren_count;
1588 
1589    node = node->next;
1590 
1591    /* Ignore whitespace before first parenthesis. */
1592    while (node && node->token->type == SPACE)
1593       node = node->next;
1594 
1595    if (node == NULL || node->token->type != '(')
1596       return FUNCTION_NOT_A_FUNCTION;
1597 
1598    node = node->next;
1599 
1600    argument = _token_list_create (parser);
1601    _argument_list_append (parser, arguments, argument);
1602 
1603    for (paren_count = 1; node; node = node->next) {
1604       if (node->token->type == '(') {
1605          paren_count++;
1606       } else if (node->token->type == ')') {
1607          paren_count--;
1608          if (paren_count == 0)
1609             break;
1610       }
1611 
1612       if (node->token->type == ',' && paren_count == 1) {
1613          _token_list_trim_trailing_space (argument);
1614          argument = _token_list_create (parser);
1615          _argument_list_append (parser, arguments, argument);
1616       } else {
1617          if (argument->head == NULL) {
1618             /* Don't treat initial whitespace as part of the argument. */
1619             if (node->token->type == SPACE)
1620                continue;
1621          }
1622          _token_list_append(parser, argument, node->token);
1623       }
1624    }
1625 
1626    if (paren_count)
1627       return FUNCTION_UNBALANCED_PARENTHESES;
1628 
1629    *last = node;
1630 
1631    return FUNCTION_STATUS_SUCCESS;
1632 }
1633 
1634 static token_list_t *
_token_list_create_with_one_ival(glcpp_parser_t * parser,int type,int ival)1635 _token_list_create_with_one_ival(glcpp_parser_t *parser, int type, int ival)
1636 {
1637    token_list_t *list;
1638    token_t *node;
1639 
1640    list = _token_list_create(parser);
1641    node = _token_create_ival(parser, type, ival);
1642    _token_list_append(parser, list, node);
1643 
1644    return list;
1645 }
1646 
1647 static token_list_t *
_token_list_create_with_one_space(glcpp_parser_t * parser)1648 _token_list_create_with_one_space(glcpp_parser_t *parser)
1649 {
1650    return _token_list_create_with_one_ival(parser, SPACE, SPACE);
1651 }
1652 
1653 static token_list_t *
_token_list_create_with_one_integer(glcpp_parser_t * parser,int ival)1654 _token_list_create_with_one_integer(glcpp_parser_t *parser, int ival)
1655 {
1656    return _token_list_create_with_one_ival(parser, INTEGER, ival);
1657 }
1658 
1659 /* Evaluate a DEFINED token node (based on subsequent tokens in the list).
1660  *
1661  * Note: This function must only be called when "node" is a DEFINED token,
1662  * (and will abort with an assertion failure otherwise).
1663  *
1664  * If "node" is followed, (ignoring any SPACE tokens), by an IDENTIFIER token
1665  * (optionally preceded and followed by '(' and ')' tokens) then the following
1666  * occurs:
1667  *
1668  *   If the identifier is a defined macro, this function returns 1.
1669  *
1670  *   If the identifier is not a defined macro, this function returns 0.
1671  *
1672  *   In either case, *last will be updated to the last node in the list
1673  *   consumed by the evaluation, (either the token of the identifier or the
1674  *   token of the closing parenthesis).
1675  *
1676  * In all other cases, (such as "node is the final node of the list", or
1677  * "missing closing parenthesis", etc.), this function generates a
1678  * preprocessor error, returns -1 and *last will not be set.
1679  */
1680 static int
_glcpp_parser_evaluate_defined(glcpp_parser_t * parser,token_node_t * node,token_node_t ** last)1681 _glcpp_parser_evaluate_defined(glcpp_parser_t *parser, token_node_t *node,
1682                                token_node_t **last)
1683 {
1684    token_node_t *argument, *defined = node;
1685 
1686    assert(node->token->type == DEFINED);
1687 
1688    node = node->next;
1689 
1690    /* Ignore whitespace after DEFINED token. */
1691    while (node && node->token->type == SPACE)
1692       node = node->next;
1693 
1694    if (node == NULL)
1695       goto FAIL;
1696 
1697    if (node->token->type == IDENTIFIER || node->token->type == OTHER) {
1698       argument = node;
1699    } else if (node->token->type == '(') {
1700       node = node->next;
1701 
1702       /* Ignore whitespace after '(' token. */
1703       while (node && node->token->type == SPACE)
1704          node = node->next;
1705 
1706       if (node == NULL || (node->token->type != IDENTIFIER &&
1707                            node->token->type != OTHER)) {
1708          goto FAIL;
1709       }
1710 
1711       argument = node;
1712 
1713       node = node->next;
1714 
1715       /* Ignore whitespace after identifier, before ')' token. */
1716       while (node && node->token->type == SPACE)
1717          node = node->next;
1718 
1719       if (node == NULL || node->token->type != ')')
1720          goto FAIL;
1721    } else {
1722       goto FAIL;
1723    }
1724 
1725    *last = node;
1726 
1727    return _mesa_hash_table_search(parser->defines,
1728                                   argument->token->value.str) ? 1 : 0;
1729 
1730 FAIL:
1731    glcpp_error (&defined->token->location, parser,
1732                 "\"defined\" not followed by an identifier");
1733    return -1;
1734 }
1735 
1736 /* Evaluate all DEFINED nodes in a given list, modifying the list in place.
1737  */
1738 static void
_glcpp_parser_evaluate_defined_in_list(glcpp_parser_t * parser,token_list_t * list)1739 _glcpp_parser_evaluate_defined_in_list(glcpp_parser_t *parser,
1740                                        token_list_t *list)
1741 {
1742    token_node_t *node, *node_prev, *replacement, *last = NULL;
1743    int value;
1744 
1745    if (list == NULL)
1746       return;
1747 
1748    node_prev = NULL;
1749    node = list->head;
1750 
1751    while (node) {
1752 
1753       if (node->token->type != DEFINED)
1754          goto NEXT;
1755 
1756       value = _glcpp_parser_evaluate_defined (parser, node, &last);
1757       if (value == -1)
1758          goto NEXT;
1759 
1760       replacement = linear_alloc_child(parser->linalloc, sizeof(token_node_t));
1761       replacement->token = _token_create_ival (parser, INTEGER, value);
1762 
1763       /* Splice replacement node into list, replacing from "node"
1764        * through "last". */
1765       if (node_prev)
1766          node_prev->next = replacement;
1767       else
1768          list->head = replacement;
1769       replacement->next = last->next;
1770       if (last == list->tail)
1771          list->tail = replacement;
1772 
1773       node = replacement;
1774 
1775    NEXT:
1776       node_prev = node;
1777       node = node->next;
1778    }
1779 }
1780 
1781 /* Perform macro expansion on 'list', placing the resulting tokens
1782  * into a new list which is initialized with a first token of type
1783  * 'head_token_type'. Then begin lexing from the resulting list,
1784  * (return to the current lexing source when this list is exhausted).
1785  *
1786  * See the documentation of _glcpp_parser_expand_token_list for a description
1787  * of the "mode" parameter.
1788  */
1789 static void
_glcpp_parser_expand_and_lex_from(glcpp_parser_t * parser,int head_token_type,token_list_t * list,expansion_mode_t mode)1790 _glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type,
1791                                   token_list_t *list, expansion_mode_t mode)
1792 {
1793    token_list_t *expanded;
1794    token_t *token;
1795 
1796    expanded = _token_list_create (parser);
1797    token = _token_create_ival (parser, head_token_type, head_token_type);
1798    _token_list_append (parser, expanded, token);
1799    _glcpp_parser_expand_token_list (parser, list, mode);
1800    _token_list_append_list (expanded, list);
1801    glcpp_parser_lex_from (parser, expanded);
1802 }
1803 
1804 static void
_glcpp_parser_apply_pastes(glcpp_parser_t * parser,token_list_t * list)1805 _glcpp_parser_apply_pastes(glcpp_parser_t *parser, token_list_t *list)
1806 {
1807    token_node_t *node;
1808 
1809    node = list->head;
1810    while (node) {
1811       token_node_t *next_non_space;
1812 
1813       /* Look ahead for a PASTE token, skipping space. */
1814       next_non_space = node->next;
1815       while (next_non_space && next_non_space->token->type == SPACE)
1816          next_non_space = next_non_space->next;
1817 
1818       if (next_non_space == NULL)
1819          break;
1820 
1821       if (next_non_space->token->type != PASTE) {
1822          node = next_non_space;
1823          continue;
1824       }
1825 
1826       /* Now find the next non-space token after the PASTE. */
1827       next_non_space = next_non_space->next;
1828       while (next_non_space && next_non_space->token->type == SPACE)
1829          next_non_space = next_non_space->next;
1830 
1831       if (next_non_space == NULL) {
1832          yyerror(&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
1833          return;
1834       }
1835 
1836       node->token = _token_paste(parser, node->token, next_non_space->token);
1837       node->next = next_non_space->next;
1838       if (next_non_space == list->tail)
1839          list->tail = node;
1840    }
1841 
1842    list->non_space_tail = list->tail;
1843 }
1844 
1845 /* This is a helper function that's essentially part of the
1846  * implementation of _glcpp_parser_expand_node. It shouldn't be called
1847  * except for by that function.
1848  *
1849  * Returns NULL if node is a simple token with no expansion, (that is,
1850  * although 'node' corresponds to an identifier defined as a
1851  * function-like macro, it is not followed with a parenthesized
1852  * argument list).
1853  *
1854  * Compute the complete expansion of node (which is a function-like
1855  * macro) and subsequent nodes which are arguments.
1856  *
1857  * Returns the token list that results from the expansion and sets
1858  * *last to the last node in the list that was consumed by the
1859  * expansion. Specifically, *last will be set as follows: as the
1860  * token of the closing right parenthesis.
1861  *
1862  * See the documentation of _glcpp_parser_expand_token_list for a description
1863  * of the "mode" parameter.
1864  */
1865 static token_list_t *
_glcpp_parser_expand_function(glcpp_parser_t * parser,token_node_t * node,token_node_t ** last,expansion_mode_t mode,macro_t * macro)1866 _glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node,
1867                               token_node_t **last, expansion_mode_t mode,
1868                               macro_t *macro)
1869 {
1870    const char *identifier;
1871    argument_list_t *arguments;
1872    function_status_t status;
1873    token_list_t *substituted;
1874    int parameter_index;
1875 
1876    assert(macro);
1877    assert(macro->is_function);
1878 
1879    identifier = node->token->value.str;
1880    arguments = _argument_list_create(parser);
1881    status = _arguments_parse(parser, arguments, node, last);
1882 
1883    switch (status) {
1884    case FUNCTION_STATUS_SUCCESS:
1885       break;
1886    case FUNCTION_NOT_A_FUNCTION:
1887       return NULL;
1888    case FUNCTION_UNBALANCED_PARENTHESES:
1889       glcpp_error(&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
1890       return NULL;
1891    }
1892 
1893    /* Replace a macro defined as empty with a SPACE token. */
1894    if (macro->replacements == NULL) {
1895       return _token_list_create_with_one_space(parser);
1896    }
1897 
1898    if (!((_argument_list_length (arguments) ==
1899           _string_list_length (macro->parameters)) ||
1900          (_string_list_length (macro->parameters) == 0 &&
1901           _argument_list_length (arguments) == 1 &&
1902           arguments->head->argument->head == NULL))) {
1903       glcpp_error(&node->token->location, parser,
1904                   "Error: macro %s invoked with %d arguments (expected %d)\n",
1905                   identifier, _argument_list_length (arguments),
1906                   _string_list_length(macro->parameters));
1907       return NULL;
1908    }
1909 
1910    /* Perform argument substitution on the replacement list. */
1911    substituted = _token_list_create(parser);
1912 
1913    for (node = macro->replacements->head; node; node = node->next) {
1914       if (node->token->type == IDENTIFIER &&
1915           _string_list_contains(macro->parameters, node->token->value.str,
1916                                 &parameter_index)) {
1917          token_list_t *argument;
1918          argument = _argument_list_member_at(arguments, parameter_index);
1919          /* Before substituting, we expand the argument tokens, or append a
1920           * placeholder token for an empty argument. */
1921          if (argument->head) {
1922             token_list_t *expanded_argument;
1923             expanded_argument = _token_list_copy(parser, argument);
1924             _glcpp_parser_expand_token_list(parser, expanded_argument, mode);
1925             _token_list_append_list(substituted, expanded_argument);
1926          } else {
1927             token_t *new_token;
1928 
1929             new_token = _token_create_ival(parser, PLACEHOLDER,
1930                                            PLACEHOLDER);
1931             _token_list_append(parser, substituted, new_token);
1932          }
1933       } else {
1934          _token_list_append(parser, substituted, node->token);
1935       }
1936    }
1937 
1938    /* After argument substitution, and before further expansion
1939     * below, implement token pasting. */
1940 
1941    _token_list_trim_trailing_space(substituted);
1942 
1943    _glcpp_parser_apply_pastes(parser, substituted);
1944 
1945    return substituted;
1946 }
1947 
1948 /* Compute the complete expansion of node, (and subsequent nodes after
1949  * 'node' in the case that 'node' is a function-like macro and
1950  * subsequent nodes are arguments).
1951  *
1952  * Returns NULL if node is a simple token with no expansion.
1953  *
1954  * Otherwise, returns the token list that results from the expansion
1955  * and sets *last to the last node in the list that was consumed by
1956  * the expansion. Specifically, *last will be set as follows:
1957  *
1958  *   As 'node' in the case of object-like macro expansion.
1959  *
1960  *   As the token of the closing right parenthesis in the case of
1961  *   function-like macro expansion.
1962  *
1963  * See the documentation of _glcpp_parser_expand_token_list for a description
1964  * of the "mode" parameter.
1965  */
1966 static token_list_t *
_glcpp_parser_expand_node(glcpp_parser_t * parser,token_node_t * node,token_node_t * node_prev,token_node_t ** last,expansion_mode_t mode,int line)1967 _glcpp_parser_expand_node(glcpp_parser_t *parser, token_node_t *node,
1968                           token_node_t *node_prev, token_node_t **last,
1969                           expansion_mode_t mode, int line)
1970 {
1971    token_t *token = node->token;
1972    const char *identifier;
1973    struct hash_entry *entry;
1974    macro_t *macro;
1975 
1976    /* If token is already being expanded return to avoid an infinite loop */
1977    if (token->expanding)
1978       return NULL;
1979 
1980    /* We only expand identifiers */
1981    if (token->type != IDENTIFIER) {
1982       return NULL;
1983    }
1984 
1985    *last = node;
1986    identifier = token->value.str;
1987 
1988    /* Special handling for __LINE__ and __FILE__, (not through
1989     * the hash table). */
1990    if (*identifier == '_') {
1991       if (strcmp(identifier, "__LINE__") == 0)
1992          return _token_list_create_with_one_integer(parser, line);
1993 
1994       if (strcmp(identifier, "__FILE__") == 0)
1995          return _token_list_create_with_one_integer(parser,
1996                                                     node->token->location.source);
1997    }
1998 
1999    /* Look up this identifier in the hash table. */
2000    entry = _mesa_hash_table_search(parser->defines, identifier);
2001    macro = entry ? entry->data : NULL;
2002 
2003    /* Not a macro, so no expansion needed. */
2004    if (macro == NULL)
2005       return NULL;
2006 
2007    /* Finally, don't expand this macro if we're already actively
2008     * expanding it, (to avoid infinite recursion). */
2009    if (_parser_active_list_contains (parser, identifier)) {
2010       /* We change the `expanding` bool to true to prevent any
2011        * future expansion of this unexpanded token. */
2012       char *str;
2013       token_list_t *expansion;
2014       token_t *final;
2015 
2016       str = linear_strdup(parser->linalloc, token->value.str);
2017       final = _token_create_str(parser, token->type, str);
2018       final->expanding = true;
2019       expansion = _token_list_create(parser);
2020       _token_list_append(parser, expansion, final);
2021       return expansion;
2022    }
2023 
2024    if (! macro->is_function) {
2025       token_list_t *replacement;
2026 
2027       /* Replace a macro defined as empty with a SPACE token. */
2028       if (macro->replacements == NULL)
2029          return _token_list_create_with_one_space(parser);
2030 
2031       replacement = _token_list_copy(parser, macro->replacements);
2032 
2033       /* If needed insert space in front of replacements to isolate them from
2034        * the code they will be inserted into. For example:
2035        *
2036        *    #define VALUE -1.0
2037        *    int a = -VALUE;
2038        *
2039        * Should be evaluated to int a = - -1.0; not int a = --1.0;
2040        */
2041       if (node_prev &&
2042           (node_prev->token->type == '-' || node_prev->token->type == '+') &&
2043           node_prev->token->type == replacement->head->token->type) {
2044          token_t *new_token = _token_create_ival(parser, SPACE, SPACE);
2045          _token_list_prepend(parser, replacement, new_token);
2046       }
2047 
2048       _glcpp_parser_apply_pastes(parser, replacement);
2049       return replacement;
2050    }
2051 
2052    return _glcpp_parser_expand_function(parser, node, last, mode, macro);
2053 }
2054 
2055 /* Push a new identifier onto the parser's active list.
2056  *
2057  * Here, 'marker' is the token node that appears in the list after the
2058  * expansion of 'identifier'. That is, when the list iterator begins
2059  * examining 'marker', then it is time to pop this node from the
2060  * active stack.
2061  */
2062 static void
_parser_active_list_push(glcpp_parser_t * parser,const char * identifier,token_node_t * marker)2063 _parser_active_list_push(glcpp_parser_t *parser, const char *identifier,
2064                          token_node_t *marker)
2065 {
2066    active_list_t *node;
2067 
2068    node = linear_alloc_child(parser->linalloc, sizeof(active_list_t));
2069    node->identifier = linear_strdup(parser->linalloc, identifier);
2070    node->marker = marker;
2071    node->next = parser->active;
2072 
2073    parser->active = node;
2074 }
2075 
2076 static void
_parser_active_list_pop(glcpp_parser_t * parser)2077 _parser_active_list_pop(glcpp_parser_t *parser)
2078 {
2079    active_list_t *node = parser->active;
2080 
2081    if (node == NULL) {
2082       parser->active = NULL;
2083       return;
2084    }
2085 
2086    node = parser->active->next;
2087    parser->active = node;
2088 }
2089 
2090 static int
_parser_active_list_contains(glcpp_parser_t * parser,const char * identifier)2091 _parser_active_list_contains(glcpp_parser_t *parser, const char *identifier)
2092 {
2093    active_list_t *node;
2094 
2095    if (parser->active == NULL)
2096       return 0;
2097 
2098    for (node = parser->active; node; node = node->next)
2099       if (strcmp(node->identifier, identifier) == 0)
2100          return 1;
2101 
2102    return 0;
2103 }
2104 
2105 /* Walk over the token list replacing nodes with their expansion.
2106  * Whenever nodes are expanded the walking will walk over the new
2107  * nodes, continuing to expand as necessary. The results are placed in
2108  * 'list' itself.
2109  *
2110  * The "mode" argument controls the handling of any DEFINED tokens that
2111  * result from expansion as follows:
2112  *
2113  *   EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be
2114  *      left in the final list, unevaluated. This is the correct mode
2115  *      for expanding any list in any context other than a
2116  *      preprocessor conditional, (#if or #elif).
2117  *
2118  *   EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be
2119  *      evaluated to 0 or 1 tokens depending on whether the following
2120  *      token is the name of a defined macro. If the DEFINED token is
2121  *      not followed by an (optionally parenthesized) identifier, then
2122  *      an error will be generated. This the correct mode for
2123  *      expanding any list in the context of a preprocessor
2124  *      conditional, (#if or #elif).
2125  */
2126 static void
_glcpp_parser_expand_token_list(glcpp_parser_t * parser,token_list_t * list,expansion_mode_t mode)2127 _glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list,
2128                                 expansion_mode_t mode)
2129 {
2130    token_node_t *node_prev;
2131    token_node_t *node, *last = NULL;
2132    token_list_t *expansion;
2133    active_list_t *active_initial = parser->active;
2134    int line;
2135 
2136    if (list == NULL)
2137       return;
2138 
2139    _token_list_trim_trailing_space (list);
2140 
2141    line = list->tail->token->location.last_line;
2142 
2143    node_prev = NULL;
2144    node = list->head;
2145 
2146    if (mode == EXPANSION_MODE_EVALUATE_DEFINED)
2147       _glcpp_parser_evaluate_defined_in_list (parser, list);
2148 
2149    while (node) {
2150 
2151       while (parser->active && parser->active->marker == node)
2152          _parser_active_list_pop (parser);
2153 
2154       expansion =
2155          _glcpp_parser_expand_node(parser, node, node_prev, &last, mode, line);
2156       if (expansion) {
2157          token_node_t *n;
2158 
2159          if (mode == EXPANSION_MODE_EVALUATE_DEFINED) {
2160             _glcpp_parser_evaluate_defined_in_list (parser, expansion);
2161          }
2162 
2163          for (n = node; n != last->next; n = n->next)
2164             while (parser->active && parser->active->marker == n) {
2165                _parser_active_list_pop (parser);
2166             }
2167 
2168          _parser_active_list_push(parser, node->token->value.str, last->next);
2169 
2170          /* Splice expansion into list, supporting a simple deletion if the
2171           * expansion is empty.
2172           */
2173          if (expansion->head) {
2174             if (node_prev)
2175                node_prev->next = expansion->head;
2176             else
2177                list->head = expansion->head;
2178             expansion->tail->next = last->next;
2179             if (last == list->tail)
2180                list->tail = expansion->tail;
2181          } else {
2182             if (node_prev)
2183                node_prev->next = last->next;
2184             else
2185                list->head = last->next;
2186             if (last == list->tail)
2187                list->tail = NULL;
2188          }
2189       } else {
2190          node_prev = node;
2191       }
2192       node = node_prev ? node_prev->next : list->head;
2193    }
2194 
2195    /* Remove any lingering effects of this invocation on the
2196     * active list. That is, pop until the list looks like it did
2197     * at the beginning of this function. */
2198    while (parser->active && parser->active != active_initial)
2199       _parser_active_list_pop (parser);
2200 
2201    list->non_space_tail = list->tail;
2202 }
2203 
2204 void
_glcpp_parser_print_expanded_token_list(glcpp_parser_t * parser,token_list_t * list)2205 _glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser,
2206                                         token_list_t *list)
2207 {
2208    if (list == NULL)
2209       return;
2210 
2211    _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED);
2212 
2213    _token_list_trim_trailing_space (list);
2214 
2215    _token_list_print (parser, list);
2216 }
2217 
2218 static void
_check_for_reserved_macro_name(glcpp_parser_t * parser,YYLTYPE * loc,const char * identifier)2219 _check_for_reserved_macro_name(glcpp_parser_t *parser, YYLTYPE *loc,
2220                                const char *identifier)
2221 {
2222    /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and
2223     * the GLSL ES spec (all versions) say:
2224     *
2225     *     "All macro names containing two consecutive underscores ( __ )
2226     *     are reserved for future use as predefined macro names. All
2227     *     macro names prefixed with "GL_" ("GL" followed by a single
2228     *     underscore) are also reserved."
2229     *
2230     * The intention is that names containing __ are reserved for internal
2231     * use by the implementation, and names prefixed with GL_ are reserved
2232     * for use by Khronos.  Since every extension adds a name prefixed
2233     * with GL_ (i.e., the name of the extension), that should be an
2234     * error.  Names simply containing __ are dangerous to use, but should
2235     * be allowed.
2236     *
2237     * A future version of the GLSL specification will clarify this.
2238     */
2239    if (strstr(identifier, "__")) {
2240       glcpp_warning(loc, parser, "Macro names containing \"__\" are reserved "
2241                     "for use by the implementation.\n");
2242    }
2243    if (strncmp(identifier, "GL_", 3) == 0) {
2244       glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
2245    }
2246    if (strcmp(identifier, "defined") == 0) {
2247       glcpp_error (loc, parser, "\"defined\" cannot be used as a macro name");
2248    }
2249 }
2250 
2251 static int
_macro_equal(macro_t * a,macro_t * b)2252 _macro_equal(macro_t *a, macro_t *b)
2253 {
2254    if (a->is_function != b->is_function)
2255       return 0;
2256 
2257    if (a->is_function) {
2258       if (! _string_list_equal (a->parameters, b->parameters))
2259          return 0;
2260    }
2261 
2262    return _token_list_equal_ignoring_space(a->replacements, b->replacements);
2263 }
2264 
2265 void
_define_object_macro(glcpp_parser_t * parser,YYLTYPE * loc,const char * identifier,token_list_t * replacements)2266 _define_object_macro(glcpp_parser_t *parser, YYLTYPE *loc,
2267                      const char *identifier, token_list_t *replacements)
2268 {
2269    macro_t *macro, *previous;
2270    struct hash_entry *entry;
2271 
2272    /* We define pre-defined macros before we've started parsing the actual
2273     * file. So if there's no location defined yet, that's what were doing and
2274     * we don't want to generate an error for using the reserved names. */
2275    if (loc != NULL)
2276       _check_for_reserved_macro_name(parser, loc, identifier);
2277 
2278    macro = linear_alloc_child(parser->linalloc, sizeof(macro_t));
2279 
2280    macro->is_function = 0;
2281    macro->parameters = NULL;
2282    macro->identifier = linear_strdup(parser->linalloc, identifier);
2283    macro->replacements = replacements;
2284 
2285    entry = _mesa_hash_table_search(parser->defines, identifier);
2286    previous = entry ? entry->data : NULL;
2287    if (previous) {
2288       if (_macro_equal (macro, previous)) {
2289          return;
2290       }
2291       glcpp_error (loc, parser, "Redefinition of macro %s\n",  identifier);
2292    }
2293 
2294    _mesa_hash_table_insert (parser->defines, identifier, macro);
2295 }
2296 
2297 void
_define_function_macro(glcpp_parser_t * parser,YYLTYPE * loc,const char * identifier,string_list_t * parameters,token_list_t * replacements)2298 _define_function_macro(glcpp_parser_t *parser, YYLTYPE *loc,
2299                        const char *identifier, string_list_t *parameters,
2300                        token_list_t *replacements)
2301 {
2302    macro_t *macro, *previous;
2303    struct hash_entry *entry;
2304    const char *dup;
2305 
2306    _check_for_reserved_macro_name(parser, loc, identifier);
2307 
2308         /* Check for any duplicate parameter names. */
2309    if ((dup = _string_list_has_duplicate (parameters)) != NULL) {
2310       glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"", dup);
2311    }
2312 
2313    macro = linear_alloc_child(parser->linalloc, sizeof(macro_t));
2314 
2315    macro->is_function = 1;
2316    macro->parameters = parameters;
2317    macro->identifier = linear_strdup(parser->linalloc, identifier);
2318    macro->replacements = replacements;
2319 
2320    entry = _mesa_hash_table_search(parser->defines, identifier);
2321    previous = entry ? entry->data : NULL;
2322    if (previous) {
2323       if (_macro_equal (macro, previous)) {
2324          return;
2325       }
2326       glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier);
2327    }
2328 
2329    _mesa_hash_table_insert(parser->defines, identifier, macro);
2330 }
2331 
2332 static int
glcpp_parser_lex(YYSTYPE * yylval,YYLTYPE * yylloc,glcpp_parser_t * parser)2333 glcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
2334 {
2335    token_node_t *node;
2336    int ret;
2337 
2338    if (parser->lex_from_list == NULL) {
2339       ret = glcpp_lex(yylval, yylloc, parser->scanner);
2340 
2341       /* XXX: This ugly block of code exists for the sole
2342        * purpose of converting a NEWLINE token into a SPACE
2343        * token, but only in the case where we have seen a
2344        * function-like macro name, but have not yet seen its
2345        * closing parenthesis.
2346        *
2347        * There's perhaps a more compact way to do this with
2348        * mid-rule actions in the grammar.
2349        *
2350        * I'm definitely not pleased with the complexity of
2351        * this code here.
2352        */
2353       if (parser->newline_as_space) {
2354          if (ret == '(') {
2355             parser->paren_count++;
2356          } else if (ret == ')') {
2357             parser->paren_count--;
2358             if (parser->paren_count == 0)
2359                parser->newline_as_space = 0;
2360          } else if (ret == NEWLINE) {
2361             ret = SPACE;
2362          } else if (ret != SPACE) {
2363             if (parser->paren_count == 0)
2364                parser->newline_as_space = 0;
2365          }
2366       } else if (parser->in_control_line) {
2367          if (ret == NEWLINE)
2368             parser->in_control_line = 0;
2369       }
2370       else if (ret == DEFINE_TOKEN || ret == UNDEF || ret == IF ||
2371                ret == IFDEF || ret == IFNDEF || ret == ELIF || ret == ELSE ||
2372                ret == ENDIF || ret == HASH_TOKEN) {
2373          parser->in_control_line = 1;
2374       } else if (ret == IDENTIFIER) {
2375          struct hash_entry *entry = _mesa_hash_table_search(parser->defines,
2376                                                             yylval->str);
2377          macro_t *macro = entry ? entry->data : NULL;
2378          if (macro && macro->is_function) {
2379             parser->newline_as_space = 1;
2380             parser->paren_count = 0;
2381          }
2382       }
2383 
2384       return ret;
2385    }
2386 
2387    node = parser->lex_from_node;
2388 
2389    if (node == NULL) {
2390       parser->lex_from_list = NULL;
2391       return NEWLINE;
2392    }
2393 
2394    *yylval = node->token->value;
2395    ret = node->token->type;
2396 
2397    parser->lex_from_node = node->next;
2398 
2399    return ret;
2400 }
2401 
2402 static void
glcpp_parser_lex_from(glcpp_parser_t * parser,token_list_t * list)2403 glcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list)
2404 {
2405    token_node_t *node;
2406 
2407    assert (parser->lex_from_list == NULL);
2408 
2409    /* Copy list, eliminating any space tokens. */
2410    parser->lex_from_list = _token_list_create (parser);
2411 
2412    for (node = list->head; node; node = node->next) {
2413       if (node->token->type == SPACE)
2414          continue;
2415       _token_list_append (parser,  parser->lex_from_list, node->token);
2416    }
2417 
2418    parser->lex_from_node = parser->lex_from_list->head;
2419 
2420    /* It's possible the list consisted of nothing but whitespace. */
2421    if (parser->lex_from_node == NULL) {
2422       parser->lex_from_list = NULL;
2423    }
2424 }
2425 
2426 static void
_glcpp_parser_skip_stack_push_if(glcpp_parser_t * parser,YYLTYPE * loc,int condition)2427 _glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc,
2428                                  int condition)
2429 {
2430    skip_type_t current = SKIP_NO_SKIP;
2431    skip_node_t *node;
2432 
2433    if (parser->skip_stack)
2434       current = parser->skip_stack->type;
2435 
2436    node = linear_alloc_child(parser->linalloc, sizeof(skip_node_t));
2437    node->loc = *loc;
2438 
2439    if (current == SKIP_NO_SKIP) {
2440       if (condition)
2441          node->type = SKIP_NO_SKIP;
2442       else
2443          node->type = SKIP_TO_ELSE;
2444    } else {
2445       node->type = SKIP_TO_ENDIF;
2446    }
2447 
2448    node->has_else = false;
2449    node->next = parser->skip_stack;
2450    parser->skip_stack = node;
2451 }
2452 
2453 static void
_glcpp_parser_skip_stack_change_if(glcpp_parser_t * parser,YYLTYPE * loc,const char * type,int condition)2454 _glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc,
2455                                    const char *type, int condition)
2456 {
2457    if (parser->skip_stack == NULL) {
2458       glcpp_error (loc, parser, "#%s without #if\n", type);
2459       return;
2460    }
2461 
2462    if (parser->skip_stack->type == SKIP_TO_ELSE) {
2463       if (condition)
2464          parser->skip_stack->type = SKIP_NO_SKIP;
2465    } else {
2466       parser->skip_stack->type = SKIP_TO_ENDIF;
2467    }
2468 }
2469 
2470 static void
_glcpp_parser_skip_stack_pop(glcpp_parser_t * parser,YYLTYPE * loc)2471 _glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc)
2472 {
2473    skip_node_t *node;
2474 
2475    if (parser->skip_stack == NULL) {
2476       glcpp_error (loc, parser, "#endif without #if\n");
2477       return;
2478    }
2479 
2480    node = parser->skip_stack;
2481    parser->skip_stack = node->next;
2482 }
2483 
2484 static void
_glcpp_parser_handle_version_declaration(glcpp_parser_t * parser,intmax_t version,const char * identifier,bool explicitly_set)2485 _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
2486                                          const char *identifier,
2487                                          bool explicitly_set)
2488 {
2489    if (parser->version_set)
2490       return;
2491 
2492    parser->version = version;
2493    parser->version_set = true;
2494 
2495    add_builtin_define (parser, "__VERSION__", version);
2496 
2497    parser->is_gles = (version == 100) ||
2498                      (identifier && (strcmp(identifier, "es") == 0));
2499    bool is_compat = version >= 150 && identifier &&
2500                     strcmp(identifier, "compatibility") == 0;
2501 
2502    /* Add pre-defined macros. */
2503    if (parser->is_gles)
2504       add_builtin_define(parser, "GL_ES", 1);
2505    else if (is_compat)
2506       add_builtin_define(parser, "GL_compatibility_profile", 1);
2507    else if (version >= 150)
2508       add_builtin_define(parser, "GL_core_profile", 1);
2509 
2510    /* Currently, all ES2/ES3 implementations support highp in the
2511     * fragment shader, so we always define this macro in ES2/ES3.
2512     * If we ever get a driver that doesn't support highp, we'll
2513     * need to add a flag to the gl_context and check that here.
2514     */
2515    if (version >= 130 || parser->is_gles)
2516       add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
2517 
2518    /* Add all the extension macros available in this context */
2519    if (parser->extensions)
2520       parser->extensions(parser->state, add_builtin_define, parser,
2521                          version, parser->is_gles);
2522 
2523    if (parser->extension_list) {
2524       /* If MESA_shader_integer_functions is supported, then the building
2525        * blocks required for the 64x64 => 64 multiply exist.  Add defines for
2526        * those functions so that they can be tested.
2527        */
2528       if (parser->extension_list->MESA_shader_integer_functions) {
2529          add_builtin_define(parser, "__have_builtin_builtin_udiv64", 1);
2530          add_builtin_define(parser, "__have_builtin_builtin_umod64", 1);
2531          add_builtin_define(parser, "__have_builtin_builtin_idiv64", 1);
2532          add_builtin_define(parser, "__have_builtin_builtin_imod64", 1);
2533       }
2534    }
2535 
2536    if (explicitly_set) {
2537       _mesa_string_buffer_printf(parser->output,
2538                                  "#version %" PRIiMAX "%s%s", version,
2539                                  identifier ? " " : "",
2540                                  identifier ? identifier : "");
2541    }
2542 }
2543 
2544 /* GLSL version if no version is explicitly specified. */
2545 #define IMPLICIT_GLSL_VERSION 110
2546 
2547 /* GLSL ES version if no version is explicitly specified. */
2548 #define IMPLICIT_GLSL_ES_VERSION 100
2549 
2550 void
glcpp_parser_resolve_implicit_version(glcpp_parser_t * parser)2551 glcpp_parser_resolve_implicit_version(glcpp_parser_t *parser)
2552 {
2553    int language_version = parser->api == API_OPENGLES2 ?
2554                           IMPLICIT_GLSL_ES_VERSION : IMPLICIT_GLSL_VERSION;
2555 
2556    _glcpp_parser_handle_version_declaration(parser, language_version,
2557                                             NULL, false);
2558 }
2559 
2560 static void
glcpp_parser_copy_defines(const void * key,void * data,void * closure)2561 glcpp_parser_copy_defines(const void *key, void *data, void *closure)
2562 {
2563    struct define_include *di = (struct define_include *) closure;
2564    macro_t *macro = (macro_t *) data;
2565 
2566    /* If we hit an error on a previous pass, just return */
2567    if (di->parser->error)
2568       return;
2569 
2570    const char *identifier =  macro->identifier;
2571    struct hash_entry *entry = _mesa_hash_table_search(di->parser->defines,
2572                                                       identifier);
2573 
2574    macro_t *previous = entry ? entry->data : NULL;
2575    if (previous) {
2576       if (_macro_equal(macro, previous)) {
2577          return;
2578       }
2579       glcpp_error(di->loc, di->parser, "Redefinition of macro %s\n",
2580                   identifier);
2581    }
2582 
2583    _mesa_hash_table_insert(di->parser->defines, identifier, macro);
2584 }
2585