// // SourceTokenizerC::doCommand_ifndef // void SourceTokenizerC::doCommand_ifndef(SourceTokenC *) { SourceTokenC::Reference name = getRaw(); doAssert(name, SourceTokenC::TT_NAM); doAssert(peekRaw(), SourceTokenC::TT_ENDL); addSkip(hasDefine(name->data) || hasMacro(name->data)); }
// // SourceTokenizerC::expand // // Expands a token. // void SourceTokenizerC::expand(MacroVec &out, std::set<std::string> &used, SourcePosition const &pos, SourceTokenC::Reference tok, SourceStream *in, MacroArgs const *altArgs, MacroParm const *altParm) { // Check for function-like macro expansion. // That is, a function-like macro name followed by an open parenthesis. // And of course, that name must not have been expanded yet. if(tok->type == SourceTokenC::TT_PAREN_O && !out.empty() && out.back()->type == SourceTokenC::TT_NAM && hasMacro(out.back()->data) && !used.count(out.back()->data)) { tok = out.back(); out.pop_back(); MacroData const &mdata = macros[tok->data]; MacroArgs margs; readArgs(margs, in, mdata, pos, altArgs, altParm); used.insert(tok->data); expand(out, used, pos, mdata, margs); used.erase(tok->data); return; } // Check for object-like macro expansion. // Like above, but it only needs one token to trigger. if(tok->type == SourceTokenC::TT_NAM && hasDefine(tok->data) && !used.count(tok->data)) { used.insert(tok->data); expand(out, used, pos, defines[tok->data]); used.erase(tok->data); return; } // Then check for __FILE__ specifically. if(tok->type == SourceTokenC::TT_NAM && tok->data == "__FILE__") { out.push_back(SourceTokenC::create(pos, pos.filename, SourceTokenC::TT_STR)); return; } // And __LINE__. if(tok->type == SourceTokenC::TT_NAM && tok->data == "__LINE__") { std::ostringstream oss; oss << pos.line; out.push_back(SourceTokenC::create(pos, oss.str(), SourceTokenC::TT_INT)); return; } // If it actually isn't any of those things, then consider the token expanded. out.push_back(tok); }
// // SourceTokenizerC::getExpand // SourceTokenC::Reference SourceTokenizerC::getExpand() { SourceTokenC::Reference tok = getRaw(); if (canExpand && tok->type == SourceTokenC::TT_NAM) { if (hasMacro(tok->data)) { SourceTokenC::Reference tmpTok = getExpand(); // Macro invocation! if (tmpTok->type == SourceTokenC::TT_PAREN_O) { expandMacro(tok); return getExpand(); } unget(tmpTok); } if (hasDefine(tok->data)) { expandDefine(tok); return getExpand(); } if (tok->data == "__FILE__") return SourceTokenC::create(tok->pos, tok->pos.filename, SourceTokenC::TT_STR); if (tok->data == "__LINE__") { std::ostringstream oss; oss << tok->pos.line; return SourceTokenC::create(tok->pos, oss.str(), SourceTokenC::TT_INT); } } return tok; }
void Driver::setupLexer( Lexer * lexer ) { // stl lexer->addSkipWord( "__STL_BEGIN_NAMESPACE" ); lexer->addSkipWord( "__STL_END_NAMESPACE" ); lexer->addSkipWord( "__STL_BEGIN_RELOPS_NAMESPACE" ); lexer->addSkipWord( "__STL_END_RELOPS_NAMESPACE" ); lexer->addSkipWord( "__STL_TEMPLATE_NULL" ); lexer->addSkipWord( "__STL_TRY" ); lexer->addSkipWord( "__STL_UNWIND" ); lexer->addSkipWord( "__STL_NOTHROW" ); lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" ); lexer->addSkipWord( "__STL_UNWIND", SkipWordAndArguments ); lexer->addSkipWord( "__GC_CONST" ); lexer->addSkipWord( "__HASH_ALLOC_INIT", SkipWordAndArguments ); lexer->addSkipWord( "__STL_DEFAULT_ALLOCATOR", SkipWordAndArguments, "T" ); lexer->addSkipWord( "__STL_MUTEX_INITIALIZER" ); lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" ); // antlr lexer->addSkipWord( "ANTLR_BEGIN_NAMESPACE", SkipWordAndArguments ); lexer->addSkipWord( "ANTLR_USE_NAMESPACE", SkipWordAndArguments ); lexer->addSkipWord( "ANTLR_USING_NAMESPACE", SkipWordAndArguments ); lexer->addSkipWord( "ANTLR_END_NAMESPACE" ); lexer->addSkipWord( "ANTLR_C_USING", SkipWordAndArguments ); lexer->addSkipWord( "ANTLR_API" ); // gnu lexer->addSkipWord( "__extension__", SkipWordAndArguments ); lexer->addSkipWord( "__attribute__", SkipWordAndArguments ); lexer->addSkipWord( "__BEGIN_DECLS" ); lexer->addSkipWord( "__END_DECLS" ); lexer->addSkipWord( "__THROW" ); lexer->addSkipWord( "__restrict" ); lexer->addSkipWord( "__restrict__" ); lexer->addSkipWord( "__attribute_pure__" ); lexer->addSkipWord( "__attribute_malloc__" ); lexer->addSkipWord( "__attribute_format_strfmon__" ); lexer->addSkipWord( "__asm__", SkipWordAndArguments ); lexer->addSkipWord( "__devinit" ); lexer->addSkipWord( "__devinit__" ); lexer->addSkipWord( "__init" ); lexer->addSkipWord( "__init__" ); lexer->addSkipWord( "__signed" ); lexer->addSkipWord( "__signed__" ); lexer->addSkipWord( "__unsigned" ); lexer->addSkipWord( "__unsigned__" ); lexer->addSkipWord( "asmlinkage" ); lexer->addSkipWord( "____cacheline_aligned" ); lexer->addSkipWord( "__glibcpp_class_requires", SkipWordAndArguments ); lexer->addSkipWord( "__glibcpp_class2_requires", SkipWordAndArguments ); lexer->addSkipWord( "__glibcpp_class4_requires", SkipWordAndArguments ); lexer->addSkipWord( "__glibcpp_function_requires", SkipWordAndArguments ); lexer->addSkipWord( "restrict" ); lexer->addSkipWord( "__BEGIN_NAMESPACE_STD" ); lexer->addSkipWord( "__END_NAMESPACE_STD" ); lexer->addSkipWord( "__BEGIN_NAMESPACE_C99" ); lexer->addSkipWord( "__END_NAMESPACE_C99" ); lexer->addSkipWord( "__USING_NAMESPACE_STD", SkipWordAndArguments ); // kde lexer->addSkipWord( "K_SYCOCATYPE", SkipWordAndArguments ); lexer->addSkipWord( "EXPORT_DOCKCLASS" ); lexer->addSkipWord( "K_EXPORT_COMPONENT_FACTORY", SkipWordAndArguments ); lexer->addSkipWord( "K_SYCOCAFACTORY", SkipWordAndArguments ); lexer->addSkipWord( "KDE_DEPRECATED" ); // qt lexer->addSkipWord( "Q_OBJECT" ); lexer->addSkipWord( "Q_OVERRIDE", SkipWordAndArguments ); lexer->addSkipWord( "Q_ENUMS", SkipWordAndArguments ); lexer->addSkipWord( "Q_PROPERTY", SkipWordAndArguments ); lexer->addSkipWord( "Q_CLASSINFO", SkipWordAndArguments ); lexer->addSkipWord( "Q_SETS", SkipWordAndArguments ); lexer->addSkipWord( "Q_UNUSED", SkipWordAndArguments ); lexer->addSkipWord( "Q_CREATE_INSTANCE", SkipWordAndArguments ); lexer->addSkipWord( "Q_DUMMY_COMPARISON_OPERATOR", SkipWordAndArguments ); lexer->addSkipWord( "ACTIVATE_SIGNAL_WITH_PARAM", SkipWordAndArguments ); lexer->addSkipWord( "Q_INLINE_TEMPLATES" ); lexer->addSkipWord( "Q_TEMPLATE_EXTERN" ); lexer->addSkipWord( "Q_TYPENAME" ); lexer->addSkipWord( "Q_REFCOUNT" ); lexer->addSkipWord( "Q_EXPLICIT" ); lexer->addSkipWord( "QMAC_PASCAL" ); lexer->addSkipWord( "QT_STATIC_CONST" ); lexer->addSkipWord( "QT_STATIC_CONST_IMPL" ); lexer->addSkipWord( "QT_WIN_PAINTER_MEMBERS" ); lexer->addSkipWord( "QT_NC_MSGBOX" ); lexer->addSkipWord( "Q_VARIANT_AS", SkipWordAndArguments ); lexer->addSkipWord( "CALLBACK_CALL_TYPE" ); // qt4 [erbsland] lexer->addSkipWord( "Q_DECLARE_FLAGS", SkipWordAndArguments ); lexer->addSkipWord( "Q_DECLARE_OPERATORS_FOR_FLAGS", SkipWordAndArguments ); // flex lexer->addSkipWord( "yyconst" ); lexer->addSkipWord( "YY_RULE_SETUP" ); lexer->addSkipWord( "YY_BREAK" ); lexer->addSkipWord( "YY_RESTORE_YY_MORE_OFFSET" ); // gtk lexer->addSkipWord( "G_BEGIN_DECLS" ); lexer->addSkipWord( "G_END_DECLS" ); lexer->addSkipWord( "G_GNUC_CONST" ); lexer->addSkipWord( "G_CONST_RETURN" ); lexer->addSkipWord( "GTKMAIN_C_VAR" ); lexer->addSkipWord( "GTKVAR" ); lexer->addSkipWord( "GDKVAR" ); lexer->addSkipWord( "G_GNUC_PRINTF", SkipWordAndArguments ); // windows lexer->addSkipWord( "WINAPI" ); lexer->addSkipWord( "__stdcall" ); lexer->addSkipWord( "__cdecl" ); lexer->addSkipWord( "_cdecl" ); lexer->addSkipWord( "CALLBACK" ); // gcc extensions if( !hasMacro( "__asm__" ) ) addMacro( Macro( "__asm__", "asm" ) ); if( !hasMacro( "__inline" ) ) addMacro( Macro( "__inline", "inline" ) ); if( !hasMacro( "__inline__" ) ) addMacro( Macro( "__inline__", "inline" ) ); if( !hasMacro( "__const" ) ) addMacro( Macro( "__const", "const" ) ); if( !hasMacro( "__const__" ) ) addMacro( Macro( "__const__", "const" ) ); if( !hasMacro( "__volatile__" ) ) addMacro( Macro( "__volatile__", "volatile" ) ); if( !hasMacro( "__complex__" ) ) addMacro( Macro( "__complex__", "" ) ); }
int MacroExtender::macroExtend() { bool canWrite = false; int numLine; int macroBound = 0; int macroLastStart = 0,macroLastEnd = 0; bool textSegment = false; bool dataSegment = false; bool isMacroBody = false; smatch auxMatch; string curLine; vector<string> currentCode; vector<string> macroParams; vector<string> macroLines; fileIn.append(".pre"); fileOut.append(".mcr"); ifstream inputFile(fileIn,ios::in); if (!inputFile) { cerr << "Fatal Error: Could not open file " << fileIn << endl; return -1; } cout << "Opened " << fileIn << " for macro-extending..." << endl; ofstream outputFile(fileOut,ios::out); if (!outputFile) { cerr << "Fatal Error: Could not create file " << fileOut << endl; return -1; } while (getline(inputFile,curLine)) { // prepareLine(curLine); if (curLine.find("SECTION ")!=string::npos && regex_search(curLine,auxMatch,regex("\\bSECTION "))) { if (regex_search(curLine,auxMatch,regex("\\bTEXT$"))) { textSegment = true; } else { textSegment = false; } if (regex_search(curLine,auxMatch,regex("\\bDATA$"))) { dataSegment = true; } else { dataSegment = false; } } else if (curLine.find(" MACRO ")!=string::npos || regex_search(curLine,auxMatch,regex(" MACRO$")) || regex_search(curLine,auxMatch,regex("\\bMACRO "))) { macroBound++; macroLastStart = numLine; if (textSegment || dataSegment) { addError(numLine,string("Semantical Error: MACRO definitions must go before all")); } } else if (regex_search(curLine,auxMatch,regex("\\bMACRO "))) { macroBound++; macroLastStart = numLine; if (textSegment || dataSegment) { addError(numLine,string("Semantical Error: MACRO definitions must go before all")); } } else if (regex_search(curLine,auxMatch,regex("\\bENDMACRO$"))) { macroBound--; macroLastEnd = numLine; if (textSegment || dataSegment) { addError(numLine,string("Semantical Error: ENDMACRO must go before all")); } } currentCode.push_back(curLine); currentCode.shrink_to_fit(); numLine++; } //cout << "Macro Bound: " << macroBound << endl; if (macroBound>0) { addError(macroLastStart,string("Semantical Error: Caught at least one MACRO without a corresponding ENDMACRO")); } else if (macroBound<0) { addError(macroLastEnd,string("Semantical Error: Caught at least one ENDMACRO without a corresponding MACRO")); } vector<string>::iterator codeIterator; for (numLine=1,codeIterator=currentCode.begin();codeIterator!=currentCode.end();codeIterator++,numLine++) { curLine = *codeIterator; canWrite = true; //cout << "@" << hasMacro(curLine) << endl; if (curLine.find("SECTION ")!=string::npos && regex_search(curLine,auxMatch,regex("\\bSECTION "))) { if (regex_search(curLine,auxMatch,regex("\\bTEXT$"))) { textSegment = true; } else { textSegment = false; } outputFile << curLine << "\n"; } else if (curLine.find(" MACRO ")!=string::npos || regex_search(curLine,auxMatch,regex(" MACRO$")) || regex_search(curLine,auxMatch,regex("\\bMACRO "))) { macroParams.clear(); macroLines.clear(); if (regex_search(curLine,auxMatch,regex("\\bMACRO ")) && curLine.find("MACRO ")==0) { addError(numLine,string("Syntactical Error: MACRO must have a definition label")); } else if (!regex_search(curLine,auxMatch,regex(labelReg))) { addError(numLine,string("Syntactical Error: MACRO must have a definition label")); } else if (macroBound<=0 || (macroBound>0 && numLine!=macroLastStart)) { int macroDefLine = numLine; int numParameters; string macroLabel = curLine.substr(0,curLine.find_last_of(':')); if (directiveTable.isDirective(macroLabel) || opcodeTable.isInstruction(macroLabel)) { addError(numLine,string("Semantical Error: Invalid use of keyword")); } if (macroLabel.find(':')!=string::npos) { addError(numLine,string("Syntactical Error: Too many definitions for MACRO constructor")); } if (curLine.find(" MACRO ") == string::npos) { numParameters = 0; } else { string auxParameters = curLine.substr(curLine.find(" MACRO ")+7); splitTokenize(auxParameters,macroParams,","); if (hasDuplicates(macroParams)) { addError(numLine,"Semantical Errors: Duplicate parameter detected"); } for (const string ¯oRef : macroParams) { if (!regex_match(macroRef,regex("\\&[\\w]"))) { addError(numLine,"Syntactical Error: Invalid parameter(s) for MACRO statement"); break; } } numParameters = macroParams.size(); if (numParameters > MACRO_MAX_PARAMS) { string pError = "Semantical Error: Too many parameters for MACRO definition (max at "; pError.append(to_string(MACRO_MAX_PARAMS)); pError.append(" )"); pError.shrink_to_fit(); addError(numLine,pError); } //cout << macroParams << endl; } if (MNT.find(macroLabel) != MNT.end()) { addError(numLine,"Semantical Error: Macro redefinition detected"); } MNT.emplace(macroLabel,make_pair(macroDefLine,numParameters)); isMacroBody = true; codeIterator++; while (isMacroBody && codeIterator != currentCode.end()) { curLine = *codeIterator; if (curLine.find(" EXTERN") != string::npos && regex_search(curLine,auxMatch,regex(" EXTERN$"))) { addError(numLine,"Semantical Error: EXTERN directive inside a macro body is forbidden"); } if (curLine.find(" BEGIN") != string::npos && regex_search(curLine,auxMatch,regex(" BEGIN$"))) { addError(numLine,"Semantical Error: BEGIN directive inside a macro body is forbidden"); } if (regex_search(curLine,auxMatch,regex("^\\bEND[\\b]?$"))) { addError(numLine,"Semantical Error: END directive inside a macro body is forbidden"); } if (curLine.find("PUBLIC ") != string::npos && regex_search(curLine,auxMatch,regex("^PUBLIC "))) { addError(numLine,"Semantical Error: PUBLIC directive inside a macro body is forbidden"); } if (curLine.find(':') != string::npos) { addError(numLine,"Semantical Error: MACRO does not support labels inside"); continue; } if (regex_search(curLine,auxMatch,regex("\\bENDMACRO$"))) { isMacroBody = false; break; } if (curLine.find("SECTION ")!=string::npos && regex_search(curLine,auxMatch,regex("^SECTION "))) { addError(numLine,"Semantical Error: SECTION directive inside a macro body is forbidden"); } else { for (unsigned i=0;i<macroParams.size();i++) { string paramRegex = macroParams[i]; string paramSub = string("#") + to_string(i+1); curLine = regex_replace(curLine,regex(paramRegex),paramSub); } if(regex_search(curLine,auxMatch,regex("\\&[\\w]"))) { addError(numLine,"Semantical Error: MACRO has less parameters than it uses"); } macroLines.push_back(curLine); } codeIterator++; numLine++; } numLine++; MDT.emplace(macroLabel,macroLines); } } //else if (regex_search(curLine,auxMatch,regex("\\bENDMACRO\\b"))) { // canWrite = false; //} else if (hasMacro(curLine)!=";") { string macroFound = hasMacro(curLine); //cout << "Found Macro \"" << macroFound << "\"at line " << numLine << endl; map<string,std::pair<int,int> >::iterator MNTCell = MNT.find(macroFound); map<string,vector<string> >::iterator MDTCell = MDT.find(macroFound); std::pair<int,int> MNTDefs = MNTCell->second; vector<string> auxiliarLines = MDTCell->second; vector<string> paramsToSub; try { string finalLine = curLine.substr(curLine.find(macroFound)+macroFound.length()+1); if (curLine.find(':') != string::npos) { string curLabel = curLine.substr(0,curLine.find(':')+1); outputFile << curLabel << " "; } splitTokenize(finalLine,paramsToSub,","); if (paramsToSub.size() != static_cast<unsigned>(MNTDefs.second)) { addError(numLine,"Syntactical Error: Wrong number of parameters for current MACRO"); } else { for (const string &subLines : auxiliarLines) { string auxSubLine = subLines; for (int j=0;j<MNTDefs.second;j++) { string MDTParamRegex = string("#") + to_string(j+1); auxSubLine = regex_replace(auxSubLine,regex(MDTParamRegex),paramsToSub[j]); } outputFile << auxSubLine << "\n"; } } } catch (std::out_of_range &e) { //cout << "Macro without params: " << e.what() << endl; if (curLine.find(':') != string::npos) { string curLabel = curLine.substr(0,curLine.find(':')+1); outputFile << curLabel << " "; } for (const string &subLines : auxiliarLines) { outputFile << subLines << "\n"; } } } else { if (!canWrite) { canWrite = true; } else { if (curLine.size()) { outputFile << curLine << "\n"; } } } } //cout << "MNT: " << endl; //cout << MNT << endl; //cout << "MDT: " << endl; //cout << MDT << endl; if (this->errorList.size()) { printErrors(); outputFile.close(); remove(fileOut.c_str()); } return this->errorList.size(); }