bump simplecpp

This commit is contained in:
Daniel Marjamäki 2019-03-10 08:47:27 +01:00
parent 3eb5de756c
commit 93194f47a1
2 changed files with 157 additions and 45 deletions

View File

@ -327,6 +327,15 @@ static void ungetChar(std::istream &istr, unsigned int bom)
istr.unget(); istr.unget();
} }
static unsigned char prevChar(std::istream &istr, unsigned int bom)
{
ungetChar(istr, bom);
ungetChar(istr, bom);
unsigned char c = readChar(istr, bom);
readChar(istr, bom);
return c;
}
static unsigned short getAndSkipBOM(std::istream &istr) static unsigned short getAndSkipBOM(std::istream &istr)
{ {
const int ch1 = istr.peek(); const int ch1 = istr.peek();
@ -384,9 +393,10 @@ static void portabilityBackslash(simplecpp::OutputList *outputList, const std::v
outputList->push_back(err); outputList->push_back(err);
} }
static bool isRawStringId(const std::string &str) static bool isStringLiteralPrefix(const std::string &str)
{ {
return str == "R" || str == "uR" || str == "UR" || str == "LR" || str == "u8R"; return str == "u" || str == "U" || str == "L" || str == "u8" ||
str == "R" || str == "uR" || str == "UR" || str == "LR" || str == "u8R";
} }
void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filename, OutputList *outputList) void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filename, OutputList *outputList)
@ -480,7 +490,7 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
prev = ch; prev = ch;
ch = readChar(istr, bom); ch = readChar(istr, bom);
} }
istr.unget(); ungetChar(istr, bom);
push_back(new Token(currentToken, location)); push_back(new Token(currentToken, location));
location.adjust(currentToken); location.adjust(currentToken);
continue; continue;
@ -512,7 +522,7 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
++multiline; ++multiline;
currentToken.erase(currentToken.size() - 1U); currentToken.erase(currentToken.size() - 1U);
} else { } else {
istr.unget(); ungetChar(istr, bom);
} }
} }
@ -545,9 +555,14 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
// string / char literal // string / char literal
else if (ch == '\"' || ch == '\'') { else if (ch == '\"' || ch == '\'') {
// C++11 raw string literal if (cback() && cback()->name && !std::isspace(prevChar(istr, bom)) && (isStringLiteralPrefix(cback()->str()))) {
if (ch == '\"' && cback() && cback()->name && isRawStringId(cback()->str())) {
std::string delim; std::string delim;
currentToken = ch;
bool hasR = *cback()->str().rbegin() == 'R';
std::string prefix = cback()->str();
if (hasR) {
prefix.resize(prefix.size() - 1);
delim = ")";
ch = readChar(istr,bom); ch = readChar(istr,bom);
while (istr.good() && ch != '(' && ch != '\n') { while (istr.good() && ch != '(' && ch != '\n') {
delim += ch; delim += ch;
@ -556,20 +571,18 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
if (!istr.good() || ch == '\n') if (!istr.good() || ch == '\n')
// TODO report // TODO report
return; return;
currentToken = '\"'; }
const std::string endOfRawString(')' + delim + '\"'); const std::string endOfRawString(delim + currentToken);
while (istr.good() && !endsWith(currentToken, endOfRawString)) while (istr.good() && !(endsWith(currentToken, endOfRawString) && currentToken.size() > 1))
currentToken += readChar(istr,bom); currentToken += readChar(istr,bom);
if (!endsWith(currentToken, endOfRawString)) if (!endsWith(currentToken, endOfRawString))
// TODO report // TODO report
return; return;
currentToken.erase(currentToken.size() - endOfRawString.size(), endOfRawString.size() - 1U); currentToken.erase(currentToken.size() - endOfRawString.size(), endOfRawString.size() - 1U);
if (cback()->op == 'R') if (hasR)
back()->setstr(escapeString(currentToken)); currentToken = escapeString(currentToken);
else { currentToken.insert(0, prefix);
back()->setstr(cback()->str().substr(0, cback()->str().size() - 1)); back()->setstr(currentToken);
push_back(new Token(currentToken, location)); // push string without newlines
}
location.adjust(currentToken); location.adjust(currentToken);
if (currentToken.find_first_of("\r\n") == std::string::npos) if (currentToken.find_first_of("\r\n") == std::string::npos)
location.col += 2 + 2 * delim.size(); location.col += 2 + 2 * delim.size();
@ -578,7 +591,7 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
continue; continue;
} }
currentToken = readUntil(istr,location,ch,ch,outputList); currentToken = readUntil(istr,location,ch,ch,outputList,bom);
if (currentToken.size() < 2U) if (currentToken.size() < 2U)
// TODO report // TODO report
return; return;
@ -607,7 +620,7 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
} }
if (currentToken == "<" && lastLine() == "# include") { if (currentToken == "<" && lastLine() == "# include") {
currentToken = readUntil(istr, location, '<', '>', outputList); currentToken = readUntil(istr, location, '<', '>', outputList, bom);
if (currentToken.size() < 2U) if (currentToken.size() < 2U)
return; return;
} }
@ -1045,7 +1058,7 @@ void simplecpp::TokenList::removeComments()
} }
} }
std::string simplecpp::TokenList::readUntil(std::istream &istr, const Location &location, const char start, const char end, OutputList *outputList) std::string simplecpp::TokenList::readUntil(std::istream &istr, const Location &location, const char start, const char end, OutputList *outputList, unsigned int bom)
{ {
std::string ret; std::string ret;
ret += start; ret += start;
@ -1053,7 +1066,7 @@ std::string simplecpp::TokenList::readUntil(std::istream &istr, const Location &
bool backslash = false; bool backslash = false;
char ch = 0; char ch = 0;
while (ch != end && ch != '\r' && ch != '\n' && istr.good()) { while (ch != end && ch != '\r' && ch != '\n' && istr.good()) {
ch = (unsigned char)istr.get(); ch = readChar(istr, bom);
if (backslash && ch == '\n') { if (backslash && ch == '\n') {
ch = 0; ch = 0;
backslash = false; backslash = false;
@ -1062,7 +1075,7 @@ std::string simplecpp::TokenList::readUntil(std::istream &istr, const Location &
backslash = false; backslash = false;
ret += ch; ret += ch;
if (ch == '\\') { if (ch == '\\') {
const char next = (unsigned char)istr.get(); const char next = readChar(istr, bom);
if (next == '\r' || next == '\n') { if (next == '\r' || next == '\n') {
ret.erase(ret.size()-1U); ret.erase(ret.size()-1U);
backslash = (next == '\r'); backslash = (next == '\r');
@ -1845,6 +1858,39 @@ namespace simplecpp {
}; };
} }
namespace simplecpp {
std::string convertCygwinToWindowsPath(const std::string &cygwinPath)
{
std::string windowsPath;
std::string::size_type pos = 0;
if (cygwinPath.size() >= 11 && startsWith(cygwinPath, "/cygdrive/")) {
unsigned char driveLetter = cygwinPath[10];
if (std::isalpha(driveLetter)) {
if (cygwinPath.size() == 11) {
windowsPath = toupper(driveLetter);
windowsPath += ":\\"; // volume root directory
pos = 11;
} else if (cygwinPath[11] == '/') {
windowsPath = toupper(driveLetter);
windowsPath += ":";
pos = 11;
}
}
}
for (; pos < cygwinPath.size(); ++pos) {
unsigned char c = cygwinPath[pos];
if (c == '/')
c = '\\';
windowsPath += c;
}
return windowsPath;
}
}
#ifdef SIMPLECPP_WINDOWS #ifdef SIMPLECPP_WINDOWS
class ScopedLock { class ScopedLock {
@ -1875,7 +1921,7 @@ public:
DeleteCriticalSection(&m_criticalSection); DeleteCriticalSection(&m_criticalSection);
} }
bool getRealPathFromCache(const std::string& path, std::string* returnPath) { bool getCacheEntry(const std::string& path, std::string* returnPath) {
ScopedLock lock(m_criticalSection); ScopedLock lock(m_criticalSection);
std::map<std::string, std::string>::iterator it = m_fileMap.find(path); std::map<std::string, std::string>::iterator it = m_fileMap.find(path);
@ -1902,9 +1948,9 @@ static bool realFileName(const std::string &f, std::string *result)
{ {
// are there alpha characters in last subpath? // are there alpha characters in last subpath?
bool alpha = false; bool alpha = false;
for (std::string::size_type pos = 1; pos < f.size(); ++pos) { for (std::string::size_type pos = 1; pos <= f.size(); ++pos) {
unsigned char c = f[f.size() - pos]; unsigned char c = f[f.size() - pos];
if (c=='/' || c=='\\') if (c == '/' || c == '\\')
break; break;
if (std::isalpha(c)) { if (std::isalpha(c)) {
alpha = true; alpha = true;
@ -1917,9 +1963,16 @@ static bool realFileName(const std::string &f, std::string *result)
return false; return false;
// Lookup filename or foldername on file system // Lookup filename or foldername on file system
if (!realFileNameMap.getRealPathFromCache(f, result)) { if (!realFileNameMap.getCacheEntry(f, result)) {
WIN32_FIND_DATAA FindFileData; WIN32_FIND_DATAA FindFileData;
#ifdef __CYGWIN__
std::string fConverted = simplecpp::convertCygwinToWindowsPath(f);
HANDLE hFind = FindFirstFileExA(fConverted.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0);
#else
HANDLE hFind = FindFirstFileExA(f.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0); HANDLE hFind = FindFirstFileExA(f.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0);
#endif
if (INVALID_HANDLE_VALUE == hFind) if (INVALID_HANDLE_VALUE == hFind)
return false; return false;
@ -1930,12 +1983,14 @@ static bool realFileName(const std::string &f, std::string *result)
return true; return true;
} }
static RealFileNameMap realFilePathMap;
/** Change case in given path to match filesystem */ /** Change case in given path to match filesystem */
static std::string realFilename(const std::string &f) static std::string realFilename(const std::string &f)
{ {
std::string ret; std::string ret;
ret.reserve(f.size()); // this will be the final size ret.reserve(f.size()); // this will be the final size
if (realFileNameMap.getRealPathFromCache(f, &ret)) if (realFilePathMap.getCacheEntry(f, &ret))
return ret; return ret;
// Current subpath // Current subpath
@ -1952,9 +2007,12 @@ static std::string realFilename(const std::string &f)
continue; continue;
} }
bool isDriveSpecification =
(pos == 2 && subpath.size() == 2 && std::isalpha(subpath[0]) && subpath[1] == ':');
// Append real filename (proper case) // Append real filename (proper case)
std::string f2; std::string f2;
if (realFileName(f.substr(0,pos),&f2)) if (!isDriveSpecification && realFileName(f.substr(0, pos), &f2))
ret += f2; ret += f2;
else else
ret += subpath; ret += subpath;
@ -1976,7 +2034,7 @@ static std::string realFilename(const std::string &f)
ret += subpath; ret += subpath;
} }
realFileNameMap.addToCache(f, ret); realFilePathMap.addToCache(f, ret);
return ret; return ret;
} }
@ -2164,23 +2222,73 @@ static const simplecpp::Token *gotoNextLine(const simplecpp::Token *tok)
return tok; return tok;
} }
#ifdef SIMPLECPP_WINDOWS
class NonExistingFilesCache {
public:
NonExistingFilesCache() {
InitializeCriticalSection(&m_criticalSection);
}
~NonExistingFilesCache() {
DeleteCriticalSection(&m_criticalSection);
}
bool contains(const std::string& path) {
ScopedLock lock(m_criticalSection);
return (m_pathSet.find(path) != m_pathSet.end());
}
void add(const std::string& path) {
ScopedLock lock(m_criticalSection);
m_pathSet.insert(path);
}
private:
std::set<std::string> m_pathSet;
CRITICAL_SECTION m_criticalSection;
};
static NonExistingFilesCache nonExistingFilesCache;
#endif
static std::string _openHeader(std::ifstream &f, const std::string &path)
{
#ifdef SIMPLECPP_WINDOWS
std::string simplePath = simplecpp::simplifyPath(path);
if (nonExistingFilesCache.contains(simplePath))
return ""; // file is known not to exist, skip expensive file open call
f.open(simplePath.c_str());
if (f.is_open())
return simplePath;
else {
nonExistingFilesCache.add(simplePath);
return "";
}
#else
f.open(path.c_str());
return f.is_open() ? simplecpp::simplifyPath(path) : "";
#endif
}
static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader) static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader)
{ {
if (isAbsolutePath(header)) { if (isAbsolutePath(header)) {
f.open(header.c_str()); return _openHeader(f, header);
return f.is_open() ? simplecpp::simplifyPath(header) : "";
} }
if (!systemheader) { if (!systemheader) {
if (sourcefile.find_first_of("\\/") != std::string::npos) { if (sourcefile.find_first_of("\\/") != std::string::npos) {
const std::string s = sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header; const std::string s = sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header;
f.open(s.c_str()); std::string simplePath = _openHeader(f, s);
if (f.is_open()) if (!simplePath.empty())
return simplecpp::simplifyPath(s); return simplePath;
} else { } else {
f.open(header.c_str()); std::string simplePath = _openHeader(f, header);
if (f.is_open()) if (!simplePath.empty())
return simplecpp::simplifyPath(header); return simplePath;
} }
} }
@ -2189,9 +2297,10 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const
if (!s.empty() && s[s.size()-1U]!='/' && s[s.size()-1U]!='\\') if (!s.empty() && s[s.size()-1U]!='/' && s[s.size()-1U]!='\\')
s += '/'; s += '/';
s += header; s += header;
f.open(s.c_str());
if (f.is_open()) std::string simplePath = _openHeader(f, s);
return simplecpp::simplifyPath(s); if (!simplePath.empty())
return simplePath;
} }
return ""; return "";

View File

@ -258,7 +258,7 @@ namespace simplecpp {
void constFoldLogicalOp(Token *tok); void constFoldLogicalOp(Token *tok);
void constFoldQuestionOp(Token **tok1); void constFoldQuestionOp(Token **tok1);
std::string readUntil(std::istream &istr, const Location &location, const char start, const char end, OutputList *outputList); std::string readUntil(std::istream &istr, const Location &location, const char start, const char end, OutputList *outputList, unsigned int bom);
std::string lastLine(int maxsize=100000) const; std::string lastLine(int maxsize=100000) const;
@ -312,6 +312,9 @@ namespace simplecpp {
/** Simplify path */ /** Simplify path */
SIMPLECPP_LIB std::string simplifyPath(std::string path); SIMPLECPP_LIB std::string simplifyPath(std::string path);
/** Convert Cygwin path to Windows path */
SIMPLECPP_LIB std::string convertCygwinToWindowsPath(const std::string &cygwinPath);
} }
#endif #endif