Preprocessor: Started working on new preprocessing that uses -D information better. Ticket: #2131
This commit is contained in:
parent
de8eb48a5c
commit
bf0386c938
|
@ -1669,6 +1669,114 @@ Preprocessor::HeaderTypes Preprocessor::getHeaderFileName(std::string &str)
|
|||
return SystemHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to open header
|
||||
* @param filename header name (in/out)
|
||||
* @param includePaths paths where to look for the file
|
||||
* @param fin file input stream (in/out)
|
||||
* @return if file is opened then true is returned
|
||||
*/
|
||||
static bool openHeader(std::string &filename, const std::list<std::string> &includePaths, const std::string &filePath, std::ifstream &fin)
|
||||
{
|
||||
std::list<std::string> includePaths2(includePaths);
|
||||
includePaths2.push_front("");
|
||||
|
||||
for (std::list<std::string>::const_iterator iter = includePaths2.begin(); iter != includePaths2.end(); ++iter) {
|
||||
const std::string nativePath(Path::toNativeSeparators(*iter));
|
||||
fin.open((nativePath + filename).c_str());
|
||||
if (fin.is_open()) {
|
||||
filename = nativePath + filename;
|
||||
return true;
|
||||
}
|
||||
fin.clear();
|
||||
}
|
||||
|
||||
fin.open(filePath + filename);
|
||||
if (fin.is_open()) {
|
||||
filename = filePath + filename;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string Preprocessor::handleIncludes(const std::string &code, const std::string &filePath, const std::list<std::string> &includePaths, std::map<std::string,int> &defs)
|
||||
{
|
||||
const std::string path(filePath.substr(0, 1 + filePath.find_last_of("\\/")));
|
||||
|
||||
unsigned int indent = 0;
|
||||
unsigned int indentmatch = 0;
|
||||
|
||||
std::ostringstream ostr;
|
||||
std::istringstream istr(code);
|
||||
std::string line;
|
||||
while (std::getline(istr,line)) {
|
||||
if (line.compare(0,9,"#include ")==0) {
|
||||
std::string filename(line.substr(9));
|
||||
|
||||
const HeaderTypes headerType = getHeaderFileName(filename);
|
||||
if (headerType == NoHeader) {
|
||||
ostr << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// try to open file
|
||||
std::ifstream fin;
|
||||
if (!openHeader(filename, includePaths, headerType == UserHeader ? path : std::string(""), fin)) {
|
||||
ostr << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
ostr << "#file " << filename << "\n"
|
||||
<< handleIncludes(read(fin, filename, NULL), filename, includePaths, defs) << std::endl
|
||||
<< "#endfile";
|
||||
} else if (line.compare(0,7,"#ifdef ") == 0) {
|
||||
if (indent == indentmatch && defs.find(getdef(line,true)) != defs.end())
|
||||
indentmatch++;
|
||||
++indent;
|
||||
} else if (line.compare(0,8,"#ifndef ") == 0) {
|
||||
if (indent == indentmatch && defs.find(getdef(line,false)) == defs.end())
|
||||
indentmatch++;
|
||||
++indent;
|
||||
} else if (line.compare(0,5,"#else") == 0) {
|
||||
if (indentmatch == indent)
|
||||
indentmatch = indent - 1;
|
||||
else if (indentmatch == indent - 1)
|
||||
indentmatch = indent;
|
||||
} else if (line == "#endif") {
|
||||
--indent;
|
||||
if (indentmatch > indent)
|
||||
indentmatch = indent;
|
||||
} else if (indentmatch == indent) {
|
||||
if (line.compare(0,8,"#define ")==0) {
|
||||
// no value
|
||||
if (line.find_first_of("( ", 8) == std::string::npos)
|
||||
defs[line.substr(8)] = 1;
|
||||
|
||||
// define value
|
||||
else if (line.find("(") == std::string::npos) {
|
||||
const std::string::size_type pos = line.find(" ", 8);
|
||||
const std::string val(line.substr(pos + 1));
|
||||
int i;
|
||||
std::istringstream istr(val);
|
||||
istr >> i;
|
||||
defs[line.substr(8,pos-8)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
ostr << line;
|
||||
}
|
||||
}
|
||||
|
||||
// A line has been read..
|
||||
ostr << "\n";
|
||||
}
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
|
||||
void Preprocessor::handleIncludes(std::string &code, const std::string &filePath, const std::list<std::string> &includePaths)
|
||||
{
|
||||
|
@ -1708,31 +1816,8 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath
|
|||
|
||||
// filename contains now a file name e.g. "menu.h"
|
||||
std::string processedFile;
|
||||
bool fileOpened = false;
|
||||
std::ifstream fin;
|
||||
{
|
||||
std::list<std::string> includePaths2(includePaths);
|
||||
includePaths2.push_front("");
|
||||
for (std::list<std::string>::const_iterator iter = includePaths2.begin(); iter != includePaths2.end(); ++iter) {
|
||||
const std::string nativePath(Path::toNativeSeparators(*iter));
|
||||
fin.open((nativePath + filename).c_str());
|
||||
if (fin.is_open()) {
|
||||
filename = nativePath + filename;
|
||||
fileOpened = true;
|
||||
break;
|
||||
}
|
||||
|
||||
fin.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (headerType == UserHeader && !fileOpened) {
|
||||
fin.open((paths.back() + filename).c_str());
|
||||
if (fin.is_open()) {
|
||||
filename = paths.back() + filename;
|
||||
fileOpened = true;
|
||||
}
|
||||
}
|
||||
const bool fileOpened(openHeader(filename, includePaths, headerType == UserHeader ? paths.back() : std::string(""), fin));
|
||||
|
||||
if (fileOpened) {
|
||||
filename = Path::simplifyPath(filename.c_str());
|
||||
|
|
|
@ -209,6 +209,16 @@ public:
|
|||
|
||||
static void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings);
|
||||
|
||||
/**
|
||||
* handle includes for a specific configuration
|
||||
* @param code code in string
|
||||
* @param filePath filename of code
|
||||
* @param includePaths Paths where headers might be
|
||||
* @param defs defines (only values)
|
||||
* \return resulting string
|
||||
*/
|
||||
std::string handleIncludes(const std::string &code, const std::string &filePath, const std::list<std::string> &includePaths, std::map<std::string,int> &defs);
|
||||
|
||||
private:
|
||||
void missingInclude(const std::string &filename, unsigned int linenr, const std::string &header, bool userheader);
|
||||
|
||||
|
|
|
@ -226,6 +226,9 @@ private:
|
|||
// Test Preprocessor::simplifyCondition
|
||||
TEST_CASE(simplifyCondition);
|
||||
TEST_CASE(invalidElIf); // #2942 segfault
|
||||
|
||||
// Test Preprocessor::handleIncludes (defines are given)
|
||||
TEST_CASE(handleIncludes_def);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2820,6 +2823,61 @@ private:
|
|||
const std::string actual = Preprocessor::getcode(code, "TEST", "test.c", &settings, this);
|
||||
ASSERT_EQUALS("\n", actual);
|
||||
}
|
||||
|
||||
void handleIncludes_def() {
|
||||
const std::string filePath("test.c");
|
||||
const std::list<std::string> includePaths;
|
||||
std::map<std::string,int> defs;
|
||||
Preprocessor preprocessor;
|
||||
|
||||
// ifdef
|
||||
{
|
||||
defs.clear();
|
||||
defs["A"] = 1;
|
||||
{
|
||||
const std::string code("#ifdef A\n123\n#endif\n");
|
||||
const std::string actual(preprocessor.handleIncludes(code,filePath,includePaths,defs));
|
||||
ASSERT_EQUALS("\n123\n\n", actual);
|
||||
}{
|
||||
const std::string code("#ifdef B\n123\n#endif\n");
|
||||
const std::string actual(preprocessor.handleIncludes(code,filePath,includePaths,defs));
|
||||
ASSERT_EQUALS("\n\n\n", actual);
|
||||
}
|
||||
}
|
||||
|
||||
// ifndef
|
||||
{
|
||||
defs.clear();
|
||||
defs["A"] = 1;
|
||||
{
|
||||
const std::string code("#ifndef A\n123\n#endif\n");
|
||||
const std::string actual(preprocessor.handleIncludes(code,filePath,includePaths,defs));
|
||||
ASSERT_EQUALS("\n\n\n", actual);
|
||||
}{
|
||||
const std::string code("#ifndef B\n123\n#endif\n");
|
||||
const std::string actual(preprocessor.handleIncludes(code,filePath,includePaths,defs));
|
||||
ASSERT_EQUALS("\n123\n\n", actual);
|
||||
}
|
||||
}
|
||||
|
||||
// define - ifndef
|
||||
{
|
||||
defs.clear();
|
||||
const std::string code("#ifndef X\n#define X\n123\n#endif\n"
|
||||
"#ifndef X\n#define X\n123\n#endif\n");
|
||||
const std::string actual(preprocessor.handleIncludes(code,filePath,includePaths,defs));
|
||||
ASSERT_EQUALS("\n\n123\n\n" "\n\n\n\n", actual);
|
||||
}
|
||||
/*
|
||||
// define X 123 - #if
|
||||
{
|
||||
defs.clear();
|
||||
const std::string code("#define X 123\n#if X==123\n456\n#endif\n");
|
||||
const std::string actual(preprocessor.handleIncludes(code,filePath,includePaths,defs));
|
||||
ASSERT_EQUALS("\n\n456\n\n", actual);
|
||||
}
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestPreprocessor)
|
||||
|
|
Loading…
Reference in New Issue