glsl: pass GLcontext::Extension info down into GLSL preprocessor
[mesa.git] / src / mesa / shader / slang / slang_preprocess.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_preprocess.c
27 * slang preprocessor
28 * \author Michal Krol
29 */
30
31 #include "main/imports.h"
32 #include "shader/grammar/grammar_mesa.h"
33 #include "slang_preprocess.h"
34
35 LONGSTRING static const char *slang_pp_directives_syn =
36 #include "library/slang_pp_directives_syn.h"
37 ;
38
39 LONGSTRING static const char *slang_pp_expression_syn =
40 #include "library/slang_pp_expression_syn.h"
41 ;
42
43 LONGSTRING static const char *slang_pp_version_syn =
44 #include "library/slang_pp_version_syn.h"
45 ;
46
47 static GLvoid
48 grammar_error_to_log (slang_info_log *log)
49 {
50 char buf[1024];
51 GLint pos;
52
53 grammar_get_last_error ((byte *) (buf), sizeof (buf), &pos);
54 slang_info_log_error (log, buf);
55 }
56
57 GLboolean
58 _slang_preprocess_version (const char *text, GLuint *version, GLuint *eaten, slang_info_log *log)
59 {
60 grammar id;
61 byte *prod, *I;
62 unsigned int size;
63
64 id = grammar_load_from_text ((const byte *) (slang_pp_version_syn));
65 if (id == 0) {
66 grammar_error_to_log (log);
67 return GL_FALSE;
68 }
69
70 if (!grammar_fast_check (id, (const byte *) (text), &prod, &size, 8)) {
71 grammar_error_to_log (log);
72 grammar_destroy (id);
73 return GL_FALSE;
74 }
75
76 /* there can be multiple #version directives - grab the last one */
77 I = &prod[size - 6];
78 *version = (GLuint) (I[0]) + (GLuint) (I[1]) * 100;
79 *eaten = (GLuint) (I[2]) + ((GLuint) (I[3]) << 8) + ((GLuint) (I[4]) << 16) + ((GLuint) (I[5]) << 24);
80
81 grammar_destroy (id);
82 grammar_alloc_free (prod);
83 return GL_TRUE;
84 }
85
86 /*
87 * The preprocessor does the following work.
88 * 1. Remove comments. Each comment block is replaced with a single space and if the
89 * block contains new-lines, they are preserved. This ensures that line numbers
90 * stay the same and if a comment block delimits two tokens, the are delitmited
91 * by the space after comment removal.
92 * 2. Remove preprocessor directives from the source string, checking their syntax and
93 * executing them if appropriate. Again, new-lines are preserved.
94 * 3. Expand macros.
95 * 4. Tokenize the source string by ensuring there is at least one space between every
96 * two adjacent tokens.
97 */
98
99 #define PP_ANNOTATE 0
100
101 static GLvoid
102 pp_annotate (slang_string *output, const char *fmt, ...)
103 {
104 #if PP_ANNOTATE
105 va_list va;
106 char buffer[1024];
107
108 va_start (va, fmt);
109 _mesa_vsprintf (buffer, fmt, va);
110 va_end (va);
111 slang_string_pushs (output, buffer, _mesa_strlen (buffer));
112 #else
113 (GLvoid) (output);
114 (GLvoid) (fmt);
115 #endif
116 }
117
118 /*
119 * The expression is executed on a fixed-sized stack. The PUSH macro makes a runtime
120 * check if the stack is not overflown by too complex expressions. In that situation the
121 * GLSL preprocessor should report internal compiler error.
122 * The BINARYDIV makes a runtime check if the divider is not 0. If it is, it reports
123 * compilation error.
124 */
125
126 #define EXECUTION_STACK_SIZE 1024
127
128 #define PUSH(x)\
129 do {\
130 if (sp == 0) {\
131 slang_info_log_error (elog, "internal compiler error: preprocessor execution stack overflow.");\
132 return GL_FALSE;\
133 }\
134 stack[--sp] = x;\
135 } while (GL_FALSE)
136
137 #define POP(x)\
138 do {\
139 assert (sp < EXECUTION_STACK_SIZE);\
140 x = stack[sp++];\
141 } while (GL_FALSE)
142
143 #define BINARY(op)\
144 do {\
145 GLint a, b;\
146 POP(b);\
147 POP(a);\
148 PUSH(a op b);\
149 } while (GL_FALSE)
150
151 #define BINARYDIV(op)\
152 do {\
153 GLint a, b;\
154 POP(b);\
155 POP(a);\
156 if (b == 0) {\
157 slang_info_log_error (elog, "division by zero in preprocessor expression.");\
158 return GL_FALSE;\
159 }\
160 PUSH(a op b);\
161 } while (GL_FALSE)
162
163 #define UNARY(op)\
164 do {\
165 GLint a;\
166 POP(a);\
167 PUSH(op a);\
168 } while (GL_FALSE)
169
170 #define OP_END 0
171 #define OP_PUSHINT 1
172 #define OP_LOGICALOR 2
173 #define OP_LOGICALAND 3
174 #define OP_OR 4
175 #define OP_XOR 5
176 #define OP_AND 6
177 #define OP_EQUAL 7
178 #define OP_NOTEQUAL 8
179 #define OP_LESSEQUAL 9
180 #define OP_GREATEREQUAL 10
181 #define OP_LESS 11
182 #define OP_GREATER 12
183 #define OP_LEFTSHIFT 13
184 #define OP_RIGHTSHIFT 14
185 #define OP_ADD 15
186 #define OP_SUBTRACT 16
187 #define OP_MULTIPLY 17
188 #define OP_DIVIDE 18
189 #define OP_MODULUS 19
190 #define OP_PLUS 20
191 #define OP_MINUS 21
192 #define OP_NEGATE 22
193 #define OP_COMPLEMENT 23
194
195 static GLboolean
196 execute_expression (slang_string *output, const byte *code, GLuint *pi, GLint *result,
197 slang_info_log *elog)
198 {
199 GLuint i = *pi;
200 GLint stack[EXECUTION_STACK_SIZE];
201 GLuint sp = EXECUTION_STACK_SIZE;
202
203 while (code[i] != OP_END) {
204 switch (code[i++]) {
205 case OP_PUSHINT:
206 i++;
207 PUSH(_mesa_atoi ((const char *) (&code[i])));
208 i += _mesa_strlen ((const char *) (&code[i])) + 1;
209 break;
210 case OP_LOGICALOR:
211 BINARY(||);
212 break;
213 case OP_LOGICALAND:
214 BINARY(&&);
215 break;
216 case OP_OR:
217 BINARY(|);
218 break;
219 case OP_XOR:
220 BINARY(^);
221 break;
222 case OP_AND:
223 BINARY(&);
224 break;
225 case OP_EQUAL:
226 BINARY(==);
227 break;
228 case OP_NOTEQUAL:
229 BINARY(!=);
230 break;
231 case OP_LESSEQUAL:
232 BINARY(<=);
233 break;
234 case OP_GREATEREQUAL:
235 BINARY(>=);
236 break;
237 case OP_LESS:
238 BINARY(<);
239 break;
240 case OP_GREATER:
241 BINARY(>);
242 break;
243 case OP_LEFTSHIFT:
244 BINARY(<<);
245 break;
246 case OP_RIGHTSHIFT:
247 BINARY(>>);
248 break;
249 case OP_ADD:
250 BINARY(+);
251 break;
252 case OP_SUBTRACT:
253 BINARY(-);
254 break;
255 case OP_MULTIPLY:
256 BINARY(*);
257 break;
258 case OP_DIVIDE:
259 BINARYDIV(/);
260 break;
261 case OP_MODULUS:
262 BINARYDIV(%);
263 break;
264 case OP_PLUS:
265 UNARY(+);
266 break;
267 case OP_MINUS:
268 UNARY(-);
269 break;
270 case OP_NEGATE:
271 UNARY(!);
272 break;
273 case OP_COMPLEMENT:
274 UNARY(~);
275 break;
276 default:
277 assert (0);
278 }
279 }
280
281 /* Write-back the index skipping the OP_END. */
282 *pi = i + 1;
283
284 /* There should be exactly one value left on the stack. This is our result. */
285 POP(*result);
286 pp_annotate (output, "%d ", *result);
287 assert (sp == EXECUTION_STACK_SIZE);
288 return GL_TRUE;
289 }
290
291 /*
292 * Function execute_expressions() executes up to 2 expressions. The second expression is there
293 * for the #line directive which takes 1 or 2 expressions that indicate line and file numbers.
294 * If it fails, it returns 0. If it succeeds, it returns the number of executed expressions.
295 */
296
297 #define EXP_END 0
298 #define EXP_EXPRESSION 1
299
300 static GLuint
301 execute_expressions (slang_string *output, grammar eid, const byte *expr, GLint results[2],
302 slang_info_log *elog)
303 {
304 GLint success;
305 byte *code;
306 GLuint size, count = 0;
307
308 success = grammar_fast_check (eid, expr, &code, &size, 64);
309 if (success) {
310 GLuint i = 0;
311
312 while (code[i++] == EXP_EXPRESSION) {
313 assert (count < 2);
314
315 if (!execute_expression (output, code, &i, &results[count], elog)) {
316 count = 0;
317 break;
318 }
319 count++;
320 }
321 grammar_alloc_free (code);
322 }
323 else {
324 slang_info_log_error (elog, "syntax error in preprocessor expression.");\
325 }
326 return count;
327 }
328
329 /*
330 * The pp_symbol structure is used to hold macro definitions and macro formal parameters. The
331 * pp_symbols strcture is a collection of pp_symbol. It is used both for storing macro formal
332 * parameters and all global macro definitions. Making this unification wastes some memory,
333 * becuse macro formal parameters don't need further lists of symbols. We lose 8 bytes per
334 * formal parameter here, but making this we can use the same code to substitute macro parameters
335 * as well as macros in the source string.
336 */
337
338 typedef struct
339 {
340 struct pp_symbol_ *symbols;
341 GLuint count;
342 } pp_symbols;
343
344 static GLvoid
345 pp_symbols_init (pp_symbols *self)
346 {
347 self->symbols = NULL;
348 self->count = 0;
349 }
350
351 static GLvoid
352 pp_symbols_free (pp_symbols *);
353
354 typedef struct pp_symbol_
355 {
356 slang_string name;
357 slang_string replacement;
358 pp_symbols parameters;
359 } pp_symbol;
360
361 static GLvoid
362 pp_symbol_init (pp_symbol *self)
363 {
364 slang_string_init (&self->name);
365 slang_string_init (&self->replacement);
366 pp_symbols_init (&self->parameters);
367 }
368
369 static GLvoid
370 pp_symbol_free (pp_symbol *self)
371 {
372 slang_string_free (&self->name);
373 slang_string_free (&self->replacement);
374 pp_symbols_free (&self->parameters);
375 }
376
377 static GLvoid
378 pp_symbol_reset (pp_symbol *self)
379 {
380 /* Leave symbol name intact. */
381 slang_string_reset (&self->replacement);
382 pp_symbols_free (&self->parameters);
383 pp_symbols_init (&self->parameters);
384 }
385
386 static GLvoid
387 pp_symbols_free (pp_symbols *self)
388 {
389 GLuint i;
390
391 for (i = 0; i < self->count; i++)
392 pp_symbol_free (&self->symbols[i]);
393 _mesa_free (self->symbols);
394 }
395
396 static pp_symbol *
397 pp_symbols_push (pp_symbols *self)
398 {
399 self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, self->count * sizeof (pp_symbol),
400 (self->count + 1) * sizeof (pp_symbol)));
401 if (self->symbols == NULL)
402 return NULL;
403 pp_symbol_init (&self->symbols[self->count]);
404 return &self->symbols[self->count++];
405 }
406
407 static GLboolean
408 pp_symbols_erase (pp_symbols *self, pp_symbol *symbol)
409 {
410 assert (symbol >= self->symbols && symbol < self->symbols + self->count);
411
412 self->count--;
413 pp_symbol_free (symbol);
414 if (symbol < self->symbols + self->count)
415 _mesa_memcpy (symbol, symbol + 1, sizeof (pp_symbol) * (self->symbols + self->count - symbol));
416 self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, (self->count + 1) * sizeof (pp_symbol),
417 self->count * sizeof (pp_symbol)));
418 return self->symbols != NULL;
419 }
420
421 static pp_symbol *
422 pp_symbols_find (pp_symbols *self, const char *name)
423 {
424 GLuint i;
425
426 for (i = 0; i < self->count; i++)
427 if (_mesa_strcmp (name, slang_string_cstr (&self->symbols[i].name)) == 0)
428 return &self->symbols[i];
429 return NULL;
430 }
431
432 /*
433 * The condition context of a single #if/#else/#endif level. Those can be nested, so there
434 * is a stack of condition contexts.
435 * There is a special global context on the bottom of the stack. It is there to simplify
436 * context handling.
437 */
438
439 typedef struct
440 {
441 GLboolean current; /* The condition value of this level. */
442 GLboolean effective; /* The effective product of current condition, outer level conditions
443 * and position within #if-#else-#endif sections. */
444 GLboolean else_allowed; /* TRUE if in #if-#else section, FALSE if in #else-#endif section
445 * and for global context. */
446 GLboolean endif_required; /* FALSE for global context only. */
447 } pp_cond_ctx;
448
449 /* Should be enuff. */
450 #define CONDITION_STACK_SIZE 64
451
452 typedef struct
453 {
454 pp_cond_ctx stack[CONDITION_STACK_SIZE];
455 pp_cond_ctx *top;
456 } pp_cond_stack;
457
458 static GLboolean
459 pp_cond_stack_push (pp_cond_stack *self, slang_info_log *elog)
460 {
461 if (self->top == self->stack) {
462 slang_info_log_error (elog, "internal compiler error: preprocessor condition stack overflow.");
463 return GL_FALSE;
464 }
465 self->top--;
466 return GL_TRUE;
467 }
468
469 static GLvoid
470 pp_cond_stack_reevaluate (pp_cond_stack *self)
471 {
472 /* There must be at least 2 conditions on the stack - one global and one being evaluated. */
473 assert (self->top <= &self->stack[CONDITION_STACK_SIZE - 2]);
474
475 self->top->effective = self->top->current && self->top[1].effective;
476 }
477
478
479 /**
480 * Extension enables through #extension directive.
481 * NOTE: Currently, only enable/disable state is stored.
482 */
483 typedef struct
484 {
485 GLboolean ARB_draw_buffers;
486 GLboolean ARB_texture_rectangle;
487 } pp_ext;
488
489
490 /**
491 * Disable all extensions. Called at startup and on #extension all: disable.
492 */
493 static GLvoid
494 pp_ext_disable_all(pp_ext *self)
495 {
496 _mesa_memset(self, 0, sizeof(self));
497 }
498
499
500 /**
501 * Called during preprocessor initialization to set the initial enable/disable
502 * state of extensions.
503 */
504 static GLvoid
505 pp_ext_init(pp_ext *self, const struct gl_extensions *extensions)
506 {
507 pp_ext_disable_all (self);
508 if (extensions->ARB_draw_buffers)
509 self->ARB_draw_buffers = GL_TRUE;
510 if (extensions->NV_texture_rectangle)
511 self->ARB_texture_rectangle = GL_TRUE;
512 }
513
514 /**
515 * Called in response to #extension directives to enable/disable
516 * the named extension.
517 */
518 static GLboolean
519 pp_ext_set(pp_ext *self, const char *name, GLboolean enable)
520 {
521 if (_mesa_strcmp (name, "GL_ARB_draw_buffers") == 0)
522 self->ARB_draw_buffers = enable;
523 else if (_mesa_strcmp (name, "GL_ARB_texture_rectangle") == 0)
524 self->ARB_texture_rectangle = enable;
525 else
526 return GL_FALSE;
527 return GL_TRUE;
528 }
529
530
531 /**
532 * The state of preprocessor: current line, file and version number, list
533 * of all defined macros and the #if/#endif context.
534 */
535 typedef struct
536 {
537 GLint line;
538 GLint file;
539 GLint version;
540 pp_symbols symbols;
541 pp_ext ext;
542 slang_info_log *elog;
543 pp_cond_stack cond;
544 } pp_state;
545
546 static GLvoid
547 pp_state_init (pp_state *self, slang_info_log *elog,
548 const struct gl_extensions *extensions)
549 {
550 self->line = 0;
551 self->file = 1;
552 #if FEATURE_es2_glsl
553 self->version = 100;
554 #else
555 self->version = 110;
556 #endif
557 pp_symbols_init (&self->symbols);
558 pp_ext_init (&self->ext, extensions);
559 self->elog = elog;
560
561 /* Initialize condition stack and create the global context. */
562 self->cond.top = &self->cond.stack[CONDITION_STACK_SIZE - 1];
563 self->cond.top->current = GL_TRUE;
564 self->cond.top->effective = GL_TRUE;
565 self->cond.top->else_allowed = GL_FALSE;
566 self->cond.top->endif_required = GL_FALSE;
567 }
568
569 static GLvoid
570 pp_state_free (pp_state *self)
571 {
572 pp_symbols_free (&self->symbols);
573 }
574
575 #define IS_FIRST_ID_CHAR(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_')
576 #define IS_NEXT_ID_CHAR(x) (IS_FIRST_ID_CHAR(x) || ((x) >= '0' && (x) <= '9'))
577 #define IS_WHITE(x) ((x) == ' ' || (x) == '\n')
578 #define IS_NULL(x) ((x) == '\0')
579
580 #define SKIP_WHITE(x) do { while (IS_WHITE(*(x))) (x)++; } while (GL_FALSE)
581
582 typedef struct
583 {
584 slang_string *output;
585 const char *input;
586 pp_state *state;
587 } expand_state;
588
589 static GLboolean
590 expand_defined (expand_state *e, slang_string *buffer)
591 {
592 GLboolean in_paren = GL_FALSE;
593 const char *id;
594
595 /* Parse the optional opening parenthesis. */
596 SKIP_WHITE(e->input);
597 if (*e->input == '(') {
598 e->input++;
599 in_paren = GL_TRUE;
600 SKIP_WHITE(e->input);
601 }
602
603 /* Parse operand. */
604 if (!IS_FIRST_ID_CHAR(*e->input)) {
605 slang_info_log_error (e->state->elog,
606 "preprocess error: identifier expected after operator 'defined'.");
607 return GL_FALSE;
608 }
609 slang_string_reset (buffer);
610 slang_string_pushc (buffer, *e->input++);
611 while (IS_NEXT_ID_CHAR(*e->input))
612 slang_string_pushc (buffer, *e->input++);
613 id = slang_string_cstr (buffer);
614
615 /* Check if the operand is defined. Output 1 if it is defined, output 0 if not. */
616 if (pp_symbols_find (&e->state->symbols, id) == NULL)
617 slang_string_pushs (e->output, " 0 ", 3);
618 else
619 slang_string_pushs (e->output, " 1 ", 3);
620
621 /* Parse the closing parentehesis if the opening one was there. */
622 if (in_paren) {
623 SKIP_WHITE(e->input);
624 if (*e->input != ')') {
625 slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");
626 return GL_FALSE;
627 }
628 e->input++;
629 SKIP_WHITE(e->input);
630 }
631 return GL_TRUE;
632 }
633
634 static GLboolean
635 expand (expand_state *, pp_symbols *);
636
637 static GLboolean
638 expand_symbol (expand_state *e, pp_symbol *symbol)
639 {
640 expand_state es;
641
642 /* If the macro has some parameters, we need to parse them. */
643 if (symbol->parameters.count != 0) {
644 GLuint i;
645
646 /* Parse the opening parenthesis. */
647 SKIP_WHITE(e->input);
648 if (*e->input != '(') {
649 slang_info_log_error (e->state->elog, "preprocess error: '(' expected.");
650 return GL_FALSE;
651 }
652 e->input++;
653 SKIP_WHITE(e->input);
654
655 /* Parse macro actual parameters. This can be anything, separated by a colon.
656 */
657 for (i = 0; i < symbol->parameters.count; i++) {
658 GLuint nested_paren_count = 0; /* track number of nested parentheses */
659
660 if (*e->input == ')') {
661 slang_info_log_error (e->state->elog, "preprocess error: unexpected ')'.");
662 return GL_FALSE;
663 }
664
665 /* Eat all characters up to the comma or closing parentheses. */
666 pp_symbol_reset (&symbol->parameters.symbols[i]);
667 while (!IS_NULL(*e->input)) {
668 /* Exit loop only when all nested parens have been eaten. */
669 if (nested_paren_count == 0 && (*e->input == ',' || *e->input == ')'))
670 break;
671
672 /* Actually count nested parens here. */
673 if (*e->input == '(')
674 nested_paren_count++;
675 else if (*e->input == ')')
676 nested_paren_count--;
677
678 slang_string_pushc (&symbol->parameters.symbols[i].replacement, *e->input++);
679 }
680
681 /* If it was not the last paremeter, skip the comma. Otherwise, skip the
682 * closing parentheses. */
683 if (i + 1 == symbol->parameters.count) {
684 /* This is the last paremeter - skip the closing parentheses. */
685 if (*e->input != ')') {
686 slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");
687 return GL_FALSE;
688 }
689 e->input++;
690 SKIP_WHITE(e->input);
691 }
692 else {
693 /* Skip the separating comma. */
694 if (*e->input != ',') {
695 slang_info_log_error (e->state->elog, "preprocess error: ',' expected.");
696 return GL_FALSE;
697 }
698 e->input++;
699 SKIP_WHITE(e->input);
700 }
701 }
702 }
703
704 /* Expand the macro. Use its parameters as a priority symbol list to expand
705 * macro parameters correctly. */
706 es.output = e->output;
707 es.input = slang_string_cstr (&symbol->replacement);
708 es.state = e->state;
709 slang_string_pushc (e->output, ' ');
710 if (!expand (&es, &symbol->parameters))
711 return GL_FALSE;
712 slang_string_pushc (e->output, ' ');
713 return GL_TRUE;
714 }
715
716 /*
717 * Function expand() expands source text from <input> to <output>. The expansion is made using
718 * the list passed in <symbols> parameter. It allows us to expand macro formal parameters with
719 * actual parameters. The global list of symbols from pp state is used when doing a recursive
720 * call of expand().
721 */
722
723 static GLboolean
724 expand (expand_state *e, pp_symbols *symbols)
725 {
726 while (!IS_NULL(*e->input)) {
727 if (IS_FIRST_ID_CHAR(*e->input)) {
728 slang_string buffer;
729 const char *id;
730
731 /* Parse the identifier. */
732 slang_string_init (&buffer);
733 slang_string_pushc (&buffer, *e->input++);
734 while (IS_NEXT_ID_CHAR(*e->input))
735 slang_string_pushc (&buffer, *e->input++);
736 id = slang_string_cstr (&buffer);
737
738 /* Now check if the identifier is special in some way. The "defined" identifier is
739 * actually an operator that we must handle here and expand it either to " 0 " or " 1 ".
740 * The other identifiers start with "__" and we expand it to appropriate values
741 * taken from the preprocessor state. */
742 if (_mesa_strcmp (id, "defined") == 0) {
743 if (!expand_defined (e, &buffer))
744 return GL_FALSE;
745 }
746 else if (_mesa_strcmp (id, "__LINE__") == 0) {
747 slang_string_pushc (e->output, ' ');
748 slang_string_pushi (e->output, e->state->line);
749 slang_string_pushc (e->output, ' ');
750 }
751 else if (_mesa_strcmp (id, "__FILE__") == 0) {
752 slang_string_pushc (e->output, ' ');
753 slang_string_pushi (e->output, e->state->file);
754 slang_string_pushc (e->output, ' ');
755 }
756 else if (_mesa_strcmp (id, "__VERSION__") == 0) {
757 slang_string_pushc (e->output, ' ');
758 slang_string_pushi (e->output, e->state->version);
759 slang_string_pushc (e->output, ' ');
760 }
761 #if FEATURE_es2_glsl
762 else if (_mesa_strcmp (id, "GL_ES") == 0 ||
763 _mesa_strcmp (id, "GL_FRAGMENT_PRECISION_HIGH") == 0) {
764 slang_string_pushc (e->output, ' ');
765 slang_string_pushi (e->output, '1');
766 slang_string_pushc (e->output, ' ');
767 }
768 #endif
769 else {
770 pp_symbol *symbol;
771
772 /* The list of symbols from <symbols> take precedence over the list from <state>.
773 * Note that in some cases this is the same list so avoid double look-up. */
774 symbol = pp_symbols_find (symbols, id);
775 if (symbol == NULL && symbols != &e->state->symbols)
776 symbol = pp_symbols_find (&e->state->symbols, id);
777
778 /* If the symbol was found, recursively expand its definition. */
779 if (symbol != NULL) {
780 if (!expand_symbol (e, symbol)) {
781 slang_string_free (&buffer);
782 return GL_FALSE;
783 }
784 }
785 else {
786 slang_string_push (e->output, &buffer);
787 }
788 }
789 slang_string_free (&buffer);
790 }
791 else if (IS_WHITE(*e->input)) {
792 slang_string_pushc (e->output, *e->input++);
793 }
794 else {
795 while (!IS_WHITE(*e->input) && !IS_NULL(*e->input) && !IS_FIRST_ID_CHAR(*e->input))
796 slang_string_pushc (e->output, *e->input++);
797 }
798 }
799 return GL_TRUE;
800 }
801
802 static GLboolean
803 parse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_state *state,
804 grammar eid)
805 {
806 const char *text;
807 GLuint len;
808
809 text = (const char *) (&prod[*pi]);
810 len = _mesa_strlen (text);
811
812 if (state->cond.top->effective) {
813 slang_string expr;
814 GLuint count;
815 GLint results[2];
816 expand_state es;
817
818 /* Expand the expression. */
819 slang_string_init (&expr);
820 es.output = &expr;
821 es.input = text;
822 es.state = state;
823 if (!expand (&es, &state->symbols))
824 return GL_FALSE;
825
826 /* Execute the expression. */
827 count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&expr)),
828 results, state->elog);
829 slang_string_free (&expr);
830 if (count != 1)
831 return GL_FALSE;
832 *result = results[0];
833 }
834 else {
835 /* The directive is dead. */
836 *result = 0;
837 }
838
839 *pi += len + 1;
840 return GL_TRUE;
841 }
842
843 #define ESCAPE_TOKEN 0
844
845 #define TOKEN_END 0
846 #define TOKEN_DEFINE 1
847 #define TOKEN_UNDEF 2
848 #define TOKEN_IF 3
849 #define TOKEN_ELSE 4
850 #define TOKEN_ELIF 5
851 #define TOKEN_ENDIF 6
852 #define TOKEN_ERROR 7
853 #define TOKEN_PRAGMA 8
854 #define TOKEN_EXTENSION 9
855 #define TOKEN_LINE 10
856
857 #define PARAM_END 0
858 #define PARAM_PARAMETER 1
859
860 #define BEHAVIOR_REQUIRE 1
861 #define BEHAVIOR_ENABLE 2
862 #define BEHAVIOR_WARN 3
863 #define BEHAVIOR_DISABLE 4
864
865 static GLboolean
866 preprocess_source (slang_string *output, const char *source,
867 grammar pid, grammar eid,
868 slang_info_log *elog,
869 const struct gl_extensions *extensions)
870 {
871 static const char *predefined[] = {
872 "__FILE__",
873 "__LINE__",
874 "__VERSION__",
875 #if FEATURE_es2_glsl
876 "GL_ES",
877 "GL_FRAGMENT_PRECISION_HIGH",
878 #endif
879 NULL
880 };
881 byte *prod;
882 GLuint size, i;
883 pp_state state;
884
885 if (!grammar_fast_check (pid, (const byte *) (source), &prod, &size, 65536)) {
886 grammar_error_to_log (elog);
887 return GL_FALSE;
888 }
889
890 pp_state_init (&state, elog, extensions);
891
892 /* add the predefined symbols to the symbol table */
893 for (i = 0; predefined[i]; i++) {
894 pp_symbol *symbol = NULL;
895 symbol = pp_symbols_push(&state.symbols);
896 assert(symbol);
897 slang_string_pushs(&symbol->name,
898 predefined[i], _mesa_strlen(predefined[i]));
899 }
900
901 i = 0;
902 while (i < size) {
903 if (prod[i] != ESCAPE_TOKEN) {
904 if (state.cond.top->effective) {
905 slang_string input;
906 expand_state es;
907
908 /* Eat only one line of source code to expand it.
909 * FIXME: This approach has one drawback. If a macro with parameters spans across
910 * multiple lines, the preprocessor will raise an error. */
911 slang_string_init (&input);
912 while (prod[i] != '\0' && prod[i] != '\n')
913 slang_string_pushc (&input, prod[i++]);
914 if (prod[i] != '\0')
915 slang_string_pushc (&input, prod[i++]);
916
917 /* Increment line number. */
918 state.line++;
919
920 es.output = output;
921 es.input = slang_string_cstr (&input);
922 es.state = &state;
923 if (!expand (&es, &state.symbols))
924 goto error;
925
926 slang_string_free (&input);
927 }
928 else {
929 /* Condition stack is disabled - keep track on line numbers and output only newlines. */
930 if (prod[i] == '\n') {
931 state.line++;
932 /*pp_annotate (output, "%c", prod[i]);*/
933 }
934 else {
935 /*pp_annotate (output, "%c", prod[i]);*/
936 }
937 i++;
938 }
939 }
940 else {
941 const char *id;
942 GLuint idlen;
943
944 i++;
945 switch (prod[i++]) {
946
947 case TOKEN_END:
948 /* End of source string.
949 * Check if all #ifs have been terminated by matching #endifs.
950 * On condition stack there should be only the global condition context. */
951 if (state.cond.top->endif_required) {
952 slang_info_log_error (elog, "end of source without matching #endif.");
953 return GL_FALSE;
954 }
955 break;
956
957 case TOKEN_DEFINE:
958 {
959 pp_symbol *symbol = NULL;
960
961 /* Parse macro name. */
962 id = (const char *) (&prod[i]);
963 idlen = _mesa_strlen (id);
964 if (state.cond.top->effective) {
965 pp_annotate (output, "// #define %s(", id);
966
967 /* If the symbol is already defined, override it. */
968 symbol = pp_symbols_find (&state.symbols, id);
969 if (symbol == NULL) {
970 symbol = pp_symbols_push (&state.symbols);
971 if (symbol == NULL)
972 goto error;
973 slang_string_pushs (&symbol->name, id, idlen);
974 }
975 else {
976 pp_symbol_reset (symbol);
977 }
978 }
979 i += idlen + 1;
980
981 /* Parse optional macro parameters. */
982 while (prod[i++] != PARAM_END) {
983 if (state.cond.top->effective) {
984 pp_symbol *param;
985
986 id = (const char *) (&prod[i]);
987 idlen = _mesa_strlen (id);
988 pp_annotate (output, "%s, ", id);
989 param = pp_symbols_push (&symbol->parameters);
990 if (param == NULL)
991 goto error;
992 slang_string_pushs (&param->name, id, idlen);
993 }
994 i += idlen + 1;
995 }
996
997 /* Parse macro replacement. */
998 id = (const char *) (&prod[i]);
999 idlen = _mesa_strlen (id);
1000 if (state.cond.top->effective) {
1001 pp_annotate (output, ") %s", id);
1002 slang_string_pushs (&symbol->replacement, id, idlen);
1003 }
1004 i += idlen + 1;
1005 }
1006 break;
1007
1008 case TOKEN_UNDEF:
1009 id = (const char *) (&prod[i]);
1010 i += _mesa_strlen (id) + 1;
1011 if (state.cond.top->effective) {
1012 pp_symbol *symbol;
1013
1014 pp_annotate (output, "// #undef %s", id);
1015 /* Try to find symbol with given name and remove it. */
1016 symbol = pp_symbols_find (&state.symbols, id);
1017 if (symbol != NULL)
1018 if (!pp_symbols_erase (&state.symbols, symbol))
1019 goto error;
1020 }
1021 break;
1022
1023 case TOKEN_IF:
1024 {
1025 GLint result;
1026
1027 /* Parse #if expression end execute it. */
1028 pp_annotate (output, "// #if ");
1029 if (!parse_if (output, prod, &i, &result, &state, eid))
1030 goto error;
1031
1032 /* Push new condition on the stack. */
1033 if (!pp_cond_stack_push (&state.cond, state.elog))
1034 goto error;
1035 state.cond.top->current = result ? GL_TRUE : GL_FALSE;
1036 state.cond.top->else_allowed = GL_TRUE;
1037 state.cond.top->endif_required = GL_TRUE;
1038 pp_cond_stack_reevaluate (&state.cond);
1039 }
1040 break;
1041
1042 case TOKEN_ELSE:
1043 /* Check if #else is alloved here. */
1044 if (!state.cond.top->else_allowed) {
1045 slang_info_log_error (elog, "#else without matching #if.");
1046 goto error;
1047 }
1048
1049 /* Negate current condition and reevaluate it. */
1050 state.cond.top->current = !state.cond.top->current;
1051 state.cond.top->else_allowed = GL_FALSE;
1052 pp_cond_stack_reevaluate (&state.cond);
1053 if (state.cond.top->effective)
1054 pp_annotate (output, "// #else");
1055 break;
1056
1057 case TOKEN_ELIF:
1058 /* Check if #elif is alloved here. */
1059 if (!state.cond.top->else_allowed) {
1060 slang_info_log_error (elog, "#elif without matching #if.");
1061 goto error;
1062 }
1063
1064 /* Negate current condition and reevaluate it. */
1065 state.cond.top->current = !state.cond.top->current;
1066 pp_cond_stack_reevaluate (&state.cond);
1067
1068 if (state.cond.top->effective)
1069 pp_annotate (output, "// #elif ");
1070
1071 {
1072 GLint result;
1073
1074 /* Parse #elif expression end execute it. */
1075 if (!parse_if (output, prod, &i, &result, &state, eid))
1076 goto error;
1077
1078 /* Update current condition and reevaluate it. */
1079 state.cond.top->current = result ? GL_TRUE : GL_FALSE;
1080 pp_cond_stack_reevaluate (&state.cond);
1081 }
1082 break;
1083
1084 case TOKEN_ENDIF:
1085 /* Check if #endif is alloved here. */
1086 if (!state.cond.top->endif_required) {
1087 slang_info_log_error (elog, "#endif without matching #if.");
1088 goto error;
1089 }
1090
1091 /* Pop the condition off the stack. */
1092 state.cond.top++;
1093 if (state.cond.top->effective)
1094 pp_annotate (output, "// #endif");
1095 break;
1096
1097 case TOKEN_EXTENSION:
1098 /* Parse the extension name. */
1099 id = (const char *) (&prod[i]);
1100 i += _mesa_strlen (id) + 1;
1101 if (state.cond.top->effective)
1102 pp_annotate (output, "// #extension %s: ", id);
1103
1104 /* Parse and apply extension behavior. */
1105 if (state.cond.top->effective) {
1106 switch (prod[i++]) {
1107
1108 case BEHAVIOR_REQUIRE:
1109 pp_annotate (output, "require");
1110 if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
1111 if (_mesa_strcmp (id, "all") == 0) {
1112 slang_info_log_error (elog, "require: bad behavior for #extension all.");
1113 goto error;
1114 }
1115 else {
1116 slang_info_log_error (elog, "%s: required extension is not supported.", id);
1117 goto error;
1118 }
1119 }
1120 break;
1121
1122 case BEHAVIOR_ENABLE:
1123 pp_annotate (output, "enable");
1124 if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
1125 if (_mesa_strcmp (id, "all") == 0) {
1126 slang_info_log_error (elog, "enable: bad behavior for #extension all.");
1127 goto error;
1128 }
1129 else {
1130 slang_info_log_warning (elog, "%s: enabled extension is not supported.", id);
1131 }
1132 }
1133 break;
1134
1135 case BEHAVIOR_WARN:
1136 pp_annotate (output, "warn");
1137 if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
1138 if (_mesa_strcmp (id, "all") != 0) {
1139 slang_info_log_warning (elog, "%s: enabled extension is not supported.", id);
1140 }
1141 }
1142 break;
1143
1144 case BEHAVIOR_DISABLE:
1145 pp_annotate (output, "disable");
1146 if (!pp_ext_set (&state.ext, id, GL_FALSE)) {
1147 if (_mesa_strcmp (id, "all") == 0) {
1148 pp_ext_disable_all (&state.ext);
1149 }
1150 else {
1151 slang_info_log_warning (elog, "%s: disabled extension is not supported.", id);
1152 }
1153 }
1154 break;
1155
1156 default:
1157 assert (0);
1158 }
1159 }
1160 break;
1161
1162 case TOKEN_LINE:
1163 id = (const char *) (&prod[i]);
1164 i += _mesa_strlen (id) + 1;
1165
1166 if (state.cond.top->effective) {
1167 slang_string buffer;
1168 GLuint count;
1169 GLint results[2];
1170 expand_state es;
1171
1172 slang_string_init (&buffer);
1173 state.line++;
1174 es.output = &buffer;
1175 es.input = id;
1176 es.state = &state;
1177 if (!expand (&es, &state.symbols))
1178 goto error;
1179
1180 pp_annotate (output, "// #line ");
1181 count = execute_expressions (output, eid,
1182 (const byte *) (slang_string_cstr (&buffer)),
1183 results, state.elog);
1184 slang_string_free (&buffer);
1185 if (count == 0)
1186 goto error;
1187
1188 state.line = results[0] - 1;
1189 if (count == 2)
1190 state.file = results[1];
1191 }
1192 break;
1193 }
1194 }
1195 }
1196
1197 /* Check for missing #endifs. */
1198 if (state.cond.top->endif_required) {
1199 slang_info_log_error (elog, "#endif expected but end of source found.");
1200 goto error;
1201 }
1202
1203 grammar_alloc_free(prod);
1204 pp_state_free (&state);
1205 return GL_TRUE;
1206
1207 error:
1208 grammar_alloc_free(prod);
1209 pp_state_free (&state);
1210 return GL_FALSE;
1211 }
1212
1213
1214 /**
1215 * Run preprocessor on source code.
1216 * \param extensions indicates which GL extensions are enabled
1217 * \param output the post-process results
1218 * \param input the input text
1219 * \param elog log to record warnings, errors
1220 * \return GL_TRUE for success, GL_FALSE for error
1221 */
1222 GLboolean
1223 _slang_preprocess_directives(slang_string *output,
1224 const char *input,
1225 slang_info_log *elog,
1226 const struct gl_extensions *extensions)
1227 {
1228 grammar pid, eid;
1229 GLboolean success;
1230
1231 pid = grammar_load_from_text ((const byte *) (slang_pp_directives_syn));
1232 if (pid == 0) {
1233 grammar_error_to_log (elog);
1234 return GL_FALSE;
1235 }
1236 eid = grammar_load_from_text ((const byte *) (slang_pp_expression_syn));
1237 if (eid == 0) {
1238 grammar_error_to_log (elog);
1239 grammar_destroy (pid);
1240 return GL_FALSE;
1241 }
1242 success = preprocess_source (output, input, pid, eid, elog, extensions);
1243 grammar_destroy (eid);
1244 grammar_destroy (pid);
1245 return success;
1246 }
1247