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