1 /****************************************************************************\
2 Copyright (c) 2002, NVIDIA Corporation.
4 NVIDIA Corporation("NVIDIA") supplies this software to you in
5 consideration of your agreement to the following terms, and your use,
6 installation, modification or redistribution of this NVIDIA software
7 constitutes acceptance of these terms. If you do not agree with these
8 terms, please do not use, install, modify or redistribute this NVIDIA
11 In consideration of your agreement to abide by the following terms, and
12 subject to these terms, NVIDIA grants you a personal, non-exclusive
13 license, under NVIDIA's copyrights in this original NVIDIA software (the
14 "NVIDIA Software"), to use, reproduce, modify and redistribute the
15 NVIDIA Software, with or without modifications, in source and/or binary
16 forms; provided that if you redistribute the NVIDIA Software, you must
17 retain the copyright notice of NVIDIA, this notice and the following
18 text and disclaimers in all such redistributions of the NVIDIA Software.
19 Neither the name, trademarks, service marks nor logos of NVIDIA
20 Corporation may be used to endorse or promote products derived from the
21 NVIDIA Software without specific prior written permission from NVIDIA.
22 Except as expressly stated in this notice, no other rights or licenses
23 express or implied, are granted by NVIDIA herein, including but not
24 limited to any patent rights that may be infringed by your derivative
25 works or by other works in which the NVIDIA Software may be
26 incorporated. No hardware is licensed hereunder.
28 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
29 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
30 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
31 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
32 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
35 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
36 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
39 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
40 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
41 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 \****************************************************************************/
54 #include "compiler/preprocessor/slglobals.h"
56 static int CPPif(yystypepp * yylvalpp);
58 /* Don't use memory.c's replacements, as we clean up properly here */
62 static int bindAtom = 0;
63 static int constAtom = 0;
64 static int defaultAtom = 0;
65 static int defineAtom = 0;
66 static int definedAtom = 0;
67 static int elseAtom = 0;
68 static int elifAtom = 0;
69 static int endifAtom = 0;
70 static int ifAtom = 0;
71 static int ifdefAtom = 0;
72 static int ifndefAtom = 0;
73 static int includeAtom = 0;
74 static int lineAtom = 0;
75 static int pragmaAtom = 0;
76 static int texunitAtom = 0;
77 static int undefAtom = 0;
78 static int errorAtom = 0;
79 static int __LINE__Atom = 0;
80 static int __FILE__Atom = 0;
81 static int __VERSION__Atom = 0;
82 static int versionAtom = 0;
83 static int extensionAtom = 0;
85 static Scope *macros = 0;
86 #define MAX_MACRO_ARGS 64
88 static SourceLoc ifloc; /* outermost #if */
95 // Add various atoms needed by the CPP line scanner:
96 bindAtom = LookUpAddString(atable, "bind");
97 constAtom = LookUpAddString(atable, "const");
98 defaultAtom = LookUpAddString(atable, "default");
99 defineAtom = LookUpAddString(atable, "define");
100 definedAtom = LookUpAddString(atable, "defined");
101 elifAtom = LookUpAddString(atable, "elif");
102 elseAtom = LookUpAddString(atable, "else");
103 endifAtom = LookUpAddString(atable, "endif");
104 ifAtom = LookUpAddString(atable, "if");
105 ifdefAtom = LookUpAddString(atable, "ifdef");
106 ifndefAtom = LookUpAddString(atable, "ifndef");
107 includeAtom = LookUpAddString(atable, "include");
108 lineAtom = LookUpAddString(atable, "line");
109 pragmaAtom = LookUpAddString(atable, "pragma");
110 texunitAtom = LookUpAddString(atable, "texunit");
111 undefAtom = LookUpAddString(atable, "undef");
112 errorAtom = LookUpAddString(atable, "error");
113 __LINE__Atom = LookUpAddString(atable, "__LINE__");
114 __FILE__Atom = LookUpAddString(atable, "__FILE__");
115 __VERSION__Atom = LookUpAddString(atable, "__VERSION__");
116 versionAtom = LookUpAddString(atable, "version");
117 extensionAtom = LookUpAddString(atable, "extension");
118 macros = NewScopeInPool(mem_CreatePool(0, 0));
119 strcpy(buffer, "PROFILE_");
120 t = buffer + strlen(buffer);
121 f = cpp->options.profileString;
122 while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
123 *t++ = toupper(*f++);
126 PredefineIntMacro("GL_ES", 1);
127 PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
136 mem_FreePool(macros->pool);
146 CPPErrorToInfoLog("#if mismatch");
150 static int CPPdefine(yystypepp * yylvalpp)
152 int token, name, args[MAX_MACRO_ARGS], argc;
157 memset(&mac, 0, sizeof(mac));
158 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
159 if (token != CPP_IDENTIFIER) {
160 CPPErrorToInfoLog("#define");
163 name = yylvalpp->sc_ident;
164 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
165 if (token == '(' && !yylvalpp->sc_int) {
169 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
170 if (argc == 0 && token == ')') break;
171 if (token != CPP_IDENTIFIER) {
172 CPPErrorToInfoLog("#define");
175 if (argc < MAX_MACRO_ARGS)
176 args[argc++] = yylvalpp->sc_ident;
177 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
178 } while (token == ',');
180 CPPErrorToInfoLog("#define");
184 mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
185 memcpy(mac.args, args, argc * sizeof(int));
186 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
188 mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
189 while (token != '\n') {
191 CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
193 } else if (token <= 0) { // EOF or error
194 CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline");
197 RecordToken(mac.body, token, yylvalpp);
198 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
201 symb = LookUpSymbol(macros, name);
203 if (!symb->details.mac.undef) {
204 // already defined -- need to make sure they are identical
205 if (symb->details.mac.argc != mac.argc) goto error;
206 for (argc=0; argc < mac.argc; argc++)
207 if (symb->details.mac.args[argc] != mac.args[argc])
209 RewindTokenStream(symb->details.mac.body);
210 RewindTokenStream(mac.body);
212 int old_lval, old_token;
213 old_token = ReadToken(symb->details.mac.body, yylvalpp);
214 old_lval = yylvalpp->sc_int;
215 token = ReadToken(mac.body, yylvalpp);
216 if (token != old_token || yylvalpp->sc_int != old_lval) {
218 StoreStr("Macro Redefined");
219 StoreStr(GetStringOfAtom(atable,name));
220 message=GetStrfromTStr();
222 CPPShInfoLogMsg(message);
228 //FreeMacro(&symb->details.mac);
232 symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
234 symb->details.mac = mac;
238 static int CPPundef(yystypepp * yylvalpp)
240 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
243 CPPErrorToInfoLog("#undef");
246 if (token != CPP_IDENTIFIER)
248 symb = LookUpSymbol(macros, yylvalpp->sc_ident);
250 symb->details.mac.undef = 1;
252 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
255 CPPErrorToInfoLog("#undef");
260 /* CPPelse -- skip forward to appropriate spot. This is actually used
261 ** to skip to and #endif after seeing an #else, AND to skip to a #else,
262 ** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
265 static int CPPelse(int matchelse, yystypepp * yylvalpp)
268 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
272 while (token != '\n') {
273 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
274 if (token <= 0) { // EOF or error
275 CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline");
279 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
282 if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
284 atom = yylvalpp->sc_ident;
285 if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
286 depth++; cpp->ifdepth++; cpp->elsetracker++;
287 if (cpp->ifdepth > MAX_IF_NESTING) {
288 CPPErrorToInfoLog("max #if nesting depth exceeded");
289 cpp->CompileError = 1;
292 // sanity check elsetracker
293 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
294 CPPErrorToInfoLog("mismatched #if/#endif statements");
295 cpp->CompileError = 1;
298 cpp->elsedepth[cpp->elsetracker] = 0;
300 else if (atom == endifAtom) {
302 if (cpp->elsetracker)
311 else if (((int)(matchelse) != 0)&& depth==0) {
312 if (atom == elseAtom ) {
313 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
315 CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
316 while (token != '\n') {
317 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
318 if (token <= 0) { // EOF or error
319 CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline");
326 else if (atom == elifAtom) {
327 /* we decrement cpp->ifdepth here, because CPPif will increment
328 * it and we really want to leave it alone */
333 return CPPif(yylvalpp);
336 else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
337 CPPErrorToInfoLog("#else after a #else");
347 COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
351 static int op_logor(int a, int b) { return a || b; }
352 static int op_logand(int a, int b) { return a && b; }
353 static int op_or(int a, int b) { return a | b; }
354 static int op_xor(int a, int b) { return a ^ b; }
355 static int op_and(int a, int b) { return a & b; }
356 static int op_eq(int a, int b) { return a == b; }
357 static int op_ne(int a, int b) { return a != b; }
358 static int op_ge(int a, int b) { return a >= b; }
359 static int op_le(int a, int b) { return a <= b; }
360 static int op_gt(int a, int b) { return a > b; }
361 static int op_lt(int a, int b) { return a < b; }
362 static int op_shl(int a, int b) { return a << b; }
363 static int op_shr(int a, int b) { return a >> b; }
364 static int op_add(int a, int b) { return a + b; }
365 static int op_sub(int a, int b) { return a - b; }
366 static int op_mul(int a, int b) { return a * b; }
367 static int op_div(int a, int b) { return a / b; }
368 static int op_mod(int a, int b) { return a % b; }
369 static int op_pos(int a) { return a; }
370 static int op_neg(int a) { return -a; }
371 static int op_cmpl(int a) { return ~a; }
372 static int op_not(int a) { return !a; }
375 int token, prec, (*op)(int, int);
377 { CPP_OR_OP, LOGOR, op_logor },
378 { CPP_AND_OP, LOGAND, op_logand },
380 { '^', XOR, op_xor },
381 { '&', AND, op_and },
382 { CPP_EQ_OP, EQUAL, op_eq },
383 { CPP_NE_OP, EQUAL, op_ne },
384 { '>', RELATION, op_gt },
385 { CPP_GE_OP, RELATION, op_ge },
386 { '<', RELATION, op_lt },
387 { CPP_LE_OP, RELATION, op_le },
388 { CPP_LEFT_OP, SHIFT, op_shl },
389 { CPP_RIGHT_OP, SHIFT, op_shr },
390 { '+', ADD, op_add },
391 { '-', ADD, op_sub },
392 { '*', MUL, op_mul },
393 { '/', MUL, op_div },
394 { '%', MUL, op_mod },
398 int token, (*op)(int);
406 #define ALEN(A) (sizeof(A)/sizeof(A[0]))
408 static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
412 if (token == CPP_IDENTIFIER) {
413 if (yylvalpp->sc_ident == definedAtom) {
415 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
418 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
420 if (token != CPP_IDENTIFIER)
422 *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
423 ? !s->details.mac.undef : 0;
424 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
428 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
430 } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
431 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
432 return eval(token, prec, res, err, yylvalpp);
436 } else if (token == CPP_INTCONSTANT) {
437 *res = yylvalpp->sc_int;
438 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
439 } else if (token == '(') {
440 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
441 token = eval(token, MIN_PREC, res, err, yylvalpp);
445 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
448 for (i = ALEN(unop) - 1; i >= 0; i--) {
449 if (unop[i].token == token)
453 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
454 token = eval(token, UNARY, res, err, yylvalpp);
455 *res = unop[i].op(*res);
461 if (token == ')' || token == '\n') break;
462 for (i = ALEN(binop) - 1; i >= 0; i--) {
463 if (binop[i].token == token)
466 if (i < 0 || binop[i].prec <= prec)
469 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
470 token = eval(token, binop[i].prec, res, err, yylvalpp);
472 if (binop[i].op == op_div || binop[i].op == op_mod)
476 CPPErrorToInfoLog("preprocessor divide or modulo by zero");
482 *res = binop[i].op(val, *res);
486 CPPErrorToInfoLog("incorrect preprocessor directive");
492 static int CPPif(yystypepp * yylvalpp) {
493 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
494 int res = 0, err = 0;
497 ifloc = *cpp->tokenLoc;
498 if(cpp->ifdepth > MAX_IF_NESTING){
499 CPPErrorToInfoLog("max #if nesting depth exceeded");
500 cpp->CompileError = 1;
504 // sanity check elsetracker
505 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
506 CPPErrorToInfoLog("mismatched #if/#endif statements");
507 cpp->CompileError = 1;
510 cpp->elsedepth[cpp->elsetracker] = 0;
512 token = eval(token, MIN_PREC, &res, &err, yylvalpp);
514 CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
515 while (token != '\n') {
516 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
517 if (token <= 0) { // EOF or error
518 CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline");
524 token = CPPelse(1, yylvalpp);
530 static int CPPifdef(int defined, yystypepp * yylvalpp)
532 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
533 int name = yylvalpp->sc_ident;
534 if(++cpp->ifdepth > MAX_IF_NESTING){
535 CPPErrorToInfoLog("max #if nesting depth exceeded");
536 cpp->CompileError = 1;
540 // sanity check elsetracker
541 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
542 CPPErrorToInfoLog("mismatched #if/#endif statements");
543 cpp->CompileError = 1;
546 cpp->elsedepth[cpp->elsetracker] = 0;
548 if (token != CPP_IDENTIFIER) {
549 defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
551 Symbol *s = LookUpSymbol(macros, name);
552 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
554 CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
555 while (token != '\n') {
556 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
557 if (token <= 0) { // EOF or error
558 CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
563 if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
564 token = CPPelse(1, yylvalpp);
569 static int CPPline(yystypepp * yylvalpp)
571 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
574 CPPErrorToInfoLog("#line");
578 else if (token == CPP_INTCONSTANT) {
579 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
580 SetLineNumber(yylvalpp->sc_int);
581 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
583 if (token == CPP_INTCONSTANT) {
584 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
585 SetStringNumber(yylvalpp->sc_int);
586 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
588 CPPErrorToInfoLog("#line");
590 else if (token == '\n'){
594 CPPErrorToInfoLog("#line");
598 CPPErrorToInfoLog("#line");
603 static int CPPerror(yystypepp * yylvalpp) {
605 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
608 while (token != '\n') {
610 CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline");
612 }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
613 StoreStr(yylvalpp->symbol_name);
614 }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
615 StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
617 StoreStr(GetStringOfAtom(atable,token));
619 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
622 //store this msg into the shader's information log..set the Compile Error flag!!!!
623 message=GetStrfromTStr();
624 CPPShInfoLogMsg(message);
631 static int CPPpragma(yystypepp * yylvalpp)
636 int maxTokenCount = 10;
640 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
644 CPPErrorToInfoLog("#pragma");
649 allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);
651 while (token != '\n') {
652 if (tokenCount >= maxTokenCount) {
654 allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
658 SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
659 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
660 strcpy(allTokens[tokenCount++], SrcStr);
662 case CPP_INTCONSTANT:
663 SrcStr = yylvalpp->symbol_name;
664 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
665 strcpy(allTokens[tokenCount++], SrcStr);
667 case CPP_FLOATCONSTANT:
668 SrcStr = yylvalpp->symbol_name;
669 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
670 strcpy(allTokens[tokenCount++], SrcStr);
674 CPPShInfoLogMsg("#pragma directive must end with a newline");
677 SrcStrName[0] = token;
678 SrcStrName[1] = '\0';
679 allTokens[tokenCount] = (char*)malloc(2);
680 strcpy(allTokens[tokenCount++], SrcStrName);
682 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
685 cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
686 HandlePragma((const char**)allTokens, tokenCount);
687 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
689 for (i = 0; i < tokenCount; ++i) {
697 #define ESSL_VERSION_NUMBER 100
698 #define ESSL_VERSION_STRING "100"
700 static int CPPversion(yystypepp * yylvalpp)
703 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
705 if (cpp->pastFirstStatement == 1)
706 CPPShInfoLogMsg("#version must occur before any other statement in the program");
710 CPPErrorToInfoLog("#version");
714 if (token != CPP_INTCONSTANT)
715 CPPErrorToInfoLog("#version");
717 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
718 //SetVersionNumber(yylvalpp->sc_int);
720 if (yylvalpp->sc_int != ESSL_VERSION_NUMBER)
721 CPPShInfoLogMsg("Version number not supported by ESSL");
723 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
729 CPPErrorToInfoLog("#version");
734 static int CPPextension(yystypepp * yylvalpp)
737 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
738 char extensionName[MAX_SYMBOL_NAME_LEN + 1];
742 CPPShInfoLogMsg("extension name not specified");
747 if (token != CPP_IDENTIFIER)
748 CPPErrorToInfoLog("#extension");
750 strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN);
751 extensionName[MAX_SYMBOL_NAME_LEN] = '\0';
753 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
755 CPPShInfoLogMsg("':' missing after extension name");
759 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
760 if (token != CPP_IDENTIFIER) {
761 CPPShInfoLogMsg("behavior for extension not specified");
765 updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
767 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
772 CPPErrorToInfoLog("#extension");
777 int readCPPline(yystypepp * yylvalpp)
779 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
783 if (token == CPP_IDENTIFIER) {
784 if (yylvalpp->sc_ident == defineAtom) {
785 token = CPPdefine(yylvalpp);
786 } else if (yylvalpp->sc_ident == elseAtom) {
787 if(ChkCorrectElseNesting()){
789 CPPErrorToInfoLog("#else mismatch");
793 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
795 CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
796 while (token != '\n') {
797 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
798 if (token <= 0) { // EOF or error
799 CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
804 token = CPPelse(0, yylvalpp);
806 CPPErrorToInfoLog("#else after a #else");
808 cpp->elsetracker = 0;
809 cpp->pastFirstStatement = 1;
810 cpp->CompileError = 1;
813 } else if (yylvalpp->sc_ident == elifAtom) {
815 CPPErrorToInfoLog("#elif mismatch");
819 // this token is really a dont care, but we still need to eat the tokens
820 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
821 while (token != '\n') {
822 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
823 if (token <= 0) { // EOF or error
824 CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
825 cpp->CompileError = 1;
829 token = CPPelse(0, yylvalpp);
830 } else if (yylvalpp->sc_ident == endifAtom) {
832 CPPErrorToInfoLog("#endif mismatch");
839 if (cpp->elsetracker)
842 } else if (yylvalpp->sc_ident == ifAtom) {
843 token = CPPif(yylvalpp);
844 } else if (yylvalpp->sc_ident == ifdefAtom) {
845 token = CPPifdef(1, yylvalpp);
846 } else if (yylvalpp->sc_ident == ifndefAtom) {
847 token = CPPifdef(0, yylvalpp);
848 } else if (yylvalpp->sc_ident == lineAtom) {
849 token = CPPline(yylvalpp);
850 } else if (yylvalpp->sc_ident == pragmaAtom) {
851 token = CPPpragma(yylvalpp);
852 } else if (yylvalpp->sc_ident == undefAtom) {
853 token = CPPundef(yylvalpp);
854 } else if (yylvalpp->sc_ident == errorAtom) {
855 token = CPPerror(yylvalpp);
856 } else if (yylvalpp->sc_ident == versionAtom) {
857 token = CPPversion(yylvalpp);
859 } else if (yylvalpp->sc_ident == extensionAtom) {
860 token = CPPextension(yylvalpp);
862 StoreStr("Invalid Directive");
863 StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
864 message=GetStrfromTStr();
865 CPPShInfoLogMsg(message);
869 while (token != '\n' && token != 0 && token != EOF) {
870 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
873 cpp->pastFirstStatement = 1;
878 void FreeMacro(MacroSymbol *s) {
879 DeleteTokenStream(s->body);
882 void PredefineIntMacro(const char *name, int value) {
883 SourceLoc location = {0};
884 Symbol *symbol = NULL;
885 MacroSymbol macro = {0};
889 macro.body = NewTokenStream(name, macros->pool);
891 sprintf(val.symbol_name, "%d", value);
892 RecordToken(macro.body, CPP_INTCONSTANT, &val);
893 atom = LookUpAddString(atable, name);
894 symbol = AddSymbol(&location, macros, atom, MACRO_S);
895 symbol->details.mac = macro;
898 static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
899 static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
901 static void PushEofSrc() {
902 InputSrc *in = malloc(sizeof(InputSrc));
903 memset(in, 0, sizeof(InputSrc));
905 in->getch = eof_scan;
907 in->prev = cpp->currentInput;
908 cpp->currentInput = in;
911 static void PopEofSrc() {
912 if (cpp->currentInput->scan == eof_scan) {
913 InputSrc *in = cpp->currentInput;
914 cpp->currentInput = in->prev;
919 static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
922 RewindTokenStream(a);
924 token = ReadToken(a, yylvalpp);
925 if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
928 if (token <= 0) return a;
929 n = NewTokenStream("macro arg", 0);
931 ReadFromTokenStream(a, 0, 0);
932 while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
933 if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
935 RecordToken(n, token, yylvalpp);
938 DeleteTokenStream(a);
942 typedef struct MacroInputSrc {
949 ** return the next token for a macro expanion, handling macro args
951 static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
953 int token = ReadToken(in->mac->body, yylvalpp);
954 if (token == CPP_IDENTIFIER) {
955 for (i = in->mac->argc-1; i>=0; i--)
956 if (in->mac->args[i] == yylvalpp->sc_ident) break;
958 ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
959 return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
962 if (token > 0) return token;
964 cpp->currentInput = in->base.prev;
966 for (i=in->mac->argc-1; i>=0; i--)
967 DeleteTokenStream(in->args[i]);
971 return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
975 ** check an identifier (atom) to see if it a macro that should be expanded.
976 ** If it is, push an InputSrc that will produce the appropriate expansion
977 ** and return TRUE. If not, return FALSE.
980 int MacroExpand(int atom, yystypepp * yylvalpp)
982 Symbol *sym = LookUpSymbol(macros, atom);
984 int i,j, token, depth=0;
986 if (atom == __LINE__Atom) {
987 yylvalpp->sc_int = GetLineNumber();
988 sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
989 UngetToken(CPP_INTCONSTANT, yylvalpp);
992 if (atom == __FILE__Atom) {
993 yylvalpp->sc_int = GetStringNumber();
994 sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
995 UngetToken(CPP_INTCONSTANT, yylvalpp);
998 if (atom == __VERSION__Atom) {
999 strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING);
1000 yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
1001 UngetToken(CPP_INTCONSTANT, yylvalpp);
1004 if (!sym || sym->details.mac.undef) return 0;
1005 if (sym->details.mac.busy) return 0; // no recursive expansions
1006 in = malloc(sizeof(*in));
1007 memset(in, 0, sizeof(*in));
1008 in->base.scan = (void *)macro_scan;
1009 in->base.line = cpp->currentInput->line;
1010 in->base.name = cpp->currentInput->name;
1011 in->mac = &sym->details.mac;
1012 if (sym->details.mac.args) {
1013 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1015 UngetToken(token, yylvalpp);
1016 yylvalpp->sc_ident = atom;
1019 in->args = malloc(in->mac->argc * sizeof(TokenStream *));
1020 for (i=0; i<in->mac->argc; i++)
1021 in->args[i] = NewTokenStream("macro arg", 0);
1026 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1028 StoreStr("EOF in Macro ");
1029 StoreStr(GetStringOfAtom(atable,atom));
1030 message=GetStrfromTStr();
1031 CPPShInfoLogMsg(message);
1035 if((in->mac->argc==0) && (token!=')')) break;
1036 if (depth == 0 && (token == ',' || token == ')')) break;
1037 if (token == '(') depth++;
1038 if (token == ')') depth--;
1039 RecordToken(in->args[i], token, yylvalpp);
1043 if((in->mac->argc==1) &&j==0)
1049 }while(i < in->mac->argc);
1051 if (i < in->mac->argc) {
1052 StoreStr("Too few args in Macro ");
1053 StoreStr(GetStringOfAtom(atable,atom));
1054 message=GetStrfromTStr();
1055 CPPShInfoLogMsg(message);
1057 } else if (token != ')') {
1059 while (token >= 0 && (depth > 0 || token != ')')) {
1060 if (token == ')') depth--;
1061 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1062 if (token == '(') depth++;
1066 StoreStr("EOF in Macro ");
1067 StoreStr(GetStringOfAtom(atable,atom));
1068 message=GetStrfromTStr();
1069 CPPShInfoLogMsg(message);
1073 StoreStr("Too many args in Macro ");
1074 StoreStr(GetStringOfAtom(atable,atom));
1075 message=GetStrfromTStr();
1076 CPPShInfoLogMsg(message);
1079 for (i=0; i<in->mac->argc; i++) {
1080 in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
1084 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
1085 loc.line, GetAtomString(atable, atom));
1086 for (i=0; i<in->mac->argc; i++) {
1087 printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
1088 DumpTokenStream(stdout, in->args[i]);
1092 /*retain the input source*/
1093 in->base.prev = cpp->currentInput;
1094 sym->details.mac.busy = 1;
1095 RewindTokenStream(sym->details.mac.body);
1096 cpp->currentInput = &in->base;
1100 int ChkCorrectElseNesting(void)
1102 // sanity check to make sure elsetracker is in a valid range
1103 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
1107 if (cpp->elsedepth[cpp->elsetracker] == 0) {
1108 cpp->elsedepth[cpp->elsetracker] = 1;