Preprocessor: Added elif handling. Check for invalid characters
This commit is contained in:
parent
8d2cdbc09f
commit
e798a4a419
2
main.cpp
2
main.cpp
|
@ -239,7 +239,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
std::ifstream fin( fname.c_str() );
|
||||
std::map<std::string, std::string> code;
|
||||
preprocess(fin, code);
|
||||
preprocess(fin, code, fname);
|
||||
for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
|
||||
CppCheck(it->second, filenames[c].c_str(), c);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
|
||||
#include "preprocessor.h"
|
||||
#include "CommonCheck.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
|
@ -44,7 +45,7 @@ static std::string getcode(const std::string &filedata, std::string cfg);
|
|||
* \param istr The (file/string) stream to read from.
|
||||
* \param result The map that will get the results
|
||||
*/
|
||||
void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
|
||||
void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string filename)
|
||||
{
|
||||
// Get filedata from stream..
|
||||
bool ignoreSpace = true;
|
||||
|
@ -52,6 +53,14 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
|
|||
std::ostringstream code;
|
||||
for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get())
|
||||
{
|
||||
if ( ch < 0 )
|
||||
{
|
||||
// Bad content..
|
||||
errout << "[" << filename << "] Bad character found: " << int((unsigned char)ch) << std::endl;
|
||||
result.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace assorted special chars with spaces..
|
||||
if ( ch < 0 )
|
||||
ch = ' ';
|
||||
|
@ -160,7 +169,7 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
|
|||
static std::string getdef(std::string line, bool def)
|
||||
{
|
||||
// If def is true, the line must start with "#ifdef"
|
||||
if ( def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 )
|
||||
if ( def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0 )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
@ -198,6 +207,8 @@ static std::list<std::string> getcfgs( const std::string &filedata )
|
|||
std::string def = getdef(line, true) + getdef(line, false);
|
||||
if (!def.empty())
|
||||
{
|
||||
if ( ! deflist.empty() && line.find("#elif ") == 0 )
|
||||
deflist.pop_back();
|
||||
deflist.push_back(def);
|
||||
def = "";
|
||||
for ( std::list<std::string>::const_iterator it = deflist.begin(); it != deflist.end(); ++it)
|
||||
|
@ -261,6 +272,7 @@ static std::string getcode(const std::string &filedata, std::string cfg)
|
|||
std::ostringstream ret;
|
||||
|
||||
std::list<bool> matching_ifdef;
|
||||
std::list<bool> matched_ifdef;
|
||||
|
||||
std::istringstream istr(filedata);
|
||||
std::string line;
|
||||
|
@ -269,17 +281,47 @@ static std::string getcode(const std::string &filedata, std::string cfg)
|
|||
std::string def = getdef( line, true );
|
||||
std::string ndef = getdef( line, false );
|
||||
|
||||
if ( ! def.empty() )
|
||||
if ( line.find("#elif ") == 0 )
|
||||
{
|
||||
if ( matched_ifdef.back() )
|
||||
{
|
||||
matching_ifdef.back() = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( match_cfg_def(cfg, def) )
|
||||
{
|
||||
matching_ifdef.back() = true;
|
||||
matched_ifdef.back() = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if ( ! def.empty() )
|
||||
{
|
||||
matching_ifdef.push_back( match_cfg_def(cfg, def) );
|
||||
matched_ifdef.push_back( matching_ifdef.back() );
|
||||
}
|
||||
|
||||
else if ( ! ndef.empty() )
|
||||
{
|
||||
matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) );
|
||||
matched_ifdef.push_back( matching_ifdef.back() );
|
||||
}
|
||||
|
||||
else if ( line == "#else" && !matching_ifdef.empty() )
|
||||
matching_ifdef.back() = ! matching_ifdef.back();
|
||||
else if ( line == "#else" )
|
||||
{
|
||||
if ( ! matched_ifdef.empty() )
|
||||
matching_ifdef.back() = ! matched_ifdef.back();
|
||||
}
|
||||
|
||||
else if ( line == "#endif" && !matching_ifdef.empty() )
|
||||
matching_ifdef.pop_back();
|
||||
else if ( line == "#endif" )
|
||||
{
|
||||
if ( ! matched_ifdef.empty() )
|
||||
matched_ifdef.pop_back();
|
||||
if ( ! matching_ifdef.empty() )
|
||||
matching_ifdef.pop_back();
|
||||
}
|
||||
|
||||
bool match = true;
|
||||
for ( std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it )
|
||||
|
@ -289,6 +331,7 @@ static std::string getcode(const std::string &filedata, std::string cfg)
|
|||
|
||||
if ( line.find("#if") == 0 ||
|
||||
line.find("#else") == 0 ||
|
||||
line.find("#elif") == 0 ||
|
||||
line.find("#endif") == 0 )
|
||||
line = "";
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <string>
|
||||
|
||||
|
||||
void preprocess(std::istream &istr, std::map<std::string, std::string> &result);
|
||||
void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,8 @@ private:
|
|||
TEST_CASE( if0 );
|
||||
TEST_CASE( if1 );
|
||||
|
||||
TEST_CASE( elif );
|
||||
|
||||
TEST_CASE( include1 );
|
||||
|
||||
TEST_CASE( if_cond1 );
|
||||
|
@ -325,6 +327,30 @@ private:
|
|||
}
|
||||
|
||||
|
||||
void elif()
|
||||
{
|
||||
const char filedata[] = "#if DEF1\n"
|
||||
"ABC\n"
|
||||
"#elif DEF2\n"
|
||||
"DEF\n"
|
||||
"#endif\n";
|
||||
|
||||
// Expected result..
|
||||
std::map<std::string, std::string> expected;
|
||||
expected[""] = "\n\n\n\n\n";
|
||||
expected["DEF1"] = "\nABC\n\n\n\n";
|
||||
expected["DEF2"] = "\n\n\nDEF\n\n";
|
||||
|
||||
// Preprocess => actual result..
|
||||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
preprocess( istr, actual );
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void include1()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue