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