static int CPPline(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if(token=='\n'){ DecLineNumber(); CPPErrorToInfoLog("#line"); IncLineNumber(); return token; } else if (token == CPP_INTCONSTANT) { yylvalpp->sc_int=atoi(yylvalpp->symbol_name); SetLineNumber(yylvalpp->sc_int); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == CPP_INTCONSTANT) { yylvalpp->sc_int=atoi(yylvalpp->symbol_name); SetStringNumber(yylvalpp->sc_int); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if(token!='\n') CPPErrorToInfoLog("#line"); } else if (token == '\n'){ return token; } else{ CPPErrorToInfoLog("#line"); } } else{ CPPErrorToInfoLog("#line"); } return token; }
static int CPPifdef(int defined, yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); int name = yylvalpp->sc_ident; if (++cpp->ifdepth > MAX_IF_NESTING) { CPPErrorToInfoLog("max #if nesting depth exceeded"); return 0; } cpp->elsetracker++; cpp->elsedepth[cpp->elsetracker] = 0; if (token != CPP_IDENTIFIER) { defined ? CPPErrorToInfoLog("ifdef") : CPPErrorToInfoLog("ifndef"); } else { Symbol *s = LookUpSymbol(macros, name); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog( "unexpected tokens following #ifdef preprocessor directive - expected a newline"); while (token != '\n') token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } if (((s && !s->details.mac.undef) ? 1 : 0) != defined) { token = CPPelse(1, yylvalpp); } } return token; } /* CPPifdef */
static int CPPline(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if(token=='\n'){ DecLineNumber(); CPPErrorToInfoLog("#line"); IncLineNumber(); return token; } else if (token == CPP_INTCONSTANT) { yylvalpp->sc_int=atoi(yylvalpp->symbol_name); SetLineNumber(yylvalpp->sc_int); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); // Modified for HLSL, which allows #line X "str", whereas GLSL is #line X Y if (token == CPP_STRCONSTANT) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if(token!='\n') CPPErrorToInfoLog("#line"); } else if (token == '\n'){ return token; } else{ CPPErrorToInfoLog("#line"); } } else{ CPPErrorToInfoLog("#line"); } return token; }
static int CPPversion(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (cpp->pastFirstStatement == 1) CPPShInfoLogMsg("#version must occur before any other statement in the program"); if(token=='\n'){ DecLineNumber(); CPPErrorToInfoLog("#version"); IncLineNumber(); return token; } if (token != CPP_INTCONSTANT) CPPErrorToInfoLog("#version"); yylvalpp->sc_int=atoi(yylvalpp->symbol_name); //SetVersionNumber(yylvalpp->sc_int); if (yylvalpp->sc_int != ESSL_VERSION_NUMBER) CPPShInfoLogMsg("Version number not supported by ESSL"); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '\n'){ return token; } else{ CPPErrorToInfoLog("#version"); } return token; } // CPPversion
static int CPPerror(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); const char *message; while (token != '\n') { if (token <= 0){ CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline"); return 0; }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ StoreStr(yylvalpp->symbol_name); }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){ StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); }else { StoreStr(GetStringOfAtom(atable,token)); } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } DecLineNumber(); //store this msg into the shader's information log..set the Compile Error flag!!!! message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); cpp->CompileError=1; IncLineNumber(); return '\n'; }//CPPerror
static int CPPif(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); int res = 0, err = 0; cpp->elsetracker++; cpp->elsedepth[cpp->elsetracker] = 0; if (!cpp->ifdepth++) ifloc = *cpp->tokenLoc; if (cpp->ifdepth > MAX_IF_NESTING) { CPPErrorToInfoLog("max #if nesting depth exceeded"); return 0; } token = eval(token, MIN_PREC, &res, &err, yylvalpp); if (token != '\n') { CPPWarningToInfoLog( "unexpected tokens following the preprocessor directive - expected a newline"); while (token != '\n') token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } if (!res && !err) { token = CPPelse(1, yylvalpp); } return token; } /* CPPif */
static void lAddToTree(Symbol **fSymbols, Symbol *fSymb) { Symbol *lSymb; int lrev, frev; lSymb = *fSymbols; if (lSymb) { frev = GetReversedAtom(atable, fSymb->name); while (lSymb) { lrev = GetReversedAtom(atable, lSymb->name); if (lrev == frev) { CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)"); break; } else { if (lrev > frev) { if (lSymb->left) { lSymb = lSymb->left; } else { lSymb->left = fSymb; break; } } else { if (lSymb->right) { lSymb = lSymb->right; } else { lSymb->right = fSymb; break; } } } } } else { *fSymbols = fSymb; } } // lAddToTree
int yylex_CPP(char* buf, int maxSize) { yystypepp yylvalpp; int token = '\n'; for(;;) { char* tokenString = 0; token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp); if(check_EOF(token)) return 0; if (token == '#') { if (cpp->previous_token == '\n'|| cpp->previous_token == 0) { token = readCPPline(&yylvalpp); if(check_EOF(token)) return 0; continue; } else { CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line"); return 0; } } cpp->previous_token = token; // expand macros if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) { cpp->pastFirstStatement = 1; continue; } if (token == '\n') continue; cpp->pastFirstStatement = 1; if (token == CPP_IDENTIFIER) { tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ tokenString = yylvalpp.symbol_name; } else { tokenString = GetStringOfAtom(atable,token); } if (tokenString) { int len = strlen(tokenString); cpp->tokensBeforeEOF = 1; if (len >= maxSize) { return maxSize; } else if (len > 0) { strcpy(buf, tokenString); return len; } return 0; } } return 0; } // yylex
static int CPPelse(int matchelse, yystypepp * yylvalpp) { int atom,depth=0; int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); while (token > 0) { if (token != '#') { while (token != '\n') token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); continue; } if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER) continue; atom = yylvalpp->sc_ident; if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){ depth++; cpp->ifdepth++; cpp->elsetracker++; cpp->elsedepth[cpp->elsetracker] = 0; } else if (atom == endifAtom) { if(--depth<0){ --cpp->elsetracker; if (cpp->ifdepth) --cpp->ifdepth; break; } --cpp->elsetracker; --cpp->ifdepth; } else if (((int)(matchelse) != 0)&& depth==0) { if (atom == elseAtom ) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); while (token != '\n') token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } break; } else if (atom == elifAtom) { /* we decrement cpp->ifdepth here, because CPPif will increment * it and we really want to leave it alone */ if (cpp->ifdepth){ --cpp->ifdepth; --cpp->elsetracker; } return CPPif(yylvalpp); } } else if((atom==elseAtom) && (!ChkCorrectElseNesting())){ CPPErrorToInfoLog("#else after a #else"); cpp->CompileError=1; } }; return token; }
static bool CopySymbolName(const std::string& name, yystypepp* yylvalpp) { if (name.length() > MAX_SYMBOL_NAME_LEN) { CPPErrorToInfoLog("BUFFER OVERFLOW"); return false; } strcpy(yylvalpp->symbol_name, name.c_str()); return true; }
static int CPPextension(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); char extensionName[MAX_SYMBOL_NAME_LEN + 1]; if(token=='\n'){ DecLineNumber(); CPPShInfoLogMsg("extension name not specified"); IncLineNumber(); return token; } if (token != CPP_IDENTIFIER) CPPErrorToInfoLog("#extension"); strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN); extensionName[MAX_SYMBOL_NAME_LEN] = '\0'; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != ':') { CPPShInfoLogMsg("':' missing after extension name"); return token; } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != CPP_IDENTIFIER) { CPPShInfoLogMsg("behavior for extension not specified"); return token; } updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '\n'){ return token; } else{ CPPErrorToInfoLog("#extension"); } return token; } // CPPextension
static int lFloatConst(int ch, int len, yystypepp * yylvalpp) { int alreadyComplained = 0; assert((ch == '.') || (ch == 'e') || (ch == 'E')); if (ch == '.') { do { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } while (ch >= '0' && ch <= '9'); } // Exponent: if (ch == 'e' || ch == 'E') { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '+') { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } else if (ch == '-') { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } if (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } } else { CPPErrorToInfoLog("EXPONENT INVALID"); } } cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); assert(len <= MAX_SYMBOL_NAME_LEN); yylvalpp->symbol_name[len] = '\0'; yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name); if (isinff(yylvalpp->sc_fval)) { CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW"); } return CPP_FLOATCONSTANT; } // lFloatConst
//Checks if the token just read is EOF or not. int check_EOF(int token) { if(token==-1){ if(cpp->ifdepth >0){ CPPErrorToInfoLog("#endif missing!! Compilation stopped"); cpp->CompileError=1; } return 1; } return 0; }
static int CPPundef(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); Symbol *symb; if (token == '\n') { CPPErrorToInfoLog("#undef"); return token; } if (token != CPP_IDENTIFIER) goto error; symb = LookUpSymbol(macros, yylvalpp->sc_ident); if (symb) { symb->details.mac.undef = 1; } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { error: CPPErrorToInfoLog("#undef"); } return token; } /* CPPundef */
static int CPPifdef(int defined, yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); int name = yylvalpp->sc_ident; if(++cpp->ifdepth > MAX_IF_NESTING){ CPPErrorToInfoLog("max #if nesting depth exceeded"); cpp->CompileError = 1; return 0; } cpp->elsetracker++; // sanity check elsetracker if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { CPPErrorToInfoLog("mismatched #if/#endif statements"); cpp->CompileError = 1; return 0; } cpp->elsedepth[cpp->elsetracker] = 0; if (token != CPP_IDENTIFIER) { defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef"); } else { Symbol *s = LookUpSymbol(macros, name); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline"); while (token != '\n') { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { // EOF or error CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); return 0; } } } if (((s && !s->details.mac.undef) ? 1 : 0) != defined) token = CPPelse(1, yylvalpp); } return token; } // CPPifdef
static int CPPif(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); int res = 0, err = 0; if (!cpp->ifdepth++) ifloc = *cpp->tokenLoc; if(cpp->ifdepth > MAX_IF_NESTING){ CPPErrorToInfoLog("max #if nesting depth exceeded"); cpp->CompileError = 1; return 0; } cpp->elsetracker++; // sanity check elsetracker if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { CPPErrorToInfoLog("mismatched #if/#endif statements"); cpp->CompileError = 1; return 0; } cpp->elsedepth[cpp->elsetracker] = 0; token = eval(token, MIN_PREC, &res, &err, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline"); while (token != '\n') { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { // EOF or error CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline"); return 0; } } } if (!res && !err) { token = CPPelse(1, yylvalpp); } return token; } // CPPif
static int CPPversion(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (cpp->notAVersionToken == 1) CPPShInfoLogMsg( "#version must occur before any other statement in the program"); if (token == '\n') { DecLineNumber(); CPPErrorToInfoLog("#version"); IncLineNumber(); return token; } if (token != CPP_INTCONSTANT) CPPErrorToInfoLog("#version"); yylvalpp->sc_int = atoi(yylvalpp->symbol_name); setVersionNumber(yylvalpp->sc_int); if (yylvalpp->sc_int != GLSL_100_VERSION_NUMBER && yylvalpp->sc_int != GLSL_110_VERSION_NUMBER && yylvalpp->sc_int != GLSL_120_VERSION_NUMBER) { CPPShInfoLogMsg("Version number not supported by GL2"); } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '\n') { return token; } else { CPPErrorToInfoLog("#version"); } return token; } /* CPPversion */
static int CPPelse(yystypepp* yylvalpp) { int token = CPPgotoEndOfIfBlock(1, yylvalpp); if (yylvalpp->sc_ident == endifAtom) { cpp->ifdepth--; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } else if (yylvalpp->sc_ident == elifAtom) { cpp->ifdepth--; // will be reincremented by CPPif token = CPPif(yylvalpp); } else if (yylvalpp->sc_ident == elseAtom) token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); else { CPPErrorToInfoLog("unclosed #if block"); return 0; } }
int readCPPline(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); const char *message; if (token == CPP_IDENTIFIER) { if (yylvalpp->sc_ident == defineAtom) { token = CPPdefine(yylvalpp); } else if (yylvalpp->sc_ident == elseAtom) { if(ChkCorrectElseNesting()){ if (!cpp->ifdepth ){ CPPErrorToInfoLog("#else mismatch"); cpp->CompileError=1; return 0; } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); while (token != '\n') { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { // EOF or error CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); return 0; } } } token = CPPelse(0, yylvalpp); }else{ CPPErrorToInfoLog("#else after a #else"); cpp->ifdepth = 0; cpp->elsetracker = 0; cpp->pastFirstStatement = 1; cpp->CompileError = 1; return 0; } } else if (yylvalpp->sc_ident == elifAtom) { if (!cpp->ifdepth){ CPPErrorToInfoLog("#elif mismatch"); cpp->CompileError=1; return 0; } // this token is really a dont care, but we still need to eat the tokens token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); while (token != '\n') { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { // EOF or error CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline"); cpp->CompileError = 1; return 0; } } token = CPPelse(0, yylvalpp); } else if (yylvalpp->sc_ident == endifAtom) { if (!cpp->ifdepth){ CPPErrorToInfoLog("#endif mismatch"); cpp->CompileError=1; return 0; } else --cpp->ifdepth; if (cpp->elsetracker) --cpp->elsetracker; } else if (yylvalpp->sc_ident == ifAtom) { token = CPPif(yylvalpp); } else if (yylvalpp->sc_ident == ifdefAtom) { token = CPPifdef(1, yylvalpp); } else if (yylvalpp->sc_ident == ifndefAtom) { token = CPPifdef(0, yylvalpp); } else if (yylvalpp->sc_ident == lineAtom) { token = CPPline(yylvalpp); } else if (yylvalpp->sc_ident == pragmaAtom) { token = CPPpragma(yylvalpp); } else if (yylvalpp->sc_ident == undefAtom) { token = CPPundef(yylvalpp); } else if (yylvalpp->sc_ident == errorAtom) { token = CPPerror(yylvalpp); } else if (yylvalpp->sc_ident == versionAtom) { token = CPPversion(yylvalpp); } else if (yylvalpp->sc_ident == extensionAtom) { token = CPPextension(yylvalpp); } else { StoreStr("Invalid Directive"); StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } } while (token != '\n' && token != 0 && token != EOF) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } cpp->pastFirstStatement = 1; return token; } // readCPPline
static int byte_scan(InputSrc *in, yystypepp * yylvalpp) { char string_val[MAX_STRING_LEN + 1]; int alreadyComplained = 0; int len, ch, ii, ival = 0; for (;;) { yylvalpp->sc_int = 0; ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); while (ch == ' ' || ch == '\t' || ch == '\r') { yylvalpp->sc_int = 1; ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } cpp->ltokenLoc.file = cpp->currentInput->name; cpp->ltokenLoc.line = cpp->currentInput->line; alreadyComplained = 0; len = 0; switch (ch) { default: return ch; // Single character token case EOF: return -1; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': do { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_'); assert(len <= MAX_SYMBOL_NAME_LEN); yylvalpp->symbol_name[len] = '\0'; cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name); return CPP_IDENTIFIER; break; case '0': APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == 'x' || ch == 'X') { // hexadecimal integer constants APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { ival = 0; do { if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { yylvalpp->symbol_name[len++] = ch; if (ch >= '0' && ch <= '9') { ii = ch - '0'; } else if (ch >= 'A' && ch <= 'F') { ii = ch - 'A' + 10; } else { ii = ch - 'a' + 10; } ival = (ival << 4) | ii; } else if (!alreadyComplained) { CPPErrorToInfoLog("HEX CONSTANT OVERFLOW"); alreadyComplained = 1; } ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } while ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')); } else { CPPErrorToInfoLog("HEX CONSTANT INVALID"); } assert(len <= MAX_SYMBOL_NAME_LEN); yylvalpp->symbol_name[len] = '\0'; cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); yylvalpp->sc_int = ival; return CPP_INTCONSTANT; } else if (ch >= '0' && ch <= '7') { // octal integer constants ival = 0; do { if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { yylvalpp->symbol_name[len++] = ch; ii = ch - '0'; ival = (ival << 3) | ii; } else if (!alreadyComplained) { CPPErrorToInfoLog("OCT CONSTANT OVERFLOW"); alreadyComplained = 1; } ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } while (ch >= '0' && ch <= '7'); if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') return lFloatConst(ch, len, yylvalpp); assert(len <= MAX_SYMBOL_NAME_LEN); yylvalpp->symbol_name[len] = '\0'; cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); yylvalpp->sc_int = ival; return CPP_INTCONSTANT; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); ch = '0'; } // Fall through... case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } while (ch >= '0' && ch <= '9'); if (ch == '.' || ch == 'e' || ch == 'E') { return lFloatConst(ch, len, yylvalpp); } else { assert(len <= MAX_SYMBOL_NAME_LEN); yylvalpp->symbol_name[len] = '\0'; cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); ival = 0; for (ii = 0; ii < len; ii++) { ch = yylvalpp->symbol_name[ii] - '0'; ival = ival*10 + ch; if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW"); break; } } yylvalpp->sc_int = ival; if(ival==0) strcpy(yylvalpp->symbol_name,"0"); return CPP_INTCONSTANT; } break; case '-': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '-') { return CPP_DEC_OP; } else if (ch == '=') { return CPP_SUB_ASSIGN; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '-'; } case '+': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '+') { return CPP_INC_OP; } else if (ch == '=') { return CPP_ADD_ASSIGN; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '+'; } case '*': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '=') { return CPP_MUL_ASSIGN; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '*'; } case '%': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '=') { return CPP_MOD_ASSIGN; } else if (ch == '>'){ return CPP_RIGHT_BRACE; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '%'; } case ':': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '>') { return CPP_RIGHT_BRACKET; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return ':'; } case '^': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '^') { return CPP_XOR_OP; } else { if (ch == '=') return CPP_XOR_ASSIGN; else{ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '^'; } } case '=': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '=') { return CPP_EQ_OP; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '='; } case '!': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '=') { return CPP_NE_OP; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '!'; } case '|': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '|') { return CPP_OR_OP; } else { if (ch == '=') return CPP_OR_ASSIGN; else{ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '|'; } } case '&': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '&') { return CPP_AND_OP; } else { if (ch == '=') return CPP_AND_ASSIGN; else{ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '&'; } } case '<': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '<') { ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if(ch == '=') return CPP_LEFT_ASSIGN; else{ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return CPP_LEFT_OP; } } else { if (ch == '=') { return CPP_LE_OP; } else { if (ch == '%') return CPP_LEFT_BRACE; else if (ch == ':') return CPP_LEFT_BRACKET; else{ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '<'; } } } case '>': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '>') { ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if(ch == '=') return CPP_RIGHT_ASSIGN; else{ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return CPP_RIGHT_OP; } } else { if (ch == '=') { return CPP_GE_OP; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '>'; } } case '.': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch >= '0' && ch <= '9') { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return lFloatConst('.', 0, yylvalpp); } else { if (ch == '.') { return -1; // Special EOF hack } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '.'; } } case '/': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '/') { do { ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } while (ch != '\n' && ch != EOF); if (ch == EOF) return -1; return '\n'; } else if (ch == '*') { ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); do { while (ch != '*') { if (ch == EOF) { CPPErrorToInfoLog("EOF IN COMMENT"); return -1; } ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == EOF) { CPPErrorToInfoLog("EOF IN COMMENT"); return -1; } } while (ch != '/'); // Go try it again... } else if (ch == '=') { return CPP_DIV_ASSIGN; } else { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return '/'; } break; case '"': ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); while (ch != '"' && ch != '\n' && ch != EOF) { if (ch == '\\') { CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); return -1; } APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); }; assert(len <= MAX_STRING_LEN); string_val[len] = '\0'; if (ch == '"') { yylvalpp->sc_ident = LookUpAddString(atable, string_val); return CPP_STRCONSTANT; } else { CPPErrorToInfoLog("EOL IN STRING"); return ERROR_SY; } break; } } } // byte_scan
int FinalCPP(void) { if (cpp->ifdepth) CPPErrorToInfoLog("#if mismatch"); return 1; }
static int CPPpragma(yystypepp * yylvalpp) { char SrcStrName[2]; char** allTokens; int tokenCount = 0; int maxTokenCount = 10; const char* SrcStr; int i; int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token=='\n') { DecLineNumber(); CPPErrorToInfoLog("#pragma"); IncLineNumber(); return token; } allTokens = (char**)malloc(sizeof(char*) * maxTokenCount); while (token != '\n') { if (tokenCount >= maxTokenCount) { maxTokenCount *= 2; allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount); } switch (token) { case CPP_IDENTIFIER: SrcStr = GetAtomString(atable, yylvalpp->sc_ident); allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); strcpy(allTokens[tokenCount++], SrcStr); break; case CPP_INTCONSTANT: SrcStr = yylvalpp->symbol_name; allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); strcpy(allTokens[tokenCount++], SrcStr); break; case CPP_FLOATCONSTANT: SrcStr = yylvalpp->symbol_name; allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); strcpy(allTokens[tokenCount++], SrcStr); break; case -1: // EOF CPPShInfoLogMsg("#pragma directive must end with a newline"); goto freeMemoryAndReturnToken; default: SrcStrName[0] = token; SrcStrName[1] = '\0'; allTokens[tokenCount] = (char*)malloc(2); strcpy(allTokens[tokenCount++], SrcStrName); } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } HandlePragma((const char**)allTokens, tokenCount); freeMemoryAndReturnToken: for (i = 0; i < tokenCount; ++i) { free (allTokens[i]); } free (allTokens); return token; } // CPPpragma
int readCPPline(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); const char *message; int isVersion = 0; if (token == CPP_IDENTIFIER) { if (yylvalpp->sc_ident == defineAtom) { token = CPPdefine(yylvalpp); } else if (yylvalpp->sc_ident == elseAtom) { token = CPPgotoEndOfIfBlock(1, yylvalpp); if (yylvalpp->sc_ident != endifAtom) { CPPErrorToInfoLog("#else or #elif mismatch"); cpp->CompileError=1; } token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); if (!cpp->ifdepth){ CPPErrorToInfoLog("#else or #elif mismatch"); cpp->CompileError=1; } else --cpp->ifdepth; } else if (yylvalpp->sc_ident == elifAtom) { token = CPPgotoEndOfIfBlock(0, yylvalpp); assert(yylvalpp->sc_ident == endifAtom); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (!cpp->ifdepth){ CPPErrorToInfoLog("#else or #elif mismatch"); cpp->CompileError=1; } else --cpp->ifdepth; } else if (yylvalpp->sc_ident == endifAtom) { if (!cpp->ifdepth){ CPPErrorToInfoLog("#endif mismatch"); cpp->CompileError=1; } else --cpp->ifdepth; } else if (yylvalpp->sc_ident == ifAtom) { token = CPPif(yylvalpp); } else if (yylvalpp->sc_ident == ifdefAtom) { token = CPPifdef(1, yylvalpp); } else if (yylvalpp->sc_ident == ifndefAtom) { token = CPPifdef(0, yylvalpp); } else if (yylvalpp->sc_ident == lineAtom) { token = CPPline(yylvalpp); } else if (yylvalpp->sc_ident == pragmaAtom) { token = CPPpragma(yylvalpp); } else if (yylvalpp->sc_ident == undefAtom) { token = CPPundef(yylvalpp); } else if (yylvalpp->sc_ident == errorAtom) { token = CPPerror(yylvalpp); } else if (yylvalpp->sc_ident == versionAtom) { token = CPPversion(yylvalpp); isVersion = 1; } else { StoreStr("Invalid Directive"); StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } } while (token != '\n' && token != 0 && token != EOF) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } cpp->notAVersionToken = !isVersion; return token; } // readCPPline
static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp) { int i, val; Symbol *s; if (token == CPP_IDENTIFIER) { if (yylvalpp->sc_ident == definedAtom) { int needclose = 0; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '(') { needclose = 1; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } if (token != CPP_IDENTIFIER) goto error; *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident)) ? !s->details.mac.undef : 0; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (needclose) { if (token != ')') goto error; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); return eval(token, prec, res, err, yylvalpp); } else { goto error; } } else if (token == CPP_INTCONSTANT) { *res = yylvalpp->sc_int; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } else if (token == '(') { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = eval(token, MIN_PREC, res, err, yylvalpp); if (!*err) { if (token != ')') goto error; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } } else { for (i = ALEN(unop) - 1; i >= 0; i--) { if (unop[i].token == token) break; } if (i >= 0) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = eval(token, UNARY, res, err, yylvalpp); *res = unop[i].op(*res); } else { goto error; } } while (!*err) { if (token == ')' || token == '\n') break; for (i = ALEN(binop) - 1; i >= 0; i--) { if (binop[i].token == token) break; } if (i < 0 || binop[i].prec <= prec) break; val = *res; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = eval(token, binop[i].prec, res, err, yylvalpp); if (binop[i].op == op_div || binop[i].op == op_mod) { if (*res == 0) { CPPErrorToInfoLog("preprocessor divide or modulo by zero"); *err = 1; return token; } } *res = binop[i].op(val, *res); } return token; error: CPPErrorToInfoLog("incorrect preprocessor directive"); *err = 1; *res = 0; return token; } // eval
static int CPPdefine(yystypepp * yylvalpp) { int token, name, args[MAX_MACRO_ARGS], argc; const char *message; MacroSymbol mac; Symbol *symb; SourceLoc dummyLoc; memset(&mac, 0, sizeof(mac)); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != CPP_IDENTIFIER) { CPPErrorToInfoLog("#define"); return token; } name = yylvalpp->sc_ident; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '(' && !yylvalpp->sc_int) { // gather arguments argc = 0; do { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (argc == 0 && token == ')') break; if (token != CPP_IDENTIFIER) { CPPErrorToInfoLog("#define"); return token; } if (argc < MAX_MACRO_ARGS) args[argc++] = yylvalpp->sc_ident; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } while (token == ','); if (token != ')') { CPPErrorToInfoLog("#define"); return token; } mac.argc = argc; mac.args = mem_Alloc(macros->pool, argc * sizeof(int)); memcpy(mac.args, args, argc * sizeof(int)); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); } mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool); while (token != '\n') { if (token == '\\') { CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); return token; } else if (token <= 0) { // EOF or error CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline"); return 0; } RecordToken(mac.body, token, yylvalpp); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); }; symb = LookUpSymbol(macros, name); if (symb) { if (!symb->details.mac.undef) { // already defined -- need to make sure they are identical if (symb->details.mac.argc != mac.argc) goto error; for (argc=0; argc < mac.argc; argc++) if (symb->details.mac.args[argc] != mac.args[argc]) goto error; RewindTokenStream(symb->details.mac.body); RewindTokenStream(mac.body); do { int old_lval, old_token; old_token = ReadToken(symb->details.mac.body, yylvalpp); old_lval = yylvalpp->sc_int; token = ReadToken(mac.body, yylvalpp); if (token != old_token || yylvalpp->sc_int != old_lval) { error: StoreStr("Macro Redefined"); StoreStr(GetStringOfAtom(atable,name)); message=GetStrfromTStr(); DecLineNumber(); CPPShInfoLogMsg(message); IncLineNumber(); ResetTString(); break; } } while (token > 0); } //FreeMacro(&symb->details.mac); } else { dummyLoc.file = 0; dummyLoc.line = 0; symb = AddSymbol(&dummyLoc, macros, name, MACRO_S); } symb->details.mac = mac; return '\n'; } // CPPdefine