LCOV - code coverage report
Current view: directory - gfx/angle/src/compiler/preprocessor - cpp.c (source / functions) Found Hit Coverage
Test: app.info Lines: 676 0 0.0 %
Date: 2012-06-02 Functions: 47 0 0.0 %

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

Generated by: LCOV version 1.7