• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 %{
2 /*
3  * Copyright © 2010 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <inttypes.h>
30 
31 #include "glcpp.h"
32 #include "main/core.h" /* for struct gl_extensions */
33 #include "main/mtypes.h" /* for gl_api enum */
34 
35 static void
36 yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
37 
38 static void
39 _define_object_macro (glcpp_parser_t *parser,
40 		      YYLTYPE *loc,
41 		      const char *macro,
42 		      token_list_t *replacements);
43 
44 static void
45 _define_function_macro (glcpp_parser_t *parser,
46 			YYLTYPE *loc,
47 			const char *macro,
48 			string_list_t *parameters,
49 			token_list_t *replacements);
50 
51 static string_list_t *
52 _string_list_create (void *ctx);
53 
54 static void
55 _string_list_append_item (string_list_t *list, const char *str);
56 
57 static int
58 _string_list_contains (string_list_t *list, const char *member, int *index);
59 
60 static int
61 _string_list_length (string_list_t *list);
62 
63 static int
64 _string_list_equal (string_list_t *a, string_list_t *b);
65 
66 static argument_list_t *
67 _argument_list_create (void *ctx);
68 
69 static void
70 _argument_list_append (argument_list_t *list, token_list_t *argument);
71 
72 static int
73 _argument_list_length (argument_list_t *list);
74 
75 static token_list_t *
76 _argument_list_member_at (argument_list_t *list, int index);
77 
78 /* Note: This function ralloc_steal()s the str pointer. */
79 static token_t *
80 _token_create_str (void *ctx, int type, char *str);
81 
82 static token_t *
83 _token_create_ival (void *ctx, int type, int ival);
84 
85 static token_list_t *
86 _token_list_create (void *ctx);
87 
88 static void
89 _token_list_append (token_list_t *list, token_t *token);
90 
91 static void
92 _token_list_append_list (token_list_t *list, token_list_t *tail);
93 
94 static int
95 _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
96 
97 static void
98 _parser_active_list_push (glcpp_parser_t *parser,
99 			  const char *identifier,
100 			  token_node_t *marker);
101 
102 static void
103 _parser_active_list_pop (glcpp_parser_t *parser);
104 
105 static int
106 _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier);
107 
108 /* Expand list, and begin lexing from the result (after first
109  * prefixing a token of type 'head_token_type').
110  */
111 static void
112 _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
113 				   int head_token_type,
114 				   token_list_t *list);
115 
116 /* Perform macro expansion in-place on the given list. */
117 static void
118 _glcpp_parser_expand_token_list (glcpp_parser_t *parser,
119 				 token_list_t *list);
120 
121 static void
122 _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
123 					 token_list_t *list);
124 
125 static void
126 _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
127 				  int condition);
128 
129 static void
130 _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
131 				    const char *type, int condition);
132 
133 static void
134 _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
135 
136 static int
137 glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
138 
139 static void
140 glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
141 
142 static void
143 add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
144 
145 %}
146 
147 %pure-parser
148 %error-verbose
149 
150 %locations
151 %initial-action {
152 	@$.first_line = 1;
153 	@$.first_column = 1;
154 	@$.last_line = 1;
155 	@$.last_column = 1;
156 	@$.source = 0;
157 }
158 
159 %parse-param {glcpp_parser_t *parser}
160 %lex-param {glcpp_parser_t *parser}
161 
162 %expect 0
163 %token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE
164 %token PASTE
165 %type <ival> expression INTEGER operator SPACE integer_constant
166 %type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER
167 %type <string_list> identifier_list
168 %type <token> preprocessing_token conditional_token
169 %type <token_list> pp_tokens replacement_list text_line conditional_tokens
170 %left OR
171 %left AND
172 %left '|'
173 %left '^'
174 %left '&'
175 %left EQUAL NOT_EQUAL
176 %left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
177 %left LEFT_SHIFT RIGHT_SHIFT
178 %left '+' '-'
179 %left '*' '/' '%'
180 %right UNARY
181 
182 %%
183 
184 input:
185 	/* empty */
186 |	input line
187 ;
188 
189 line:
190 	control_line {
191 		ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
192 	}
193 |	text_line {
194 		_glcpp_parser_print_expanded_token_list (parser, $1);
195 		ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
196 		ralloc_free ($1);
197 	}
198 |	expanded_line
199 |	HASH non_directive
200 ;
201 
202 expanded_line:
203 	IF_EXPANDED expression NEWLINE {
204 		_glcpp_parser_skip_stack_push_if (parser, & @1, $2);
205 	}
206 |	ELIF_EXPANDED expression NEWLINE {
207 		_glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2);
208 	}
209 |	LINE_EXPANDED integer_constant NEWLINE {
210 		parser->has_new_line_number = 1;
211 		parser->new_line_number = $2;
212 		ralloc_asprintf_rewrite_tail (&parser->output,
213 					      &parser->output_length,
214 					      "#line %" PRIiMAX "\n",
215 					      $2);
216 	}
217 |	LINE_EXPANDED integer_constant integer_constant NEWLINE {
218 		parser->has_new_line_number = 1;
219 		parser->new_line_number = $2;
220 		parser->has_new_source_number = 1;
221 		parser->new_source_number = $3;
222 		ralloc_asprintf_rewrite_tail (&parser->output,
223 					      &parser->output_length,
224 					      "#line %" PRIiMAX " %" PRIiMAX "\n",
225 					      $2, $3);
226 	}
227 ;
228 
229 control_line:
230 	HASH_DEFINE OBJ_IDENTIFIER replacement_list NEWLINE {
231 		_define_object_macro (parser, & @2, $2, $3);
232 	}
233 |	HASH_DEFINE FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE {
234 		_define_function_macro (parser, & @2, $2, NULL, $5);
235 	}
236 |	HASH_DEFINE FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
237 		_define_function_macro (parser, & @2, $2, $4, $6);
238 	}
239 |	HASH_UNDEF IDENTIFIER NEWLINE {
240 		macro_t *macro = hash_table_find (parser->defines, $2);
241 		if (macro) {
242 			hash_table_remove (parser->defines, $2);
243 			ralloc_free (macro);
244 		}
245 		ralloc_free ($2);
246 	}
247 |	HASH_LINE pp_tokens NEWLINE {
248 		if (parser->skip_stack == NULL ||
249 		    parser->skip_stack->type == SKIP_NO_SKIP)
250 		{
251 			_glcpp_parser_expand_and_lex_from (parser,
252 							   LINE_EXPANDED, $2);
253 		}
254 	}
255 |	HASH_IF conditional_tokens NEWLINE {
256 		/* Be careful to only evaluate the 'if' expression if
257 		 * we are not skipping. When we are skipping, we
258 		 * simply push a new 0-valued 'if' onto the skip
259 		 * stack.
260 		 *
261 		 * This avoids generating diagnostics for invalid
262 		 * expressions that are being skipped. */
263 		if (parser->skip_stack == NULL ||
264 		    parser->skip_stack->type == SKIP_NO_SKIP)
265 		{
266 			_glcpp_parser_expand_and_lex_from (parser,
267 							   IF_EXPANDED, $2);
268 		}
269 		else
270 		{
271 			_glcpp_parser_skip_stack_push_if (parser, & @1, 0);
272 			parser->skip_stack->type = SKIP_TO_ENDIF;
273 		}
274 	}
275 |	HASH_IF NEWLINE {
276 		/* #if without an expression is only an error if we
277 		 *  are not skipping */
278 		if (parser->skip_stack == NULL ||
279 		    parser->skip_stack->type == SKIP_NO_SKIP)
280 		{
281 			glcpp_error(& @1, parser, "#if with no expression");
282 		}
283 		_glcpp_parser_skip_stack_push_if (parser, & @1, 0);
284 	}
285 |	HASH_IFDEF IDENTIFIER junk NEWLINE {
286 		macro_t *macro = hash_table_find (parser->defines, $2);
287 		ralloc_free ($2);
288 		_glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
289 	}
290 |	HASH_IFNDEF IDENTIFIER junk NEWLINE {
291 		macro_t *macro = hash_table_find (parser->defines, $2);
292 		ralloc_free ($2);
293 		_glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
294 	}
295 |	HASH_ELIF conditional_tokens NEWLINE {
296 		/* Be careful to only evaluate the 'elif' expression
297 		 * if we are not skipping. When we are skipping, we
298 		 * simply change to a 0-valued 'elif' on the skip
299 		 * stack.
300 		 *
301 		 * This avoids generating diagnostics for invalid
302 		 * expressions that are being skipped. */
303 		if (parser->skip_stack &&
304 		    parser->skip_stack->type == SKIP_TO_ELSE)
305 		{
306 			_glcpp_parser_expand_and_lex_from (parser,
307 							   ELIF_EXPANDED, $2);
308 		}
309 		else
310 		{
311 			_glcpp_parser_skip_stack_change_if (parser, & @1,
312 							    "elif", 0);
313 		}
314 	}
315 |	HASH_ELIF NEWLINE {
316 		/* #elif without an expression is an error unless we
317 		 * are skipping. */
318 		if (parser->skip_stack &&
319 		    parser->skip_stack->type == SKIP_TO_ELSE)
320 		{
321 			glcpp_error(& @1, parser, "#elif with no expression");
322 		}
323 		else
324 		{
325 			_glcpp_parser_skip_stack_change_if (parser, & @1,
326 							    "elif", 0);
327 			glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
328 		}
329 	}
330 |	HASH_ELSE {
331 		_glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
332 	} NEWLINE
333 |	HASH_ENDIF {
334 		_glcpp_parser_skip_stack_pop (parser, & @1);
335 	} NEWLINE
336 |	HASH_VERSION integer_constant NEWLINE {
337 		macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
338 		if (macro) {
339 			hash_table_remove (parser->defines, "__VERSION__");
340 			ralloc_free (macro);
341 		}
342 		add_builtin_define (parser, "__VERSION__", $2);
343 
344 		if ($2 == 100)
345 			add_builtin_define (parser, "GL_ES", 1);
346 
347 		/* Currently, all ES2 implementations support highp in the
348 		 * fragment shader, so we always define this macro in ES2.
349 		 * If we ever get a driver that doesn't support highp, we'll
350 		 * need to add a flag to the gl_context and check that here.
351 		 */
352 		if ($2 >= 130 || $2 == 100)
353 			add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
354 
355 		ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#version %" PRIiMAX, $2);
356 	}
357 |	HASH NEWLINE
358 ;
359 
360 integer_constant:
361 	INTEGER_STRING {
362 		if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
363 			$$ = strtoll ($1 + 2, NULL, 16);
364 		} else if ($1[0] == '0') {
365 			$$ = strtoll ($1, NULL, 8);
366 		} else {
367 			$$ = strtoll ($1, NULL, 10);
368 		}
369 	}
370 |	INTEGER {
371 		$$ = $1;
372 	}
373 
374 expression:
375 	integer_constant
376 |	IDENTIFIER {
377 		$$ = 0;
378 	}
379 |	expression OR expression {
380 		$$ = $1 || $3;
381 	}
382 |	expression AND expression {
383 		$$ = $1 && $3;
384 	}
385 |	expression '|' expression {
386 		$$ = $1 | $3;
387 	}
388 |	expression '^' expression {
389 		$$ = $1 ^ $3;
390 	}
391 |	expression '&' expression {
392 		$$ = $1 & $3;
393 	}
394 |	expression NOT_EQUAL expression {
395 		$$ = $1 != $3;
396 	}
397 |	expression EQUAL expression {
398 		$$ = $1 == $3;
399 	}
400 |	expression GREATER_OR_EQUAL expression {
401 		$$ = $1 >= $3;
402 	}
403 |	expression LESS_OR_EQUAL expression {
404 		$$ = $1 <= $3;
405 	}
406 |	expression '>' expression {
407 		$$ = $1 > $3;
408 	}
409 |	expression '<' expression {
410 		$$ = $1 < $3;
411 	}
412 |	expression RIGHT_SHIFT expression {
413 		$$ = $1 >> $3;
414 	}
415 |	expression LEFT_SHIFT expression {
416 		$$ = $1 << $3;
417 	}
418 |	expression '-' expression {
419 		$$ = $1 - $3;
420 	}
421 |	expression '+' expression {
422 		$$ = $1 + $3;
423 	}
424 |	expression '%' expression {
425 		if ($3 == 0) {
426 			yyerror (& @1, parser,
427 				 "zero modulus in preprocessor directive");
428 		} else {
429 			$$ = $1 % $3;
430 		}
431 	}
432 |	expression '/' expression {
433 		if ($3 == 0) {
434 			yyerror (& @1, parser,
435 				 "division by 0 in preprocessor directive");
436 		} else {
437 			$$ = $1 / $3;
438 		}
439 	}
440 |	expression '*' expression {
441 		$$ = $1 * $3;
442 	}
443 |	'!' expression %prec UNARY {
444 		$$ = ! $2;
445 	}
446 |	'~' expression %prec UNARY {
447 		$$ = ~ $2;
448 	}
449 |	'-' expression %prec UNARY {
450 		$$ = - $2;
451 	}
452 |	'+' expression %prec UNARY {
453 		$$ = + $2;
454 	}
455 |	'(' expression ')' {
456 		$$ = $2;
457 	}
458 ;
459 
460 identifier_list:
461 	IDENTIFIER {
462 		$$ = _string_list_create (parser);
463 		_string_list_append_item ($$, $1);
464 		ralloc_steal ($$, $1);
465 	}
466 |	identifier_list ',' IDENTIFIER {
467 		$$ = $1;
468 		_string_list_append_item ($$, $3);
469 		ralloc_steal ($$, $3);
470 	}
471 ;
472 
473 text_line:
474 	NEWLINE { $$ = NULL; }
475 |	pp_tokens NEWLINE
476 ;
477 
478 non_directive:
479 	pp_tokens NEWLINE {
480 		yyerror (& @1, parser, "Invalid tokens after #");
481 	}
482 ;
483 
484 replacement_list:
485 	/* empty */ { $$ = NULL; }
486 |	pp_tokens
487 ;
488 
489 junk:
490 	/* empty */
491 |	pp_tokens {
492 		glcpp_warning(&@1, parser, "extra tokens at end of directive");
493 	}
494 ;
495 
496 conditional_token:
497 	/* Handle "defined" operator */
498 	DEFINED IDENTIFIER {
499 		int v = hash_table_find (parser->defines, $2) ? 1 : 0;
500 		$$ = _token_create_ival (parser, INTEGER, v);
501 	}
502 |	DEFINED '(' IDENTIFIER ')' {
503 		int v = hash_table_find (parser->defines, $3) ? 1 : 0;
504 		$$ = _token_create_ival (parser, INTEGER, v);
505 	}
506 |	preprocessing_token
507 ;
508 
509 conditional_tokens:
510 	/* Exactly the same as pp_tokens, but using conditional_token */
511 	conditional_token {
512 		$$ = _token_list_create (parser);
513 		_token_list_append ($$, $1);
514 	}
515 |	conditional_tokens conditional_token {
516 		$$ = $1;
517 		_token_list_append ($$, $2);
518 	}
519 ;
520 
521 pp_tokens:
522 	preprocessing_token {
523 		parser->space_tokens = 1;
524 		$$ = _token_list_create (parser);
525 		_token_list_append ($$, $1);
526 	}
527 |	pp_tokens preprocessing_token {
528 		$$ = $1;
529 		_token_list_append ($$, $2);
530 	}
531 ;
532 
533 preprocessing_token:
534 	IDENTIFIER {
535 		$$ = _token_create_str (parser, IDENTIFIER, $1);
536 		$$->location = yylloc;
537 	}
538 |	INTEGER_STRING {
539 		$$ = _token_create_str (parser, INTEGER_STRING, $1);
540 		$$->location = yylloc;
541 	}
542 |	operator {
543 		$$ = _token_create_ival (parser, $1, $1);
544 		$$->location = yylloc;
545 	}
546 |	OTHER {
547 		$$ = _token_create_str (parser, OTHER, $1);
548 		$$->location = yylloc;
549 	}
550 |	SPACE {
551 		$$ = _token_create_ival (parser, SPACE, SPACE);
552 		$$->location = yylloc;
553 	}
554 ;
555 
556 operator:
557 	'['			{ $$ = '['; }
558 |	']'			{ $$ = ']'; }
559 |	'('			{ $$ = '('; }
560 |	')'			{ $$ = ')'; }
561 |	'{'			{ $$ = '{'; }
562 |	'}'			{ $$ = '}'; }
563 |	'.'			{ $$ = '.'; }
564 |	'&'			{ $$ = '&'; }
565 |	'*'			{ $$ = '*'; }
566 |	'+'			{ $$ = '+'; }
567 |	'-'			{ $$ = '-'; }
568 |	'~'			{ $$ = '~'; }
569 |	'!'			{ $$ = '!'; }
570 |	'/'			{ $$ = '/'; }
571 |	'%'			{ $$ = '%'; }
572 |	LEFT_SHIFT		{ $$ = LEFT_SHIFT; }
573 |	RIGHT_SHIFT		{ $$ = RIGHT_SHIFT; }
574 |	'<'			{ $$ = '<'; }
575 |	'>'			{ $$ = '>'; }
576 |	LESS_OR_EQUAL		{ $$ = LESS_OR_EQUAL; }
577 |	GREATER_OR_EQUAL	{ $$ = GREATER_OR_EQUAL; }
578 |	EQUAL			{ $$ = EQUAL; }
579 |	NOT_EQUAL		{ $$ = NOT_EQUAL; }
580 |	'^'			{ $$ = '^'; }
581 |	'|'			{ $$ = '|'; }
582 |	AND			{ $$ = AND; }
583 |	OR			{ $$ = OR; }
584 |	';'			{ $$ = ';'; }
585 |	','			{ $$ = ','; }
586 |	'='			{ $$ = '='; }
587 |	PASTE			{ $$ = PASTE; }
588 ;
589 
590 %%
591 
592 string_list_t *
593 _string_list_create (void *ctx)
594 {
595 	string_list_t *list;
596 
597 	list = ralloc (ctx, string_list_t);
598 	list->head = NULL;
599 	list->tail = NULL;
600 
601 	return list;
602 }
603 
604 void
_string_list_append_item(string_list_t * list,const char * str)605 _string_list_append_item (string_list_t *list, const char *str)
606 {
607 	string_node_t *node;
608 
609 	node = ralloc (list, string_node_t);
610 	node->str = ralloc_strdup (node, str);
611 
612 	node->next = NULL;
613 
614 	if (list->head == NULL) {
615 		list->head = node;
616 	} else {
617 		list->tail->next = node;
618 	}
619 
620 	list->tail = node;
621 }
622 
623 int
_string_list_contains(string_list_t * list,const char * member,int * index)624 _string_list_contains (string_list_t *list, const char *member, int *index)
625 {
626 	string_node_t *node;
627 	int i;
628 
629 	if (list == NULL)
630 		return 0;
631 
632 	for (i = 0, node = list->head; node; i++, node = node->next) {
633 		if (strcmp (node->str, member) == 0) {
634 			if (index)
635 				*index = i;
636 			return 1;
637 		}
638 	}
639 
640 	return 0;
641 }
642 
643 int
_string_list_length(string_list_t * list)644 _string_list_length (string_list_t *list)
645 {
646 	int length = 0;
647 	string_node_t *node;
648 
649 	if (list == NULL)
650 		return 0;
651 
652 	for (node = list->head; node; node = node->next)
653 		length++;
654 
655 	return length;
656 }
657 
658 int
_string_list_equal(string_list_t * a,string_list_t * b)659 _string_list_equal (string_list_t *a, string_list_t *b)
660 {
661 	string_node_t *node_a, *node_b;
662 
663 	if (a == NULL && b == NULL)
664 		return 1;
665 
666 	if (a == NULL || b == NULL)
667 		return 0;
668 
669 	for (node_a = a->head, node_b = b->head;
670 	     node_a && node_b;
671 	     node_a = node_a->next, node_b = node_b->next)
672 	{
673 		if (strcmp (node_a->str, node_b->str))
674 			return 0;
675 	}
676 
677 	/* Catch the case of lists being different lengths, (which
678 	 * would cause the loop above to terminate after the shorter
679 	 * list). */
680 	return node_a == node_b;
681 }
682 
683 argument_list_t *
_argument_list_create(void * ctx)684 _argument_list_create (void *ctx)
685 {
686 	argument_list_t *list;
687 
688 	list = ralloc (ctx, argument_list_t);
689 	list->head = NULL;
690 	list->tail = NULL;
691 
692 	return list;
693 }
694 
695 void
_argument_list_append(argument_list_t * list,token_list_t * argument)696 _argument_list_append (argument_list_t *list, token_list_t *argument)
697 {
698 	argument_node_t *node;
699 
700 	node = ralloc (list, argument_node_t);
701 	node->argument = argument;
702 
703 	node->next = NULL;
704 
705 	if (list->head == NULL) {
706 		list->head = node;
707 	} else {
708 		list->tail->next = node;
709 	}
710 
711 	list->tail = node;
712 }
713 
714 int
_argument_list_length(argument_list_t * list)715 _argument_list_length (argument_list_t *list)
716 {
717 	int length = 0;
718 	argument_node_t *node;
719 
720 	if (list == NULL)
721 		return 0;
722 
723 	for (node = list->head; node; node = node->next)
724 		length++;
725 
726 	return length;
727 }
728 
729 token_list_t *
_argument_list_member_at(argument_list_t * list,int index)730 _argument_list_member_at (argument_list_t *list, int index)
731 {
732 	argument_node_t *node;
733 	int i;
734 
735 	if (list == NULL)
736 		return NULL;
737 
738 	node = list->head;
739 	for (i = 0; i < index; i++) {
740 		node = node->next;
741 		if (node == NULL)
742 			break;
743 	}
744 
745 	if (node)
746 		return node->argument;
747 
748 	return NULL;
749 }
750 
751 /* Note: This function ralloc_steal()s the str pointer. */
752 token_t *
_token_create_str(void * ctx,int type,char * str)753 _token_create_str (void *ctx, int type, char *str)
754 {
755 	token_t *token;
756 
757 	token = ralloc (ctx, token_t);
758 	token->type = type;
759 	token->value.str = str;
760 
761 	ralloc_steal (token, str);
762 
763 	return token;
764 }
765 
766 token_t *
_token_create_ival(void * ctx,int type,int ival)767 _token_create_ival (void *ctx, int type, int ival)
768 {
769 	token_t *token;
770 
771 	token = ralloc (ctx, token_t);
772 	token->type = type;
773 	token->value.ival = ival;
774 
775 	return token;
776 }
777 
778 token_list_t *
_token_list_create(void * ctx)779 _token_list_create (void *ctx)
780 {
781 	token_list_t *list;
782 
783 	list = ralloc (ctx, token_list_t);
784 	list->head = NULL;
785 	list->tail = NULL;
786 	list->non_space_tail = NULL;
787 
788 	return list;
789 }
790 
791 void
_token_list_append(token_list_t * list,token_t * token)792 _token_list_append (token_list_t *list, token_t *token)
793 {
794 	token_node_t *node;
795 
796 	node = ralloc (list, token_node_t);
797 	node->token = token;
798 	node->next = NULL;
799 
800 	if (list->head == NULL) {
801 		list->head = node;
802 	} else {
803 		list->tail->next = node;
804 	}
805 
806 	list->tail = node;
807 	if (token->type != SPACE)
808 		list->non_space_tail = node;
809 }
810 
811 void
_token_list_append_list(token_list_t * list,token_list_t * tail)812 _token_list_append_list (token_list_t *list, token_list_t *tail)
813 {
814 	if (tail == NULL || tail->head == NULL)
815 		return;
816 
817 	if (list->head == NULL) {
818 		list->head = tail->head;
819 	} else {
820 		list->tail->next = tail->head;
821 	}
822 
823 	list->tail = tail->tail;
824 	list->non_space_tail = tail->non_space_tail;
825 }
826 
827 static token_list_t *
_token_list_copy(void * ctx,token_list_t * other)828 _token_list_copy (void *ctx, token_list_t *other)
829 {
830 	token_list_t *copy;
831 	token_node_t *node;
832 
833 	if (other == NULL)
834 		return NULL;
835 
836 	copy = _token_list_create (ctx);
837 	for (node = other->head; node; node = node->next) {
838 		token_t *new_token = ralloc (copy, token_t);
839 		*new_token = *node->token;
840 		_token_list_append (copy, new_token);
841 	}
842 
843 	return copy;
844 }
845 
846 static void
_token_list_trim_trailing_space(token_list_t * list)847 _token_list_trim_trailing_space (token_list_t *list)
848 {
849 	token_node_t *tail, *next;
850 
851 	if (list->non_space_tail) {
852 		tail = list->non_space_tail->next;
853 		list->non_space_tail->next = NULL;
854 		list->tail = list->non_space_tail;
855 
856 		while (tail) {
857 			next = tail->next;
858 			ralloc_free (tail);
859 			tail = next;
860 		}
861 	}
862 }
863 
864 static int
_token_list_is_empty_ignoring_space(token_list_t * l)865 _token_list_is_empty_ignoring_space (token_list_t *l)
866 {
867 	token_node_t *n;
868 
869 	if (l == NULL)
870 		return 1;
871 
872 	n = l->head;
873 	while (n != NULL && n->token->type == SPACE)
874 		n = n->next;
875 
876 	return n == NULL;
877 }
878 
879 int
_token_list_equal_ignoring_space(token_list_t * a,token_list_t * b)880 _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
881 {
882 	token_node_t *node_a, *node_b;
883 
884 	if (a == NULL || b == NULL) {
885 		int a_empty = _token_list_is_empty_ignoring_space(a);
886 		int b_empty = _token_list_is_empty_ignoring_space(b);
887 		return a_empty == b_empty;
888 	}
889 
890 	node_a = a->head;
891 	node_b = b->head;
892 
893 	while (1)
894 	{
895 		if (node_a == NULL && node_b == NULL)
896 			break;
897 
898 		if (node_a == NULL || node_b == NULL)
899 			return 0;
900 
901 		if (node_a->token->type == SPACE) {
902 			node_a = node_a->next;
903 			continue;
904 		}
905 
906 		if (node_b->token->type == SPACE) {
907 			node_b = node_b->next;
908 			continue;
909 		}
910 
911 		if (node_a->token->type != node_b->token->type)
912 			return 0;
913 
914 		switch (node_a->token->type) {
915 		case INTEGER:
916 			if (node_a->token->value.ival !=
917 			    node_b->token->value.ival)
918 			{
919 				return 0;
920 			}
921 			break;
922 		case IDENTIFIER:
923 		case INTEGER_STRING:
924 		case OTHER:
925 			if (strcmp (node_a->token->value.str,
926 				    node_b->token->value.str))
927 			{
928 				return 0;
929 			}
930 			break;
931 		}
932 
933 		node_a = node_a->next;
934 		node_b = node_b->next;
935 	}
936 
937 	return 1;
938 }
939 
940 static void
_token_print(char ** out,size_t * len,token_t * token)941 _token_print (char **out, size_t *len, token_t *token)
942 {
943 	if (token->type < 256) {
944 		ralloc_asprintf_rewrite_tail (out, len, "%c", token->type);
945 		return;
946 	}
947 
948 	switch (token->type) {
949 	case INTEGER:
950 		ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival);
951 		break;
952 	case IDENTIFIER:
953 	case INTEGER_STRING:
954 	case OTHER:
955 		ralloc_asprintf_rewrite_tail (out, len, "%s", token->value.str);
956 		break;
957 	case SPACE:
958 		ralloc_asprintf_rewrite_tail (out, len, " ");
959 		break;
960 	case LEFT_SHIFT:
961 		ralloc_asprintf_rewrite_tail (out, len, "<<");
962 		break;
963 	case RIGHT_SHIFT:
964 		ralloc_asprintf_rewrite_tail (out, len, ">>");
965 		break;
966 	case LESS_OR_EQUAL:
967 		ralloc_asprintf_rewrite_tail (out, len, "<=");
968 		break;
969 	case GREATER_OR_EQUAL:
970 		ralloc_asprintf_rewrite_tail (out, len, ">=");
971 		break;
972 	case EQUAL:
973 		ralloc_asprintf_rewrite_tail (out, len, "==");
974 		break;
975 	case NOT_EQUAL:
976 		ralloc_asprintf_rewrite_tail (out, len, "!=");
977 		break;
978 	case AND:
979 		ralloc_asprintf_rewrite_tail (out, len, "&&");
980 		break;
981 	case OR:
982 		ralloc_asprintf_rewrite_tail (out, len, "||");
983 		break;
984 	case PASTE:
985 		ralloc_asprintf_rewrite_tail (out, len, "##");
986 		break;
987 	case COMMA_FINAL:
988 		ralloc_asprintf_rewrite_tail (out, len, ",");
989 		break;
990 	case PLACEHOLDER:
991 		/* Nothing to print. */
992 		break;
993 	default:
994 		assert(!"Error: Don't know how to print token.");
995 		break;
996 	}
997 }
998 
999 /* Return a new token (ralloc()ed off of 'token') formed by pasting
1000  * 'token' and 'other'. Note that this function may return 'token' or
1001  * 'other' directly rather than allocating anything new.
1002  *
1003  * Caution: Only very cursory error-checking is performed to see if
1004  * the final result is a valid single token. */
1005 static token_t *
_token_paste(glcpp_parser_t * parser,token_t * token,token_t * other)1006 _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
1007 {
1008 	token_t *combined = NULL;
1009 
1010 	/* Pasting a placeholder onto anything makes no change. */
1011 	if (other->type == PLACEHOLDER)
1012 		return token;
1013 
1014 	/* When 'token' is a placeholder, just return 'other'. */
1015 	if (token->type == PLACEHOLDER)
1016 		return other;
1017 
1018 	/* A very few single-character punctuators can be combined
1019 	 * with another to form a multi-character punctuator. */
1020 	switch (token->type) {
1021 	case '<':
1022 		if (other->type == '<')
1023 			combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
1024 		else if (other->type == '=')
1025 			combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
1026 		break;
1027 	case '>':
1028 		if (other->type == '>')
1029 			combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
1030 		else if (other->type == '=')
1031 			combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
1032 		break;
1033 	case '=':
1034 		if (other->type == '=')
1035 			combined = _token_create_ival (token, EQUAL, EQUAL);
1036 		break;
1037 	case '!':
1038 		if (other->type == '=')
1039 			combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
1040 		break;
1041 	case '&':
1042 		if (other->type == '&')
1043 			combined = _token_create_ival (token, AND, AND);
1044 		break;
1045 	case '|':
1046 		if (other->type == '|')
1047 			combined = _token_create_ival (token, OR, OR);
1048 		break;
1049 	}
1050 
1051 	if (combined != NULL) {
1052 		/* Inherit the location from the first token */
1053 		combined->location = token->location;
1054 		return combined;
1055 	}
1056 
1057 	/* Two string-valued tokens can usually just be mashed
1058 	 * together.
1059 	 *
1060 	 * XXX: This isn't actually legitimate. Several things here
1061 	 * should result in a diagnostic since the result cannot be a
1062 	 * valid, single pre-processing token. For example, pasting
1063 	 * "123" and "abc" is not legal, but we don't catch that
1064 	 * here. */
1065 	if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
1066 	    (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
1067 	{
1068 		char *str;
1069 
1070 		str = ralloc_asprintf (token, "%s%s", token->value.str,
1071 				       other->value.str);
1072 		combined = _token_create_str (token, token->type, str);
1073 		combined->location = token->location;
1074 		return combined;
1075 	}
1076 
1077 	glcpp_error (&token->location, parser, "");
1078 	ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \"");
1079 	_token_print (&parser->info_log, &parser->info_log_length, token);
1080 	ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" and \"");
1081 	_token_print (&parser->info_log, &parser->info_log_length, other);
1082 	ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" does not give a valid preprocessing token.\n");
1083 
1084 	return token;
1085 }
1086 
1087 static void
_token_list_print(glcpp_parser_t * parser,token_list_t * list)1088 _token_list_print (glcpp_parser_t *parser, token_list_t *list)
1089 {
1090 	token_node_t *node;
1091 
1092 	if (list == NULL)
1093 		return;
1094 
1095 	for (node = list->head; node; node = node->next)
1096 		_token_print (&parser->output, &parser->output_length, node->token);
1097 }
1098 
1099 void
yyerror(YYLTYPE * locp,glcpp_parser_t * parser,const char * error)1100 yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
1101 {
1102 	glcpp_error(locp, parser, "%s", error);
1103 }
1104 
add_builtin_define(glcpp_parser_t * parser,const char * name,int value)1105 static void add_builtin_define(glcpp_parser_t *parser,
1106 			       const char *name, int value)
1107 {
1108    token_t *tok;
1109    token_list_t *list;
1110 
1111    tok = _token_create_ival (parser, INTEGER, value);
1112 
1113    list = _token_list_create(parser);
1114    _token_list_append(list, tok);
1115    _define_object_macro(parser, NULL, name, list);
1116 }
1117 
1118 glcpp_parser_t *
glcpp_parser_create(const struct gl_extensions * extensions,int api)1119 glcpp_parser_create (const struct gl_extensions *extensions, int api)
1120 {
1121 	glcpp_parser_t *parser;
1122 	int language_version;
1123 
1124 	parser = ralloc (NULL, glcpp_parser_t);
1125 
1126 	glcpp_lex_init_extra (parser, &parser->scanner);
1127 	parser->defines = hash_table_ctor (32, hash_table_string_hash,
1128 					   hash_table_string_compare);
1129 	parser->active = NULL;
1130 	parser->lexing_if = 0;
1131 	parser->space_tokens = 1;
1132 	parser->newline_as_space = 0;
1133 	parser->in_control_line = 0;
1134 	parser->paren_count = 0;
1135 
1136 	parser->skip_stack = NULL;
1137 
1138 	parser->lex_from_list = NULL;
1139 	parser->lex_from_node = NULL;
1140 
1141 	parser->output = ralloc_strdup(parser, "");
1142 	parser->output_length = 0;
1143 	parser->info_log = ralloc_strdup(parser, "");
1144 	parser->info_log_length = 0;
1145 	parser->error = 0;
1146 
1147 	parser->has_new_line_number = 0;
1148 	parser->new_line_number = 1;
1149 	parser->has_new_source_number = 0;
1150 	parser->new_source_number = 0;
1151 
1152 	/* Add pre-defined macros. */
1153 	add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
1154 	add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
1155 
1156 	if (api == API_OPENGLES2)
1157 		add_builtin_define(parser, "GL_ES", 1);
1158 
1159 	if (extensions != NULL) {
1160 	   if (extensions->EXT_texture_array) {
1161 	      add_builtin_define(parser, "GL_EXT_texture_array", 1);
1162 	   }
1163 
1164 	   if (extensions->ARB_fragment_coord_conventions)
1165 	      add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
1166 				 1);
1167 
1168 	   if (extensions->ARB_explicit_attrib_location)
1169 	      add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
1170 
1171 	   if (extensions->ARB_shader_texture_lod)
1172 	      add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1);
1173 
1174 	   if (extensions->ARB_draw_instanced)
1175 	      add_builtin_define(parser, "GL_ARB_draw_instanced", 1);
1176 
1177 	   if (extensions->ARB_conservative_depth) {
1178 	      add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
1179 	      add_builtin_define(parser, "GL_ARB_conservative_depth", 1);
1180 	   }
1181 
1182 	   if (extensions->OES_EGL_image_external)
1183 	      add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
1184 
1185 	   if (extensions->ARB_shader_bit_encoding)
1186 	      add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1);
1187 
1188 	   if (extensions->ARB_uniform_buffer_object)
1189 	      add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1);
1190 	}
1191 
1192 	language_version = 110;
1193 	add_builtin_define(parser, "__VERSION__", language_version);
1194 
1195 	return parser;
1196 }
1197 
1198 void
glcpp_parser_destroy(glcpp_parser_t * parser)1199 glcpp_parser_destroy (glcpp_parser_t *parser)
1200 {
1201 	glcpp_lex_destroy (parser->scanner);
1202 	hash_table_dtor (parser->defines);
1203 	ralloc_free (parser);
1204 }
1205 
1206 typedef enum function_status
1207 {
1208 	FUNCTION_STATUS_SUCCESS,
1209 	FUNCTION_NOT_A_FUNCTION,
1210 	FUNCTION_UNBALANCED_PARENTHESES
1211 } function_status_t;
1212 
1213 /* Find a set of function-like macro arguments by looking for a
1214  * balanced set of parentheses.
1215  *
1216  * When called, 'node' should be the opening-parenthesis token, (or
1217  * perhaps preceeding SPACE tokens). Upon successful return *last will
1218  * be the last consumed node, (corresponding to the closing right
1219  * parenthesis).
1220  *
1221  * Return values:
1222  *
1223  *   FUNCTION_STATUS_SUCCESS:
1224  *
1225  *	Successfully parsed a set of function arguments.
1226  *
1227  *   FUNCTION_NOT_A_FUNCTION:
1228  *
1229  *	Macro name not followed by a '('. This is not an error, but
1230  *	simply that the macro name should be treated as a non-macro.
1231  *
1232  *   FUNCTION_UNBALANCED_PARENTHESES
1233  *
1234  *	Macro name is not followed by a balanced set of parentheses.
1235  */
1236 static function_status_t
_arguments_parse(argument_list_t * arguments,token_node_t * node,token_node_t ** last)1237 _arguments_parse (argument_list_t *arguments,
1238 		  token_node_t *node,
1239 		  token_node_t **last)
1240 {
1241 	token_list_t *argument;
1242 	int paren_count;
1243 
1244 	node = node->next;
1245 
1246 	/* Ignore whitespace before first parenthesis. */
1247 	while (node && node->token->type == SPACE)
1248 		node = node->next;
1249 
1250 	if (node == NULL || node->token->type != '(')
1251 		return FUNCTION_NOT_A_FUNCTION;
1252 
1253 	node = node->next;
1254 
1255 	argument = _token_list_create (arguments);
1256 	_argument_list_append (arguments, argument);
1257 
1258 	for (paren_count = 1; node; node = node->next) {
1259 		if (node->token->type == '(')
1260 		{
1261 			paren_count++;
1262 		}
1263 		else if (node->token->type == ')')
1264 		{
1265 			paren_count--;
1266 			if (paren_count == 0)
1267 				break;
1268 		}
1269 
1270 		if (node->token->type == ',' &&
1271 			 paren_count == 1)
1272 		{
1273 			_token_list_trim_trailing_space (argument);
1274 			argument = _token_list_create (arguments);
1275 			_argument_list_append (arguments, argument);
1276 		}
1277 		else {
1278 			if (argument->head == NULL) {
1279 				/* Don't treat initial whitespace as
1280 				 * part of the arguement. */
1281 				if (node->token->type == SPACE)
1282 					continue;
1283 			}
1284 			_token_list_append (argument, node->token);
1285 		}
1286 	}
1287 
1288 	if (paren_count)
1289 		return FUNCTION_UNBALANCED_PARENTHESES;
1290 
1291 	*last = node;
1292 
1293 	return FUNCTION_STATUS_SUCCESS;
1294 }
1295 
1296 static token_list_t *
_token_list_create_with_one_space(void * ctx)1297 _token_list_create_with_one_space (void *ctx)
1298 {
1299 	token_list_t *list;
1300 	token_t *space;
1301 
1302 	list = _token_list_create (ctx);
1303 	space = _token_create_ival (list, SPACE, SPACE);
1304 	_token_list_append (list, space);
1305 
1306 	return list;
1307 }
1308 
1309 /* Perform macro expansion on 'list', placing the resulting tokens
1310  * into a new list which is initialized with a first token of type
1311  * 'head_token_type'. Then begin lexing from the resulting list,
1312  * (return to the current lexing source when this list is exhausted).
1313  */
1314 static void
_glcpp_parser_expand_and_lex_from(glcpp_parser_t * parser,int head_token_type,token_list_t * list)1315 _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
1316 				   int head_token_type,
1317 				   token_list_t *list)
1318 {
1319 	token_list_t *expanded;
1320 	token_t *token;
1321 
1322 	expanded = _token_list_create (parser);
1323 	token = _token_create_ival (parser, head_token_type, head_token_type);
1324 	_token_list_append (expanded, token);
1325 	_glcpp_parser_expand_token_list (parser, list);
1326 	_token_list_append_list (expanded, list);
1327 	glcpp_parser_lex_from (parser, expanded);
1328 }
1329 
1330 static void
_glcpp_parser_apply_pastes(glcpp_parser_t * parser,token_list_t * list)1331 _glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list)
1332 {
1333 	token_node_t *node;
1334 
1335 	node = list->head;
1336 	while (node)
1337 	{
1338 		token_node_t *next_non_space;
1339 
1340 		/* Look ahead for a PASTE token, skipping space. */
1341 		next_non_space = node->next;
1342 		while (next_non_space && next_non_space->token->type == SPACE)
1343 			next_non_space = next_non_space->next;
1344 
1345 		if (next_non_space == NULL)
1346 			break;
1347 
1348 		if (next_non_space->token->type != PASTE) {
1349 			node = next_non_space;
1350 			continue;
1351 		}
1352 
1353 		/* Now find the next non-space token after the PASTE. */
1354 		next_non_space = next_non_space->next;
1355 		while (next_non_space && next_non_space->token->type == SPACE)
1356 			next_non_space = next_non_space->next;
1357 
1358 		if (next_non_space == NULL) {
1359 			yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
1360 			return;
1361 		}
1362 
1363 		node->token = _token_paste (parser, node->token, next_non_space->token);
1364 		node->next = next_non_space->next;
1365 		if (next_non_space == list->tail)
1366 			list->tail = node;
1367 	}
1368 
1369 	list->non_space_tail = list->tail;
1370 }
1371 
1372 /* This is a helper function that's essentially part of the
1373  * implementation of _glcpp_parser_expand_node. It shouldn't be called
1374  * except for by that function.
1375  *
1376  * Returns NULL if node is a simple token with no expansion, (that is,
1377  * although 'node' corresponds to an identifier defined as a
1378  * function-like macro, it is not followed with a parenthesized
1379  * argument list).
1380  *
1381  * Compute the complete expansion of node (which is a function-like
1382  * macro) and subsequent nodes which are arguments.
1383  *
1384  * Returns the token list that results from the expansion and sets
1385  * *last to the last node in the list that was consumed by the
1386  * expansion. Specifically, *last will be set as follows: as the
1387  * token of the closing right parenthesis.
1388  */
1389 static token_list_t *
_glcpp_parser_expand_function(glcpp_parser_t * parser,token_node_t * node,token_node_t ** last)1390 _glcpp_parser_expand_function (glcpp_parser_t *parser,
1391 			       token_node_t *node,
1392 			       token_node_t **last)
1393 
1394 {
1395 	macro_t *macro;
1396 	const char *identifier;
1397 	argument_list_t *arguments;
1398 	function_status_t status;
1399 	token_list_t *substituted;
1400 	int parameter_index;
1401 
1402 	identifier = node->token->value.str;
1403 
1404 	macro = hash_table_find (parser->defines, identifier);
1405 
1406 	assert (macro->is_function);
1407 
1408 	arguments = _argument_list_create (parser);
1409 	status = _arguments_parse (arguments, node, last);
1410 
1411 	switch (status) {
1412 	case FUNCTION_STATUS_SUCCESS:
1413 		break;
1414 	case FUNCTION_NOT_A_FUNCTION:
1415 		return NULL;
1416 	case FUNCTION_UNBALANCED_PARENTHESES:
1417 		glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
1418 		return NULL;
1419 	}
1420 
1421 	/* Replace a macro defined as empty with a SPACE token. */
1422 	if (macro->replacements == NULL) {
1423 		ralloc_free (arguments);
1424 		return _token_list_create_with_one_space (parser);
1425 	}
1426 
1427 	if (! ((_argument_list_length (arguments) ==
1428 		_string_list_length (macro->parameters)) ||
1429 	       (_string_list_length (macro->parameters) == 0 &&
1430 		_argument_list_length (arguments) == 1 &&
1431 		arguments->head->argument->head == NULL)))
1432 	{
1433 		glcpp_error (&node->token->location, parser,
1434 			      "Error: macro %s invoked with %d arguments (expected %d)\n",
1435 			      identifier,
1436 			      _argument_list_length (arguments),
1437 			      _string_list_length (macro->parameters));
1438 		return NULL;
1439 	}
1440 
1441 	/* Perform argument substitution on the replacement list. */
1442 	substituted = _token_list_create (arguments);
1443 
1444 	for (node = macro->replacements->head; node; node = node->next)
1445 	{
1446 		if (node->token->type == IDENTIFIER &&
1447 		    _string_list_contains (macro->parameters,
1448 					   node->token->value.str,
1449 					   &parameter_index))
1450 		{
1451 			token_list_t *argument;
1452 			argument = _argument_list_member_at (arguments,
1453 							     parameter_index);
1454 			/* Before substituting, we expand the argument
1455 			 * tokens, or append a placeholder token for
1456 			 * an empty argument. */
1457 			if (argument->head) {
1458 				token_list_t *expanded_argument;
1459 				expanded_argument = _token_list_copy (parser,
1460 								      argument);
1461 				_glcpp_parser_expand_token_list (parser,
1462 								 expanded_argument);
1463 				_token_list_append_list (substituted,
1464 							 expanded_argument);
1465 			} else {
1466 				token_t *new_token;
1467 
1468 				new_token = _token_create_ival (substituted,
1469 								PLACEHOLDER,
1470 								PLACEHOLDER);
1471 				_token_list_append (substituted, new_token);
1472 			}
1473 		} else {
1474 			_token_list_append (substituted, node->token);
1475 		}
1476 	}
1477 
1478 	/* After argument substitution, and before further expansion
1479 	 * below, implement token pasting. */
1480 
1481 	_token_list_trim_trailing_space (substituted);
1482 
1483 	_glcpp_parser_apply_pastes (parser, substituted);
1484 
1485 	return substituted;
1486 }
1487 
1488 /* Compute the complete expansion of node, (and subsequent nodes after
1489  * 'node' in the case that 'node' is a function-like macro and
1490  * subsequent nodes are arguments).
1491  *
1492  * Returns NULL if node is a simple token with no expansion.
1493  *
1494  * Otherwise, returns the token list that results from the expansion
1495  * and sets *last to the last node in the list that was consumed by
1496  * the expansion. Specifically, *last will be set as follows:
1497  *
1498  *	As 'node' in the case of object-like macro expansion.
1499  *
1500  *	As the token of the closing right parenthesis in the case of
1501  *	function-like macro expansion.
1502  */
1503 static token_list_t *
_glcpp_parser_expand_node(glcpp_parser_t * parser,token_node_t * node,token_node_t ** last)1504 _glcpp_parser_expand_node (glcpp_parser_t *parser,
1505 			   token_node_t *node,
1506 			   token_node_t **last)
1507 {
1508 	token_t *token = node->token;
1509 	const char *identifier;
1510 	macro_t *macro;
1511 
1512 	/* We only expand identifiers */
1513 	if (token->type != IDENTIFIER) {
1514 		/* We change any COMMA into a COMMA_FINAL to prevent
1515 		 * it being mistaken for an argument separator
1516 		 * later. */
1517 		if (token->type == ',') {
1518 			token->type = COMMA_FINAL;
1519 			token->value.ival = COMMA_FINAL;
1520 		}
1521 
1522 		return NULL;
1523 	}
1524 
1525 	/* Look up this identifier in the hash table. */
1526 	identifier = token->value.str;
1527 	macro = hash_table_find (parser->defines, identifier);
1528 
1529 	/* Not a macro, so no expansion needed. */
1530 	if (macro == NULL)
1531 		return NULL;
1532 
1533 	/* Finally, don't expand this macro if we're already actively
1534 	 * expanding it, (to avoid infinite recursion). */
1535 	if (_parser_active_list_contains (parser, identifier)) {
1536 		/* We change the token type here from IDENTIFIER to
1537 		 * OTHER to prevent any future expansion of this
1538 		 * unexpanded token. */
1539 		char *str;
1540 		token_list_t *expansion;
1541 		token_t *final;
1542 
1543 		str = ralloc_strdup (parser, token->value.str);
1544 		final = _token_create_str (parser, OTHER, str);
1545 		expansion = _token_list_create (parser);
1546 		_token_list_append (expansion, final);
1547 		*last = node;
1548 		return expansion;
1549 	}
1550 
1551 	if (! macro->is_function)
1552 	{
1553 		token_list_t *replacement;
1554 		*last = node;
1555 
1556 		/* Replace a macro defined as empty with a SPACE token. */
1557 		if (macro->replacements == NULL)
1558 			return _token_list_create_with_one_space (parser);
1559 
1560 		replacement = _token_list_copy (parser, macro->replacements);
1561 		_glcpp_parser_apply_pastes (parser, replacement);
1562 		return replacement;
1563 	}
1564 
1565 	return _glcpp_parser_expand_function (parser, node, last);
1566 }
1567 
1568 /* Push a new identifier onto the parser's active list.
1569  *
1570  * Here, 'marker' is the token node that appears in the list after the
1571  * expansion of 'identifier'. That is, when the list iterator begins
1572  * examining 'marker', then it is time to pop this node from the
1573  * active stack.
1574  */
1575 static void
_parser_active_list_push(glcpp_parser_t * parser,const char * identifier,token_node_t * marker)1576 _parser_active_list_push (glcpp_parser_t *parser,
1577 			  const char *identifier,
1578 			  token_node_t *marker)
1579 {
1580 	active_list_t *node;
1581 
1582 	node = ralloc (parser->active, active_list_t);
1583 	node->identifier = ralloc_strdup (node, identifier);
1584 	node->marker = marker;
1585 	node->next = parser->active;
1586 
1587 	parser->active = node;
1588 }
1589 
1590 static void
_parser_active_list_pop(glcpp_parser_t * parser)1591 _parser_active_list_pop (glcpp_parser_t *parser)
1592 {
1593 	active_list_t *node = parser->active;
1594 
1595 	if (node == NULL) {
1596 		parser->active = NULL;
1597 		return;
1598 	}
1599 
1600 	node = parser->active->next;
1601 	ralloc_free (parser->active);
1602 
1603 	parser->active = node;
1604 }
1605 
1606 static int
_parser_active_list_contains(glcpp_parser_t * parser,const char * identifier)1607 _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier)
1608 {
1609 	active_list_t *node;
1610 
1611 	if (parser->active == NULL)
1612 		return 0;
1613 
1614 	for (node = parser->active; node; node = node->next)
1615 		if (strcmp (node->identifier, identifier) == 0)
1616 			return 1;
1617 
1618 	return 0;
1619 }
1620 
1621 /* Walk over the token list replacing nodes with their expansion.
1622  * Whenever nodes are expanded the walking will walk over the new
1623  * nodes, continuing to expand as necessary. The results are placed in
1624  * 'list' itself;
1625  */
1626 static void
_glcpp_parser_expand_token_list(glcpp_parser_t * parser,token_list_t * list)1627 _glcpp_parser_expand_token_list (glcpp_parser_t *parser,
1628 				 token_list_t *list)
1629 {
1630 	token_node_t *node_prev;
1631 	token_node_t *node, *last = NULL;
1632 	token_list_t *expansion;
1633 	active_list_t *active_initial = parser->active;
1634 
1635 	if (list == NULL)
1636 		return;
1637 
1638 	_token_list_trim_trailing_space (list);
1639 
1640 	node_prev = NULL;
1641 	node = list->head;
1642 
1643 	while (node) {
1644 
1645 		while (parser->active && parser->active->marker == node)
1646 			_parser_active_list_pop (parser);
1647 
1648 		expansion = _glcpp_parser_expand_node (parser, node, &last);
1649 		if (expansion) {
1650 			token_node_t *n;
1651 
1652 			for (n = node; n != last->next; n = n->next)
1653 				while (parser->active &&
1654 				       parser->active->marker == n)
1655 				{
1656 					_parser_active_list_pop (parser);
1657 				}
1658 
1659 			_parser_active_list_push (parser,
1660 						  node->token->value.str,
1661 						  last->next);
1662 
1663 			/* Splice expansion into list, supporting a
1664 			 * simple deletion if the expansion is
1665 			 * empty. */
1666 			if (expansion->head) {
1667 				if (node_prev)
1668 					node_prev->next = expansion->head;
1669 				else
1670 					list->head = expansion->head;
1671 				expansion->tail->next = last->next;
1672 				if (last == list->tail)
1673 					list->tail = expansion->tail;
1674 			} else {
1675 				if (node_prev)
1676 					node_prev->next = last->next;
1677 				else
1678 					list->head = last->next;
1679 				if (last == list->tail)
1680 					list->tail = NULL;
1681 			}
1682 		} else {
1683 			node_prev = node;
1684 		}
1685 		node = node_prev ? node_prev->next : list->head;
1686 	}
1687 
1688 	/* Remove any lingering effects of this invocation on the
1689 	 * active list. That is, pop until the list looks like it did
1690 	 * at the beginning of this function. */
1691 	while (parser->active && parser->active != active_initial)
1692 		_parser_active_list_pop (parser);
1693 
1694 	list->non_space_tail = list->tail;
1695 }
1696 
1697 void
_glcpp_parser_print_expanded_token_list(glcpp_parser_t * parser,token_list_t * list)1698 _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
1699 					 token_list_t *list)
1700 {
1701 	if (list == NULL)
1702 		return;
1703 
1704 	_glcpp_parser_expand_token_list (parser, list);
1705 
1706 	_token_list_trim_trailing_space (list);
1707 
1708 	_token_list_print (parser, list);
1709 }
1710 
1711 static void
_check_for_reserved_macro_name(glcpp_parser_t * parser,YYLTYPE * loc,const char * identifier)1712 _check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
1713 				const char *identifier)
1714 {
1715 	/* According to the GLSL specification, macro names starting with "__"
1716 	 * or "GL_" are reserved for future use.  So, don't allow them.
1717 	 */
1718 	if (strstr(identifier, "__")) {
1719 		glcpp_error (loc, parser, "Macro names containing \"__\" are reserved.\n");
1720 	}
1721 	if (strncmp(identifier, "GL_", 3) == 0) {
1722 		glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
1723 	}
1724 }
1725 
1726 static int
_macro_equal(macro_t * a,macro_t * b)1727 _macro_equal (macro_t *a, macro_t *b)
1728 {
1729 	if (a->is_function != b->is_function)
1730 		return 0;
1731 
1732 	if (a->is_function) {
1733 		if (! _string_list_equal (a->parameters, b->parameters))
1734 			return 0;
1735 	}
1736 
1737 	return _token_list_equal_ignoring_space (a->replacements,
1738 						 b->replacements);
1739 }
1740 
1741 void
_define_object_macro(glcpp_parser_t * parser,YYLTYPE * loc,const char * identifier,token_list_t * replacements)1742 _define_object_macro (glcpp_parser_t *parser,
1743 		      YYLTYPE *loc,
1744 		      const char *identifier,
1745 		      token_list_t *replacements)
1746 {
1747 	macro_t *macro, *previous;
1748 
1749 	if (loc != NULL)
1750 		_check_for_reserved_macro_name(parser, loc, identifier);
1751 
1752 	macro = ralloc (parser, macro_t);
1753 
1754 	macro->is_function = 0;
1755 	macro->parameters = NULL;
1756 	macro->identifier = ralloc_strdup (macro, identifier);
1757 	macro->replacements = replacements;
1758 	ralloc_steal (macro, replacements);
1759 
1760 	previous = hash_table_find (parser->defines, identifier);
1761 	if (previous) {
1762 		if (_macro_equal (macro, previous)) {
1763 			ralloc_free (macro);
1764 			return;
1765 		}
1766 		glcpp_error (loc, parser, "Redefinition of macro %s\n",
1767 			     identifier);
1768 	}
1769 
1770 	hash_table_insert (parser->defines, macro, identifier);
1771 }
1772 
1773 void
_define_function_macro(glcpp_parser_t * parser,YYLTYPE * loc,const char * identifier,string_list_t * parameters,token_list_t * replacements)1774 _define_function_macro (glcpp_parser_t *parser,
1775 			YYLTYPE *loc,
1776 			const char *identifier,
1777 			string_list_t *parameters,
1778 			token_list_t *replacements)
1779 {
1780 	macro_t *macro, *previous;
1781 
1782 	_check_for_reserved_macro_name(parser, loc, identifier);
1783 
1784 	macro = ralloc (parser, macro_t);
1785 	ralloc_steal (macro, parameters);
1786 	ralloc_steal (macro, replacements);
1787 
1788 	macro->is_function = 1;
1789 	macro->parameters = parameters;
1790 	macro->identifier = ralloc_strdup (macro, identifier);
1791 	macro->replacements = replacements;
1792 	previous = hash_table_find (parser->defines, identifier);
1793 	if (previous) {
1794 		if (_macro_equal (macro, previous)) {
1795 			ralloc_free (macro);
1796 			return;
1797 		}
1798 		glcpp_error (loc, parser, "Redefinition of macro %s\n",
1799 			     identifier);
1800 	}
1801 
1802 	hash_table_insert (parser->defines, macro, identifier);
1803 }
1804 
1805 static int
glcpp_parser_lex(YYSTYPE * yylval,YYLTYPE * yylloc,glcpp_parser_t * parser)1806 glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
1807 {
1808 	token_node_t *node;
1809 	int ret;
1810 
1811 	if (parser->lex_from_list == NULL) {
1812 		ret = glcpp_lex (yylval, yylloc, parser->scanner);
1813 
1814 		/* XXX: This ugly block of code exists for the sole
1815 		 * purpose of converting a NEWLINE token into a SPACE
1816 		 * token, but only in the case where we have seen a
1817 		 * function-like macro name, but have not yet seen its
1818 		 * closing parenthesis.
1819 		 *
1820 		 * There's perhaps a more compact way to do this with
1821 		 * mid-rule actions in the grammar.
1822 		 *
1823 		 * I'm definitely not pleased with the complexity of
1824 		 * this code here.
1825 		 */
1826 		if (parser->newline_as_space)
1827 		{
1828 			if (ret == '(') {
1829 				parser->paren_count++;
1830 			} else if (ret == ')') {
1831 				parser->paren_count--;
1832 				if (parser->paren_count == 0)
1833 					parser->newline_as_space = 0;
1834 			} else if (ret == NEWLINE) {
1835 				ret = SPACE;
1836 			} else if (ret != SPACE) {
1837 				if (parser->paren_count == 0)
1838 					parser->newline_as_space = 0;
1839 			}
1840 		}
1841 		else if (parser->in_control_line)
1842 		{
1843 			if (ret == NEWLINE)
1844 				parser->in_control_line = 0;
1845 		}
1846 		else if (ret == HASH_DEFINE ||
1847 			   ret == HASH_UNDEF || ret == HASH_IF ||
1848 			   ret == HASH_IFDEF || ret == HASH_IFNDEF ||
1849 			   ret == HASH_ELIF || ret == HASH_ELSE ||
1850 			   ret == HASH_ENDIF || ret == HASH)
1851 		{
1852 			parser->in_control_line = 1;
1853 		}
1854 		else if (ret == IDENTIFIER)
1855 		{
1856 			macro_t *macro;
1857 			macro = hash_table_find (parser->defines,
1858 						 yylval->str);
1859 			if (macro && macro->is_function) {
1860 				parser->newline_as_space = 1;
1861 				parser->paren_count = 0;
1862 			}
1863 		}
1864 
1865 		return ret;
1866 	}
1867 
1868 	node = parser->lex_from_node;
1869 
1870 	if (node == NULL) {
1871 		ralloc_free (parser->lex_from_list);
1872 		parser->lex_from_list = NULL;
1873 		return NEWLINE;
1874 	}
1875 
1876 	*yylval = node->token->value;
1877 	ret = node->token->type;
1878 
1879 	parser->lex_from_node = node->next;
1880 
1881 	return ret;
1882 }
1883 
1884 static void
glcpp_parser_lex_from(glcpp_parser_t * parser,token_list_t * list)1885 glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
1886 {
1887 	token_node_t *node;
1888 
1889 	assert (parser->lex_from_list == NULL);
1890 
1891 	/* Copy list, eliminating any space tokens. */
1892 	parser->lex_from_list = _token_list_create (parser);
1893 
1894 	for (node = list->head; node; node = node->next) {
1895 		if (node->token->type == SPACE)
1896 			continue;
1897 		_token_list_append (parser->lex_from_list, node->token);
1898 	}
1899 
1900 	ralloc_free (list);
1901 
1902 	parser->lex_from_node = parser->lex_from_list->head;
1903 
1904 	/* It's possible the list consisted of nothing but whitespace. */
1905 	if (parser->lex_from_node == NULL) {
1906 		ralloc_free (parser->lex_from_list);
1907 		parser->lex_from_list = NULL;
1908 	}
1909 }
1910 
1911 static void
_glcpp_parser_skip_stack_push_if(glcpp_parser_t * parser,YYLTYPE * loc,int condition)1912 _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
1913 				  int condition)
1914 {
1915 	skip_type_t current = SKIP_NO_SKIP;
1916 	skip_node_t *node;
1917 
1918 	if (parser->skip_stack)
1919 		current = parser->skip_stack->type;
1920 
1921 	node = ralloc (parser, skip_node_t);
1922 	node->loc = *loc;
1923 
1924 	if (current == SKIP_NO_SKIP) {
1925 		if (condition)
1926 			node->type = SKIP_NO_SKIP;
1927 		else
1928 			node->type = SKIP_TO_ELSE;
1929 	} else {
1930 		node->type = SKIP_TO_ENDIF;
1931 	}
1932 
1933 	node->next = parser->skip_stack;
1934 	parser->skip_stack = node;
1935 }
1936 
1937 static void
_glcpp_parser_skip_stack_change_if(glcpp_parser_t * parser,YYLTYPE * loc,const char * type,int condition)1938 _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
1939 				    const char *type, int condition)
1940 {
1941 	if (parser->skip_stack == NULL) {
1942 		glcpp_error (loc, parser, "%s without #if\n", type);
1943 		return;
1944 	}
1945 
1946 	if (parser->skip_stack->type == SKIP_TO_ELSE) {
1947 		if (condition)
1948 			parser->skip_stack->type = SKIP_NO_SKIP;
1949 	} else {
1950 		parser->skip_stack->type = SKIP_TO_ENDIF;
1951 	}
1952 }
1953 
1954 static void
_glcpp_parser_skip_stack_pop(glcpp_parser_t * parser,YYLTYPE * loc)1955 _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
1956 {
1957 	skip_node_t *node;
1958 
1959 	if (parser->skip_stack == NULL) {
1960 		glcpp_error (loc, parser, "#endif without #if\n");
1961 		return;
1962 	}
1963 
1964 	node = parser->skip_stack;
1965 	parser->skip_stack = node->next;
1966 	ralloc_free (node);
1967 }
1968