Home | History | Annotate | Download | only in preprocessor
      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 // scanner.c
     46 //
     47 
     48 #include <assert.h>
     49 #include <stdarg.h>
     50 #include <stdio.h>
     51 #include <stdlib.h>
     52 #include <string.h>
     53 
     54 #if 0
     55     #include <ieeefp.h>
     56 #else
     57     #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
     58                        ((*(int *)&(x) & 0x007fffffL)==0000000000L))
     59 #endif
     60 
     61 #include "compiler/preprocessor/slglobals.h"
     62 #include "compiler/util.h"
     63 
     64 typedef struct StringInputSrc {
     65     InputSrc base;
     66     char *p;
     67 } StringInputSrc;
     68 
     69 static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
     70 {
     71     return EOF;
     72 } // eof_scan
     73 
     74 static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
     75 
     76 static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
     77 
     78 static int byte_scan(InputSrc *, yystypepp * yylvalpp);
     79 
     80 #define EOL_SY '\n'
     81 
     82 #if defined(_MSC_VER)
     83     #define DBG_BREAKPOINT() __asm int 3
     84 #elif defined(_M_AMD64)
     85     #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
     86 #else
     87     #define DBG_BREAKPOINT()
     88 #endif
     89 
     90 #if defined(_MSC_VER) && !defined(_M_AMD64)
     91     __int64 RDTSC ( void ) {
     92 
     93         __int64 v;
     94 
     95         __asm __emit 0x0f
     96         __asm __emit 0x31
     97         __asm mov dword ptr v, eax
     98         __asm mov dword ptr v+4, edx
     99 
    100         return v;
    101     }
    102 #endif
    103 
    104 
    105 int InitScanner(CPPStruct *cpp)
    106 {
    107     // Add various atoms needed by the CPP line scanner:
    108     if (!InitCPP())
    109         return 0;
    110 
    111     cpp->mostRecentToken = 0;
    112     cpp->tokenLoc = &cpp->ltokenLoc;
    113 
    114     cpp->ltokenLoc.file = 0;
    115     cpp->ltokenLoc.line = 0;
    116 
    117     cpp->currentInput = &eof_inputsrc;
    118     cpp->previous_token = '\n';
    119     cpp->pastFirstStatement = 0;
    120 
    121     return 1;
    122 } // InitScanner
    123 
    124 int FreeScanner(void)
    125 {
    126     return (FreeCPP());
    127 }
    128 
    129 /*
    130  * str_getch()
    131  * takes care of reading from multiple strings.
    132  * returns the next-char from the input stream.
    133  * returns EOF when the complete shader is parsed.
    134  */
    135 static int str_getch(StringInputSrc *in)
    136 {
    137     for(;;){
    138        if (*in->p){
    139           if (*in->p == '\n') {
    140              in->base.line++;
    141              IncLineNumber();
    142           }
    143           return *in->p++;
    144        }
    145        if(++(cpp->PaWhichStr) < cpp->PaArgc){
    146           free(in);
    147           SetStringNumber(cpp->PaWhichStr);
    148           SetLineNumber(1);
    149           ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
    150           in=(StringInputSrc*)cpp->currentInput;
    151           continue;
    152        }
    153        else{
    154           cpp->currentInput = in->base.prev;
    155           cpp->PaWhichStr=0;
    156           free(in);
    157           return EOF;
    158        }
    159     }
    160 } // str_getch
    161 
    162 static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
    163     if (in->p[-1] == ch)in->p--;
    164     else {
    165         *(in->p)='\0'; //this would take care of shifting to the previous string.
    166         cpp->PaWhichStr--;
    167     }
    168     if (ch == '\n') {
    169         in->base.line--;
    170         DecLineNumber();
    171     }
    172 } // str_ungetch
    173 
    174 int ScanFromString(const char *s)
    175 {
    176 
    177     StringInputSrc *in = malloc(sizeof(StringInputSrc));
    178     memset(in, 0, sizeof(StringInputSrc));
    179     in->p = (char*) s;
    180     in->base.line = 1;
    181     in->base.scan = byte_scan;
    182     in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
    183     in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
    184     in->base.prev = cpp->currentInput;
    185     cpp->currentInput = &in->base;
    186 
    187     return 1;
    188 } // ScanFromString;
    189 
    190 
    191 ///////////////////////////////////////////////////////////////////////////////////////////////
    192 /////////////////////////////////// Floating point constants: /////////////////////////////////
    193 ///////////////////////////////////////////////////////////////////////////////////////////////
    194 
    195 #define APPEND_CHAR_S(ch, str, len, max_len) \
    196       if (len < max_len) { \
    197           str[len++] = ch; \
    198       } else if (!alreadyComplained) { \
    199           CPPErrorToInfoLog("BUFFER OVERFLOW"); \
    200           alreadyComplained = 1; \
    201       }
    202 
    203 /*
    204  * lFloatConst() - Scan a floating point constant.  Assumes that the scanner
    205  *         has seen at least one digit, followed by either a decimal '.' or the
    206  *         letter 'e'.
    207  * ch - '.' or 'e'
    208  * len - length of string already copied into yylvalpp->symbol_name.
    209  */
    210 
    211 static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
    212 {
    213     int alreadyComplained = 0;
    214     assert((ch == '.') || (ch == 'e') || (ch == 'E'));
    215 
    216     if (ch == '.') {
    217         do {
    218             APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    219             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    220         } while (ch >= '0' && ch <= '9');
    221     }
    222 
    223     // Exponent:
    224     if (ch == 'e' || ch == 'E') {
    225         APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    226         ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    227         if (ch == '+') {
    228             APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    229             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    230         } else if (ch == '-') {
    231             APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    232             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    233         }
    234         if (ch >= '0' && ch <= '9') {
    235             while (ch >= '0' && ch <= '9') {
    236                 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    237                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    238             }
    239         } else {
    240             CPPErrorToInfoLog("EXPONENT INVALID");
    241         }
    242     }
    243     cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    244 
    245     assert(len <= MAX_SYMBOL_NAME_LEN);
    246     yylvalpp->symbol_name[len] = '\0';
    247     yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name);
    248     if (isinff(yylvalpp->sc_fval)) {
    249         CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
    250     }
    251     return CPP_FLOATCONSTANT;
    252 } // lFloatConst
    253 
    254 ///////////////////////////////////////////////////////////////////////////////////////////////
    255 ///////////////////////////////////////// Normal Scanner //////////////////////////////////////
    256 ///////////////////////////////////////////////////////////////////////////////////////////////
    257 
    258 static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
    259 {
    260     char string_val[MAX_STRING_LEN + 1];
    261     int alreadyComplained = 0;
    262     int len, ch, ii, ival = 0;
    263 
    264     for (;;) {
    265         yylvalpp->sc_int = 0;
    266         ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    267 
    268         while (ch == ' ' || ch == '\t' || ch == '\r') {
    269             yylvalpp->sc_int = 1;
    270             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    271         }
    272 
    273         cpp->ltokenLoc.file = cpp->currentInput->name;
    274         cpp->ltokenLoc.line = cpp->currentInput->line;
    275         alreadyComplained = 0;
    276         len = 0;
    277         switch (ch) {
    278         default:
    279             return ch; // Single character token
    280         case EOF:
    281             return -1;
    282         case 'A': case 'B': case 'C': case 'D': case 'E':
    283         case 'F': case 'G': case 'H': case 'I': case 'J':
    284         case 'K': case 'L': case 'M': case 'N': case 'O':
    285         case 'P': case 'Q': case 'R': case 'S': case 'T':
    286         case 'U': case 'V': case 'W': case 'X': case 'Y':
    287         case 'Z': case '_':
    288         case 'a': case 'b': case 'c': case 'd': case 'e':
    289         case 'f': case 'g': case 'h': case 'i': case 'j':
    290         case 'k': case 'l': case 'm': case 'n': case 'o':
    291         case 'p': case 'q': case 'r': case 's': case 't':
    292         case 'u': case 'v': case 'w': case 'x': case 'y':
    293         case 'z':
    294             do {
    295                 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    296                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    297             } while ((ch >= 'a' && ch <= 'z') ||
    298                      (ch >= 'A' && ch <= 'Z') ||
    299                      (ch >= '0' && ch <= '9') ||
    300                      ch == '_');
    301             assert(len <= MAX_SYMBOL_NAME_LEN);
    302             yylvalpp->symbol_name[len] = '\0';
    303             cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    304             yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name);
    305             return CPP_IDENTIFIER;
    306             break;
    307         case '0':
    308             APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    309             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    310             if (ch == 'x' || ch == 'X') {  // hexadecimal integer constants
    311                 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    312                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    313                 if ((ch >= '0' && ch <= '9') ||
    314                     (ch >= 'A' && ch <= 'F') ||
    315                     (ch >= 'a' && ch <= 'f'))
    316                 {
    317                     ival = 0;
    318                     do {
    319                         if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
    320                             yylvalpp->symbol_name[len++] = ch;
    321                             if (ch >= '0' && ch <= '9') {
    322                                 ii = ch - '0';
    323                             } else if (ch >= 'A' && ch <= 'F') {
    324                                 ii = ch - 'A' + 10;
    325                             } else {
    326                                 ii = ch - 'a' + 10;
    327                             }
    328                             ival = (ival << 4) | ii;
    329                         } else if (!alreadyComplained) {
    330                             CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
    331                             alreadyComplained = 1;
    332                         }
    333                         ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    334                     } while ((ch >= '0' && ch <= '9') ||
    335                              (ch >= 'A' && ch <= 'F') ||
    336                              (ch >= 'a' && ch <= 'f'));
    337                 } else {
    338                     CPPErrorToInfoLog("HEX CONSTANT INVALID");
    339                 }
    340                 assert(len <= MAX_SYMBOL_NAME_LEN);
    341                 yylvalpp->symbol_name[len] = '\0';
    342                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    343                 yylvalpp->sc_int = ival;
    344                 return CPP_INTCONSTANT;
    345             } else if (ch >= '0' && ch <= '7') { // octal integer constants
    346                 ival = 0;
    347                 do {
    348                     if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
    349                         yylvalpp->symbol_name[len++] = ch;
    350                         ii = ch - '0';
    351                         ival = (ival << 3) | ii;
    352                     } else if (!alreadyComplained) {
    353                         CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
    354                         alreadyComplained = 1;
    355                     }
    356                     ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    357                 } while (ch >= '0' && ch <= '7');
    358                 if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E')
    359                      return lFloatConst(ch, len, yylvalpp);
    360                 assert(len <= MAX_SYMBOL_NAME_LEN);
    361                 yylvalpp->symbol_name[len] = '\0';
    362                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    363                 yylvalpp->sc_int = ival;
    364                 return CPP_INTCONSTANT;
    365             } else {
    366                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    367                 ch = '0';
    368             }
    369             // Fall through...
    370         case '1': case '2': case '3': case '4':
    371         case '5': case '6': case '7': case '8': case '9':
    372             do {
    373                 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
    374                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    375             } while (ch >= '0' && ch <= '9');
    376             if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
    377                 return lFloatConst(ch, len, yylvalpp);
    378             } else {
    379                 assert(len <= MAX_SYMBOL_NAME_LEN);
    380                 yylvalpp->symbol_name[len] = '\0';
    381                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    382                 ival = 0;
    383                 for (ii = 0; ii < len; ii++) {
    384                     ch = yylvalpp->symbol_name[ii] - '0';
    385                     ival = ival*10 + ch;
    386                     if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
    387                         CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
    388                         break;
    389                     }
    390                 }
    391                 yylvalpp->sc_int = ival;
    392                 if(ival==0)
    393                    strcpy(yylvalpp->symbol_name,"0");
    394                 return CPP_INTCONSTANT;
    395             }
    396             break;
    397         case '-':
    398             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    399             if (ch == '-') {
    400                 return CPP_DEC_OP;
    401             } else if (ch == '=') {
    402                 return CPP_SUB_ASSIGN;
    403             } else {
    404                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    405                 return '-';
    406             }
    407         case '+':
    408             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    409             if (ch == '+') {
    410                 return CPP_INC_OP;
    411             } else if (ch == '=') {
    412                 return CPP_ADD_ASSIGN;
    413             } else {
    414                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    415                 return '+';
    416             }
    417         case '*':
    418             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    419             if (ch == '=') {
    420                 return CPP_MUL_ASSIGN;
    421             } else {
    422                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    423                 return '*';
    424             }
    425         case '%':
    426             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    427             if (ch == '=') {
    428                 return CPP_MOD_ASSIGN;
    429             } else if (ch == '>'){
    430                 return CPP_RIGHT_BRACE;
    431             } else {
    432                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    433                 return '%';
    434             }
    435         case ':':
    436             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    437             if (ch == '>') {
    438                 return CPP_RIGHT_BRACKET;
    439             } else {
    440                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    441                 return ':';
    442             }
    443         case '^':
    444             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    445             if (ch == '^') {
    446                 return CPP_XOR_OP;
    447             } else {
    448                 if (ch == '=')
    449                     return CPP_XOR_ASSIGN;
    450                 else{
    451                   cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    452                   return '^';
    453                 }
    454             }
    455 
    456         case '=':
    457             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    458             if (ch == '=') {
    459                 return CPP_EQ_OP;
    460             } else {
    461                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    462                 return '=';
    463             }
    464         case '!':
    465             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    466             if (ch == '=') {
    467                 return CPP_NE_OP;
    468             } else {
    469                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    470                 return '!';
    471             }
    472         case '|':
    473             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    474             if (ch == '|') {
    475                 return CPP_OR_OP;
    476             } else {
    477                 if (ch == '=')
    478                     return CPP_OR_ASSIGN;
    479                 else{
    480                   cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    481                   return '|';
    482                 }
    483             }
    484         case '&':
    485             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    486             if (ch == '&') {
    487                 return CPP_AND_OP;
    488             } else {
    489                 if (ch == '=')
    490                     return CPP_AND_ASSIGN;
    491                 else{
    492                   cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    493                   return '&';
    494                 }
    495             }
    496         case '<':
    497             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    498             if (ch == '<') {
    499                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    500                 if(ch == '=')
    501                     return CPP_LEFT_ASSIGN;
    502                 else{
    503                     cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    504                     return CPP_LEFT_OP;
    505                 }
    506             } else {
    507                 if (ch == '=') {
    508                     return CPP_LE_OP;
    509                 } else {
    510                     if (ch == '%')
    511                         return CPP_LEFT_BRACE;
    512                     else if (ch == ':')
    513                         return CPP_LEFT_BRACKET;
    514                     else{
    515                         cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    516                         return '<';
    517                     }
    518                 }
    519             }
    520         case '>':
    521             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    522             if (ch == '>') {
    523                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    524                 if(ch == '=')
    525                     return CPP_RIGHT_ASSIGN;
    526                 else{
    527                     cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    528                     return CPP_RIGHT_OP;
    529                 }
    530             } else {
    531                 if (ch == '=') {
    532                     return CPP_GE_OP;
    533                 } else {
    534                     cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    535                     return '>';
    536                 }
    537             }
    538         case '.':
    539             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    540             if (ch >= '0' && ch <= '9') {
    541                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    542                 return lFloatConst('.', 0, yylvalpp);
    543             } else {
    544                 if (ch == '.') {
    545                     return -1; // Special EOF hack
    546                 } else {
    547                     cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    548                     return '.';
    549                 }
    550             }
    551         case '/':
    552             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    553             if (ch == '/') {
    554                 do {
    555                     ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    556                 } while (ch != '\n' && ch != EOF);
    557                 if (ch == EOF)
    558                     return -1;
    559                 return '\n';
    560             } else if (ch == '*') {
    561                 int nlcount = 0;
    562                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    563                 do {
    564                     while (ch != '*') {
    565                         if (ch == '\n') nlcount++;
    566                         if (ch == EOF) {
    567                             CPPErrorToInfoLog("EOF IN COMMENT");
    568                             return -1;
    569                         }
    570                         ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    571                     }
    572                     ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    573                     if (ch == EOF) {
    574                         CPPErrorToInfoLog("EOF IN COMMENT");
    575                         return -1;
    576                     }
    577                 } while (ch != '/');
    578                 if (nlcount) {
    579                     return '\n';
    580                 }
    581                 // Go try it again...
    582             } else if (ch == '=') {
    583                 return CPP_DIV_ASSIGN;
    584             } else {
    585                 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
    586                 return '/';
    587             }
    588             break;
    589         case '"':
    590             ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    591             while (ch != '"' && ch != '\n' && ch != EOF) {
    592                 if (ch == '\\') {
    593                     CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
    594                     return -1;
    595                 }
    596                 APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
    597                 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
    598             };
    599             assert(len <= MAX_STRING_LEN);
    600             string_val[len] = '\0';
    601             if (ch == '"') {
    602                 yylvalpp->sc_ident = LookUpAddString(atable, string_val);
    603                 return CPP_STRCONSTANT;
    604             } else {
    605                 CPPErrorToInfoLog("EOL IN STRING");
    606                 return ERROR_SY;
    607             }
    608             break;
    609         }
    610     }
    611 } // byte_scan
    612 
    613 int yylex_CPP(char* buf, int maxSize)
    614 {
    615     yystypepp yylvalpp;
    616     int token = '\n';
    617 
    618     for(;;) {
    619 
    620         char* tokenString = 0;
    621         token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
    622         if(check_EOF(token))
    623             return 0;
    624         if (token == '#') {
    625             if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
    626                 token = readCPPline(&yylvalpp);
    627                 if(check_EOF(token))
    628                     return 0;
    629                 continue;
    630             } else {
    631                 CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
    632                 return 0;
    633             }
    634         }
    635         cpp->previous_token = token;
    636         // expand macros
    637         if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
    638             cpp->pastFirstStatement = 1;
    639             continue;
    640         }
    641 
    642         if (token == '\n')
    643             continue;
    644         cpp->pastFirstStatement = 1;
    645 
    646         if (token == CPP_IDENTIFIER) {
    647             tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
    648         } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
    649             tokenString = yylvalpp.symbol_name;
    650         } else {
    651             tokenString = GetStringOfAtom(atable,token);
    652         }
    653 
    654         if (tokenString) {
    655             int len = strlen(tokenString);
    656             cpp->tokensBeforeEOF = 1;
    657             if (len >= maxSize) {
    658                 return maxSize;
    659             } else  if (len > 0) {
    660                 strcpy(buf, tokenString);
    661                 return len;
    662             }
    663 
    664             return 0;
    665         }
    666     }
    667 
    668     return 0;
    669 } // yylex
    670 
    671 //Checks if the token just read is EOF or not.
    672 int check_EOF(int token)
    673 {
    674    if(token==-1){
    675        if(cpp->ifdepth >0){
    676         CPPErrorToInfoLog("#endif missing!! Compilation stopped");
    677         cpp->CompileError=1;
    678        }
    679       return 1;
    680    }
    681    return 0;
    682 }
    683 
    684 ///////////////////////////////////////////////////////////////////////////////////////////////
    685 /////////////////////////////////////// End of scanner.c //////////////////////////////////////
    686 ///////////////////////////////////////////////////////////////////////////////////////////////
    687 
    688