diff --git a/main.cpp b/main.cpp index f05cf793..d3ff7b0b 100644 --- a/main.cpp +++ b/main.cpp @@ -17,6 +17,7 @@ int main(int argc, char **argv) { bool error = false; const char *filename = nullptr; + bool precompile = false; bool use_istream = false; // Settings.. @@ -66,6 +67,12 @@ int main(int argc, char **argv) quiet = true; found = true; break; + case 'p': + if (std::strcmp(arg, "-pc")==0) { + precompile = true; + found = true; + } + break; case 'e': error_only = true; found = true; @@ -102,6 +109,7 @@ int main(int argc, char **argv) std::cout << " -q Quiet mode (no output)." << std::endl; std::cout << " -is Use std::istream interface." << std::endl; std::cout << " -e Output errors only." << std::endl; + std::cout << " -pc Precompile header." << std::endl; std::exit(0); } @@ -123,15 +131,19 @@ int main(int argc, char **argv) } rawtokens->removeComments(); simplecpp::TokenList outputTokens(files); - std::map filedata; - simplecpp::preprocess(outputTokens, *rawtokens, files, filedata, dui, &outputList); - simplecpp::cleanup(filedata); + if (precompile) { + std::cout << simplecpp::precompileHeader(*rawtokens, files, dui, &outputList); + } else { + std::map filedata; + simplecpp::preprocess(outputTokens, *rawtokens, files, filedata, dui, &outputList); + simplecpp::cleanup(filedata); + } delete rawtokens; rawtokens = nullptr; // Output if (!quiet) { - if (!error_only) + if (!error_only && !precompile) std::cout << outputTokens.stringify() << std::endl; for (const simplecpp::Output &output : outputList) { diff --git a/simplecpp.cpp b/simplecpp.cpp index 2316c42b..f939ff9d 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -1681,6 +1681,13 @@ namespace simplecpp { return invalidHashHash(loc, macroName, "Combining '\\"+ tokenA->str()+ "' and '"+ strAB.substr(tokenA->str().size()) + "' yields universal character '\\" + strAB + "'. This is undefined behavior according to C standard chapter 5.1.1.2, paragraph 4."); } }; + + std::string dump() const { + std::string ret; + for (const Token *tok = nameTokDef; sameline(nameTokDef,tok); tok = tok->next) + ret += "\n" + toString(tok->location.col) + ":" + tok->str(); + return ret.substr(1); + } private: /** Create new token where Token::macro is set for replaced tokens */ Token *newMacroToken(const TokenString &str, const Location &loc, bool replaced, const Token *expandedFromToken=nullptr) const { @@ -3314,8 +3321,10 @@ static std::string getTimeDefine(const struct tm *timep) return std::string("\"").append(buf).append("\""); } -void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) +static void simplecppPreprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond, simplecpp::MacroMap& macros) { + using namespace simplecpp; + #ifdef SIMPLECPP_WINDOWS if (dui.clearIncludeCache) nonExistingFilesCache.clear(); @@ -3347,7 +3356,6 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL std::vector dummy; const bool hasInclude = isCpp17OrLater(dui); - MacroMap macros; for (std::list::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) { const std::string ¯ostr = *it; const std::string::size_type eq = macrostr.find('='); @@ -3792,6 +3800,66 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } } +void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) +{ + MacroMap macroMap; + simplecppPreprocess(output, + rawtokens, + files, + filedata, + dui, + outputList, + macroUsage, + ifCond, + macroMap); +} + + +std::string simplecpp::precompileHeader(const TokenList &rawtokens, std::vector &files, const DUI &dui, OutputList *outputList) +{ + std::map filedata; + simplecpp::TokenList output(files); + std::list macroUsage; + std::list ifCond; + simplecpp::MacroMap macroMap; + simplecppPreprocess(output, + rawtokens, + files, + filedata, + dui, + outputList, + ¯oUsage, + &ifCond, + macroMap); + + std::string ret; + ret = "files\n"; + for (int i = 0; i < files.size(); ++i) + ret += toString(i) + ":" + files[i] + "\n"; + ret += "tokens\n"; + unsigned int fileIndex = 0; + unsigned int line = 0; + unsigned int col = 0; + for (const simplecpp::Token *tok = output.cfront(); tok; tok = tok->next) { + if (tok->location.fileIndex != fileIndex) { + fileIndex = tok->location.fileIndex; + ret += "f" + toString(fileIndex); + } + if (tok->location.line != line) { + line = tok->location.line; + ret += "l" + toString(line); + } + if (tok->location.col != col) { + col = tok->location.col; + ret += "c" + toString(col); + } + ret += ":" + tok->str() + "\n"; + } + for (simplecpp::MacroMap::const_iterator it = macroMap.begin(); it != macroMap.end(); ++it) + ret += "[MACRO]\n" + it->second.dump() + "\n"; + return ret; +} + void simplecpp::cleanup(std::map &filedata) { for (std::map::iterator it = filedata.begin(); it != filedata.end(); ++it) diff --git a/simplecpp.h b/simplecpp.h index f5c69593..fad27cf0 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -365,6 +365,16 @@ namespace simplecpp { */ SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, std::map &filedata, const DUI &dui, OutputList *outputList = nullptr, std::list *macroUsage = nullptr, std::list *ifCond = nullptr); + /** + * Precompile header + * @param rawtokens Raw tokenlist for top sourcefile + * @param files internal data of simplecpp + * @param dui defines, undefs, and include paths + * @param outputList output: list that will receive output messages + * @return precompiled header data + */ + SIMPLECPP_LIB std::string precompileHeader(const TokenList &rawtokens, std::vector &files, const DUI &dui, OutputList *outputList = nullptr); + /** * Deallocate data */