1 // 2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 //Copyright (C) 2013 LunarG, Inc. 4 //All rights reserved. 5 // 6 //Redistribution and use in source and binary forms, with or without 7 //modification, are permitted provided that the following conditions 8 //are met: 9 // 10 // Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // 13 // Redistributions in binary form must reproduce the above 14 // copyright notice, this list of conditions and the following 15 // disclaimer in the documentation and/or other materials provided 16 // with the distribution. 17 // 18 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 19 // contributors may be used to endorse or promote products derived 20 // from this software without specific prior written permission. 21 // 22 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 //POSSIBILITY OF SUCH DAMAGE. 34 // 35 /****************************************************************************\ 36 Copyright (c) 2002, NVIDIA Corporation. 37 38 NVIDIA Corporation("NVIDIA") supplies this software to you in 39 consideration of your agreement to the following terms, and your use, 40 installation, modification or redistribution of this NVIDIA software 41 constitutes acceptance of these terms. If you do not agree with these 42 terms, please do not use, install, modify or redistribute this NVIDIA 43 software. 44 45 In consideration of your agreement to abide by the following terms, and 46 subject to these terms, NVIDIA grants you a personal, non-exclusive 47 license, under NVIDIA's copyrights in this original NVIDIA software (the 48 "NVIDIA Software"), to use, reproduce, modify and redistribute the 49 NVIDIA Software, with or without modifications, in source and/or binary 50 forms; provided that if you redistribute the NVIDIA Software, you must 51 retain the copyright notice of NVIDIA, this notice and the following 52 text and disclaimers in all such redistributions of the NVIDIA Software. 53 Neither the name, trademarks, service marks nor logos of NVIDIA 54 Corporation may be used to endorse or promote products derived from the 55 NVIDIA Software without specific prior written permission from NVIDIA. 56 Except as expressly stated in this notice, no other rights or licenses 57 express or implied, are granted by NVIDIA herein, including but not 58 limited to any patent rights that may be infringed by your derivative 59 works or by other works in which the NVIDIA Software may be 60 incorporated. No hardware is licensed hereunder. 61 62 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT 63 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 64 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, 65 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 66 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER 67 PRODUCTS. 68 69 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, 70 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 71 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 72 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY 73 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE 74 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, 75 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 76 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 77 \****************************************************************************/ 78 // 79 // scanner.c 80 // 81 82 #define _CRT_SECURE_NO_WARNINGS 83 84 #include <stdarg.h> 85 #include <stdio.h> 86 #include <stdlib.h> 87 #include <string.h> 88 89 #include "PpContext.h" 90 #include "PpTokens.h" 91 #include "../Scan.h" 92 93 namespace glslang { 94 95 int TPpContext::InitScanner() 96 { 97 // Add various atoms needed by the CPP line scanner: 98 if (!InitCPP()) 99 return 0; 100 101 previous_token = '\n'; 102 103 return 1; 104 } 105 106 /////////////////////////////////////////////////////////////////////////////////////////////// 107 /////////////////////////////////// Floating point constants: ///////////////////////////////// 108 /////////////////////////////////////////////////////////////////////////////////////////////// 109 110 /* 111 * lFloatConst() - Scan a single- or double-precision floating point constant. Assumes that the scanner 112 * has seen at least one digit, followed by either a decimal '.' or the 113 * letter 'e', or a precision ending (e.g., F or LF). 114 */ 115 116 int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) 117 { 118 bool HasDecimalOrExponent = false; 119 int declen; 120 int str_len; 121 int isDouble = 0; 122 123 declen = 0; 124 125 str_len=len; 126 char* str = ppToken->name; 127 if (ch == '.') { 128 HasDecimalOrExponent = true; 129 str[len++] = (char)ch; 130 ch = getChar(); 131 while (ch >= '0' && ch <= '9') { 132 if (len < MaxTokenLength) { 133 declen++; 134 if (len > 0 || ch != '0') { 135 str[len] = (char)ch; 136 len++; 137 str_len++; 138 } 139 ch = getChar(); 140 } else { 141 parseContext.ppError(ppToken->loc, "float literal too long", "", ""); 142 len = 1; 143 str_len = 1; 144 } 145 } 146 } 147 148 // Exponent: 149 150 if (ch == 'e' || ch == 'E') { 151 HasDecimalOrExponent = true; 152 if (len >= MaxTokenLength) { 153 parseContext.ppError(ppToken->loc, "float literal too long", "", ""); 154 len = 1; 155 str_len = 1; 156 } else { 157 str[len++] = (char)ch; 158 ch = getChar(); 159 if (ch == '+') { 160 str[len++] = (char)ch; 161 ch = getChar(); 162 } else if (ch == '-') { 163 str[len++] = (char)ch; 164 ch = getChar(); 165 } 166 if (ch >= '0' && ch <= '9') { 167 while (ch >= '0' && ch <= '9') { 168 if (len < MaxTokenLength) { 169 str[len++] = (char)ch; 170 ch = getChar(); 171 } else { 172 parseContext.ppError(ppToken->loc, "float literal too long", "", ""); 173 len = 1; 174 str_len = 1; 175 } 176 } 177 } else { 178 parseContext.ppError(ppToken->loc, "bad character in float exponent", "", ""); 179 } 180 } 181 } 182 183 if (len == 0) { 184 ppToken->dval = 0.0; 185 strcpy(str, "0.0"); 186 } else { 187 if (ch == 'l' || ch == 'L') { 188 parseContext.doubleCheck(ppToken->loc, "double floating-point suffix"); 189 if (! HasDecimalOrExponent) 190 parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); 191 int ch2 = getChar(); 192 if (ch2 != 'f' && ch2 != 'F') { 193 ungetChar(); 194 ungetChar(); 195 } else { 196 if (len < MaxTokenLength) { 197 str[len++] = (char)ch; 198 str[len++] = (char)ch2; 199 isDouble = 1; 200 } else { 201 parseContext.ppError(ppToken->loc, "float literal too long", "", ""); 202 len = 1,str_len=1; 203 } 204 } 205 } else if (ch == 'f' || ch == 'F') { 206 parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix"); 207 if (! parseContext.relaxedErrors()) 208 parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix"); 209 if (! HasDecimalOrExponent) 210 parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); 211 if (len < MaxTokenLength) 212 str[len++] = (char)ch; 213 else { 214 parseContext.ppError(ppToken->loc, "float literal too long", "", ""); 215 len = 1,str_len=1; 216 } 217 } else 218 ungetChar(); 219 220 str[len]='\0'; 221 222 ppToken->dval = strtod(str, nullptr); 223 } 224 225 if (isDouble) 226 return PpAtomConstDouble; 227 else 228 return PpAtomConstFloat; 229 } 230 231 // 232 // Scanner used to tokenize source stream. 233 // 234 int TPpContext::tStringInput::scan(TPpToken* ppToken) 235 { 236 char* tokenText = ppToken->name; 237 int AlreadyComplained = 0; 238 int len = 0; 239 int ch = 0; 240 int ii = 0; 241 unsigned long long ival = 0; 242 bool enableInt64 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64); 243 244 ppToken->ival = 0; 245 ppToken->i64val = 0; 246 ppToken->space = false; 247 ch = getch(); 248 for (;;) { 249 while (ch == ' ' || ch == '\t') { 250 ppToken->space = true; 251 ch = getch(); 252 } 253 254 ppToken->loc = pp->parseContext.getCurrentLoc(); 255 len = 0; 256 switch (ch) { 257 default: 258 // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token) 259 return ch; 260 261 case 'A': case 'B': case 'C': case 'D': case 'E': 262 case 'F': case 'G': case 'H': case 'I': case 'J': 263 case 'K': case 'L': case 'M': case 'N': case 'O': 264 case 'P': case 'Q': case 'R': case 'S': case 'T': 265 case 'U': case 'V': case 'W': case 'X': case 'Y': 266 case 'Z': case '_': 267 case 'a': case 'b': case 'c': case 'd': case 'e': 268 case 'f': case 'g': case 'h': case 'i': case 'j': 269 case 'k': case 'l': case 'm': case 'n': case 'o': 270 case 'p': case 'q': case 'r': case 's': case 't': 271 case 'u': case 'v': case 'w': case 'x': case 'y': 272 case 'z': 273 do { 274 if (len < MaxTokenLength) { 275 tokenText[len++] = (char)ch; 276 ch = getch(); 277 } else { 278 if (! AlreadyComplained) { 279 pp->parseContext.ppError(ppToken->loc, "name too long", "", ""); 280 AlreadyComplained = 1; 281 } 282 ch = getch(); 283 } 284 } while ((ch >= 'a' && ch <= 'z') || 285 (ch >= 'A' && ch <= 'Z') || 286 (ch >= '0' && ch <= '9') || 287 ch == '_'); 288 289 // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc. 290 if (len == 0) 291 continue; 292 293 tokenText[len] = '\0'; 294 ungetch(); 295 ppToken->atom = pp->LookUpAddString(tokenText); 296 return PpAtomIdentifier; 297 case '0': 298 ppToken->name[len++] = (char)ch; 299 ch = getch(); 300 if (ch == 'x' || ch == 'X') { 301 // must be hexidecimal 302 303 bool isUnsigned = false; 304 bool isInt64 = false; 305 ppToken->name[len++] = (char)ch; 306 ch = getch(); 307 if ((ch >= '0' && ch <= '9') || 308 (ch >= 'A' && ch <= 'F') || 309 (ch >= 'a' && ch <= 'f')) { 310 311 ival = 0; 312 do { 313 if (ival <= 0x0fffffff || (enableInt64 && ival <= 0x0fffffffffffffffull)) { 314 ppToken->name[len++] = (char)ch; 315 if (ch >= '0' && ch <= '9') { 316 ii = ch - '0'; 317 } else if (ch >= 'A' && ch <= 'F') { 318 ii = ch - 'A' + 10; 319 } else if (ch >= 'a' && ch <= 'f') { 320 ii = ch - 'a' + 10; 321 } else 322 pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", ""); 323 ival = (ival << 4) | ii; 324 } else { 325 if (! AlreadyComplained) { 326 pp->parseContext.ppError(ppToken->loc, "hexidecimal literal too big", "", ""); 327 AlreadyComplained = 1; 328 } 329 ival = 0xffffffffffffffffull; 330 } 331 ch = getch(); 332 } while ((ch >= '0' && ch <= '9') || 333 (ch >= 'A' && ch <= 'F') || 334 (ch >= 'a' && ch <= 'f')); 335 } else { 336 pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", ""); 337 } 338 if (ch == 'u' || ch == 'U') { 339 if (len < MaxTokenLength) 340 ppToken->name[len++] = (char)ch; 341 isUnsigned = true; 342 343 if (enableInt64) { 344 int nextCh = getch(); 345 if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) { 346 if (len < MaxTokenLength) 347 ppToken->name[len++] = (char)nextCh; 348 isInt64 = true; 349 } else 350 ungetch(); 351 } 352 } 353 else if (enableInt64 && (ch == 'l' || ch == 'L')) { 354 if (len < MaxTokenLength) 355 ppToken->name[len++] = (char)ch; 356 isInt64 = true; 357 } else 358 ungetch(); 359 ppToken->name[len] = '\0'; 360 361 if (isInt64) { 362 ppToken->i64val = ival; 363 return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; 364 } else { 365 ppToken->ival = (int)ival; 366 return isUnsigned ? PpAtomConstUint : PpAtomConstInt; 367 } 368 } else { 369 // could be octal integer or floating point, speculative pursue octal until it must be floating point 370 371 bool isUnsigned = false; 372 bool isInt64 = false; 373 bool octalOverflow = false; 374 bool nonOctal = false; 375 ival = 0; 376 377 // see how much octal-like stuff we can read 378 while (ch >= '0' && ch <= '7') { 379 if (len < MaxTokenLength) 380 ppToken->name[len++] = (char)ch; 381 else if (! AlreadyComplained) { 382 pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); 383 AlreadyComplained = 1; 384 } 385 if (ival <= 0x1fffffff || (enableInt64 && ival <= 0x1fffffffffffffffull)) { 386 ii = ch - '0'; 387 ival = (ival << 3) | ii; 388 } else 389 octalOverflow = true; 390 ch = getch(); 391 } 392 393 // could be part of a float... 394 if (ch == '8' || ch == '9') { 395 nonOctal = true; 396 do { 397 if (len < MaxTokenLength) 398 ppToken->name[len++] = (char)ch; 399 else if (! AlreadyComplained) { 400 pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); 401 AlreadyComplained = 1; 402 } 403 ch = getch(); 404 } while (ch >= '0' && ch <= '9'); 405 } 406 if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') 407 return pp->lFloatConst(len, ch, ppToken); 408 409 // wasn't a float, so must be octal... 410 if (nonOctal) 411 pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", ""); 412 413 if (ch == 'u' || ch == 'U') { 414 if (len < MaxTokenLength) 415 ppToken->name[len++] = (char)ch; 416 isUnsigned = true; 417 418 if (enableInt64) { 419 int nextCh = getch(); 420 if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) { 421 if (len < MaxTokenLength) 422 ppToken->name[len++] = (char)nextCh; 423 isInt64 = true; 424 } else 425 ungetch(); 426 } 427 } 428 else if (enableInt64 && (ch == 'l' || ch == 'L')) { 429 if (len < MaxTokenLength) 430 ppToken->name[len++] = (char)ch; 431 isInt64 = true; 432 } else 433 ungetch(); 434 ppToken->name[len] = '\0'; 435 436 if (octalOverflow) 437 pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", ""); 438 439 if (isInt64) { 440 ppToken->i64val = ival; 441 return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; 442 } else { 443 ppToken->ival = (int)ival; 444 return isUnsigned ? PpAtomConstUint : PpAtomConstInt; 445 } 446 } 447 break; 448 case '1': case '2': case '3': case '4': 449 case '5': case '6': case '7': case '8': case '9': 450 // can't be hexidecimal or octal, is either decimal or floating point 451 452 do { 453 if (len < MaxTokenLength) 454 ppToken->name[len++] = (char)ch; 455 else if (! AlreadyComplained) { 456 pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); 457 AlreadyComplained = 1; 458 } 459 ch = getch(); 460 } while (ch >= '0' && ch <= '9'); 461 if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') { 462 return pp->lFloatConst(len, ch, ppToken); 463 } else { 464 // Finish handling signed and unsigned integers 465 int numericLen = len; 466 bool isUnsigned = false; 467 bool isInt64 = false; 468 if (ch == 'u' || ch == 'U') { 469 if (len < MaxTokenLength) 470 ppToken->name[len++] = (char)ch; 471 isUnsigned = true; 472 473 if (enableInt64) { 474 int nextCh = getch(); 475 if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) { 476 if (len < MaxTokenLength) 477 ppToken->name[len++] = (char)nextCh; 478 isInt64 = true; 479 } else 480 ungetch(); 481 } 482 } else if (enableInt64 && (ch == 'l' || ch == 'L')) { 483 if (len < MaxTokenLength) 484 ppToken->name[len++] = (char)ch; 485 isInt64 = true; 486 } else 487 ungetch(); 488 489 ppToken->name[len] = '\0'; 490 ival = 0; 491 const unsigned oneTenthMaxInt = 0xFFFFFFFFu / 10; 492 const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt; 493 const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10; 494 const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64; 495 for (int i = 0; i < numericLen; i++) { 496 ch = ppToken->name[i] - '0'; 497 if ((enableInt64 == false && ((ival > oneTenthMaxInt) || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt))) || 498 (enableInt64 && ((ival > oneTenthMaxInt64) || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)))) { 499 pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", ""); 500 ival = 0xFFFFFFFFFFFFFFFFull; 501 break; 502 } else 503 ival = ival * 10 + ch; 504 } 505 506 if (isInt64) { 507 ppToken->i64val = ival; 508 return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; 509 } else { 510 ppToken->ival = (int)ival; 511 return isUnsigned ? PpAtomConstUint : PpAtomConstInt; 512 } 513 } 514 break; 515 case '-': 516 ch = getch(); 517 if (ch == '-') { 518 return PpAtomDecrement; 519 } else if (ch == '=') { 520 return PpAtomSub; 521 } else { 522 ungetch(); 523 return '-'; 524 } 525 case '+': 526 ch = getch(); 527 if (ch == '+') { 528 return PpAtomIncrement; 529 } else if (ch == '=') { 530 return PpAtomAdd; 531 } else { 532 ungetch(); 533 return '+'; 534 } 535 case '*': 536 ch = getch(); 537 if (ch == '=') { 538 return PpAtomMul; 539 } else { 540 ungetch(); 541 return '*'; 542 } 543 case '%': 544 ch = getch(); 545 if (ch == '=') { 546 return PpAtomMod; 547 } else { 548 ungetch(); 549 return '%'; 550 } 551 case '^': 552 ch = getch(); 553 if (ch == '^') { 554 return PpAtomXor; 555 } else { 556 if (ch == '=') 557 return PpAtomXorAssign; 558 else{ 559 ungetch(); 560 return '^'; 561 } 562 } 563 564 case '=': 565 ch = getch(); 566 if (ch == '=') { 567 return PpAtomEQ; 568 } else { 569 ungetch(); 570 return '='; 571 } 572 case '!': 573 ch = getch(); 574 if (ch == '=') { 575 return PpAtomNE; 576 } else { 577 ungetch(); 578 return '!'; 579 } 580 case '|': 581 ch = getch(); 582 if (ch == '|') { 583 return PpAtomOr; 584 } else if (ch == '=') { 585 return PpAtomOrAssign; 586 } else { 587 ungetch(); 588 return '|'; 589 } 590 case '&': 591 ch = getch(); 592 if (ch == '&') { 593 return PpAtomAnd; 594 } else if (ch == '=') { 595 return PpAtomAndAssign; 596 } else { 597 ungetch(); 598 return '&'; 599 } 600 case '<': 601 ch = getch(); 602 if (ch == '<') { 603 ch = getch(); 604 if (ch == '=') 605 return PpAtomLeftAssign; 606 else { 607 ungetch(); 608 return PpAtomLeft; 609 } 610 } else if (ch == '=') { 611 return PpAtomLE; 612 } else { 613 ungetch(); 614 return '<'; 615 } 616 case '>': 617 ch = getch(); 618 if (ch == '>') { 619 ch = getch(); 620 if (ch == '=') 621 return PpAtomRightAssign; 622 else { 623 ungetch(); 624 return PpAtomRight; 625 } 626 } else if (ch == '=') { 627 return PpAtomGE; 628 } else { 629 ungetch(); 630 return '>'; 631 } 632 case '.': 633 ch = getch(); 634 if (ch >= '0' && ch <= '9') { 635 ungetch(); 636 return pp->lFloatConst(0, '.', ppToken); 637 } else { 638 ungetch(); 639 return '.'; 640 } 641 case '/': 642 ch = getch(); 643 if (ch == '/') { 644 pp->inComment = true; 645 do { 646 ch = getch(); 647 } while (ch != '\n' && ch != EndOfInput); 648 ppToken->space = true; 649 pp->inComment = false; 650 651 return ch; 652 } else if (ch == '*') { 653 ch = getch(); 654 do { 655 while (ch != '*') { 656 if (ch == EndOfInput) { 657 pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); 658 return ch; 659 } 660 ch = getch(); 661 } 662 ch = getch(); 663 if (ch == EndOfInput) { 664 pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); 665 return ch; 666 } 667 } while (ch != '/'); 668 ppToken->space = true; 669 // loop again to get the next token... 670 break; 671 } else if (ch == '=') { 672 return PpAtomDiv; 673 } else { 674 ungetch(); 675 return '/'; 676 } 677 break; 678 case '"': 679 ch = getch(); 680 while (ch != '"' && ch != '\n' && ch != EndOfInput) { 681 if (len < MaxTokenLength) { 682 tokenText[len] = (char)ch; 683 len++; 684 ch = getch(); 685 } else 686 break; 687 }; 688 tokenText[len] = '\0'; 689 if (ch != '"') { 690 ungetch(); 691 pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", ""); 692 } 693 return PpAtomConstString; 694 } 695 696 ch = getch(); 697 } 698 } 699 700 // 701 // The main functional entry-point into the preprocessor, which will 702 // scan the source strings to figure out and return the next processing token. 703 // 704 // Return string pointer to next token. 705 // Return 0 when no more tokens. 706 // 707 const char* TPpContext::tokenize(TPpToken* ppToken) 708 { 709 int token = '\n'; 710 711 for(;;) { 712 token = scanToken(ppToken); 713 ppToken->token = token; 714 if (token == EndOfInput) { 715 missingEndifCheck(); 716 return nullptr; 717 } 718 if (token == '#') { 719 if (previous_token == '\n') { 720 token = readCPPline(ppToken); 721 if (token == EndOfInput) { 722 missingEndifCheck(); 723 return nullptr; 724 } 725 continue; 726 } else { 727 parseContext.ppError(ppToken->loc, "preprocessor directive cannot be preceded by another token", "#", ""); 728 return nullptr; 729 } 730 } 731 previous_token = token; 732 733 if (token == '\n') 734 continue; 735 736 // expand macros 737 if (token == PpAtomIdentifier && MacroExpand(ppToken->atom, ppToken, false, true) != 0) 738 continue; 739 740 const char* tokenString = nullptr; 741 switch (token) { 742 case PpAtomIdentifier: 743 case PpAtomConstInt: 744 case PpAtomConstUint: 745 case PpAtomConstFloat: 746 case PpAtomConstInt64: 747 case PpAtomConstUint64: 748 case PpAtomConstDouble: 749 tokenString = ppToken->name; 750 break; 751 case PpAtomConstString: 752 parseContext.ppError(ppToken->loc, "string literals not supported", "\"\"", ""); 753 break; 754 case '\'': 755 parseContext.ppError(ppToken->loc, "character literals not supported", "\'", ""); 756 break; 757 default: 758 tokenString = GetAtomString(token); 759 break; 760 } 761 762 if (tokenString) { 763 if (tokenString[0] != 0) 764 parseContext.tokensBeforeEOF = 1; 765 766 return tokenString; 767 } 768 } 769 } 770 771 // Checks if we've seen balanced #if...#endif 772 void TPpContext::missingEndifCheck() 773 { 774 if (ifdepth > 0) 775 parseContext.ppError(parseContext.getCurrentLoc(), "missing #endif", "", ""); 776 } 777 778 } // end namespace glslang 779