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