// // The main functional entry-point into the preprocessor, which will // scan the source strings to figure out and return the next processing token. // // Return string pointer to next token. // Return 0 when no more tokens. // const char* TPpContext::tokenize(TPpToken* ppToken) { int token = '\n'; for(;;) { const char* tokenString = nullptr; token = scanToken(ppToken); ppToken->token = token; if (token == EOF) { missingEndifCheck(); return nullptr; } if (token == '#') { if (previous_token == '\n') { token = readCPPline(ppToken); if (token == EOF) { missingEndifCheck(); return nullptr; } continue; } else { parseContext.error(ppToken->loc, "preprocessor directive cannot be preceded by another token", "#", ""); return nullptr; } } previous_token = token; if (token == '\n') continue; // expand macros if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false, true) != 0) continue; if (token == CPP_IDENTIFIER) tokenString = GetAtomString(ppToken->atom); else if (token == CPP_INTCONSTANT || token == CPP_UINTCONSTANT || token == CPP_FLOATCONSTANT || token == CPP_DOUBLECONSTANT) tokenString = ppToken->name; else if (token == CPP_STRCONSTANT) { parseContext.error(ppToken->loc, "string literals not supported", "\"\"", ""); tokenString = nullptr; } else if (token == '\'') { parseContext.error(ppToken->loc, "character literals not supported", "\'", ""); tokenString = nullptr; } else tokenString = GetAtomString(token); if (tokenString) { if (tokenString[0] != 0) parseContext.tokensBeforeEOF = 1; return tokenString; } } }
void DefineConnectorBinding(SourceLoc *loc, int cname, int mname, int rname) { BindingTree *lTree; lTree = LookupBinding(cname, mname); if (lTree) { SemanticError(loc, ERROR_SSSD_DUPLICATE_BINDING, GetAtomString(atable, cname), GetAtomString(atable, mname), GetAtomString(atable, lTree->loc.file), lTree->loc.line); return; } lTree = NewConnectorBindingTree(loc, cname, mname, rname); AddBinding(lTree); } // DefineConnectorBinding
void DefineTexunitBinding(SourceLoc *loc, int pname, int aname, int unitno) { BindingTree *lTree; lTree = LookupBinding(pname, aname); if (lTree) { SemanticError(loc, ERROR_SSSD_DUPLICATE_BINDING, GetAtomString(atable, pname), GetAtomString(atable, aname), GetAtomString(atable, lTree->loc.file), lTree->loc.line); return; } lTree = NewTexunitBindingTree(loc, pname, aname, unitno); AddBinding(lTree); } // DefineTexunitBinding
void DefineDefaultBinding(SourceLoc *loc, int pname, int aname, int count, float *fval) { BindingTree *lTree; lTree = LookupBinding(pname, aname); if (lTree) { SemanticError(loc, ERROR_SSSD_DUPLICATE_BINDING, GetAtomString(atable, pname), GetAtomString(atable, aname), GetAtomString(atable, lTree->loc.file), lTree->loc.line); return; } lTree = NewConstDefaultBindingTree(loc, BK_DEFAULT, pname, aname, count, fval); AddBinding(lTree); } // DefineDefaultBinding
void DefineRegArrayBinding(SourceLoc *loc, int pname, int aname, int rname, int index, int count) { BindingTree *lTree; lTree = LookupBinding(pname, aname); if (lTree) { SemanticError(loc, ERROR_SSSD_DUPLICATE_BINDING, GetAtomString(atable, pname), GetAtomString(atable, aname), GetAtomString(atable, lTree->loc.file), lTree->loc.line); return; } lTree = NewRegArrayBindingTree(loc, pname, aname, rname, index, count); AddBinding(lTree); } // DefineRegArrayBinding
void yyerror(const char *s) { if (!Cg->options.ErrorMode) { if (Cg->ltokenLoc.file) { fprintf(Cg->options.listfd, "%s(%d) : error C0000: ", GetAtomString(atable, Cg->ltokenLoc.file), Cg->ltokenLoc.line); } else { fprintf(Cg->options.listfd, "(%d) : error C0000: ", Cg->currentInput->line); } fprintf(Cg->options.listfd, "%s at token \"%s\"\n", s, GetAtomString(atable, Cg->mostRecentToken)); Cg->AllowSemanticParseErrors = 1; } bumpErrorCount(); } // yyerror
void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp) { const char *s; char *str=NULL; if (token > 256) lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); else lAddByte(pTok, (unsigned char)(token & 0x7f)); switch (token) { case CPP_IDENTIFIER: case CPP_TYPEIDENTIFIER: case CPP_STRCONSTANT: s = GetAtomString(atable, yylvalpp->sc_ident); while (*s) lAddByte(pTok, (unsigned char) *s++); lAddByte(pTok, 0); break; case CPP_FLOATCONSTANT: case CPP_INTCONSTANT: str=yylvalpp->symbol_name; while (*str){ lAddByte(pTok, (unsigned char) *str++); } lAddByte(pTok, 0); break; case '(': lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0)); default: break; } } // RecordToken
/* * Add a token to the end of a list for later playback. */ void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken) { const char* s; char* str = NULL; if (token > 256) lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); else lAddByte(pTok, (unsigned char)(token & 0x7f)); switch (token) { case CPP_IDENTIFIER: case CPP_STRCONSTANT: s = GetAtomString(ppToken->atom); while (*s) lAddByte(pTok, (unsigned char) *s++); lAddByte(pTok, 0); break; case CPP_INTCONSTANT: case CPP_UINTCONSTANT: case CPP_FLOATCONSTANT: case CPP_DOUBLECONSTANT: str = ppToken->name; while (*str){ lAddByte(pTok, (unsigned char) *str); str++; } lAddByte(pTok, 0); break; default: break; } }
void RecordToken(TokenStream *pTok, int token) { const char *s; // token = lCompressToken(token); if (token > 256) lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); else lAddByte(pTok, (unsigned char)(token & 0x7f)); switch (token) { case IDENT_SY: case TYPEIDENT_SY: case STRCONST_SY: s = GetAtomString(atable, yylval.sc_ident); while (*s) lAddByte(pTok, (unsigned char) *s++); lAddByte(pTok, 0); break; case CFLOATCONST_SY: case FLOATCONST_SY: case FLOATHCONST_SY: case FLOATXCONST_SY: lAdd4Bytes(pTok, (unsigned char *) &yylval.sc_fval); break; case INTCONST_SY: lAdd4Bytes(pTok, (unsigned char *) &yylval.sc_int); break; case '(': lAddByte(pTok, (unsigned char)(yylval.sc_int ? 1 : 0)); default: break; } } // RecordToken
static STDMETHODIMP WriteDepency(stratom depFile, void* _pParam) { KHandlerParam* pParam = (KHandlerParam*)_pParam; _ftprintf(pParam->fpDest, g_szNewLineFmt, GetAtomString(pParam->tblAtom, depFile)); _dbg_fflush(pParam->fpDest); return S_OK; }
// Handle #error int TPpContext::CPPerror(TPpToken* ppToken) { int token = scanToken(ppToken); std::string message; TSourceLoc loc = ppToken->loc; while (token != '\n' && token != EndOfInput) { if (token == PpAtomConstInt || token == PpAtomConstUint || token == PpAtomConstInt64 || token == PpAtomConstUint64 || #ifdef AMD_EXTENSIONS token == PpAtomConstFloat16 || #endif token == PpAtomConstFloat || token == PpAtomConstDouble) { message.append(ppToken->name); } else if (token == PpAtomIdentifier || token == PpAtomConstString) { message.append(ppToken->name); } else { message.append(GetAtomString(token)); } message.append(" "); token = scanToken(ppToken); } parseContext.notifyErrorDirective(loc.line, message.c_str()); //store this msg into the shader's information log..set the Compile Error flag!!!! parseContext.ppError(loc, message.c_str(), "#error", ""); return '\n'; }
int TPpContext::CPPpragma(TPpToken * yylvalpp) { char SrcStrName[2]; char** allTokens; int tokenCount = 0; int maxTokenCount = 10; const char* SrcStr; int i; int token = currentInput->scan(this, currentInput, yylvalpp); if (token=='\n') { parseContext.error(yylvalpp->loc, "must be followed by pragma arguments", "#pragma", ""); 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(&atomTable, yylvalpp->atom); allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); strcpy(allTokens[tokenCount++], SrcStr); break; case CPP_INTCONSTANT: case CPP_UINTCONSTANT: case CPP_FLOATCONSTANT: case CPP_DOUBLECONSTANT: SrcStr = yylvalpp->name; allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); strcpy(allTokens[tokenCount++], SrcStr); break; case EOF: parseContext.error(yylvalpp->loc, "directive must end with a newline", "#pragma", ""); return token; default: SrcStrName[0] = token; SrcStrName[1] = '\0'; allTokens[tokenCount] = (char*)malloc(2); strcpy(allTokens[tokenCount++], SrcStrName); } token = currentInput->scan(this, currentInput, yylvalpp); } currentInput->ungetch(this, currentInput, token, yylvalpp); parseContext.handlePragma((const char**)allTokens, tokenCount); token = currentInput->scan(this, currentInput, yylvalpp); for (i = 0; i < tokenCount; ++i) { free (allTokens[i]); } free (allTokens); return token; } // CPPpragma
// Handle #line int TPpContext::CPPline(TPpToken* ppToken) { // "#line must have, after macro substitution, one of the following forms: // "#line line // "#line line source-string-number" int token = scanToken(ppToken); const TSourceLoc directiveLoc = ppToken->loc; if (token == '\n') { parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); return token; } int lineRes = 0; // Line number after macro expansion. int lineToken = 0; bool hasFile = false; int fileRes = 0; // Source file number after macro expansion. const char* sourceName = nullptr; // Optional source file name. bool lineErr = false; bool fileErr = false; token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); if (! lineErr) { lineToken = lineRes; if (token == '\n') ++lineRes; if (parseContext.lineDirectiveShouldSetNextLine()) --lineRes; parseContext.setCurrentLine(lineRes); if (token != '\n') { if (token == PpAtomConstString) { parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line"); // We need to save a copy of the string instead of pointing // to the name field of the token since the name field // will likely be overwritten by the next token scan. sourceName = GetAtomString(LookUpAddString(ppToken->name)); parseContext.setCurrentSourceName(sourceName); hasFile = true; token = scanToken(ppToken); } else { token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); if (! fileErr) { parseContext.setCurrentString(fileRes); hasFile = true; } } } } if (!fileErr && !lineErr) { parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName); } token = extraTokenCheck(PpAtomLine, ppToken, token); return token; }
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
int TPpContext::CPPextension(TPpToken * yylvalpp) { int token = currentInput->scan(this, currentInput, yylvalpp); char extensionName[80]; if (token=='\n') { parseContext.error(yylvalpp->loc, "extension name not specified", "#extension", ""); return token; } if (token != CPP_IDENTIFIER) parseContext.error(yylvalpp->loc, "extension name expected", "#extension", ""); strcpy(extensionName, GetAtomString(&atomTable, yylvalpp->atom)); token = currentInput->scan(this, currentInput, yylvalpp); if (token != ':') { parseContext.error(yylvalpp->loc, "':' missing after extension name", "#extension", ""); return token; } token = currentInput->scan(this, currentInput, yylvalpp); if (token != CPP_IDENTIFIER) { parseContext.error(yylvalpp->loc, "behavior for extension not specified", "#extension", ""); return token; } parseContext.updateExtensionBehavior(extensionName, GetAtomString(&atomTable, yylvalpp->atom)); token = currentInput->scan(this, currentInput, yylvalpp); if (token == '\n') return token; else parseContext.error(yylvalpp->loc, "extra tokens -- expected newline", "#extension",""); return token; } // CPPextension
// Handle #error int TPpContext::CPPerror(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); std::string message; TSourceLoc loc = ppToken->loc; while (token != '\n') { if (token == CPP_INTCONSTANT || token == CPP_UINTCONSTANT || token == CPP_FLOATCONSTANT || token == CPP_DOUBLECONSTANT) { message.append(ppToken->name); } else if (token == CPP_IDENTIFIER || token == CPP_STRCONSTANT) { message.append(GetAtomString(ppToken->atom)); } else { message.append(GetAtomString(token)); } message.append(" "); token = currentInput->scan(this, currentInput, ppToken); } //store this msg into the shader's information log..set the Compile Error flag!!!! parseContext.error(loc, message.c_str(), "#error", ""); return '\n'; }
void InternalError(SourceLoc *loc, int num, const char *mess, ...) { va_list args; if (loc->file) { fprintf(Cg->options.listfd, "%s(%d) : error C%04d: ", GetAtomString(atable, loc->file), loc->line, num); } else { fprintf(Cg->options.listfd, "(%d) : error C%04d: ", loc->line, num); } va_start(args, mess); vfprintf(Cg->options.listfd, mess, args); va_end(args); fprintf(Cg->options.listfd, "\n"); bumpErrorCount(); } // InternalError
void InformationalNotice(SourceLoc *loc, int num, const char *mess, ...) { va_list args; if (!Cg->options.NoWarnings) { if (!Cg->options.ErrorMode) { if (loc->file) { fprintf(Cg->options.listfd, "%s(%d) : notice C%04d: ", GetAtomString(atable, loc->file), loc->line, num); } else { fprintf(Cg->options.listfd, "(%d) : notice C%04d: ", loc->line, num); } va_start(args, mess); vfprintf(Cg->options.listfd, mess, args); va_end(args); fprintf(Cg->options.listfd, "\n"); } } } // InformationalNotice
void SemanticWarning(SourceLoc *loc, int num, const char *mess, ...) { va_list args; if (!Cg->options.NoWarnings) { if (!Cg->options.ErrorMode) { if (loc->file) { fprintf(Cg->options.listfd, "%s(%d) : warning C%04d: ", GetAtomString(atable, loc->file), loc->line, num); } else { fprintf(Cg->options.listfd, "(%d) : warning C%04d: ", loc->line, num); } va_start(args, mess); vfprintf(Cg->options.listfd, mess, args); va_end(args); fprintf(Cg->options.listfd, "\n"); } bumpWarningCount(); } } // SemanticWarning
// Handle #pragma int TPpContext::CPPpragma(TPpToken* ppToken) { char SrcStrName[2]; int tokenCount = 0; int maxTokenCount = 10; const char* SrcStr; TVector<TString> tokens; TSourceLoc loc = ppToken->loc; // because we go to the next line before processing int token = currentInput->scan(this, currentInput, ppToken); while (token != '\n' && token != EOF) { switch (token) { case CPP_IDENTIFIER: SrcStr = GetAtomString(ppToken->atom); tokens.push_back(SrcStr); break; case CPP_INTCONSTANT: case CPP_UINTCONSTANT: case CPP_FLOATCONSTANT: case CPP_DOUBLECONSTANT: SrcStr = ppToken->name; tokens.push_back(SrcStr); break; default: SrcStrName[0] = token; SrcStrName[1] = '\0'; tokens.push_back(SrcStrName); } token = currentInput->scan(this, currentInput, ppToken); } if (token == EOF) parseContext.error(loc, "directive must end with a newline", "#pragma", ""); else parseContext.handlePragma(loc, tokens); return token; }
// Handle #undef int TPpContext::CPPundef(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); Symbol *symb; if (token != CPP_IDENTIFIER) { parseContext.error(ppToken->loc, "must be followed by macro name", "#undef", ""); return token; } const char* name = GetAtomString(ppToken->atom); // TODO preprocessor simplification: the token text should have been built into the ppToken during currentInput->scan() parseContext.reservedPpErrorCheck(ppToken->loc, name, "#undef"); symb = LookUpSymbol(ppToken->atom); if (symb) { symb->mac.undef = 1; } token = currentInput->scan(this, currentInput, ppToken); if (token != '\n') parseContext.error(ppToken->loc, "can only be followed by a single macro name", "#undef", ""); return token; }
static void lAddToTree(Symbol **fSymbols, Symbol *fSymb, Type *fType) { Symbol *lSymb; int lrev, frev; lSymb = *fSymbols; if (lSymb) { frev = GetReversedAtom(atable, fSymb->name); while (lSymb) { lrev = GetReversedAtom(atable, lSymb->name); if (lrev == frev) { InternalError(Cg->tokenLoc, 9999, "symbol \"%s\" already in table", 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
void SemanticParseError(SourceLoc *loc, int num, const char *mess, ...) { va_list args; if (Cg->AllowSemanticParseErrors) { if (!Cg->options.ErrorMode) { if (loc->file) { fprintf(Cg->options.listfd, "%s(%d) : error C%04d: ", GetAtomString(atable, loc->file), loc->line, num); } else { fprintf(Cg->options.listfd, "(%d) : error C%04d: ", loc->line, num); } va_start(args, mess); vfprintf(Cg->options.listfd, mess, args); va_end(args); fprintf(Cg->options.listfd, "\n"); bumpErrorCount(); } else { MarkErrorPosHit(loc); } Cg->AllowSemanticParseErrors = 0; } } // SemanticParseError
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
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
/* MacroExpand ** Check an identifier (atom) to see if it is a macro that should be expanded. ** If it is, push an InputSrc that will produce the appropriate expansion ** and return 1. ** If it is, but undefined, it should expand to 0, push an InputSrc that will ** expand to 0 and return -1. ** Otherwise, return 0. */ int TPpContext::MacroExpand(int atom, TPpToken* yylvalpp, int expandUndef) { Symbol *sym = LookUpSymbol(macros, atom); MacroInputSrc *in; int i, j, token; int depth = 0; if (atom == __LINE__Atom) { yylvalpp->ival = parseContext.currentLoc.line; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __FILE__Atom) { yylvalpp->ival = parseContext.currentLoc.string; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __VERSION__Atom) { yylvalpp->ival = parseContext.version; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } // no recursive expansions if (sym && sym->details.mac.busy) return 0; // not expanding of undefined symbols if ((! sym || sym->details.mac.undef) && ! expandUndef) return 0; in = (MacroInputSrc*)malloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->base.line = currentInput->line; in->base.name = currentInput->name; if ((! sym || sym->details.mac.undef) && expandUndef) { // push input in->base.scan = zero_scan; in->base.prev = currentInput; currentInput = &in->base; return -1; } in->base.scan = macro_scan; in->mac = &sym->details.mac; if (sym->details.mac.args) { token = currentInput->scan(this, currentInput, yylvalpp); if (token != '(') { UngetToken(token, yylvalpp); yylvalpp->atom = atom; return 0; } in->args = (TokenStream**)malloc(in->mac->argc * sizeof(TokenStream *)); for (i = 0; i < in->mac->argc; i++) in->args[i] = NewTokenStream("macro arg", 0); i = 0; j = 0; do { depth = 0; while (1) { token = currentInput->scan(this, currentInput, yylvalpp); if (token <= 0) { parseContext.error(yylvalpp->loc, "EOF in macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); return 1; } if ((in->mac->argc==0) && (token!=')')) break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[i], token, yylvalpp); j=1; } if (token == ')') { if ((in->mac->argc==1) &&j==0) break; i++; break; } i++; } while (i < in->mac->argc); if (i < in->mac->argc) parseContext.error(yylvalpp->loc, "Too few args in Macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = currentInput->scan(this, currentInput, yylvalpp); if (token == '(') depth++; } if (token <= 0) { parseContext.error(yylvalpp->loc, "EOF in macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); return 1; } parseContext.error(yylvalpp->loc, "Too many args in Macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); } for (i = 0; i<in->mac->argc; i++) { in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); } } #if 0 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), loc.line, GetAtomString(atable, atom)); for (i = 0; i<in->mac->argc; i++) { printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); DumpTokenStream(stdout, in->args[i]); printf("'\n"); } #endif /*retain the input source*/ in->base.prev = currentInput; sym->details.mac.busy = 1; RewindTokenStream(sym->details.mac.body); currentInput = &in->base; return 1; } // MacroExpand
int TPpContext::CPPdefine(TPpToken * yylvalpp) { int token, name, args[maxMacroArgs], argc; MacroSymbol mac; Symbol *symb; memset(&mac, 0, sizeof(mac)); token = currentInput->scan(this, currentInput, yylvalpp); if (token != CPP_IDENTIFIER) { parseContext.error(yylvalpp->loc, "must be followed by macro name", "#define", ""); return token; } name = yylvalpp->atom; token = currentInput->scan(this, currentInput, yylvalpp); if (token == '(' && !yylvalpp->ival) { // gather arguments argc = 0; do { token = currentInput->scan(this, currentInput, yylvalpp); if (argc == 0 && token == ')') break; if (token != CPP_IDENTIFIER) { parseContext.error(yylvalpp->loc, "bad argument", "#define", ""); return token; } if (argc < maxMacroArgs) args[argc++] = yylvalpp->atom; token = currentInput->scan(this, currentInput, yylvalpp); } while (token == ','); if (token != ')') { parseContext.error(yylvalpp->loc, "missing parenthesis", "#define", ""); return token; } mac.argc = argc; mac.args = (int*)mem_Alloc(macros->pool, argc * sizeof(int)); memcpy(mac.args, args, argc * sizeof(int)); token = currentInput->scan(this, currentInput, yylvalpp); } mac.body = NewTokenStream(GetAtomString(&atomTable, name), macros->pool); while (token != '\n') { while (token == '\\') { token = currentInput->scan(this, currentInput, yylvalpp); if (token == '\n') token = currentInput->scan(this, currentInput, yylvalpp); else RecordToken(mac.body, '\\', yylvalpp); } RecordToken(mac.body, token, yylvalpp); token = currentInput->scan(this, 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->ival; token = ReadToken(mac.body, yylvalpp); if (token != old_token || yylvalpp->ival != old_lval) { error: parseContext.error(yylvalpp->loc, "Macro Redefined", "#define", GetStringOfAtom(&atomTable, name)); break; } } while (token > 0); } //FreeMacro(&symb->details.mac); } else { symb = AddSymbol(&yylvalpp->loc, macros, name, MACRO_S); } symb->details.mac = mac; return '\n'; } // CPPdefine
int MacroExpand(int atom, yystypepp * yylvalpp) { Symbol *sym = LookUpSymbol(macros, atom); MacroInputSrc *in; int i,j, token, depth=0; const char *message; if (atom == __LINE__Atom) { yylvalpp->sc_int = GetLineNumber(); snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __FILE__Atom) { yylvalpp->sc_int = GetStringNumber(); snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __VERSION__Atom) { strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING); yylvalpp->sc_int = atoi(yylvalpp->symbol_name); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (!sym || sym->details.mac.undef) return 0; if (sym->details.mac.busy) return 0; // no recursive expansions in = malloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->base.scan = (void *)macro_scan; in->base.line = cpp->currentInput->line; in->base.name = cpp->currentInput->name; in->mac = &sym->details.mac; if (sym->details.mac.args) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '(') { UngetToken(token, yylvalpp); yylvalpp->sc_ident = atom; return 0; } in->args = malloc(in->mac->argc * sizeof(TokenStream *)); for (i=0; i<in->mac->argc; i++) in->args[i] = NewTokenStream("macro arg", 0); i=0;j=0; do{ depth = 0; while(1) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { StoreStr("EOF in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); return 1; } if((in->mac->argc==0) && (token!=')')) break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[i], token, yylvalpp); j=1; } if (token == ')') { if((in->mac->argc==1) &&j==0) break; i++; break; } i++; }while(i < in->mac->argc); if (i < in->mac->argc) { StoreStr("Too few args in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '(') depth++; } if (token <= 0) { StoreStr("EOF in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); return 1; } StoreStr("Too many args in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } for (i=0; i<in->mac->argc; i++) { in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); } } #if 0 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), loc.line, GetAtomString(atable, atom)); for (i=0; i<in->mac->argc; i++) { printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); DumpTokenStream(stdout, in->args[i]); printf("'\n"); } #endif /*retain the input source*/ in->base.prev = cpp->currentInput; sym->details.mac.busy = 1; RewindTokenStream(sym->details.mac.body); cpp->currentInput = &in->base; return 1; } // MacroExpand
STDMETHODIMP CheckDepency(stratom srcFile, KCheckDepencyParam* pParam) { BOOL fCheckCurDir; FILE* fpSrc; stratom depFile; LPCTSTR psz; LPCTSTR szSrcFile; LPTSTR szSrcPath; LPTSTR szDepFileAbs; LPTSTR szDepFile; HRESULT hr = E_PATH_INVALID; KCheckDepencyLocal* pLocal = NULL; szSrcFile = GetAtomString(pParam->tblAtom, srcFile); TRACE("Checking Depency Of %s...\n", szSrcFile); psz = _tcsrchr(szSrcFile, '/'); if (psz == NULL) goto lzError; // 要求szSrcFile是标准路径,也就是说,肯定有 '/' // >>> 在Windows下发生了栈溢出 (Linux下还没有:-) // 这样做是为了减少对栈的使用,从而减少栈溢出的可能性。 pLocal = (KCheckDepencyLocal*)malloc(sizeof(KCheckDepencyLocal)); szSrcPath = pLocal->szSrcPath; szDepFileAbs = pLocal->szDepFileAbs; szDepFile = pLocal->szDepFile; _tcsncpy(szSrcPath, szSrcFile, psz - szSrcFile); szSrcPath[psz - szSrcFile] = 0; StartCheckDepency(srcFile, pParam); fpSrc = _tfopen(szSrcFile, _T("r")); if (fpSrc == NULL) goto lzError; // 文件不存在? while (LookupDepFile(szDepFile, fpSrc, &fCheckCurDir) == S_OK) { if ( S_OK == SearchFilePath( szDepFileAbs, szDepFile, pParam->szIncDirs, pParam->nIncDirs, fCheckCurDir ? szSrcPath : NULL) ) { depFile = AddStringAtom(pParam->tblAtom, szDepFileAbs); if (!IsDepencyChecked(depFile, pParam)) { CheckDepency(depFile, pParam); } AddDepency(srcFile, depFile, pParam); } } fclose(fpSrc); TRACE(">>> End Checking Depency Of %s\n", szSrcFile); hr = S_OK; lzError: if (pLocal) free(pLocal); return hr; }
// Handle #define int TPpContext::CPPdefine(TPpToken* ppToken) { MacroSymbol mac; Symbol *symb; // get macro name int token = scanToken(ppToken); if (token != PpAtomIdentifier) { parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", ""); return token; } if (ppToken->loc.string >= 0) { // We are in user code; check for reserved name use: parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define"); } // save the original atom const int defAtom = ppToken->atom; // gather parameters to the macro, between (...) token = scanToken(ppToken); if (token == '(' && ! ppToken->space) { int argc = 0; int args[maxMacroArgs]; do { token = scanToken(ppToken); if (argc == 0 && token == ')') break; if (token != PpAtomIdentifier) { parseContext.ppError(ppToken->loc, "bad argument", "#define", ""); return token; } // check for duplication of parameter name bool duplicate = false; for (int a = 0; a < argc; ++a) { if (args[a] == ppToken->atom) { parseContext.ppError(ppToken->loc, "duplicate macro parameter", "#define", ""); duplicate = true; break; } } if (! duplicate) { if (argc < maxMacroArgs) args[argc++] = ppToken->atom; else parseContext.ppError(ppToken->loc, "too many macro parameters", "#define", ""); } token = scanToken(ppToken); } while (token == ','); if (token != ')') { parseContext.ppError(ppToken->loc, "missing parenthesis", "#define", ""); return token; } mac.argc = argc; mac.args = (int*)mem_Alloc(pool, argc * sizeof(int)); memcpy(mac.args, args, argc * sizeof(int)); token = scanToken(ppToken); } // record the definition of the macro TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors mac.body = new TokenStream; while (token != '\n' && token != EndOfInput) { RecordToken(mac.body, token, ppToken); token = scanToken(ppToken); if (token != '\n' && ppToken->space) RecordToken(mac.body, ' ', ppToken); } // check for duplicate definition symb = LookUpSymbol(defAtom); if (symb) { if (! symb->mac.undef) { // Already defined -- need to make sure they are identical: // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, // ordering, spelling, and white-space separation, where all white-space separations are considered identical." if (symb->mac.argc != mac.argc) parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", GetAtomString(defAtom)); else { for (int argc = 0; argc < mac.argc; argc++) { if (symb->mac.args[argc] != mac.args[argc]) parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", GetAtomString(defAtom)); } RewindTokenStream(symb->mac.body); RewindTokenStream(mac.body); int newToken; do { int oldToken; TPpToken oldPpToken; TPpToken newPpToken; oldToken = ReadToken(symb->mac.body, &oldPpToken); newToken = ReadToken(mac.body, &newPpToken); if (oldToken != newToken || oldPpToken != newPpToken) { parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", GetAtomString(defAtom)); break; } } while (newToken > 0); } } } else symb = AddSymbol(defAtom); delete symb->mac.body; symb->mac = mac; return '\n'; }