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