blob: 03dd4f6741095dc8fcd900a59d74772065570992 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001/****************************************************************************\
2Copyright (c) 2002, NVIDIA Corporation.
3
4NVIDIA Corporation("NVIDIA") supplies this software to you in
5consideration of your agreement to the following terms, and your use,
6installation, modification or redistribution of this NVIDIA software
7constitutes acceptance of these terms. If you do not agree with these
8terms, please do not use, install, modify or redistribute this NVIDIA
9software.
10
11In consideration of your agreement to abide by the following terms, and
12subject to these terms, NVIDIA grants you a personal, non-exclusive
13license, under NVIDIA's copyrights in this original NVIDIA software (the
14"NVIDIA Software"), to use, reproduce, modify and redistribute the
15NVIDIA Software, with or without modifications, in source and/or binary
16forms; provided that if you redistribute the NVIDIA Software, you must
17retain the copyright notice of NVIDIA, this notice and the following
18text and disclaimers in all such redistributions of the NVIDIA Software.
19Neither the name, trademarks, service marks nor logos of NVIDIA
20Corporation may be used to endorse or promote products derived from the
21NVIDIA Software without specific prior written permission from NVIDIA.
22Except as expressly stated in this notice, no other rights or licenses
23express or implied, are granted by NVIDIA herein, including but not
24limited to any patent rights that may be infringed by your derivative
25works or by other works in which the NVIDIA Software may be
26incorporated. No hardware is licensed hereunder.
27
28THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
29WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
30INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
31NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
32ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
33PRODUCTS.
34
35IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
36INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
39OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
40NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
41TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42NVIDIA 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
daniel@transgaming.come6842292010-04-20 18:52:50 +000054#include "compiler/preprocessor/slglobals.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055
56static 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
62static int bindAtom = 0;
63static int constAtom = 0;
64static int defaultAtom = 0;
65static int defineAtom = 0;
66static int definedAtom = 0;
67static int elseAtom = 0;
68static int elifAtom = 0;
69static int endifAtom = 0;
70static int ifAtom = 0;
71static int ifdefAtom = 0;
72static int ifndefAtom = 0;
73static int includeAtom = 0;
74static int lineAtom = 0;
75static int pragmaAtom = 0;
76static int texunitAtom = 0;
77static int undefAtom = 0;
78static int errorAtom = 0;
79static int __LINE__Atom = 0;
80static int __FILE__Atom = 0;
81static int __VERSION__Atom = 0;
82static int versionAtom = 0;
83static int extensionAtom = 0;
84
85static Scope *macros = 0;
86#define MAX_MACRO_ARGS 64
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087
88static SourceLoc ifloc; /* outermost #if */
89
90int InitCPP(void)
91{
92 char buffer[64], *t;
93 const char *f;
daniel@transgaming.comd8e93722010-05-14 17:31:09 +000094
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 // 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++);
124 *t = 0;
daniel@transgaming.comd8e93722010-05-14 17:31:09 +0000125
daniel@transgaming.comcd0a9a82010-05-18 18:51:59 +0000126 PredefineIntMacro("GL_ES", 1);
127 PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
daniel@transgaming.comd8e93722010-05-14 17:31:09 +0000128
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129 return 1;
130} // InitCPP
131
132int FreeCPP(void)
133{
134 if (macros)
135 {
136 mem_FreePool(macros->pool);
137 macros = 0;
138 }
139
140 return 1;
141}
142
143int FinalCPP(void)
144{
145 if (cpp->ifdepth)
146 CPPErrorToInfoLog("#if mismatch");
147 return 1;
148}
149
150static 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 memset(&mac, 0, sizeof(mac));
158 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
159 if (token != CPP_IDENTIFIER) {
160 CPPErrorToInfoLog("#define");
161 return token;
162 }
163 name = yylvalpp->sc_ident;
164 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
165 if (token == '(' && !yylvalpp->sc_int) {
166 // gather arguments
167 argc = 0;
168 do {
169 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
170 if (argc == 0 && token == ')') break;
171 if (token != CPP_IDENTIFIER) {
172 CPPErrorToInfoLog("#define");
173 return token;
174 }
175 if (argc < MAX_MACRO_ARGS)
176 args[argc++] = yylvalpp->sc_ident;
177 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
178 } while (token == ',');
179 if (token != ')') {
180 CPPErrorToInfoLog("#define");
181 return token;
182 }
183 mac.argc = argc;
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);
187 }
188 mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
189 while (token != '\n') {
daniel@transgaming.comedff8dc2010-05-14 17:30:27 +0000190 if (token == '\\') {
191 CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
192 return token;
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000193 } else if (token <= 0) { // EOF or error
194 CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline");
195 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196 }
197 RecordToken(mac.body, token, yylvalpp);
198 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
199 };
200
201 symb = LookUpSymbol(macros, name);
202 if (symb) {
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])
208 goto error;
209 RewindTokenStream(symb->details.mac.body);
210 RewindTokenStream(mac.body);
211 do {
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) {
217 error:
218 StoreStr("Macro Redefined");
219 StoreStr(GetStringOfAtom(atable,name));
220 message=GetStrfromTStr();
221 DecLineNumber();
222 CPPShInfoLogMsg(message);
223 IncLineNumber();
224 ResetTString();
225 break; }
226 } while (token > 0);
227 }
228 //FreeMacro(&symb->details.mac);
229 } else {
230 dummyLoc.file = 0;
231 dummyLoc.line = 0;
232 symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
233 }
234 symb->details.mac = mac;
235 return '\n';
236} // CPPdefine
237
238static int CPPundef(yystypepp * yylvalpp)
239{
240 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
241 Symbol *symb;
242 if(token == '\n'){
243 CPPErrorToInfoLog("#undef");
244 return token;
245 }
246 if (token != CPP_IDENTIFIER)
247 goto error;
248 symb = LookUpSymbol(macros, yylvalpp->sc_ident);
249 if (symb) {
250 symb->details.mac.undef = 1;
251 }
252 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
253 if (token != '\n') {
254 error:
255 CPPErrorToInfoLog("#undef");
256 }
257 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
265static int CPPelse(int matchelse, yystypepp * yylvalpp)
266{
267 int atom,depth=0;
268 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
269
270 while (token > 0) {
271 if (token != '#') {
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000272 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000274 if (token <= 0) { // EOF or error
275 CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline");
276 return 0;
277 }
278 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
280 continue;
281 }
282 if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
283 continue;
284 atom = yylvalpp->sc_ident;
285 if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
286 depth++; cpp->ifdepth++; cpp->elsetracker++;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000287 if (cpp->ifdepth > MAX_IF_NESTING) {
288 CPPErrorToInfoLog("max #if nesting depth exceeded");
289 cpp->CompileError = 1;
290 return 0;
291 }
292 // sanity check elsetracker
293 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
294 CPPErrorToInfoLog("mismatched #if/#endif statements");
295 cpp->CompileError = 1;
296 return 0;
297 }
daniel@transgaming.com9e78e5e2010-04-29 03:39:02 +0000298 cpp->elsedepth[cpp->elsetracker] = 0;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000299 }
300 else if (atom == endifAtom) {
daniel@transgaming.com9e78e5e2010-04-29 03:39:02 +0000301 if(--depth<0){
daniel@transgaming.come9874052011-01-26 17:32:26 +0000302 if (cpp->elsetracker)
303 --cpp->elsetracker;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304 if (cpp->ifdepth)
305 --cpp->ifdepth;
306 break;
307 }
daniel@transgaming.come9874052011-01-26 17:32:26 +0000308 --cpp->elsetracker;
309 --cpp->ifdepth;
310 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311 else if (((int)(matchelse) != 0)&& depth==0) {
312 if (atom == elseAtom ) {
313 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
314 if (token != '\n') {
315 CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000316 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000318 if (token <= 0) { // EOF or error
319 CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline");
320 return 0;
321 }
322 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323 }
324 break;
325 }
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 */
329 if (cpp->ifdepth){
330 --cpp->ifdepth;
331 --cpp->elsetracker;
332 }
333 return CPPif(yylvalpp);
334 }
335 }
336 else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
337 CPPErrorToInfoLog("#else after a #else");
338 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000339 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340 }
341 };
342 return token;
343}
344
345enum eval_prec {
346 MIN_PREC,
347 COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
348 MAX_PREC
349};
350
351static int op_logor(int a, int b) { return a || b; }
352static int op_logand(int a, int b) { return a && b; }
353static int op_or(int a, int b) { return a | b; }
354static int op_xor(int a, int b) { return a ^ b; }
355static int op_and(int a, int b) { return a & b; }
356static int op_eq(int a, int b) { return a == b; }
357static int op_ne(int a, int b) { return a != b; }
358static int op_ge(int a, int b) { return a >= b; }
359static int op_le(int a, int b) { return a <= b; }
360static int op_gt(int a, int b) { return a > b; }
361static int op_lt(int a, int b) { return a < b; }
362static int op_shl(int a, int b) { return a << b; }
363static int op_shr(int a, int b) { return a >> b; }
364static int op_add(int a, int b) { return a + b; }
365static int op_sub(int a, int b) { return a - b; }
366static int op_mul(int a, int b) { return a * b; }
367static int op_div(int a, int b) { return a / b; }
368static int op_mod(int a, int b) { return a % b; }
369static int op_pos(int a) { return a; }
370static int op_neg(int a) { return -a; }
371static int op_cmpl(int a) { return ~a; }
372static int op_not(int a) { return !a; }
373
374struct {
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
397struct {
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
408static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
409{
410 int i, val;
411 Symbol *s;
412 if (token == CPP_IDENTIFIER) {
413 if (yylvalpp->sc_ident == definedAtom) {
414 int needclose = 0;
415 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
416 if (token == '(') {
417 needclose = 1;
418 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
419 }
420 if (token != CPP_IDENTIFIER)
421 goto error;
422 *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
423 ? !s->details.mac.undef : 0;
424 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
425 if (needclose) {
426 if (token != ')')
427 goto error;
428 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
429 }
430 } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
431 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
432 return eval(token, prec, res, err, yylvalpp);
433 } else {
434 goto error;
435 }
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);
442 if (!*err) {
443 if (token != ')')
444 goto error;
445 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
446 }
447 } else {
448 for (i = ALEN(unop) - 1; i >= 0; i--) {
449 if (unop[i].token == token)
450 break;
451 }
452 if (i >= 0) {
453 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
454 token = eval(token, UNARY, res, err, yylvalpp);
455 *res = unop[i].op(*res);
456 } else {
457 goto error;
458 }
459 }
460 while (!*err) {
461 if (token == ')' || token == '\n') break;
462 for (i = ALEN(binop) - 1; i >= 0; i--) {
463 if (binop[i].token == token)
464 break;
465 }
466 if (i < 0 || binop[i].prec <= prec)
467 break;
468 val = *res;
469 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
470 token = eval(token, binop[i].prec, res, err, yylvalpp);
daniel@transgaming.com3b5643c2011-02-28 15:06:55 +0000471
472 if (binop[i].op == op_div || binop[i].op == op_mod)
473 {
474 if (*res == 0)
475 {
476 CPPErrorToInfoLog("preprocessor divide or modulo by zero");
477 *err = 1;
478 return token;
479 }
480 }
481
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482 *res = binop[i].op(val, *res);
483 }
484 return token;
485error:
486 CPPErrorToInfoLog("incorrect preprocessor directive");
487 *err = 1;
488 *res = 0;
489 return token;
490} // eval
491
492static int CPPif(yystypepp * yylvalpp) {
493 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
494 int res = 0, err = 0;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000495
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496 if (!cpp->ifdepth++)
497 ifloc = *cpp->tokenLoc;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000498 if(cpp->ifdepth > MAX_IF_NESTING){
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499 CPPErrorToInfoLog("max #if nesting depth exceeded");
daniel@transgaming.come9874052011-01-26 17:32:26 +0000500 cpp->CompileError = 1;
501 return 0;
502 }
503 cpp->elsetracker++;
504 // sanity check elsetracker
505 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
506 CPPErrorToInfoLog("mismatched #if/#endif statements");
507 cpp->CompileError = 1;
508 return 0;
509 }
510 cpp->elsedepth[cpp->elsetracker] = 0;
511
512 token = eval(token, MIN_PREC, &res, &err, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513 if (token != '\n') {
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000514 CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
515 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000517 if (token <= 0) { // EOF or error
518 CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline");
519 return 0;
520 }
521 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000522 }
523 if (!res && !err) {
524 token = CPPelse(1, yylvalpp);
525 }
526
527 return token;
528} // CPPif
529
530static int CPPifdef(int defined, yystypepp * yylvalpp)
531{
532 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
533 int name = yylvalpp->sc_ident;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000534 if(++cpp->ifdepth > MAX_IF_NESTING){
535 CPPErrorToInfoLog("max #if nesting depth exceeded");
536 cpp->CompileError = 1;
537 return 0;
538 }
539 cpp->elsetracker++;
540 // sanity check elsetracker
541 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
542 CPPErrorToInfoLog("mismatched #if/#endif statements");
543 cpp->CompileError = 1;
544 return 0;
545 }
daniel@transgaming.com9e78e5e2010-04-29 03:39:02 +0000546 cpp->elsedepth[cpp->elsetracker] = 0;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000547
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000548 if (token != CPP_IDENTIFIER) {
549 defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
550 } else {
551 Symbol *s = LookUpSymbol(macros, name);
552 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
553 if (token != '\n') {
554 CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000555 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000557 if (token <= 0) { // EOF or error
558 CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
559 return 0;
560 }
561 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000562 }
563 if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
564 token = CPPelse(1, yylvalpp);
565 }
566 return token;
567} // CPPifdef
568
569static int CPPline(yystypepp * yylvalpp)
570{
571 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
572 if(token=='\n'){
573 DecLineNumber();
574 CPPErrorToInfoLog("#line");
575 IncLineNumber();
576 return token;
577 }
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);
582
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);
587 if(token!='\n')
588 CPPErrorToInfoLog("#line");
589 }
590 else if (token == '\n'){
591 return token;
592 }
593 else{
594 CPPErrorToInfoLog("#line");
595 }
596 }
597 else{
598 CPPErrorToInfoLog("#line");
599 }
600 return token;
601}
602
603static int CPPerror(yystypepp * yylvalpp) {
604
605 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
606 const char *message;
607
608 while (token != '\n') {
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000609 if (token <= 0){
610 CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline");
611 return 0;
612 }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613 StoreStr(yylvalpp->symbol_name);
614 }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
615 StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
616 }else {
617 StoreStr(GetStringOfAtom(atable,token));
618 }
619 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
620 }
621 DecLineNumber();
622 //store this msg into the shader's information log..set the Compile Error flag!!!!
623 message=GetStrfromTStr();
624 CPPShInfoLogMsg(message);
625 ResetTString();
626 cpp->CompileError=1;
627 IncLineNumber();
628 return '\n';
629}//CPPerror
630
631static int CPPpragma(yystypepp * yylvalpp)
632{
633 char SrcStrName[2];
634 char** allTokens;
635 int tokenCount = 0;
636 int maxTokenCount = 10;
637 const char* SrcStr;
638 int i;
639
640 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
641
642 if (token=='\n') {
643 DecLineNumber();
644 CPPErrorToInfoLog("#pragma");
645 IncLineNumber();
646 return token;
647 }
648
649 allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);
650
651 while (token != '\n') {
652 if (tokenCount >= maxTokenCount) {
653 maxTokenCount *= 2;
654 allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
655 }
656 switch (token) {
657 case CPP_IDENTIFIER:
658 SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
659 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
660 strcpy(allTokens[tokenCount++], SrcStr);
661 break;
662 case CPP_INTCONSTANT:
663 SrcStr = yylvalpp->symbol_name;
664 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
665 strcpy(allTokens[tokenCount++], SrcStr);
666 break;
667 case CPP_FLOATCONSTANT:
668 SrcStr = yylvalpp->symbol_name;
669 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
670 strcpy(allTokens[tokenCount++], SrcStr);
671 break;
672 case -1:
673 // EOF
674 CPPShInfoLogMsg("#pragma directive must end with a newline");
675 return token;
676 default:
677 SrcStrName[0] = token;
678 SrcStrName[1] = '\0';
679 allTokens[tokenCount] = (char*)malloc(2);
680 strcpy(allTokens[tokenCount++], SrcStrName);
681 }
682 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
683 }
684
685 cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
686 HandlePragma((const char**)allTokens, tokenCount);
687 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
688
689 for (i = 0; i < tokenCount; ++i) {
690 free (allTokens[i]);
691 }
692 free (allTokens);
693
694 return token;
695} // CPPpragma
696
daniel@transgaming.com76039472010-04-15 20:45:18 +0000697#define ESSL_VERSION_NUMBER 100
698#define ESSL_VERSION_STRING "100"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000699
700static int CPPversion(yystypepp * yylvalpp)
701{
702
703 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
704
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000705 if (cpp->pastFirstStatement == 1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000706 CPPShInfoLogMsg("#version must occur before any other statement in the program");
707
708 if(token=='\n'){
709 DecLineNumber();
710 CPPErrorToInfoLog("#version");
711 IncLineNumber();
712 return token;
713 }
714 if (token != CPP_INTCONSTANT)
715 CPPErrorToInfoLog("#version");
716
717 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
718 //SetVersionNumber(yylvalpp->sc_int);
719
daniel@transgaming.com76039472010-04-15 20:45:18 +0000720 if (yylvalpp->sc_int != ESSL_VERSION_NUMBER)
721 CPPShInfoLogMsg("Version number not supported by ESSL");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722
723 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
724
725 if (token == '\n'){
726 return token;
727 }
728 else{
729 CPPErrorToInfoLog("#version");
730 }
731 return token;
732} // CPPversion
733
734static int CPPextension(yystypepp * yylvalpp)
735{
736
737 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000738 char extensionName[MAX_SYMBOL_NAME_LEN + 1];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739
740 if(token=='\n'){
741 DecLineNumber();
742 CPPShInfoLogMsg("extension name not specified");
743 IncLineNumber();
744 return token;
745 }
746
747 if (token != CPP_IDENTIFIER)
748 CPPErrorToInfoLog("#extension");
749
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000750 strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN);
751 extensionName[MAX_SYMBOL_NAME_LEN] = '\0';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752
753 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
754 if (token != ':') {
755 CPPShInfoLogMsg("':' missing after extension name");
756 return token;
757 }
758
759 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
760 if (token != CPP_IDENTIFIER) {
761 CPPShInfoLogMsg("behavior for extension not specified");
762 return token;
763 }
764
765 updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
766
767 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
768 if (token == '\n'){
769 return token;
770 }
771 else{
772 CPPErrorToInfoLog("#extension");
773 }
774 return token;
775} // CPPextension
776
777int readCPPline(yystypepp * yylvalpp)
778{
779 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
780 const char *message;
781 int isVersion = 0;
782
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()){
788 if (!cpp->ifdepth ){
789 CPPErrorToInfoLog("#else mismatch");
790 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000791 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792 }
793 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
794 if (token != '\n') {
795 CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000796 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000798 if (token <= 0) { // EOF or error
799 CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
800 return 0;
801 }
802 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000803 }
804 token = CPPelse(0, yylvalpp);
805 }else{
806 CPPErrorToInfoLog("#else after a #else");
daniel@transgaming.come9874052011-01-26 17:32:26 +0000807 cpp->ifdepth = 0;
808 cpp->elsetracker = 0;
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000809 cpp->pastFirstStatement = 1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000810 cpp->CompileError = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811 return 0;
812 }
813 } else if (yylvalpp->sc_ident == elifAtom) {
814 if (!cpp->ifdepth){
815 CPPErrorToInfoLog("#elif mismatch");
816 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000817 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818 }
819 // this token is really a dont care, but we still need to eat the tokens
820 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000821 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000822 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000823 if (token <= 0) { // EOF or error
824 CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
825 cpp->CompileError = 1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000826 return 0;
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000827 }
828 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000829 token = CPPelse(0, yylvalpp);
830 } else if (yylvalpp->sc_ident == endifAtom) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831 if (!cpp->ifdepth){
832 CPPErrorToInfoLog("#endif mismatch");
833 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000834 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000835 }
836 else
daniel@transgaming.come9874052011-01-26 17:32:26 +0000837 --cpp->ifdepth;
838
839 if (cpp->elsetracker)
840 --cpp->elsetracker;
841
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000842 } 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);
858 isVersion = 1;
859 } else if (yylvalpp->sc_ident == extensionAtom) {
860 token = CPPextension(yylvalpp);
861 } else {
862 StoreStr("Invalid Directive");
863 StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
864 message=GetStrfromTStr();
865 CPPShInfoLogMsg(message);
866 ResetTString();
867 }
868 }
869 while (token != '\n' && token != 0 && token != EOF) {
870 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
871 }
872
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000873 cpp->pastFirstStatement = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000874
875 return token;
876} // readCPPline
877
878void FreeMacro(MacroSymbol *s) {
879 DeleteTokenStream(s->body);
880}
881
daniel@transgaming.comcd0a9a82010-05-18 18:51:59 +0000882void PredefineIntMacro(const char *name, int value) {
883 SourceLoc location = {0};
884 Symbol *symbol = NULL;
885 MacroSymbol macro = {0};
886 yystypepp val = {0};
887 int atom = 0;
888
889 macro.body = NewTokenStream(name, macros->pool);
890 val.sc_int = value;
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;
896}
897
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000898static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
899static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
900
901static void PushEofSrc() {
902 InputSrc *in = malloc(sizeof(InputSrc));
903 memset(in, 0, sizeof(InputSrc));
904 in->scan = eof_scan;
905 in->getch = eof_scan;
906 in->ungetch = noop;
907 in->prev = cpp->currentInput;
908 cpp->currentInput = in;
909}
910
911static void PopEofSrc() {
912 if (cpp->currentInput->scan == eof_scan) {
913 InputSrc *in = cpp->currentInput;
914 cpp->currentInput = in->prev;
915 free(in);
916 }
917}
918
919static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
920 int token;
921 TokenStream *n;
922 RewindTokenStream(a);
923 do {
924 token = ReadToken(a, yylvalpp);
925 if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
926 break;
927 } while (token > 0);
928 if (token <= 0) return a;
929 n = NewTokenStream("macro arg", 0);
930 PushEofSrc();
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))
934 continue;
935 RecordToken(n, token, yylvalpp);
936 }
937 PopEofSrc();
938 DeleteTokenStream(a);
939 return n;
940} // PrescanMacroArg
941
942typedef 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*/
951static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
952 int i;
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;
957 if (i >= 0) {
958 ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
959 return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
960 }
961 }
962 if (token > 0) return token;
963 in->mac->busy = 0;
964 cpp->currentInput = in->base.prev;
965 if (in->args) {
966 for (i=in->mac->argc-1; i>=0; i--)
967 DeleteTokenStream(in->args[i]);
968 free(in->args);
969 }
970 free(in);
971 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
980int MacroExpand(int atom, yystypepp * yylvalpp)
981{
982 Symbol *sym = LookUpSymbol(macros, atom);
983 MacroInputSrc *in;
984 int i,j, token, depth=0;
985 const char *message;
986 if (atom == __LINE__Atom) {
987 yylvalpp->sc_int = GetLineNumber();
988 sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
989 UngetToken(CPP_INTCONSTANT, yylvalpp);
990 return 1;
991 }
992 if (atom == __FILE__Atom) {
993 yylvalpp->sc_int = GetStringNumber();
994 sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
995 UngetToken(CPP_INTCONSTANT, yylvalpp);
996 return 1;
997 }
998 if (atom == __VERSION__Atom) {
daniel@transgaming.com76039472010-04-15 20:45:18 +0000999 strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001000 yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
1001 UngetToken(CPP_INTCONSTANT, yylvalpp);
1002 return 1;
1003 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001004 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);
1014 if (token != '(') {
1015 UngetToken(token, yylvalpp);
1016 yylvalpp->sc_ident = atom;
1017 return 0;
1018 }
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);
1022 i=0;j=0;
1023 do{
1024 depth = 0;
1025 while(1) {
1026 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1027 if (token <= 0) {
1028 StoreStr("EOF in Macro ");
1029 StoreStr(GetStringOfAtom(atable,atom));
1030 message=GetStrfromTStr();
1031 CPPShInfoLogMsg(message);
1032 ResetTString();
1033 return 1;
1034 }
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);
1040 j=1;
1041 }
1042 if (token == ')') {
1043 if((in->mac->argc==1) &&j==0)
1044 break;
1045 i++;
1046 break;
1047 }
1048 i++;
1049 }while(i < in->mac->argc);
1050
1051 if (i < in->mac->argc) {
1052 StoreStr("Too few args in Macro ");
1053 StoreStr(GetStringOfAtom(atable,atom));
1054 message=GetStrfromTStr();
1055 CPPShInfoLogMsg(message);
1056 ResetTString();
1057 } else if (token != ')') {
1058 depth=0;
1059 while (token >= 0 && (depth > 0 || token != ')')) {
1060 if (token == ')') depth--;
1061 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1062 if (token == '(') depth++;
1063 }
1064
1065 if (token <= 0) {
1066 StoreStr("EOF in Macro ");
1067 StoreStr(GetStringOfAtom(atable,atom));
1068 message=GetStrfromTStr();
1069 CPPShInfoLogMsg(message);
1070 ResetTString();
1071 return 1;
1072 }
1073 StoreStr("Too many args in Macro ");
1074 StoreStr(GetStringOfAtom(atable,atom));
1075 message=GetStrfromTStr();
1076 CPPShInfoLogMsg(message);
1077 ResetTString();
1078 }
1079 for (i=0; i<in->mac->argc; i++) {
1080 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 in->base.prev = cpp->currentInput;
1094 sym->details.mac.busy = 1;
1095 RewindTokenStream(sym->details.mac.body);
1096 cpp->currentInput = &in->base;
1097 return 1;
1098} // MacroExpand
1099
1100int ChkCorrectElseNesting(void)
1101{
daniel@transgaming.come9874052011-01-26 17:32:26 +00001102 // sanity check to make sure elsetracker is in a valid range
1103 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
1104 return 0;
1105 }
1106
1107 if (cpp->elsedepth[cpp->elsetracker] == 0) {
1108 cpp->elsedepth[cpp->elsetracker] = 1;
1109 return 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001110 }
1111 return 0;
1112}
1113
1114