1 : /****************************************************************************\
2 : Copyright (c) 2002, NVIDIA Corporation.
3 :
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
9 : software.
10 :
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.
27 :
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
33 : PRODUCTS.
34 :
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 : \****************************************************************************/
44 : //
45 : // cpp.c
46 : //
47 :
48 : #include <stdarg.h>
49 : #include <stdio.h>
50 : #include <stdlib.h>
51 : #include <string.h>
52 : #include <ctype.h>
53 :
54 : #include "compiler/preprocessor/slglobals.h"
55 :
56 : static int CPPif(yystypepp * yylvalpp);
57 :
58 : /* Don't use memory.c's replacements, as we clean up properly here */
59 : #undef malloc
60 : #undef free
61 :
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;
84 :
85 : static Scope *macros = 0;
86 : #define MAX_MACRO_ARGS 64
87 :
88 : static SourceLoc ifloc; /* outermost #if */
89 :
90 0 : int InitCPP(void)
91 : {
92 : char buffer[64], *t;
93 : const char *f;
94 :
95 : // Add various atoms needed by the CPP line scanner:
96 0 : bindAtom = LookUpAddString(atable, "bind");
97 0 : constAtom = LookUpAddString(atable, "const");
98 0 : defaultAtom = LookUpAddString(atable, "default");
99 0 : defineAtom = LookUpAddString(atable, "define");
100 0 : definedAtom = LookUpAddString(atable, "defined");
101 0 : elifAtom = LookUpAddString(atable, "elif");
102 0 : elseAtom = LookUpAddString(atable, "else");
103 0 : endifAtom = LookUpAddString(atable, "endif");
104 0 : ifAtom = LookUpAddString(atable, "if");
105 0 : ifdefAtom = LookUpAddString(atable, "ifdef");
106 0 : ifndefAtom = LookUpAddString(atable, "ifndef");
107 0 : includeAtom = LookUpAddString(atable, "include");
108 0 : lineAtom = LookUpAddString(atable, "line");
109 0 : pragmaAtom = LookUpAddString(atable, "pragma");
110 0 : texunitAtom = LookUpAddString(atable, "texunit");
111 0 : undefAtom = LookUpAddString(atable, "undef");
112 0 : errorAtom = LookUpAddString(atable, "error");
113 0 : __LINE__Atom = LookUpAddString(atable, "__LINE__");
114 0 : __FILE__Atom = LookUpAddString(atable, "__FILE__");
115 0 : __VERSION__Atom = LookUpAddString(atable, "__VERSION__");
116 0 : versionAtom = LookUpAddString(atable, "version");
117 0 : extensionAtom = LookUpAddString(atable, "extension");
118 0 : macros = NewScopeInPool(mem_CreatePool(0, 0));
119 0 : strcpy(buffer, "PROFILE_");
120 0 : t = buffer + strlen(buffer);
121 0 : f = cpp->options.profileString;
122 0 : while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
123 0 : *t++ = toupper(*f++);
124 0 : *t = 0;
125 :
126 0 : PredefineIntMacro("GL_ES", 1);
127 0 : PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
128 :
129 0 : return 1;
130 : } // InitCPP
131 :
132 0 : int FreeCPP(void)
133 : {
134 0 : if (macros)
135 : {
136 0 : mem_FreePool(macros->pool);
137 0 : macros = 0;
138 : }
139 :
140 0 : return 1;
141 : }
142 :
143 0 : int FinalCPP(void)
144 : {
145 0 : if (cpp->ifdepth)
146 0 : CPPErrorToInfoLog("#if mismatch");
147 0 : return 1;
148 : }
149 :
150 0 : static int CPPdefine(yystypepp * yylvalpp)
151 : {
152 : int token, name, args[MAX_MACRO_ARGS], argc;
153 : const char *message;
154 : MacroSymbol mac;
155 : Symbol *symb;
156 : SourceLoc dummyLoc;
157 0 : memset(&mac, 0, sizeof(mac));
158 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
159 0 : if (token != CPP_IDENTIFIER) {
160 0 : CPPErrorToInfoLog("#define");
161 0 : return token;
162 : }
163 0 : name = yylvalpp->sc_ident;
164 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
165 0 : if (token == '(' && !yylvalpp->sc_int) {
166 : // gather arguments
167 0 : argc = 0;
168 : do {
169 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
170 0 : if (argc == 0 && token == ')') break;
171 0 : if (token != CPP_IDENTIFIER) {
172 0 : CPPErrorToInfoLog("#define");
173 0 : return token;
174 : }
175 0 : if (argc < MAX_MACRO_ARGS)
176 0 : args[argc++] = yylvalpp->sc_ident;
177 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
178 0 : } while (token == ',');
179 0 : if (token != ')') {
180 0 : CPPErrorToInfoLog("#define");
181 0 : return token;
182 : }
183 0 : mac.argc = argc;
184 0 : mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
185 0 : memcpy(mac.args, args, argc * sizeof(int));
186 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
187 : }
188 0 : mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
189 0 : while (token != '\n') {
190 0 : if (token == '\\') {
191 0 : CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
192 0 : return token;
193 0 : } else if (token <= 0) { // EOF or error
194 0 : CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline");
195 0 : return 0;
196 : }
197 0 : RecordToken(mac.body, token, yylvalpp);
198 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
199 : };
200 :
201 0 : symb = LookUpSymbol(macros, name);
202 0 : if (symb) {
203 0 : if (!symb->details.mac.undef) {
204 : // already defined -- need to make sure they are identical
205 0 : if (symb->details.mac.argc != mac.argc) goto error;
206 0 : for (argc=0; argc < mac.argc; argc++)
207 0 : if (symb->details.mac.args[argc] != mac.args[argc])
208 0 : goto error;
209 0 : RewindTokenStream(symb->details.mac.body);
210 0 : RewindTokenStream(mac.body);
211 : do {
212 : int old_lval, old_token;
213 0 : old_token = ReadToken(symb->details.mac.body, yylvalpp);
214 0 : old_lval = yylvalpp->sc_int;
215 0 : token = ReadToken(mac.body, yylvalpp);
216 0 : if (token != old_token || yylvalpp->sc_int != old_lval) {
217 : error:
218 0 : StoreStr("Macro Redefined");
219 0 : StoreStr(GetStringOfAtom(atable,name));
220 0 : message=GetStrfromTStr();
221 0 : DecLineNumber();
222 0 : CPPShInfoLogMsg(message);
223 0 : IncLineNumber();
224 0 : ResetTString();
225 0 : break; }
226 0 : } while (token > 0);
227 : }
228 : //FreeMacro(&symb->details.mac);
229 : } else {
230 0 : dummyLoc.file = 0;
231 0 : dummyLoc.line = 0;
232 0 : symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
233 : }
234 0 : symb->details.mac = mac;
235 0 : return '\n';
236 : } // CPPdefine
237 :
238 0 : static int CPPundef(yystypepp * yylvalpp)
239 : {
240 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
241 : Symbol *symb;
242 0 : if(token == '\n'){
243 0 : CPPErrorToInfoLog("#undef");
244 0 : return token;
245 : }
246 0 : if (token != CPP_IDENTIFIER)
247 0 : goto error;
248 0 : symb = LookUpSymbol(macros, yylvalpp->sc_ident);
249 0 : if (symb) {
250 0 : symb->details.mac.undef = 1;
251 : }
252 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
253 0 : if (token != '\n') {
254 : error:
255 0 : CPPErrorToInfoLog("#undef");
256 : }
257 0 : return token;
258 : } // CPPundef
259 :
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
263 : */
264 :
265 0 : static int CPPelse(int matchelse, yystypepp * yylvalpp)
266 : {
267 0 : int atom,depth=0;
268 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
269 :
270 0 : while (token > 0) {
271 0 : if (token != '#') {
272 0 : while (token != '\n') {
273 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
274 0 : if (token <= 0) { // EOF or error
275 0 : CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline");
276 0 : return 0;
277 : }
278 : }
279 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
280 0 : continue;
281 : }
282 0 : if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
283 0 : continue;
284 0 : atom = yylvalpp->sc_ident;
285 0 : if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
286 0 : depth++; cpp->ifdepth++; cpp->elsetracker++;
287 0 : if (cpp->ifdepth > MAX_IF_NESTING) {
288 0 : CPPErrorToInfoLog("max #if nesting depth exceeded");
289 0 : cpp->CompileError = 1;
290 0 : return 0;
291 : }
292 : // sanity check elsetracker
293 0 : if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
294 0 : CPPErrorToInfoLog("mismatched #if/#endif statements");
295 0 : cpp->CompileError = 1;
296 0 : return 0;
297 : }
298 0 : cpp->elsedepth[cpp->elsetracker] = 0;
299 : }
300 0 : else if (atom == endifAtom) {
301 0 : if(--depth<0){
302 0 : if (cpp->elsetracker)
303 0 : --cpp->elsetracker;
304 0 : if (cpp->ifdepth)
305 0 : --cpp->ifdepth;
306 0 : break;
307 : }
308 0 : --cpp->elsetracker;
309 0 : --cpp->ifdepth;
310 : }
311 0 : else if (((int)(matchelse) != 0)&& depth==0) {
312 0 : if (atom == elseAtom ) {
313 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
314 0 : if (token != '\n') {
315 0 : CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
316 0 : while (token != '\n') {
317 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
318 0 : if (token <= 0) { // EOF or error
319 0 : CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline");
320 0 : return 0;
321 : }
322 : }
323 : }
324 0 : break;
325 : }
326 0 : else if (atom == elifAtom) {
327 : /* we decrement cpp->ifdepth here, because CPPif will increment
328 : * it and we really want to leave it alone */
329 0 : if (cpp->ifdepth){
330 0 : --cpp->ifdepth;
331 0 : --cpp->elsetracker;
332 : }
333 0 : return CPPif(yylvalpp);
334 : }
335 : }
336 0 : else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
337 0 : CPPErrorToInfoLog("#else after a #else");
338 0 : cpp->CompileError=1;
339 0 : return 0;
340 : }
341 : };
342 0 : return token;
343 : }
344 :
345 : enum eval_prec {
346 : MIN_PREC,
347 : COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
348 : MAX_PREC
349 : };
350 :
351 0 : static int op_logor(int a, int b) { return a || b; }
352 0 : static int op_logand(int a, int b) { return a && b; }
353 0 : static int op_or(int a, int b) { return a | b; }
354 0 : static int op_xor(int a, int b) { return a ^ b; }
355 0 : static int op_and(int a, int b) { return a & b; }
356 0 : static int op_eq(int a, int b) { return a == b; }
357 0 : static int op_ne(int a, int b) { return a != b; }
358 0 : static int op_ge(int a, int b) { return a >= b; }
359 0 : static int op_le(int a, int b) { return a <= b; }
360 0 : static int op_gt(int a, int b) { return a > b; }
361 0 : static int op_lt(int a, int b) { return a < b; }
362 0 : static int op_shl(int a, int b) { return a << b; }
363 0 : static int op_shr(int a, int b) { return a >> b; }
364 0 : static int op_add(int a, int b) { return a + b; }
365 0 : static int op_sub(int a, int b) { return a - b; }
366 0 : static int op_mul(int a, int b) { return a * b; }
367 0 : static int op_div(int a, int b) { return a / b; }
368 0 : static int op_mod(int a, int b) { return a % b; }
369 0 : static int op_pos(int a) { return a; }
370 0 : static int op_neg(int a) { return -a; }
371 0 : static int op_cmpl(int a) { return ~a; }
372 0 : static int op_not(int a) { return !a; }
373 :
374 : struct {
375 : int token, prec, (*op)(int, int);
376 : } binop[] = {
377 : { CPP_OR_OP, LOGOR, op_logor },
378 : { CPP_AND_OP, LOGAND, op_logand },
379 : { '|', OR, op_or },
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 },
395 : };
396 :
397 : struct {
398 : int token, (*op)(int);
399 : } unop[] = {
400 : { '+', op_pos },
401 : { '-', op_neg },
402 : { '~', op_cmpl },
403 : { '!', op_not },
404 : };
405 :
406 : #define ALEN(A) (sizeof(A)/sizeof(A[0]))
407 :
408 0 : static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
409 : {
410 : int i, val;
411 : Symbol *s;
412 0 : if (token == CPP_IDENTIFIER) {
413 0 : if (yylvalpp->sc_ident == definedAtom) {
414 0 : int needclose = 0;
415 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
416 0 : if (token == '(') {
417 0 : needclose = 1;
418 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
419 : }
420 0 : if (token != CPP_IDENTIFIER)
421 0 : goto error;
422 0 : *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
423 0 : ? !s->details.mac.undef : 0;
424 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
425 0 : if (needclose) {
426 0 : if (token != ')')
427 0 : goto error;
428 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
429 : }
430 0 : } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
431 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
432 0 : return eval(token, prec, res, err, yylvalpp);
433 : } else {
434 0 : goto error;
435 : }
436 0 : } else if (token == CPP_INTCONSTANT) {
437 0 : *res = yylvalpp->sc_int;
438 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
439 0 : } else if (token == '(') {
440 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
441 0 : token = eval(token, MIN_PREC, res, err, yylvalpp);
442 0 : if (!*err) {
443 0 : if (token != ')')
444 0 : goto error;
445 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
446 : }
447 : } else {
448 0 : for (i = ALEN(unop) - 1; i >= 0; i--) {
449 0 : if (unop[i].token == token)
450 0 : break;
451 : }
452 0 : if (i >= 0) {
453 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
454 0 : token = eval(token, UNARY, res, err, yylvalpp);
455 0 : *res = unop[i].op(*res);
456 : } else {
457 0 : goto error;
458 : }
459 : }
460 0 : while (!*err) {
461 0 : if (token == ')' || token == '\n') break;
462 0 : for (i = ALEN(binop) - 1; i >= 0; i--) {
463 0 : if (binop[i].token == token)
464 0 : break;
465 : }
466 0 : if (i < 0 || binop[i].prec <= prec)
467 : break;
468 0 : val = *res;
469 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
470 0 : token = eval(token, binop[i].prec, res, err, yylvalpp);
471 :
472 0 : if (binop[i].op == op_div || binop[i].op == op_mod)
473 : {
474 0 : if (*res == 0)
475 : {
476 0 : CPPErrorToInfoLog("preprocessor divide or modulo by zero");
477 0 : *err = 1;
478 0 : return token;
479 : }
480 : }
481 :
482 0 : *res = binop[i].op(val, *res);
483 : }
484 0 : return token;
485 : error:
486 0 : CPPErrorToInfoLog("incorrect preprocessor directive");
487 0 : *err = 1;
488 0 : *res = 0;
489 0 : return token;
490 : } // eval
491 :
492 0 : static int CPPif(yystypepp * yylvalpp) {
493 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
494 0 : int res = 0, err = 0;
495 :
496 0 : if (!cpp->ifdepth++)
497 0 : ifloc = *cpp->tokenLoc;
498 0 : if(cpp->ifdepth > MAX_IF_NESTING){
499 0 : CPPErrorToInfoLog("max #if nesting depth exceeded");
500 0 : cpp->CompileError = 1;
501 0 : return 0;
502 : }
503 0 : cpp->elsetracker++;
504 : // sanity check elsetracker
505 0 : if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
506 0 : CPPErrorToInfoLog("mismatched #if/#endif statements");
507 0 : cpp->CompileError = 1;
508 0 : return 0;
509 : }
510 0 : cpp->elsedepth[cpp->elsetracker] = 0;
511 :
512 0 : token = eval(token, MIN_PREC, &res, &err, yylvalpp);
513 0 : if (token != '\n') {
514 0 : CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
515 0 : while (token != '\n') {
516 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
517 0 : if (token <= 0) { // EOF or error
518 0 : CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline");
519 0 : return 0;
520 : }
521 : }
522 : }
523 0 : if (!res && !err) {
524 0 : token = CPPelse(1, yylvalpp);
525 : }
526 :
527 0 : return token;
528 : } // CPPif
529 :
530 0 : static int CPPifdef(int defined, yystypepp * yylvalpp)
531 : {
532 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
533 0 : int name = yylvalpp->sc_ident;
534 0 : if(++cpp->ifdepth > MAX_IF_NESTING){
535 0 : CPPErrorToInfoLog("max #if nesting depth exceeded");
536 0 : cpp->CompileError = 1;
537 0 : return 0;
538 : }
539 0 : cpp->elsetracker++;
540 : // sanity check elsetracker
541 0 : if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
542 0 : CPPErrorToInfoLog("mismatched #if/#endif statements");
543 0 : cpp->CompileError = 1;
544 0 : return 0;
545 : }
546 0 : cpp->elsedepth[cpp->elsetracker] = 0;
547 :
548 0 : if (token != CPP_IDENTIFIER) {
549 0 : defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
550 : } else {
551 0 : Symbol *s = LookUpSymbol(macros, name);
552 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
553 0 : if (token != '\n') {
554 0 : CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
555 0 : while (token != '\n') {
556 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
557 0 : if (token <= 0) { // EOF or error
558 0 : CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
559 0 : return 0;
560 : }
561 : }
562 : }
563 0 : if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
564 0 : token = CPPelse(1, yylvalpp);
565 : }
566 0 : return token;
567 : } // CPPifdef
568 :
569 0 : static int CPPline(yystypepp * yylvalpp)
570 : {
571 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
572 0 : if(token=='\n'){
573 0 : DecLineNumber();
574 0 : CPPErrorToInfoLog("#line");
575 0 : IncLineNumber();
576 0 : return token;
577 : }
578 0 : else if (token == CPP_INTCONSTANT) {
579 0 : yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
580 0 : SetLineNumber(yylvalpp->sc_int);
581 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
582 :
583 0 : if (token == CPP_INTCONSTANT) {
584 0 : yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
585 0 : SetStringNumber(yylvalpp->sc_int);
586 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
587 0 : if(token!='\n')
588 0 : CPPErrorToInfoLog("#line");
589 : }
590 0 : else if (token == '\n'){
591 0 : return token;
592 : }
593 : else{
594 0 : CPPErrorToInfoLog("#line");
595 : }
596 : }
597 : else{
598 0 : CPPErrorToInfoLog("#line");
599 : }
600 0 : return token;
601 : }
602 :
603 0 : static int CPPerror(yystypepp * yylvalpp) {
604 :
605 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
606 : const char *message;
607 :
608 0 : while (token != '\n') {
609 0 : if (token <= 0){
610 0 : CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline");
611 0 : return 0;
612 0 : }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
613 0 : StoreStr(yylvalpp->symbol_name);
614 0 : }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
615 0 : StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
616 : }else {
617 0 : StoreStr(GetStringOfAtom(atable,token));
618 : }
619 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
620 : }
621 0 : DecLineNumber();
622 : //store this msg into the shader's information log..set the Compile Error flag!!!!
623 0 : message=GetStrfromTStr();
624 0 : CPPShInfoLogMsg(message);
625 0 : ResetTString();
626 0 : cpp->CompileError=1;
627 0 : IncLineNumber();
628 0 : return '\n';
629 : }//CPPerror
630 :
631 0 : static int CPPpragma(yystypepp * yylvalpp)
632 : {
633 : char SrcStrName[2];
634 : char** allTokens;
635 0 : int tokenCount = 0;
636 0 : int maxTokenCount = 10;
637 : const char* SrcStr;
638 : int i;
639 :
640 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
641 :
642 0 : if (token=='\n') {
643 0 : DecLineNumber();
644 0 : CPPErrorToInfoLog("#pragma");
645 0 : IncLineNumber();
646 0 : return token;
647 : }
648 :
649 0 : allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);
650 :
651 0 : while (token != '\n') {
652 0 : if (tokenCount >= maxTokenCount) {
653 0 : maxTokenCount *= 2;
654 0 : allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
655 : }
656 0 : switch (token) {
657 : case CPP_IDENTIFIER:
658 0 : SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
659 0 : allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
660 0 : strcpy(allTokens[tokenCount++], SrcStr);
661 0 : break;
662 : case CPP_INTCONSTANT:
663 0 : SrcStr = yylvalpp->symbol_name;
664 0 : allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
665 0 : strcpy(allTokens[tokenCount++], SrcStr);
666 0 : break;
667 : case CPP_FLOATCONSTANT:
668 0 : SrcStr = yylvalpp->symbol_name;
669 0 : allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
670 0 : strcpy(allTokens[tokenCount++], SrcStr);
671 0 : break;
672 : case -1:
673 : // EOF
674 0 : CPPShInfoLogMsg("#pragma directive must end with a newline");
675 0 : return token;
676 : default:
677 0 : SrcStrName[0] = token;
678 0 : SrcStrName[1] = '\0';
679 0 : allTokens[tokenCount] = (char*)malloc(2);
680 0 : strcpy(allTokens[tokenCount++], SrcStrName);
681 : }
682 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
683 : }
684 :
685 0 : cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
686 0 : HandlePragma((const char**)allTokens, tokenCount);
687 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
688 :
689 0 : for (i = 0; i < tokenCount; ++i) {
690 0 : free (allTokens[i]);
691 : }
692 0 : free (allTokens);
693 :
694 0 : return token;
695 : } // CPPpragma
696 :
697 : #define ESSL_VERSION_NUMBER 100
698 : #define ESSL_VERSION_STRING "100"
699 :
700 0 : static int CPPversion(yystypepp * yylvalpp)
701 : {
702 :
703 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
704 :
705 0 : if (cpp->pastFirstStatement == 1)
706 0 : CPPShInfoLogMsg("#version must occur before any other statement in the program");
707 :
708 0 : if(token=='\n'){
709 0 : DecLineNumber();
710 0 : CPPErrorToInfoLog("#version");
711 0 : IncLineNumber();
712 0 : return token;
713 : }
714 0 : if (token != CPP_INTCONSTANT)
715 0 : CPPErrorToInfoLog("#version");
716 :
717 0 : yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
718 : //SetVersionNumber(yylvalpp->sc_int);
719 :
720 0 : if (yylvalpp->sc_int != ESSL_VERSION_NUMBER)
721 0 : CPPShInfoLogMsg("Version number not supported by ESSL");
722 :
723 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
724 :
725 0 : if (token == '\n'){
726 0 : return token;
727 : }
728 : else{
729 0 : CPPErrorToInfoLog("#version");
730 : }
731 0 : return token;
732 : } // CPPversion
733 :
734 0 : static int CPPextension(yystypepp * yylvalpp)
735 : {
736 :
737 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
738 : char extensionName[MAX_SYMBOL_NAME_LEN + 1];
739 :
740 0 : if(token=='\n'){
741 0 : DecLineNumber();
742 0 : CPPShInfoLogMsg("extension name not specified");
743 0 : IncLineNumber();
744 0 : return token;
745 : }
746 :
747 0 : if (token != CPP_IDENTIFIER)
748 0 : CPPErrorToInfoLog("#extension");
749 :
750 0 : strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN);
751 0 : extensionName[MAX_SYMBOL_NAME_LEN] = '\0';
752 :
753 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
754 0 : if (token != ':') {
755 0 : CPPShInfoLogMsg("':' missing after extension name");
756 0 : return token;
757 : }
758 :
759 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
760 0 : if (token != CPP_IDENTIFIER) {
761 0 : CPPShInfoLogMsg("behavior for extension not specified");
762 0 : return token;
763 : }
764 :
765 0 : updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
766 :
767 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
768 0 : if (token == '\n'){
769 0 : return token;
770 : }
771 : else{
772 0 : CPPErrorToInfoLog("#extension");
773 : }
774 0 : return token;
775 : } // CPPextension
776 :
777 0 : int readCPPline(yystypepp * yylvalpp)
778 : {
779 0 : int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
780 : const char *message;
781 0 : int isVersion = 0;
782 :
783 0 : if (token == CPP_IDENTIFIER) {
784 0 : if (yylvalpp->sc_ident == defineAtom) {
785 0 : token = CPPdefine(yylvalpp);
786 0 : } else if (yylvalpp->sc_ident == elseAtom) {
787 0 : if(ChkCorrectElseNesting()){
788 0 : if (!cpp->ifdepth ){
789 0 : CPPErrorToInfoLog("#else mismatch");
790 0 : cpp->CompileError=1;
791 0 : return 0;
792 : }
793 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
794 0 : if (token != '\n') {
795 0 : CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
796 0 : while (token != '\n') {
797 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
798 0 : if (token <= 0) { // EOF or error
799 0 : CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
800 0 : return 0;
801 : }
802 : }
803 : }
804 0 : token = CPPelse(0, yylvalpp);
805 : }else{
806 0 : CPPErrorToInfoLog("#else after a #else");
807 0 : cpp->ifdepth = 0;
808 0 : cpp->elsetracker = 0;
809 0 : cpp->pastFirstStatement = 1;
810 0 : cpp->CompileError = 1;
811 0 : return 0;
812 : }
813 0 : } else if (yylvalpp->sc_ident == elifAtom) {
814 0 : if (!cpp->ifdepth){
815 0 : CPPErrorToInfoLog("#elif mismatch");
816 0 : cpp->CompileError=1;
817 0 : return 0;
818 : }
819 : // this token is really a dont care, but we still need to eat the tokens
820 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
821 0 : while (token != '\n') {
822 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
823 0 : if (token <= 0) { // EOF or error
824 0 : CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
825 0 : cpp->CompileError = 1;
826 0 : return 0;
827 : }
828 : }
829 0 : token = CPPelse(0, yylvalpp);
830 0 : } else if (yylvalpp->sc_ident == endifAtom) {
831 0 : if (!cpp->ifdepth){
832 0 : CPPErrorToInfoLog("#endif mismatch");
833 0 : cpp->CompileError=1;
834 0 : return 0;
835 : }
836 : else
837 0 : --cpp->ifdepth;
838 :
839 0 : if (cpp->elsetracker)
840 0 : --cpp->elsetracker;
841 :
842 0 : } else if (yylvalpp->sc_ident == ifAtom) {
843 0 : token = CPPif(yylvalpp);
844 0 : } else if (yylvalpp->sc_ident == ifdefAtom) {
845 0 : token = CPPifdef(1, yylvalpp);
846 0 : } else if (yylvalpp->sc_ident == ifndefAtom) {
847 0 : token = CPPifdef(0, yylvalpp);
848 0 : } else if (yylvalpp->sc_ident == lineAtom) {
849 0 : token = CPPline(yylvalpp);
850 0 : } else if (yylvalpp->sc_ident == pragmaAtom) {
851 0 : token = CPPpragma(yylvalpp);
852 0 : } else if (yylvalpp->sc_ident == undefAtom) {
853 0 : token = CPPundef(yylvalpp);
854 0 : } else if (yylvalpp->sc_ident == errorAtom) {
855 0 : token = CPPerror(yylvalpp);
856 0 : } else if (yylvalpp->sc_ident == versionAtom) {
857 0 : token = CPPversion(yylvalpp);
858 0 : isVersion = 1;
859 0 : } else if (yylvalpp->sc_ident == extensionAtom) {
860 0 : token = CPPextension(yylvalpp);
861 : } else {
862 0 : StoreStr("Invalid Directive");
863 0 : StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
864 0 : message=GetStrfromTStr();
865 0 : CPPShInfoLogMsg(message);
866 0 : ResetTString();
867 : }
868 : }
869 0 : while (token != '\n' && token != 0 && token != EOF) {
870 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
871 : }
872 :
873 0 : cpp->pastFirstStatement = 1;
874 :
875 0 : return token;
876 : } // readCPPline
877 :
878 0 : void FreeMacro(MacroSymbol *s) {
879 0 : DeleteTokenStream(s->body);
880 0 : }
881 :
882 0 : void PredefineIntMacro(const char *name, int value) {
883 0 : SourceLoc location = {0};
884 0 : Symbol *symbol = NULL;
885 0 : MacroSymbol macro = {0};
886 0 : yystypepp val = {0};
887 0 : int atom = 0;
888 :
889 0 : macro.body = NewTokenStream(name, macros->pool);
890 0 : val.sc_int = value;
891 0 : sprintf(val.symbol_name, "%d", value);
892 0 : RecordToken(macro.body, CPP_INTCONSTANT, &val);
893 0 : atom = LookUpAddString(atable, name);
894 0 : symbol = AddSymbol(&location, macros, atom, MACRO_S);
895 0 : symbol->details.mac = macro;
896 0 : }
897 :
898 0 : static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
899 0 : static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
900 :
901 0 : static void PushEofSrc() {
902 0 : InputSrc *in = malloc(sizeof(InputSrc));
903 0 : memset(in, 0, sizeof(InputSrc));
904 0 : in->scan = eof_scan;
905 0 : in->getch = eof_scan;
906 0 : in->ungetch = noop;
907 0 : in->prev = cpp->currentInput;
908 0 : cpp->currentInput = in;
909 0 : }
910 :
911 0 : static void PopEofSrc() {
912 0 : if (cpp->currentInput->scan == eof_scan) {
913 0 : InputSrc *in = cpp->currentInput;
914 0 : cpp->currentInput = in->prev;
915 0 : free(in);
916 : }
917 0 : }
918 :
919 0 : static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
920 : int token;
921 : TokenStream *n;
922 0 : RewindTokenStream(a);
923 : do {
924 0 : token = ReadToken(a, yylvalpp);
925 0 : if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
926 0 : break;
927 0 : } while (token > 0);
928 0 : if (token <= 0) return a;
929 0 : n = NewTokenStream("macro arg", 0);
930 0 : PushEofSrc();
931 0 : ReadFromTokenStream(a, 0, 0);
932 0 : while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
933 0 : if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
934 0 : continue;
935 0 : RecordToken(n, token, yylvalpp);
936 : }
937 0 : PopEofSrc();
938 0 : DeleteTokenStream(a);
939 0 : return n;
940 : } // PrescanMacroArg
941 :
942 : typedef struct MacroInputSrc {
943 : InputSrc base;
944 : MacroSymbol *mac;
945 : TokenStream **args;
946 : } MacroInputSrc;
947 :
948 : /* macro_scan ---
949 : ** return the next token for a macro expanion, handling macro args
950 : */
951 0 : static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
952 : int i;
953 0 : int token = ReadToken(in->mac->body, yylvalpp);
954 0 : if (token == CPP_IDENTIFIER) {
955 0 : for (i = in->mac->argc-1; i>=0; i--)
956 0 : if (in->mac->args[i] == yylvalpp->sc_ident) break;
957 0 : if (i >= 0) {
958 0 : ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
959 0 : return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
960 : }
961 : }
962 0 : if (token > 0) return token;
963 0 : in->mac->busy = 0;
964 0 : cpp->currentInput = in->base.prev;
965 0 : if (in->args) {
966 0 : for (i=in->mac->argc-1; i>=0; i--)
967 0 : DeleteTokenStream(in->args[i]);
968 0 : free(in->args);
969 : }
970 0 : free(in);
971 0 : return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
972 : } // macro_scan
973 :
974 : /* MacroExpand
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.
978 : */
979 :
980 0 : int MacroExpand(int atom, yystypepp * yylvalpp)
981 : {
982 0 : Symbol *sym = LookUpSymbol(macros, atom);
983 : MacroInputSrc *in;
984 0 : int i,j, token, depth=0;
985 : const char *message;
986 0 : if (atom == __LINE__Atom) {
987 0 : yylvalpp->sc_int = GetLineNumber();
988 0 : sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
989 0 : UngetToken(CPP_INTCONSTANT, yylvalpp);
990 0 : return 1;
991 : }
992 0 : if (atom == __FILE__Atom) {
993 0 : yylvalpp->sc_int = GetStringNumber();
994 0 : sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
995 0 : UngetToken(CPP_INTCONSTANT, yylvalpp);
996 0 : return 1;
997 : }
998 0 : if (atom == __VERSION__Atom) {
999 0 : strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING);
1000 0 : yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
1001 0 : UngetToken(CPP_INTCONSTANT, yylvalpp);
1002 0 : return 1;
1003 : }
1004 0 : if (!sym || sym->details.mac.undef) return 0;
1005 0 : if (sym->details.mac.busy) return 0; // no recursive expansions
1006 0 : in = malloc(sizeof(*in));
1007 0 : memset(in, 0, sizeof(*in));
1008 0 : in->base.scan = (void *)macro_scan;
1009 0 : in->base.line = cpp->currentInput->line;
1010 0 : in->base.name = cpp->currentInput->name;
1011 0 : in->mac = &sym->details.mac;
1012 0 : if (sym->details.mac.args) {
1013 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1014 0 : if (token != '(') {
1015 0 : UngetToken(token, yylvalpp);
1016 0 : yylvalpp->sc_ident = atom;
1017 0 : return 0;
1018 : }
1019 0 : in->args = malloc(in->mac->argc * sizeof(TokenStream *));
1020 0 : for (i=0; i<in->mac->argc; i++)
1021 0 : in->args[i] = NewTokenStream("macro arg", 0);
1022 0 : i=0;j=0;
1023 : do{
1024 0 : depth = 0;
1025 : while(1) {
1026 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1027 0 : if (token <= 0) {
1028 0 : StoreStr("EOF in Macro ");
1029 0 : StoreStr(GetStringOfAtom(atable,atom));
1030 0 : message=GetStrfromTStr();
1031 0 : CPPShInfoLogMsg(message);
1032 0 : ResetTString();
1033 0 : return 1;
1034 : }
1035 0 : if((in->mac->argc==0) && (token!=')')) break;
1036 0 : if (depth == 0 && (token == ',' || token == ')')) break;
1037 0 : if (token == '(') depth++;
1038 0 : if (token == ')') depth--;
1039 0 : RecordToken(in->args[i], token, yylvalpp);
1040 0 : j=1;
1041 0 : }
1042 0 : if (token == ')') {
1043 0 : if((in->mac->argc==1) &&j==0)
1044 0 : break;
1045 0 : i++;
1046 0 : break;
1047 : }
1048 0 : i++;
1049 0 : }while(i < in->mac->argc);
1050 :
1051 0 : if (i < in->mac->argc) {
1052 0 : StoreStr("Too few args in Macro ");
1053 0 : StoreStr(GetStringOfAtom(atable,atom));
1054 0 : message=GetStrfromTStr();
1055 0 : CPPShInfoLogMsg(message);
1056 0 : ResetTString();
1057 0 : } else if (token != ')') {
1058 0 : depth=0;
1059 0 : while (token >= 0 && (depth > 0 || token != ')')) {
1060 0 : if (token == ')') depth--;
1061 0 : token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1062 0 : if (token == '(') depth++;
1063 : }
1064 :
1065 0 : if (token <= 0) {
1066 0 : StoreStr("EOF in Macro ");
1067 0 : StoreStr(GetStringOfAtom(atable,atom));
1068 0 : message=GetStrfromTStr();
1069 0 : CPPShInfoLogMsg(message);
1070 0 : ResetTString();
1071 0 : return 1;
1072 : }
1073 0 : StoreStr("Too many args in Macro ");
1074 0 : StoreStr(GetStringOfAtom(atable,atom));
1075 0 : message=GetStrfromTStr();
1076 0 : CPPShInfoLogMsg(message);
1077 0 : ResetTString();
1078 : }
1079 0 : for (i=0; i<in->mac->argc; i++) {
1080 0 : in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
1081 : }
1082 : }
1083 : #if 0
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]);
1089 : printf("'\n");
1090 : }
1091 : #endif
1092 : /*retain the input source*/
1093 0 : in->base.prev = cpp->currentInput;
1094 0 : sym->details.mac.busy = 1;
1095 0 : RewindTokenStream(sym->details.mac.body);
1096 0 : cpp->currentInput = &in->base;
1097 0 : return 1;
1098 : } // MacroExpand
1099 :
1100 0 : int ChkCorrectElseNesting(void)
1101 : {
1102 : // sanity check to make sure elsetracker is in a valid range
1103 0 : if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
1104 0 : return 0;
1105 : }
1106 :
1107 0 : if (cpp->elsedepth[cpp->elsetracker] == 0) {
1108 0 : cpp->elsedepth[cpp->elsetracker] = 1;
1109 0 : return 1;
1110 : }
1111 0 : return 0;
1112 : }
1113 :
1114 :
|