Merge commit 'origin/gallium-0.1'
[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 self->ARB_draw_buffers = GL_TRUE;
512 if (extensions->NV_texture_rectangle)
513 self->ARB_texture_rectangle = GL_TRUE;
514 }
515
516 /**
517 * Called in response to #extension directives to enable/disable
518 * the named extension.
519 */
520 static GLboolean
521 pp_ext_set(pp_ext *self, const char *name, GLboolean enable)
522 {
523 if (_mesa_strcmp (name, "GL_ARB_draw_buffers") == 0)
524 self->ARB_draw_buffers = enable;
525 else if (_mesa_strcmp (name, "GL_ARB_texture_rectangle") == 0)
526 self->ARB_texture_rectangle = enable;
527 else
528 return GL_FALSE;
529 return GL_TRUE;
530 }
531
532
533 static void
534 pp_pragmas_init(struct gl_sl_pragmas *pragmas)
535 {
536 pragmas->Optimize = GL_TRUE;
537 pragmas->Debug = GL_FALSE;
538 }
539
540
541 /**
542 * Called in response to #pragma. For example, "#pragma debug(on)" would
543 * call this function as pp_pragma("debug", "on").
544 * \return GL_TRUE if pragma is valid, GL_FALSE if invalid
545 */
546 static GLboolean
547 pp_pragma(struct gl_sl_pragmas *pragmas, const char *pragma, const char *param)
548 {
549 #if 0
550 printf("#pragma %s %s\n", pragma, param);
551 #endif
552 if (_mesa_strcmp(pragma, "optimize") == 0) {
553 if (!param)
554 return GL_FALSE; /* missing required param */
555 if (_mesa_strcmp(param, "on") == 0) {
556 pragmas->Optimize = GL_TRUE;
557 }
558 else if (_mesa_strcmp(param, "off") == 0) {
559 pragmas->Optimize = GL_FALSE;
560 }
561 else {
562 return GL_FALSE; /* invalid param */
563 }
564 }
565 else if (_mesa_strcmp(pragma, "debug") == 0) {
566 if (!param)
567 return GL_FALSE; /* missing required param */
568 if (_mesa_strcmp(param, "on") == 0) {
569 pragmas->Debug = GL_TRUE;
570 }
571 else if (_mesa_strcmp(param, "off") == 0) {
572 pragmas->Debug = GL_FALSE;
573 }
574 else {
575 return GL_FALSE; /* invalid param */
576 }
577 }
578 /* all other pragmas are silently ignored */
579 return GL_TRUE;
580 }
581
582
583 /**
584 * The state of preprocessor: current line, file and version number, list
585 * of all defined macros and the #if/#endif context.
586 */
587 typedef struct
588 {
589 GLint line;
590 GLint file;
591 GLint version;
592 pp_symbols symbols;
593 pp_ext ext;
594 slang_info_log *elog;
595 pp_cond_stack cond;
596 } pp_state;
597
598 static GLvoid
599 pp_state_init (pp_state *self, slang_info_log *elog,
600 const struct gl_extensions *extensions)
601 {
602 self->line = 0;
603 self->file = 1;
604 #if FEATURE_es2_glsl
605 self->version = 100;
606 #else
607 self->version = 110;
608 #endif
609 pp_symbols_init (&self->symbols);
610 pp_ext_init (&self->ext, extensions);
611 self->elog = elog;
612
613 /* Initialize condition stack and create the global context. */
614 self->cond.top = &self->cond.stack[CONDITION_STACK_SIZE - 1];
615 self->cond.top->current = GL_TRUE;
616 self->cond.top->effective = GL_TRUE;
617 self->cond.top->else_allowed = GL_FALSE;
618 self->cond.top->endif_required = GL_FALSE;
619 }
620
621 static GLvoid
622 pp_state_free (pp_state *self)
623 {
624 pp_symbols_free (&self->symbols);
625 }
626
627 #define IS_FIRST_ID_CHAR(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_')
628 #define IS_NEXT_ID_CHAR(x) (IS_FIRST_ID_CHAR(x) || ((x) >= '0' && (x) <= '9'))
629 #define IS_WHITE(x) ((x) == ' ' || (x) == '\n')
630 #define IS_NULL(x) ((x) == '\0')
631
632 #define SKIP_WHITE(x) do { while (IS_WHITE(*(x))) (x)++; } while (GL_FALSE)
633
634 typedef struct
635 {
636 slang_string *output;
637 const char *input;
638 pp_state *state;
639 } expand_state;
640
641 static GLboolean
642 expand_defined (expand_state *e, slang_string *buffer)
643 {
644 GLboolean in_paren = GL_FALSE;
645 const char *id;
646
647 /* Parse the optional opening parenthesis. */
648 SKIP_WHITE(e->input);
649 if (*e->input == '(') {
650 e->input++;
651 in_paren = GL_TRUE;
652 SKIP_WHITE(e->input);
653 }
654
655 /* Parse operand. */
656 if (!IS_FIRST_ID_CHAR(*e->input)) {
657 slang_info_log_error (e->state->elog,
658 "preprocess error: identifier expected after operator 'defined'.");
659 return GL_FALSE;
660 }
661 slang_string_reset (buffer);
662 slang_string_pushc (buffer, *e->input++);
663 while (IS_NEXT_ID_CHAR(*e->input))
664 slang_string_pushc (buffer, *e->input++);
665 id = slang_string_cstr (buffer);
666
667 /* Check if the operand is defined. Output 1 if it is defined, output 0 if not. */
668 if (pp_symbols_find (&e->state->symbols, id) == NULL)
669 slang_string_pushs (e->output, " 0 ", 3);
670 else
671 slang_string_pushs (e->output, " 1 ", 3);
672
673 /* Parse the closing parentehesis if the opening one was there. */
674 if (in_paren) {
675 SKIP_WHITE(e->input);
676 if (*e->input != ')') {
677 slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");
678 return GL_FALSE;
679 }
680 e->input++;
681 SKIP_WHITE(e->input);
682 }
683 return GL_TRUE;
684 }
685
686 static GLboolean
687 expand (expand_state *, pp_symbols *);
688
689 static GLboolean
690 expand_symbol (expand_state *e, pp_symbol *symbol)
691 {
692 expand_state es;
693
694 /* If the macro has some parameters, we need to parse them. */
695 if (symbol->parameters.count != 0) {
696 GLuint i;
697
698 /* Parse the opening parenthesis. */
699 SKIP_WHITE(e->input);
700 if (*e->input != '(') {
701 slang_info_log_error (e->state->elog, "preprocess error: '(' expected.");
702 return GL_FALSE;
703 }
704 e->input++;
705 SKIP_WHITE(e->input);
706
707 /* Parse macro actual parameters. This can be anything, separated by a colon.
708 */
709 for (i = 0; i < symbol->parameters.count; i++) {
710 GLuint nested_paren_count = 0; /* track number of nested parentheses */
711
712 if (*e->input == ')') {
713 slang_info_log_error (e->state->elog, "preprocess error: unexpected ')'.");
714 return GL_FALSE;
715 }
716
717 /* Eat all characters up to the comma or closing parentheses. */
718 pp_symbol_reset (&symbol->parameters.symbols[i]);
719 while (!IS_NULL(*e->input)) {
720 /* Exit loop only when all nested parens have been eaten. */
721 if (nested_paren_count == 0 && (*e->input == ',' || *e->input == ')'))
722 break;
723
724 /* Actually count nested parens here. */
725 if (*e->input == '(')
726 nested_paren_count++;
727 else if (*e->input == ')')
728 nested_paren_count--;
729
730 slang_string_pushc (&symbol->parameters.symbols[i].replacement, *e->input++);
731 }
732
733 /* If it was not the last paremeter, skip the comma. Otherwise, skip the
734 * closing parentheses. */
735 if (i + 1 == symbol->parameters.count) {
736 /* This is the last paremeter - skip the closing parentheses. */
737 if (*e->input != ')') {
738 slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");
739 return GL_FALSE;
740 }
741 e->input++;
742 SKIP_WHITE(e->input);
743 }
744 else {
745 /* Skip the separating comma. */
746 if (*e->input != ',') {
747 slang_info_log_error (e->state->elog, "preprocess error: ',' expected.");
748 return GL_FALSE;
749 }
750 e->input++;
751 SKIP_WHITE(e->input);
752 }
753 }
754 }
755
756 /* Expand the macro. Use its parameters as a priority symbol list to expand
757 * macro parameters correctly. */
758 es.output = e->output;
759 es.input = slang_string_cstr (&symbol->replacement);
760 es.state = e->state;
761 slang_string_pushc (e->output, ' ');
762 if (!expand (&es, &symbol->parameters))
763 return GL_FALSE;
764 slang_string_pushc (e->output, ' ');
765 return GL_TRUE;
766 }
767
768 /*
769 * Function expand() expands source text from <input> to <output>. The expansion is made using
770 * the list passed in <symbols> parameter. It allows us to expand macro formal parameters with
771 * actual parameters. The global list of symbols from pp state is used when doing a recursive
772 * call of expand().
773 */
774
775 static GLboolean
776 expand (expand_state *e, pp_symbols *symbols)
777 {
778 while (!IS_NULL(*e->input)) {
779 if (IS_FIRST_ID_CHAR(*e->input)) {
780 slang_string buffer;
781 const char *id;
782
783 /* Parse the identifier. */
784 slang_string_init (&buffer);
785 slang_string_pushc (&buffer, *e->input++);
786 while (IS_NEXT_ID_CHAR(*e->input))
787 slang_string_pushc (&buffer, *e->input++);
788 id = slang_string_cstr (&buffer);
789
790 /* Now check if the identifier is special in some way. The "defined" identifier is
791 * actually an operator that we must handle here and expand it either to " 0 " or " 1 ".
792 * The other identifiers start with "__" and we expand it to appropriate values
793 * taken from the preprocessor state. */
794 if (_mesa_strcmp (id, "defined") == 0) {
795 if (!expand_defined (e, &buffer))
796 return GL_FALSE;
797 }
798 else if (_mesa_strcmp (id, "__LINE__") == 0) {
799 slang_string_pushc (e->output, ' ');
800 slang_string_pushi (e->output, e->state->line);
801 slang_string_pushc (e->output, ' ');
802 }
803 else if (_mesa_strcmp (id, "__FILE__") == 0) {
804 slang_string_pushc (e->output, ' ');
805 slang_string_pushi (e->output, e->state->file);
806 slang_string_pushc (e->output, ' ');
807 }
808 else if (_mesa_strcmp (id, "__VERSION__") == 0) {
809 slang_string_pushc (e->output, ' ');
810 slang_string_pushi (e->output, e->state->version);
811 slang_string_pushc (e->output, ' ');
812 }
813 #if FEATURE_es2_glsl
814 else if (_mesa_strcmp (id, "GL_ES") == 0 ||
815 _mesa_strcmp (id, "GL_FRAGMENT_PRECISION_HIGH") == 0) {
816 slang_string_pushc (e->output, ' ');
817 slang_string_pushi (e->output, '1');
818 slang_string_pushc (e->output, ' ');
819 }
820 #endif
821 else {
822 pp_symbol *symbol;
823
824 /* The list of symbols from <symbols> take precedence over the list from <state>.
825 * Note that in some cases this is the same list so avoid double look-up. */
826 symbol = pp_symbols_find (symbols, id);
827 if (symbol == NULL && symbols != &e->state->symbols)
828 symbol = pp_symbols_find (&e->state->symbols, id);
829
830 /* If the symbol was found, recursively expand its definition. */
831 if (symbol != NULL) {
832 if (!expand_symbol (e, symbol)) {
833 slang_string_free (&buffer);
834 return GL_FALSE;
835 }
836 }
837 else {
838 slang_string_push (e->output, &buffer);
839 }
840 }
841 slang_string_free (&buffer);
842 }
843 else if (IS_WHITE(*e->input)) {
844 slang_string_pushc (e->output, *e->input++);
845 }
846 else {
847 while (!IS_WHITE(*e->input) && !IS_NULL(*e->input) && !IS_FIRST_ID_CHAR(*e->input))
848 slang_string_pushc (e->output, *e->input++);
849 }
850 }
851 return GL_TRUE;
852 }
853
854 static GLboolean
855 parse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_state *state,
856 grammar eid)
857 {
858 const char *text;
859 GLuint len;
860
861 text = (const char *) (&prod[*pi]);
862 len = _mesa_strlen (text);
863
864 if (state->cond.top->effective) {
865 slang_string expr;
866 GLuint count;
867 GLint results[2];
868 expand_state es;
869
870 /* Expand the expression. */
871 slang_string_init (&expr);
872 es.output = &expr;
873 es.input = text;
874 es.state = state;
875 if (!expand (&es, &state->symbols))
876 return GL_FALSE;
877
878 /* Execute the expression. */
879 count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&expr)),
880 results, state->elog);
881 slang_string_free (&expr);
882 if (count != 1)
883 return GL_FALSE;
884 *result = results[0];
885 }
886 else {
887 /* The directive is dead. */
888 *result = 0;
889 }
890
891 *pi += len + 1;
892 return GL_TRUE;
893 }
894
895 #define ESCAPE_TOKEN 0
896
897 #define TOKEN_END 0
898 #define TOKEN_DEFINE 1
899 #define TOKEN_UNDEF 2
900 #define TOKEN_IF 3
901 #define TOKEN_ELSE 4
902 #define TOKEN_ELIF 5
903 #define TOKEN_ENDIF 6
904 #define TOKEN_ERROR 7
905 #define TOKEN_PRAGMA 8
906 #define TOKEN_EXTENSION 9
907 #define TOKEN_LINE 10
908
909 #define PARAM_END 0
910 #define PARAM_PARAMETER 1
911
912 #define BEHAVIOR_REQUIRE 1
913 #define BEHAVIOR_ENABLE 2
914 #define BEHAVIOR_WARN 3
915 #define BEHAVIOR_DISABLE 4
916
917 #define PRAGMA_NO_PARAM 0
918 #define PRAGMA_PARAM 1
919
920
921 static GLboolean
922 preprocess_source (slang_string *output, const char *source,
923 grammar pid, grammar eid,
924 slang_info_log *elog,
925 const struct gl_extensions *extensions,
926 struct gl_sl_pragmas *pragmas)
927 {
928 static const char *predefined[] = {
929 "__FILE__",
930 "__LINE__",
931 "__VERSION__",
932 #if FEATURE_es2_glsl
933 "GL_ES",
934 "GL_FRAGMENT_PRECISION_HIGH",
935 #endif
936 NULL
937 };
938 byte *prod;
939 GLuint size, i;
940 pp_state state;
941
942 if (!grammar_fast_check (pid, (const byte *) (source), &prod, &size, 65536)) {
943 grammar_error_to_log (elog);
944 return GL_FALSE;
945 }
946
947 pp_state_init (&state, elog, extensions);
948 pp_pragmas_init (pragmas);
949
950 /* add the predefined symbols to the symbol table */
951 for (i = 0; predefined[i]; i++) {
952 pp_symbol *symbol = NULL;
953 symbol = pp_symbols_push(&state.symbols);
954 assert(symbol);
955 slang_string_pushs(&symbol->name,
956 predefined[i], _mesa_strlen(predefined[i]));
957 }
958
959 i = 0;
960 while (i < size) {
961 if (prod[i] != ESCAPE_TOKEN) {
962 if (state.cond.top->effective) {
963 slang_string input;
964 expand_state es;
965
966 /* Eat only one line of source code to expand it.
967 * FIXME: This approach has one drawback. If a macro with parameters spans across
968 * multiple lines, the preprocessor will raise an error. */
969 slang_string_init (&input);
970 while (prod[i] != '\0' && prod[i] != '\n')
971 slang_string_pushc (&input, prod[i++]);
972 if (prod[i] != '\0')
973 slang_string_pushc (&input, prod[i++]);
974
975 /* Increment line number. */
976 state.line++;
977
978 es.output = output;
979 es.input = slang_string_cstr (&input);
980 es.state = &state;
981 if (!expand (&es, &state.symbols))
982 goto error;
983
984 slang_string_free (&input);
985 }
986 else {
987 /* Condition stack is disabled - keep track on line numbers and output only newlines. */
988 if (prod[i] == '\n') {
989 state.line++;
990 /*pp_annotate (output, "%c", prod[i]);*/
991 }
992 else {
993 /*pp_annotate (output, "%c", prod[i]);*/
994 }
995 i++;
996 }
997 }
998 else {
999 const char *id;
1000 GLuint idlen;
1001 GLubyte token;
1002
1003 i++;
1004 token = prod[i++];
1005 switch (token) {
1006
1007 case TOKEN_END:
1008 /* End of source string.
1009 * Check if all #ifs have been terminated by matching #endifs.
1010 * On condition stack there should be only the global condition context. */
1011 if (state.cond.top->endif_required) {
1012 slang_info_log_error (elog, "end of source without matching #endif.");
1013 return GL_FALSE;
1014 }
1015 break;
1016
1017 case TOKEN_DEFINE:
1018 {
1019 pp_symbol *symbol = NULL;
1020
1021 /* Parse macro name. */
1022 id = (const char *) (&prod[i]);
1023 idlen = _mesa_strlen (id);
1024 if (state.cond.top->effective) {
1025 pp_annotate (output, "// #define %s(", id);
1026
1027 /* If the symbol is already defined, override it. */
1028 symbol = pp_symbols_find (&state.symbols, id);
1029 if (symbol == NULL) {
1030 symbol = pp_symbols_push (&state.symbols);
1031 if (symbol == NULL)
1032 goto error;
1033 slang_string_pushs (&symbol->name, id, idlen);
1034 }
1035 else {
1036 pp_symbol_reset (symbol);
1037 }
1038 }
1039 i += idlen + 1;
1040
1041 /* Parse optional macro parameters. */
1042 while (prod[i++] != PARAM_END) {
1043 if (state.cond.top->effective) {
1044 pp_symbol *param;
1045
1046 id = (const char *) (&prod[i]);
1047 idlen = _mesa_strlen (id);
1048 pp_annotate (output, "%s, ", id);
1049 param = pp_symbols_push (&symbol->parameters);
1050 if (param == NULL)
1051 goto error;
1052 slang_string_pushs (&param->name, id, idlen);
1053 }
1054 i += idlen + 1;
1055 }
1056
1057 /* Parse macro replacement. */
1058 id = (const char *) (&prod[i]);
1059 idlen = _mesa_strlen (id);
1060 if (state.cond.top->effective) {
1061 pp_annotate (output, ") %s", id);
1062 slang_string_pushs (&symbol->replacement, id, idlen);
1063 }
1064 i += idlen + 1;
1065 }
1066 break;
1067
1068 case TOKEN_UNDEF:
1069 id = (const char *) (&prod[i]);
1070 i += _mesa_strlen (id) + 1;
1071 if (state.cond.top->effective) {
1072 pp_symbol *symbol;
1073
1074 pp_annotate (output, "// #undef %s", id);
1075 /* Try to find symbol with given name and remove it. */
1076 symbol = pp_symbols_find (&state.symbols, id);
1077 if (symbol != NULL)
1078 if (!pp_symbols_erase (&state.symbols, symbol))
1079 goto error;
1080 }
1081 break;
1082
1083 case TOKEN_IF:
1084 {
1085 GLint result;
1086
1087 /* Parse #if expression end execute it. */
1088 pp_annotate (output, "// #if ");
1089 if (!parse_if (output, prod, &i, &result, &state, eid))
1090 goto error;
1091
1092 /* Push new condition on the stack. */
1093 if (!pp_cond_stack_push (&state.cond, state.elog))
1094 goto error;
1095 state.cond.top->current = result ? GL_TRUE : GL_FALSE;
1096 state.cond.top->else_allowed = GL_TRUE;
1097 state.cond.top->endif_required = GL_TRUE;
1098 pp_cond_stack_reevaluate (&state.cond);
1099 }
1100 break;
1101
1102 case TOKEN_ELSE:
1103 /* Check if #else is alloved here. */
1104 if (!state.cond.top->else_allowed) {
1105 slang_info_log_error (elog, "#else without matching #if.");
1106 goto error;
1107 }
1108
1109 /* Negate current condition and reevaluate it. */
1110 state.cond.top->current = !state.cond.top->current;
1111 state.cond.top->else_allowed = GL_FALSE;
1112 pp_cond_stack_reevaluate (&state.cond);
1113 if (state.cond.top->effective)
1114 pp_annotate (output, "// #else");
1115 break;
1116
1117 case TOKEN_ELIF:
1118 /* Check if #elif is alloved here. */
1119 if (!state.cond.top->else_allowed) {
1120 slang_info_log_error (elog, "#elif without matching #if.");
1121 goto error;
1122 }
1123
1124 /* Negate current condition and reevaluate it. */
1125 state.cond.top->current = !state.cond.top->current;
1126 pp_cond_stack_reevaluate (&state.cond);
1127
1128 if (state.cond.top->effective)
1129 pp_annotate (output, "// #elif ");
1130
1131 {
1132 GLint result;
1133
1134 /* Parse #elif expression end execute it. */
1135 if (!parse_if (output, prod, &i, &result, &state, eid))
1136 goto error;
1137
1138 /* Update current condition and reevaluate it. */
1139 state.cond.top->current = result ? GL_TRUE : GL_FALSE;
1140 pp_cond_stack_reevaluate (&state.cond);
1141 }
1142 break;
1143
1144 case TOKEN_ENDIF:
1145 /* Check if #endif is alloved here. */
1146 if (!state.cond.top->endif_required) {
1147 slang_info_log_error (elog, "#endif without matching #if.");
1148 goto error;
1149 }
1150
1151 /* Pop the condition off the stack. */
1152 state.cond.top++;
1153 if (state.cond.top->effective)
1154 pp_annotate (output, "// #endif");
1155 break;
1156
1157 case TOKEN_EXTENSION:
1158 /* Parse the extension name. */
1159 id = (const char *) (&prod[i]);
1160 i += _mesa_strlen (id) + 1;
1161 if (state.cond.top->effective)
1162 pp_annotate (output, "// #extension %s: ", id);
1163
1164 /* Parse and apply extension behavior. */
1165 if (state.cond.top->effective) {
1166 switch (prod[i++]) {
1167
1168 case BEHAVIOR_REQUIRE:
1169 pp_annotate (output, "require");
1170 if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
1171 if (_mesa_strcmp (id, "all") == 0) {
1172 slang_info_log_error (elog, "require: bad behavior for #extension all.");
1173 goto error;
1174 }
1175 else {
1176 slang_info_log_error (elog, "%s: required extension is not supported.", id);
1177 goto error;
1178 }
1179 }
1180 break;
1181
1182 case BEHAVIOR_ENABLE:
1183 pp_annotate (output, "enable");
1184 if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
1185 if (_mesa_strcmp (id, "all") == 0) {
1186 slang_info_log_error (elog, "enable: bad behavior for #extension all.");
1187 goto error;
1188 }
1189 else {
1190 slang_info_log_warning (elog, "%s: enabled extension is not supported.", id);
1191 }
1192 }
1193 break;
1194
1195 case BEHAVIOR_WARN:
1196 pp_annotate (output, "warn");
1197 if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
1198 if (_mesa_strcmp (id, "all") != 0) {
1199 slang_info_log_warning (elog, "%s: enabled extension is not supported.", id);
1200 }
1201 }
1202 break;
1203
1204 case BEHAVIOR_DISABLE:
1205 pp_annotate (output, "disable");
1206 if (!pp_ext_set (&state.ext, id, GL_FALSE)) {
1207 if (_mesa_strcmp (id, "all") == 0) {
1208 pp_ext_disable_all (&state.ext);
1209 }
1210 else {
1211 slang_info_log_warning (elog, "%s: disabled extension is not supported.", id);
1212 }
1213 }
1214 break;
1215
1216 default:
1217 assert (0);
1218 }
1219 }
1220 break;
1221
1222 case TOKEN_PRAGMA:
1223 {
1224 GLint have_param;
1225 const char *pragma, *param;
1226
1227 pragma = (const char *) (&prod[i]);
1228 i += _mesa_strlen(pragma) + 1;
1229 have_param = (prod[i++] == PRAGMA_PARAM);
1230 if (have_param) {
1231 param = (const char *) (&prod[i]);
1232 i += _mesa_strlen(param) + 1;
1233 }
1234 else {
1235 param = NULL;
1236 }
1237 pp_pragma(pragmas, pragma, param);
1238 }
1239 break;
1240
1241 case TOKEN_LINE:
1242 id = (const char *) (&prod[i]);
1243 i += _mesa_strlen (id) + 1;
1244
1245 if (state.cond.top->effective) {
1246 slang_string buffer;
1247 GLuint count;
1248 GLint results[2];
1249 expand_state es;
1250
1251 slang_string_init (&buffer);
1252 state.line++;
1253 es.output = &buffer;
1254 es.input = id;
1255 es.state = &state;
1256 if (!expand (&es, &state.symbols))
1257 goto error;
1258
1259 pp_annotate (output, "// #line ");
1260 count = execute_expressions (output, eid,
1261 (const byte *) (slang_string_cstr (&buffer)),
1262 results, state.elog);
1263 slang_string_free (&buffer);
1264 if (count == 0)
1265 goto error;
1266
1267 state.line = results[0] - 1;
1268 if (count == 2)
1269 state.file = results[1];
1270 }
1271 break;
1272 }
1273 }
1274 }
1275
1276 /* Check for missing #endifs. */
1277 if (state.cond.top->endif_required) {
1278 slang_info_log_error (elog, "#endif expected but end of source found.");
1279 goto error;
1280 }
1281
1282 grammar_alloc_free(prod);
1283 pp_state_free (&state);
1284 return GL_TRUE;
1285
1286 error:
1287 grammar_alloc_free(prod);
1288 pp_state_free (&state);
1289 return GL_FALSE;
1290 }
1291
1292
1293 /**
1294 * Run preprocessor on source code.
1295 * \param extensions indicates which GL extensions are enabled
1296 * \param output the post-process results
1297 * \param input the input text
1298 * \param elog log to record warnings, errors
1299 * \return GL_TRUE for success, GL_FALSE for error
1300 */
1301 GLboolean
1302 _slang_preprocess_directives(slang_string *output,
1303 const char *input,
1304 slang_info_log *elog,
1305 const struct gl_extensions *extensions,
1306 struct gl_sl_pragmas *pragmas)
1307 {
1308 grammar pid, eid;
1309 GLboolean success;
1310
1311 pid = grammar_load_from_text ((const byte *) (slang_pp_directives_syn));
1312 if (pid == 0) {
1313 grammar_error_to_log (elog);
1314 return GL_FALSE;
1315 }
1316 eid = grammar_load_from_text ((const byte *) (slang_pp_expression_syn));
1317 if (eid == 0) {
1318 grammar_error_to_log (elog);
1319 grammar_destroy (pid);
1320 return GL_FALSE;
1321 }
1322 success = preprocess_source (output, input, pid, eid, elog, extensions, pragmas);
1323 grammar_destroy (eid);
1324 grammar_destroy (pid);
1325 return success;
1326 }
1327