From 18c97c5456802882efced028bc867c625e600799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 21 Jun 2017 12:09:50 +0200 Subject: [PATCH] bump simplecpp --- externals/simplecpp/simplecpp.cpp | 445 ++++++++++++++++++------------ externals/simplecpp/simplecpp.h | 1 + 2 files changed, 271 insertions(+), 175 deletions(-) diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index b50ed418d..f96612204 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -16,6 +16,9 @@ * License along with this library. If not, see . */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +#define NOMINMAX +#endif #include "simplecpp.h" #include @@ -31,7 +34,6 @@ #include #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) -#define NOMINMAX #include #undef ERROR #undef TRUE @@ -134,7 +136,7 @@ void simplecpp::Location::adjust(const std::string &str) for (std::size_t i = 0U; i < str.size(); ++i) { col++; if (str[i] == '\n' || str[i] == '\r') { - col = 0; + col = 1; line++; if (str[i] == '\r' && (i+1)setstr(escapeString(currentToken)); - location.col += currentToken.size() + 2U + 2 * delim.size(); + location.adjust(currentToken); + if (currentToken.find_first_of("\r\n") == std::string::npos) + location.col += 2 + 2 * delim.size(); + else + location.col += 1 + delim.size(); continue; } @@ -1673,48 +1679,106 @@ namespace simplecpp { namespace simplecpp { #ifdef SIMPLECPP_WINDOWS - static bool realFileName(const std::vector &buf, std::ostream &ostr) + bool realFileName(const std::string &f, std::string *result) { - // Detect root directory, see simplecpp:realFileName returns the wrong root path #45 - if ((buf.size()==2 || (buf.size()>2 && buf[2]=='\0')) - && std::isalpha(buf[0]) && buf[1]==':') { - ostr << (char)buf[0]; - ostr << (char)buf[1]; + // If path is a drive letter, uppercase it + if (f.size() == 2 && std::isalpha((unsigned char)f[0]) && f[1] == ':') { + *result = (char)std::toupper((unsigned char)f[0]) + std::string(":"); return true; } + + // are there alpha characters in last subpath? + bool alpha = false; + for (std::string::size_type pos = 1; pos < f.size(); ++pos) { + unsigned char c = f[f.size() - pos]; + if (c=='/' || c=='\\') + break; + if (std::isalpha(c)) { + alpha = true; + break; + } + } + + // do not convert this path if there are no alpha characters (either pointless or cause wrong results for . and ..) + if (!alpha) + return false; + + // Convert char path to CHAR path + std::vector buf(f.size()+1U, 0); + for (unsigned int i = 0; i < f.size(); ++i) + buf[i] = f[i]; + + // Lookup filename or foldername on file system WIN32_FIND_DATAA FindFileData; HANDLE hFind = FindFirstFileA(&buf[0], &FindFileData); if (hFind == INVALID_HANDLE_VALUE) return false; - ostr << FindFileData.cFileName; + *result = FindFileData.cFileName; FindClose(hFind); return true; } + /** Change case in given path to match filesystem */ std::string realFilename(const std::string &f) { - std::vector buf(f.size()+1U, 0); - for (unsigned int i = 0; i < f.size(); ++i) - buf[i] = f[i]; - std::ostringstream ostr; - std::string::size_type sep = 0; - while ((sep = f.find_first_of("\\/", sep + 1U)) != std::string::npos) { - if (sep >= 2 && f.compare(sep-2,2,"..",0,2) == 0) { - ostr << "../"; - continue; + std::string ret; + ret.reserve(f.size()); // this will be the final size + + // Current subpath + std::string subpath; + + for (std::string::size_type pos = 0; pos < f.size(); ++pos) { + unsigned char c = f[pos]; + + // Separator.. add subpath and separator + if (c == '/' || c == '\\') { + // if subpath is empty just add separator + if (subpath.empty()) { + ret += c; + continue; + } + + // Append real filename (proper case) + std::string f2; + if (realFileName(f.substr(0,pos),&f2)) + ret += f2; + else + ret += subpath; + + subpath.clear(); + + // Append separator + ret += c; + } else { + subpath += c; } - buf[sep] = 0; - if (!realFileName(buf,ostr)) - return f; - ostr << '/'; - buf[sep] = '/'; } - if (!realFileName(buf, ostr)) - return f; - return ostr.str(); + + if (!subpath.empty()) { + std::string f2; + if (realFileName(f,&f2)) + ret += f2; + else + ret += subpath; + } + + return ret; } + + bool isAbsolutePath(const std::string &path) + { + if (path.length() >= 3 && path[0] > 0 && std::isalpha(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) + return true; + return path.length() > 1U && (path[0] == '/' || path[0] == '/'); + } + #else #define realFilename(f) f + + bool isAbsolutePath(const std::string &path) + { + return path.length() > 1U && path[0] == '/'; + } #endif /** @@ -1727,6 +1791,14 @@ namespace simplecpp { // replace backslash separators std::replace(path.begin(), path.end(), '\\', '/'); + const bool unc(path.compare(0,2,"//") == 0); + + // replace "//" with "/" + pos = 0; + while ((pos = path.find("//",pos)) != std::string::npos) { + path.erase(pos,1); + } + // remove "./" pos = 0; while ((pos = path.find("./",pos)) != std::string::npos) { @@ -1736,184 +1808,207 @@ namespace simplecpp { pos += 2; } - // remove "xyz/../" - pos = 1U; - while ((pos = path.find("/../", pos)) != std::string::npos) { - const std::string::size_type pos1 = path.rfind('/', pos - 1U); - if (pos1 == std::string::npos) { - path.erase(0,pos+4); - pos = 0; + // remove trailing dot if path ends with "/." + if (endsWith(path,"/.")) + path.erase(path.size()-1); + + // simplify ".." + pos = 1; // don't simplify ".." if path starts with that + while ((pos = path.find("/..", pos)) != std::string::npos) { + // not end of path, then string must be "/../" + if (pos + 3 < path.size() && path[pos + 3] != '/') { + ++pos; + continue; + } + // get previous subpath + const std::string::size_type pos1 = path.rfind('/', pos - 1U) + 1U; + const std::string previousSubPath = path.substr(pos1, pos-pos1); + if (previousSubPath == "..") { + // don't simplify + ++pos; } else { - path.erase(pos1,pos-pos1+3); - pos = std::min((std::string::size_type)1, pos1); + // remove previous subpath and ".." + path.erase(pos1,pos-pos1+4); + if (path.empty()) + path = "."; + // update pos + pos = (pos1 == 0) ? 1 : (pos1 - 1); } } + // Remove trailing '/'? + //if (path.size() > 1 && endsWith(path, "/")) + // path.erase(path.size()-1); + + if (unc) + path = '/' + path; + return realFilename(path); } } -namespace { - /** Evaluate sizeof(type) */ - void simplifySizeof(simplecpp::TokenList &expr, const std::map &sizeOfType) - { - for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { - if (tok->str != "sizeof") - continue; - simplecpp::Token *tok1 = tok->next; - if (!tok1) { - throw std::runtime_error("missed sizeof argument"); - } - simplecpp::Token *tok2 = tok1->next; - if (!tok2) { - throw std::runtime_error("missed sizeof argument"); - } - if (tok1->op == '(') { - tok1 = tok1->next; - while (tok2->op != ')') - tok2 = tok2->next; - } - - std::string type; - for (simplecpp::Token *typeToken = tok1; typeToken != tok2; typeToken = typeToken->next) { - if ((typeToken->str == "unsigned" || typeToken->str == "signed") && typeToken->next->name) - continue; - if (typeToken->str == "*" && type.find('*') != std::string::npos) - continue; - if (!type.empty()) - type += ' '; - type += typeToken->str; - } - - const std::map::const_iterator it = sizeOfType.find(type); - if (it != sizeOfType.end()) - tok->setstr(toString(it->second)); - else - continue; - - tok2 = tok2->next; - while (tok->next != tok2) - expr.deleteToken(tok->next); +/** Evaluate sizeof(type) */ +static void simplifySizeof(simplecpp::TokenList &expr, const std::map &sizeOfType) +{ + for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { + if (tok->str != "sizeof") + continue; + simplecpp::Token *tok1 = tok->next; + if (!tok1) { + throw std::runtime_error("missed sizeof argument"); + } + simplecpp::Token *tok2 = tok1->next; + if (!tok2) { + throw std::runtime_error("missed sizeof argument"); + } + if (tok1->op == '(') { + tok1 = tok1->next; + while (tok2->op != ')') + tok2 = tok2->next; } - } - void simplifyName(simplecpp::TokenList &expr) - { - std::set altop; - altop.insert("and"); - altop.insert("or"); - altop.insert("bitand"); - altop.insert("bitor"); - altop.insert("not"); - altop.insert("not_eq"); - altop.insert("xor"); - for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { - if (tok->name) { - if (altop.find(tok->str) != altop.end()) { - bool alt; - if (tok->str == "not") { - alt = isAlternativeUnaryOp(tok,tok->str); - } else { - alt = isAlternativeBinaryOp(tok,tok->str); - } - if (alt) - continue; + std::string type; + for (simplecpp::Token *typeToken = tok1; typeToken != tok2; typeToken = typeToken->next) { + if ((typeToken->str == "unsigned" || typeToken->str == "signed") && typeToken->next->name) + continue; + if (typeToken->str == "*" && type.find('*') != std::string::npos) + continue; + if (!type.empty()) + type += ' '; + type += typeToken->str; + } + + const std::map::const_iterator it = sizeOfType.find(type); + if (it != sizeOfType.end()) + tok->setstr(toString(it->second)); + else + continue; + + tok2 = tok2->next; + while (tok->next != tok2) + expr.deleteToken(tok->next); + } +} + +static const char * const altopData[] = {"and","or","bitand","bitor","not","not_eq","xor"}; +static const std::set altop(&altopData[0], &altopData[7]); +static void simplifyName(simplecpp::TokenList &expr) +{ + for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { + if (tok->name) { + if (altop.find(tok->str) != altop.end()) { + bool alt; + if (tok->str == "not") { + alt = isAlternativeUnaryOp(tok,tok->str); + } else { + alt = isAlternativeBinaryOp(tok,tok->str); } - tok->setstr("0"); + if (alt) + continue; } + tok->setstr("0"); } } +} - void simplifyNumbers(simplecpp::TokenList &expr) - { - for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { - if (tok->str.size() == 1U) - continue; - if (tok->str.compare(0,2,"0x") == 0) - tok->setstr(toString(stringToULL(tok->str))); - else if (tok->str[0] == '\'') - tok->setstr(toString(tok->str[1] & 0xffU)); - } +static void simplifyNumbers(simplecpp::TokenList &expr) +{ + for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { + if (tok->str.size() == 1U) + continue; + if (tok->str.compare(0,2,"0x") == 0) + tok->setstr(toString(stringToULL(tok->str))); + else if (tok->str[0] == '\'') + tok->setstr(toString(tok->str[1] & 0xffU)); + } +} + +static long long evaluate(simplecpp::TokenList &expr, const std::map &sizeOfType) +{ + simplifySizeof(expr, sizeOfType); + simplifyName(expr); + simplifyNumbers(expr); + expr.constFold(); + // TODO: handle invalid expressions + return expr.cfront() && expr.cfront() == expr.cback() && expr.cfront()->number ? stringToLL(expr.cfront()->str) : 0LL; +} + +static const simplecpp::Token *gotoNextLine(const simplecpp::Token *tok) +{ + const unsigned int line = tok->location.line; + const unsigned int file = tok->location.fileIndex; + while (tok && tok->location.line == line && tok->location.fileIndex == file) + tok = tok->next; + return tok; +} + +static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader) +{ + if (simplecpp::isAbsolutePath(header)) { + f.open(header.c_str()); + return f.is_open() ? simplecpp::simplifyPath(header) : ""; } - long long evaluate(simplecpp::TokenList &expr, const std::map &sizeOfType) - { - simplifySizeof(expr, sizeOfType); - simplifyName(expr); - simplifyNumbers(expr); - expr.constFold(); - // TODO: handle invalid expressions - return expr.cfront() && expr.cfront() == expr.cback() && expr.cfront()->number ? stringToLL(expr.cfront()->str) : 0LL; - } - - const simplecpp::Token *gotoNextLine(const simplecpp::Token *tok) - { - const unsigned int line = tok->location.line; - const unsigned int file = tok->location.fileIndex; - while (tok && tok->location.line == line && tok->location.fileIndex == file) - tok = tok->next; - return tok; - } - - std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader) - { - if (!systemheader) { - if (sourcefile.find_first_of("\\/") != std::string::npos) { - const std::string s = sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header; - f.open(s.c_str()); - if (f.is_open()) - return simplecpp::simplifyPath(s); - } else { - f.open(header.c_str()); - if (f.is_open()) - return simplecpp::simplifyPath(header); - } - } - - for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { - std::string s = *it; - if (!s.empty() && s[s.size()-1U]!='/' && s[s.size()-1U]!='\\') - s += '/'; - s += header; + if (!systemheader) { + if (sourcefile.find_first_of("\\/") != std::string::npos) { + const std::string s = sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header; f.open(s.c_str()); if (f.is_open()) return simplecpp::simplifyPath(s); + } else { + f.open(header.c_str()); + if (f.is_open()) + return simplecpp::simplifyPath(header); } - - return ""; } - std::string getFileName(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) - { - if (!systemheader) { - if (sourcefile.find_first_of("\\/") != std::string::npos) { - const std::string s(simplecpp::simplifyPath(sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header)); - if (filedata.find(s) != filedata.end()) - return s; - } else { - std::string s = simplecpp::simplifyPath(header); - if (filedata.find(s) != filedata.end()) - return s; - } - } + for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { + std::string s = *it; + if (!s.empty() && s[s.size()-1U]!='/' && s[s.size()-1U]!='\\') + s += '/'; + s += header; + f.open(s.c_str()); + if (f.is_open()) + return simplecpp::simplifyPath(s); + } - for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { - std::string s = *it; - if (!s.empty() && s[s.size()-1U]!='/' && s[s.size()-1U]!='\\') - s += '/'; - s += header; - s = simplecpp::simplifyPath(s); + return ""; +} + +static std::string getFileName(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) +{ + if (simplecpp::isAbsolutePath(header)) { + return (filedata.find(header) != filedata.end()) ? simplecpp::simplifyPath(header) : ""; + } + + if (!systemheader) { + if (sourcefile.find_first_of("\\/") != std::string::npos) { + const std::string s(simplecpp::simplifyPath(sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header)); + if (filedata.find(s) != filedata.end()) + return s; + } else { + std::string s = simplecpp::simplifyPath(header); if (filedata.find(s) != filedata.end()) return s; } - - return ""; } - bool hasFile(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) - { - return !getFileName(filedata, sourcefile, header, dui, systemheader).empty(); + for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { + std::string s = *it; + if (!s.empty() && s[s.size()-1U]!='/' && s[s.size()-1U]!='\\') + s += '/'; + s += header; + s = simplecpp::simplifyPath(s); + if (filedata.find(s) != filedata.end()) + return s; } + + return ""; +} + +static bool hasFile(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) +{ + return !getFileName(filedata, sourcefile, header, dui, systemheader).empty(); } std::map simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &fileNumbers, const simplecpp::DUI &dui, simplecpp::OutputList *outputList) diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 76ee90d8e..cefd3d1cf 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -268,6 +268,7 @@ namespace simplecpp { }; struct SIMPLECPP_LIB DUI { + DUI() {} std::list defines; std::set undefined; std::list includePaths;