blob: 13a5df18a9b3eaaa749a36db1452b7c70b37d4b1 [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
apatrick@chromium.orga1d80592012-01-25 21:52:10 +000056#if defined(_MSC_VER)
57#pragma warning(disable: 4054)
58#pragma warning(disable: 4152)
59#pragma warning(disable: 4706)
60#endif
61
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000062static int CPPif(yystypepp * yylvalpp);
63
64/* Don't use memory.c's replacements, as we clean up properly here */
65#undef malloc
66#undef free
67
68static int bindAtom = 0;
69static int constAtom = 0;
70static int defaultAtom = 0;
71static int defineAtom = 0;
72static int definedAtom = 0;
73static int elseAtom = 0;
74static int elifAtom = 0;
75static int endifAtom = 0;
76static int ifAtom = 0;
77static int ifdefAtom = 0;
78static int ifndefAtom = 0;
79static int includeAtom = 0;
80static int lineAtom = 0;
81static int pragmaAtom = 0;
82static int texunitAtom = 0;
83static int undefAtom = 0;
84static int errorAtom = 0;
85static int __LINE__Atom = 0;
86static int __FILE__Atom = 0;
87static int __VERSION__Atom = 0;
88static int versionAtom = 0;
89static int extensionAtom = 0;
90
91static Scope *macros = 0;
92#define MAX_MACRO_ARGS 64
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093
94static SourceLoc ifloc; /* outermost #if */
95
96int InitCPP(void)
97{
98 char buffer[64], *t;
99 const char *f;
daniel@transgaming.comd8e93722010-05-14 17:31:09 +0000100
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101 // Add various atoms needed by the CPP line scanner:
102 bindAtom = LookUpAddString(atable, "bind");
103 constAtom = LookUpAddString(atable, "const");
104 defaultAtom = LookUpAddString(atable, "default");
105 defineAtom = LookUpAddString(atable, "define");
106 definedAtom = LookUpAddString(atable, "defined");
107 elifAtom = LookUpAddString(atable, "elif");
108 elseAtom = LookUpAddString(atable, "else");
109 endifAtom = LookUpAddString(atable, "endif");
110 ifAtom = LookUpAddString(atable, "if");
111 ifdefAtom = LookUpAddString(atable, "ifdef");
112 ifndefAtom = LookUpAddString(atable, "ifndef");
113 includeAtom = LookUpAddString(atable, "include");
114 lineAtom = LookUpAddString(atable, "line");
115 pragmaAtom = LookUpAddString(atable, "pragma");
116 texunitAtom = LookUpAddString(atable, "texunit");
117 undefAtom = LookUpAddString(atable, "undef");
118 errorAtom = LookUpAddString(atable, "error");
119 __LINE__Atom = LookUpAddString(atable, "__LINE__");
120 __FILE__Atom = LookUpAddString(atable, "__FILE__");
121 __VERSION__Atom = LookUpAddString(atable, "__VERSION__");
122 versionAtom = LookUpAddString(atable, "version");
123 extensionAtom = LookUpAddString(atable, "extension");
124 macros = NewScopeInPool(mem_CreatePool(0, 0));
125 strcpy(buffer, "PROFILE_");
126 t = buffer + strlen(buffer);
127 f = cpp->options.profileString;
128 while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
129 *t++ = toupper(*f++);
130 *t = 0;
daniel@transgaming.comd8e93722010-05-14 17:31:09 +0000131
daniel@transgaming.comcd0a9a82010-05-18 18:51:59 +0000132 PredefineIntMacro("GL_ES", 1);
133 PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
daniel@transgaming.comd8e93722010-05-14 17:31:09 +0000134
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135 return 1;
136} // InitCPP
137
138int FreeCPP(void)
139{
140 if (macros)
141 {
142 mem_FreePool(macros->pool);
143 macros = 0;
144 }
145
146 return 1;
147}
148
149int FinalCPP(void)
150{
151 if (cpp->ifdepth)
152 CPPErrorToInfoLog("#if mismatch");
153 return 1;
154}
155
156static int CPPdefine(yystypepp * yylvalpp)
157{
158 int token, name, args[MAX_MACRO_ARGS], argc;
159 const char *message;
160 MacroSymbol mac;
161 Symbol *symb;
162 SourceLoc dummyLoc;
163 memset(&mac, 0, sizeof(mac));
164 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
165 if (token != CPP_IDENTIFIER) {
166 CPPErrorToInfoLog("#define");
167 return token;
168 }
169 name = yylvalpp->sc_ident;
170 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
171 if (token == '(' && !yylvalpp->sc_int) {
172 // gather arguments
173 argc = 0;
174 do {
175 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
176 if (argc == 0 && token == ')') break;
177 if (token != CPP_IDENTIFIER) {
178 CPPErrorToInfoLog("#define");
179 return token;
180 }
181 if (argc < MAX_MACRO_ARGS)
182 args[argc++] = yylvalpp->sc_ident;
183 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
184 } while (token == ',');
185 if (token != ')') {
186 CPPErrorToInfoLog("#define");
187 return token;
188 }
189 mac.argc = argc;
190 mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
191 memcpy(mac.args, args, argc * sizeof(int));
192 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
193 }
194 mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
195 while (token != '\n') {
daniel@transgaming.comedff8dc2010-05-14 17:30:27 +0000196 if (token == '\\') {
197 CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
198 return token;
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000199 } else if (token <= 0) { // EOF or error
200 CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline");
201 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202 }
203 RecordToken(mac.body, token, yylvalpp);
204 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
205 };
206
207 symb = LookUpSymbol(macros, name);
208 if (symb) {
209 if (!symb->details.mac.undef) {
210 // already defined -- need to make sure they are identical
211 if (symb->details.mac.argc != mac.argc) goto error;
212 for (argc=0; argc < mac.argc; argc++)
213 if (symb->details.mac.args[argc] != mac.args[argc])
214 goto error;
215 RewindTokenStream(symb->details.mac.body);
216 RewindTokenStream(mac.body);
217 do {
218 int old_lval, old_token;
219 old_token = ReadToken(symb->details.mac.body, yylvalpp);
220 old_lval = yylvalpp->sc_int;
221 token = ReadToken(mac.body, yylvalpp);
222 if (token != old_token || yylvalpp->sc_int != old_lval) {
223 error:
224 StoreStr("Macro Redefined");
225 StoreStr(GetStringOfAtom(atable,name));
226 message=GetStrfromTStr();
227 DecLineNumber();
228 CPPShInfoLogMsg(message);
229 IncLineNumber();
230 ResetTString();
231 break; }
232 } while (token > 0);
233 }
234 //FreeMacro(&symb->details.mac);
235 } else {
236 dummyLoc.file = 0;
237 dummyLoc.line = 0;
238 symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
239 }
240 symb->details.mac = mac;
241 return '\n';
242} // CPPdefine
243
244static int CPPundef(yystypepp * yylvalpp)
245{
246 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
247 Symbol *symb;
248 if(token == '\n'){
249 CPPErrorToInfoLog("#undef");
250 return token;
251 }
252 if (token != CPP_IDENTIFIER)
253 goto error;
254 symb = LookUpSymbol(macros, yylvalpp->sc_ident);
255 if (symb) {
256 symb->details.mac.undef = 1;
257 }
258 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
259 if (token != '\n') {
260 error:
261 CPPErrorToInfoLog("#undef");
262 }
263 return token;
264} // CPPundef
265
266/* CPPelse -- skip forward to appropriate spot. This is actually used
267** to skip to and #endif after seeing an #else, AND to skip to a #else,
268** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
269*/
270
271static int CPPelse(int matchelse, yystypepp * yylvalpp)
272{
273 int atom,depth=0;
274 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
275
276 while (token > 0) {
277 if (token != '#') {
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000278 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000280 if (token <= 0) { // EOF or error
281 CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline");
282 return 0;
283 }
284 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
286 continue;
287 }
288 if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
289 continue;
290 atom = yylvalpp->sc_ident;
291 if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
292 depth++; cpp->ifdepth++; cpp->elsetracker++;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000293 if (cpp->ifdepth > MAX_IF_NESTING) {
294 CPPErrorToInfoLog("max #if nesting depth exceeded");
295 cpp->CompileError = 1;
296 return 0;
297 }
298 // sanity check elsetracker
299 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
300 CPPErrorToInfoLog("mismatched #if/#endif statements");
301 cpp->CompileError = 1;
302 return 0;
303 }
daniel@transgaming.com9e78e5e2010-04-29 03:39:02 +0000304 cpp->elsedepth[cpp->elsetracker] = 0;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000305 }
306 else if (atom == endifAtom) {
daniel@transgaming.com9e78e5e2010-04-29 03:39:02 +0000307 if(--depth<0){
daniel@transgaming.come9874052011-01-26 17:32:26 +0000308 if (cpp->elsetracker)
309 --cpp->elsetracker;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310 if (cpp->ifdepth)
311 --cpp->ifdepth;
312 break;
313 }
daniel@transgaming.come9874052011-01-26 17:32:26 +0000314 --cpp->elsetracker;
315 --cpp->ifdepth;
316 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317 else if (((int)(matchelse) != 0)&& depth==0) {
318 if (atom == elseAtom ) {
319 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
320 if (token != '\n') {
321 CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000322 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000324 if (token <= 0) { // EOF or error
325 CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline");
326 return 0;
327 }
328 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329 }
330 break;
331 }
332 else if (atom == elifAtom) {
333 /* we decrement cpp->ifdepth here, because CPPif will increment
334 * it and we really want to leave it alone */
335 if (cpp->ifdepth){
336 --cpp->ifdepth;
337 --cpp->elsetracker;
338 }
339 return CPPif(yylvalpp);
340 }
341 }
342 else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
343 CPPErrorToInfoLog("#else after a #else");
344 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000345 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346 }
347 };
348 return token;
349}
350
351enum eval_prec {
352 MIN_PREC,
353 COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
354 MAX_PREC
355};
356
357static int op_logor(int a, int b) { return a || b; }
358static int op_logand(int a, int b) { return a && b; }
359static int op_or(int a, int b) { return a | b; }
360static int op_xor(int a, int b) { return a ^ b; }
361static int op_and(int a, int b) { return a & b; }
362static int op_eq(int a, int b) { return a == b; }
363static int op_ne(int a, int b) { return a != b; }
364static int op_ge(int a, int b) { return a >= b; }
365static int op_le(int a, int b) { return a <= b; }
366static int op_gt(int a, int b) { return a > b; }
367static int op_lt(int a, int b) { return a < b; }
368static int op_shl(int a, int b) { return a << b; }
369static int op_shr(int a, int b) { return a >> b; }
370static int op_add(int a, int b) { return a + b; }
371static int op_sub(int a, int b) { return a - b; }
372static int op_mul(int a, int b) { return a * b; }
373static int op_div(int a, int b) { return a / b; }
374static int op_mod(int a, int b) { return a % b; }
375static int op_pos(int a) { return a; }
376static int op_neg(int a) { return -a; }
377static int op_cmpl(int a) { return ~a; }
378static int op_not(int a) { return !a; }
379
380struct {
381 int token, prec, (*op)(int, int);
382} binop[] = {
383 { CPP_OR_OP, LOGOR, op_logor },
384 { CPP_AND_OP, LOGAND, op_logand },
385 { '|', OR, op_or },
386 { '^', XOR, op_xor },
387 { '&', AND, op_and },
388 { CPP_EQ_OP, EQUAL, op_eq },
389 { CPP_NE_OP, EQUAL, op_ne },
390 { '>', RELATION, op_gt },
391 { CPP_GE_OP, RELATION, op_ge },
392 { '<', RELATION, op_lt },
393 { CPP_LE_OP, RELATION, op_le },
394 { CPP_LEFT_OP, SHIFT, op_shl },
395 { CPP_RIGHT_OP, SHIFT, op_shr },
396 { '+', ADD, op_add },
397 { '-', ADD, op_sub },
398 { '*', MUL, op_mul },
399 { '/', MUL, op_div },
400 { '%', MUL, op_mod },
401};
402
403struct {
404 int token, (*op)(int);
405} unop[] = {
406 { '+', op_pos },
407 { '-', op_neg },
408 { '~', op_cmpl },
409 { '!', op_not },
410};
411
412#define ALEN(A) (sizeof(A)/sizeof(A[0]))
413
414static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
415{
416 int i, val;
417 Symbol *s;
418 if (token == CPP_IDENTIFIER) {
419 if (yylvalpp->sc_ident == definedAtom) {
420 int needclose = 0;
421 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
422 if (token == '(') {
423 needclose = 1;
424 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
425 }
426 if (token != CPP_IDENTIFIER)
427 goto error;
428 *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
429 ? !s->details.mac.undef : 0;
430 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
431 if (needclose) {
432 if (token != ')')
433 goto error;
434 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
435 }
436 } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
437 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
438 return eval(token, prec, res, err, yylvalpp);
439 } else {
440 goto error;
441 }
442 } else if (token == CPP_INTCONSTANT) {
443 *res = yylvalpp->sc_int;
444 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
445 } else if (token == '(') {
446 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
447 token = eval(token, MIN_PREC, res, err, yylvalpp);
448 if (!*err) {
449 if (token != ')')
450 goto error;
451 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
452 }
453 } else {
454 for (i = ALEN(unop) - 1; i >= 0; i--) {
455 if (unop[i].token == token)
456 break;
457 }
458 if (i >= 0) {
459 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
460 token = eval(token, UNARY, res, err, yylvalpp);
461 *res = unop[i].op(*res);
462 } else {
463 goto error;
464 }
465 }
466 while (!*err) {
467 if (token == ')' || token == '\n') break;
468 for (i = ALEN(binop) - 1; i >= 0; i--) {
469 if (binop[i].token == token)
470 break;
471 }
472 if (i < 0 || binop[i].prec <= prec)
473 break;
474 val = *res;
475 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
476 token = eval(token, binop[i].prec, res, err, yylvalpp);
daniel@transgaming.com3b5643c2011-02-28 15:06:55 +0000477
478 if (binop[i].op == op_div || binop[i].op == op_mod)
479 {
480 if (*res == 0)
481 {
482 CPPErrorToInfoLog("preprocessor divide or modulo by zero");
483 *err = 1;
484 return token;
485 }
486 }
487
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488 *res = binop[i].op(val, *res);
489 }
490 return token;
491error:
492 CPPErrorToInfoLog("incorrect preprocessor directive");
493 *err = 1;
494 *res = 0;
495 return token;
496} // eval
497
498static int CPPif(yystypepp * yylvalpp) {
499 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
500 int res = 0, err = 0;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000501
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502 if (!cpp->ifdepth++)
503 ifloc = *cpp->tokenLoc;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000504 if(cpp->ifdepth > MAX_IF_NESTING){
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000505 CPPErrorToInfoLog("max #if nesting depth exceeded");
daniel@transgaming.come9874052011-01-26 17:32:26 +0000506 cpp->CompileError = 1;
507 return 0;
508 }
509 cpp->elsetracker++;
510 // sanity check elsetracker
511 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
512 CPPErrorToInfoLog("mismatched #if/#endif statements");
513 cpp->CompileError = 1;
514 return 0;
515 }
516 cpp->elsedepth[cpp->elsetracker] = 0;
517
518 token = eval(token, MIN_PREC, &res, &err, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519 if (token != '\n') {
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000520 CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
521 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000522 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000523 if (token <= 0) { // EOF or error
524 CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline");
525 return 0;
526 }
527 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000528 }
529 if (!res && !err) {
530 token = CPPelse(1, yylvalpp);
531 }
532
533 return token;
534} // CPPif
535
536static int CPPifdef(int defined, yystypepp * yylvalpp)
537{
538 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
539 int name = yylvalpp->sc_ident;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000540 if(++cpp->ifdepth > MAX_IF_NESTING){
541 CPPErrorToInfoLog("max #if nesting depth exceeded");
542 cpp->CompileError = 1;
543 return 0;
544 }
545 cpp->elsetracker++;
546 // sanity check elsetracker
547 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
548 CPPErrorToInfoLog("mismatched #if/#endif statements");
549 cpp->CompileError = 1;
550 return 0;
551 }
daniel@transgaming.com9e78e5e2010-04-29 03:39:02 +0000552 cpp->elsedepth[cpp->elsetracker] = 0;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000553
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000554 if (token != CPP_IDENTIFIER) {
555 defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
556 } else {
557 Symbol *s = LookUpSymbol(macros, name);
558 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
559 if (token != '\n') {
560 CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000561 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000562 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000563 if (token <= 0) { // EOF or error
564 CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
565 return 0;
566 }
567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568 }
569 if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
570 token = CPPelse(1, yylvalpp);
571 }
572 return token;
573} // CPPifdef
574
575static int CPPline(yystypepp * yylvalpp)
576{
577 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
578 if(token=='\n'){
579 DecLineNumber();
580 CPPErrorToInfoLog("#line");
581 IncLineNumber();
582 return token;
583 }
584 else if (token == CPP_INTCONSTANT) {
585 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
586 SetLineNumber(yylvalpp->sc_int);
587 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
588
589 if (token == CPP_INTCONSTANT) {
590 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
591 SetStringNumber(yylvalpp->sc_int);
592 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
593 if(token!='\n')
594 CPPErrorToInfoLog("#line");
595 }
596 else if (token == '\n'){
597 return token;
598 }
599 else{
600 CPPErrorToInfoLog("#line");
601 }
602 }
603 else{
604 CPPErrorToInfoLog("#line");
605 }
606 return token;
607}
608
609static int CPPerror(yystypepp * yylvalpp) {
610
611 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
612 const char *message;
613
614 while (token != '\n') {
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000615 if (token <= 0){
616 CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline");
617 return 0;
618 }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619 StoreStr(yylvalpp->symbol_name);
620 }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
621 StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
622 }else {
623 StoreStr(GetStringOfAtom(atable,token));
624 }
625 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
626 }
627 DecLineNumber();
628 //store this msg into the shader's information log..set the Compile Error flag!!!!
629 message=GetStrfromTStr();
630 CPPShInfoLogMsg(message);
631 ResetTString();
632 cpp->CompileError=1;
633 IncLineNumber();
634 return '\n';
635}//CPPerror
636
637static int CPPpragma(yystypepp * yylvalpp)
638{
639 char SrcStrName[2];
640 char** allTokens;
641 int tokenCount = 0;
642 int maxTokenCount = 10;
643 const char* SrcStr;
644 int i;
645
646 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
647
648 if (token=='\n') {
649 DecLineNumber();
650 CPPErrorToInfoLog("#pragma");
651 IncLineNumber();
652 return token;
653 }
654
655 allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);
656
657 while (token != '\n') {
658 if (tokenCount >= maxTokenCount) {
659 maxTokenCount *= 2;
660 allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
661 }
662 switch (token) {
663 case CPP_IDENTIFIER:
664 SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
665 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
666 strcpy(allTokens[tokenCount++], SrcStr);
667 break;
668 case CPP_INTCONSTANT:
669 SrcStr = yylvalpp->symbol_name;
670 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
671 strcpy(allTokens[tokenCount++], SrcStr);
672 break;
673 case CPP_FLOATCONSTANT:
674 SrcStr = yylvalpp->symbol_name;
675 allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
676 strcpy(allTokens[tokenCount++], SrcStr);
677 break;
678 case -1:
679 // EOF
680 CPPShInfoLogMsg("#pragma directive must end with a newline");
681 return token;
682 default:
683 SrcStrName[0] = token;
684 SrcStrName[1] = '\0';
685 allTokens[tokenCount] = (char*)malloc(2);
686 strcpy(allTokens[tokenCount++], SrcStrName);
687 }
688 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
689 }
690
691 cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
692 HandlePragma((const char**)allTokens, tokenCount);
693 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
694
695 for (i = 0; i < tokenCount; ++i) {
696 free (allTokens[i]);
697 }
698 free (allTokens);
699
700 return token;
701} // CPPpragma
702
daniel@transgaming.com76039472010-04-15 20:45:18 +0000703#define ESSL_VERSION_NUMBER 100
704#define ESSL_VERSION_STRING "100"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705
706static int CPPversion(yystypepp * yylvalpp)
707{
708
709 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
710
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000711 if (cpp->pastFirstStatement == 1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712 CPPShInfoLogMsg("#version must occur before any other statement in the program");
713
714 if(token=='\n'){
715 DecLineNumber();
716 CPPErrorToInfoLog("#version");
717 IncLineNumber();
718 return token;
719 }
720 if (token != CPP_INTCONSTANT)
721 CPPErrorToInfoLog("#version");
722
723 yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
724 //SetVersionNumber(yylvalpp->sc_int);
725
daniel@transgaming.com76039472010-04-15 20:45:18 +0000726 if (yylvalpp->sc_int != ESSL_VERSION_NUMBER)
727 CPPShInfoLogMsg("Version number not supported by ESSL");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728
729 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
730
731 if (token == '\n'){
732 return token;
733 }
734 else{
735 CPPErrorToInfoLog("#version");
736 }
737 return token;
738} // CPPversion
739
740static int CPPextension(yystypepp * yylvalpp)
741{
742
743 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000744 char extensionName[MAX_SYMBOL_NAME_LEN + 1];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745
746 if(token=='\n'){
747 DecLineNumber();
748 CPPShInfoLogMsg("extension name not specified");
749 IncLineNumber();
750 return token;
751 }
752
753 if (token != CPP_IDENTIFIER)
754 CPPErrorToInfoLog("#extension");
755
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000756 strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN);
757 extensionName[MAX_SYMBOL_NAME_LEN] = '\0';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000758
759 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
760 if (token != ':') {
761 CPPShInfoLogMsg("':' missing after extension name");
762 return token;
763 }
764
765 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
766 if (token != CPP_IDENTIFIER) {
767 CPPShInfoLogMsg("behavior for extension not specified");
768 return token;
769 }
770
771 updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
772
773 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
774 if (token == '\n'){
775 return token;
776 }
777 else{
778 CPPErrorToInfoLog("#extension");
779 }
780 return token;
781} // CPPextension
782
783int readCPPline(yystypepp * yylvalpp)
784{
785 int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
786 const char *message;
787 int isVersion = 0;
788
789 if (token == CPP_IDENTIFIER) {
790 if (yylvalpp->sc_ident == defineAtom) {
791 token = CPPdefine(yylvalpp);
792 } else if (yylvalpp->sc_ident == elseAtom) {
793 if(ChkCorrectElseNesting()){
794 if (!cpp->ifdepth ){
795 CPPErrorToInfoLog("#else mismatch");
796 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000797 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798 }
799 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
800 if (token != '\n') {
801 CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000802 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000803 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000804 if (token <= 0) { // EOF or error
805 CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
806 return 0;
807 }
808 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000809 }
810 token = CPPelse(0, yylvalpp);
811 }else{
812 CPPErrorToInfoLog("#else after a #else");
daniel@transgaming.come9874052011-01-26 17:32:26 +0000813 cpp->ifdepth = 0;
814 cpp->elsetracker = 0;
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000815 cpp->pastFirstStatement = 1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000816 cpp->CompileError = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817 return 0;
818 }
819 } else if (yylvalpp->sc_ident == elifAtom) {
820 if (!cpp->ifdepth){
821 CPPErrorToInfoLog("#elif mismatch");
822 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000823 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000824 }
825 // this token is really a dont care, but we still need to eat the tokens
826 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000827 while (token != '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000829 if (token <= 0) { // EOF or error
830 CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
831 cpp->CompileError = 1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000832 return 0;
daniel@transgaming.com5efd8b42010-12-13 14:48:03 +0000833 }
834 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000835 token = CPPelse(0, yylvalpp);
836 } else if (yylvalpp->sc_ident == endifAtom) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000837 if (!cpp->ifdepth){
838 CPPErrorToInfoLog("#endif mismatch");
839 cpp->CompileError=1;
daniel@transgaming.come9874052011-01-26 17:32:26 +0000840 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000841 }
842 else
daniel@transgaming.come9874052011-01-26 17:32:26 +0000843 --cpp->ifdepth;
844
845 if (cpp->elsetracker)
846 --cpp->elsetracker;
847
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000848 } else if (yylvalpp->sc_ident == ifAtom) {
849 token = CPPif(yylvalpp);
850 } else if (yylvalpp->sc_ident == ifdefAtom) {
851 token = CPPifdef(1, yylvalpp);
852 } else if (yylvalpp->sc_ident == ifndefAtom) {
853 token = CPPifdef(0, yylvalpp);
854 } else if (yylvalpp->sc_ident == lineAtom) {
855 token = CPPline(yylvalpp);
856 } else if (yylvalpp->sc_ident == pragmaAtom) {
857 token = CPPpragma(yylvalpp);
858 } else if (yylvalpp->sc_ident == undefAtom) {
859 token = CPPundef(yylvalpp);
860 } else if (yylvalpp->sc_ident == errorAtom) {
861 token = CPPerror(yylvalpp);
862 } else if (yylvalpp->sc_ident == versionAtom) {
863 token = CPPversion(yylvalpp);
864 isVersion = 1;
865 } else if (yylvalpp->sc_ident == extensionAtom) {
866 token = CPPextension(yylvalpp);
867 } else {
868 StoreStr("Invalid Directive");
869 StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
870 message=GetStrfromTStr();
871 CPPShInfoLogMsg(message);
872 ResetTString();
873 }
874 }
875 while (token != '\n' && token != 0 && token != EOF) {
876 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
877 }
878
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000879 cpp->pastFirstStatement = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000880
881 return token;
882} // readCPPline
883
884void FreeMacro(MacroSymbol *s) {
885 DeleteTokenStream(s->body);
886}
887
daniel@transgaming.comcd0a9a82010-05-18 18:51:59 +0000888void PredefineIntMacro(const char *name, int value) {
889 SourceLoc location = {0};
890 Symbol *symbol = NULL;
891 MacroSymbol macro = {0};
892 yystypepp val = {0};
893 int atom = 0;
894
895 macro.body = NewTokenStream(name, macros->pool);
896 val.sc_int = value;
897 sprintf(val.symbol_name, "%d", value);
898 RecordToken(macro.body, CPP_INTCONSTANT, &val);
899 atom = LookUpAddString(atable, name);
900 symbol = AddSymbol(&location, macros, atom, MACRO_S);
901 symbol->details.mac = macro;
902}
903
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000904static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
905static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
906
907static void PushEofSrc() {
908 InputSrc *in = malloc(sizeof(InputSrc));
909 memset(in, 0, sizeof(InputSrc));
910 in->scan = eof_scan;
911 in->getch = eof_scan;
912 in->ungetch = noop;
913 in->prev = cpp->currentInput;
914 cpp->currentInput = in;
915}
916
917static void PopEofSrc() {
918 if (cpp->currentInput->scan == eof_scan) {
919 InputSrc *in = cpp->currentInput;
920 cpp->currentInput = in->prev;
921 free(in);
922 }
923}
924
925static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
926 int token;
927 TokenStream *n;
928 RewindTokenStream(a);
929 do {
930 token = ReadToken(a, yylvalpp);
931 if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
932 break;
933 } while (token > 0);
934 if (token <= 0) return a;
935 n = NewTokenStream("macro arg", 0);
936 PushEofSrc();
937 ReadFromTokenStream(a, 0, 0);
938 while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
939 if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
940 continue;
941 RecordToken(n, token, yylvalpp);
942 }
943 PopEofSrc();
944 DeleteTokenStream(a);
945 return n;
946} // PrescanMacroArg
947
948typedef struct MacroInputSrc {
949 InputSrc base;
950 MacroSymbol *mac;
951 TokenStream **args;
952} MacroInputSrc;
953
954/* macro_scan ---
955** return the next token for a macro expanion, handling macro args
956*/
957static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
958 int i;
959 int token = ReadToken(in->mac->body, yylvalpp);
960 if (token == CPP_IDENTIFIER) {
961 for (i = in->mac->argc-1; i>=0; i--)
962 if (in->mac->args[i] == yylvalpp->sc_ident) break;
963 if (i >= 0) {
964 ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
965 return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
966 }
967 }
968 if (token > 0) return token;
969 in->mac->busy = 0;
970 cpp->currentInput = in->base.prev;
971 if (in->args) {
972 for (i=in->mac->argc-1; i>=0; i--)
973 DeleteTokenStream(in->args[i]);
974 free(in->args);
975 }
976 free(in);
977 return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
978} // macro_scan
979
980/* MacroExpand
981** check an identifier (atom) to see if it a macro that should be expanded.
982** If it is, push an InputSrc that will produce the appropriate expansion
983** and return TRUE. If not, return FALSE.
984*/
985
986int MacroExpand(int atom, yystypepp * yylvalpp)
987{
988 Symbol *sym = LookUpSymbol(macros, atom);
989 MacroInputSrc *in;
990 int i,j, token, depth=0;
991 const char *message;
992 if (atom == __LINE__Atom) {
993 yylvalpp->sc_int = GetLineNumber();
994 sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
995 UngetToken(CPP_INTCONSTANT, yylvalpp);
996 return 1;
997 }
998 if (atom == __FILE__Atom) {
999 yylvalpp->sc_int = GetStringNumber();
1000 sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
1001 UngetToken(CPP_INTCONSTANT, yylvalpp);
1002 return 1;
1003 }
1004 if (atom == __VERSION__Atom) {
daniel@transgaming.com76039472010-04-15 20:45:18 +00001005 strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006 yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
1007 UngetToken(CPP_INTCONSTANT, yylvalpp);
1008 return 1;
1009 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001010 if (!sym || sym->details.mac.undef) return 0;
1011 if (sym->details.mac.busy) return 0; // no recursive expansions
1012 in = malloc(sizeof(*in));
1013 memset(in, 0, sizeof(*in));
1014 in->base.scan = (void *)macro_scan;
1015 in->base.line = cpp->currentInput->line;
1016 in->base.name = cpp->currentInput->name;
1017 in->mac = &sym->details.mac;
1018 if (sym->details.mac.args) {
1019 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1020 if (token != '(') {
1021 UngetToken(token, yylvalpp);
1022 yylvalpp->sc_ident = atom;
1023 return 0;
1024 }
1025 in->args = malloc(in->mac->argc * sizeof(TokenStream *));
1026 for (i=0; i<in->mac->argc; i++)
1027 in->args[i] = NewTokenStream("macro arg", 0);
1028 i=0;j=0;
1029 do{
1030 depth = 0;
1031 while(1) {
1032 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1033 if (token <= 0) {
1034 StoreStr("EOF in Macro ");
1035 StoreStr(GetStringOfAtom(atable,atom));
1036 message=GetStrfromTStr();
1037 CPPShInfoLogMsg(message);
1038 ResetTString();
1039 return 1;
1040 }
1041 if((in->mac->argc==0) && (token!=')')) break;
1042 if (depth == 0 && (token == ',' || token == ')')) break;
1043 if (token == '(') depth++;
1044 if (token == ')') depth--;
1045 RecordToken(in->args[i], token, yylvalpp);
1046 j=1;
1047 }
1048 if (token == ')') {
1049 if((in->mac->argc==1) &&j==0)
1050 break;
1051 i++;
1052 break;
1053 }
1054 i++;
1055 }while(i < in->mac->argc);
1056
1057 if (i < in->mac->argc) {
1058 StoreStr("Too few args in Macro ");
1059 StoreStr(GetStringOfAtom(atable,atom));
1060 message=GetStrfromTStr();
1061 CPPShInfoLogMsg(message);
1062 ResetTString();
1063 } else if (token != ')') {
1064 depth=0;
1065 while (token >= 0 && (depth > 0 || token != ')')) {
1066 if (token == ')') depth--;
1067 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
1068 if (token == '(') depth++;
1069 }
1070
1071 if (token <= 0) {
1072 StoreStr("EOF in Macro ");
1073 StoreStr(GetStringOfAtom(atable,atom));
1074 message=GetStrfromTStr();
1075 CPPShInfoLogMsg(message);
1076 ResetTString();
1077 return 1;
1078 }
1079 StoreStr("Too many args in Macro ");
1080 StoreStr(GetStringOfAtom(atable,atom));
1081 message=GetStrfromTStr();
1082 CPPShInfoLogMsg(message);
1083 ResetTString();
1084 }
1085 for (i=0; i<in->mac->argc; i++) {
1086 in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
1087 }
1088 }
1089#if 0
1090 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
1091 loc.line, GetAtomString(atable, atom));
1092 for (i=0; i<in->mac->argc; i++) {
1093 printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
1094 DumpTokenStream(stdout, in->args[i]);
1095 printf("'\n");
1096 }
1097#endif
1098 /*retain the input source*/
1099 in->base.prev = cpp->currentInput;
1100 sym->details.mac.busy = 1;
1101 RewindTokenStream(sym->details.mac.body);
1102 cpp->currentInput = &in->base;
1103 return 1;
1104} // MacroExpand
1105
1106int ChkCorrectElseNesting(void)
1107{
daniel@transgaming.come9874052011-01-26 17:32:26 +00001108 // sanity check to make sure elsetracker is in a valid range
1109 if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
1110 return 0;
1111 }
1112
1113 if (cpp->elsedepth[cpp->elsetracker] == 0) {
1114 cpp->elsedepth[cpp->elsetracker] = 1;
1115 return 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001116 }
1117 return 0;
1118}
1119
1120