Preprocessor: Added elif handling. Check for invalid characters

This commit is contained in:
Daniel Marjamäki 2008-10-31 18:52:47 +00:00
parent 8d2cdbc09f
commit e798a4a419
4 changed files with 78 additions and 9 deletions

View File

@ -239,7 +239,7 @@ int main(int argc, char* argv[])
std::ifstream fin( fname.c_str() ); std::ifstream fin( fname.c_str() );
std::map<std::string, std::string> code; 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 ) for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
CppCheck(it->second, filenames[c].c_str(), c); CppCheck(it->second, filenames[c].c_str(), c);

View File

@ -18,6 +18,7 @@
#include "preprocessor.h" #include "preprocessor.h"
#include "CommonCheck.h"
#include <algorithm> #include <algorithm>
#include <list> #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 istr The (file/string) stream to read from.
* \param result The map that will get the results * \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.. // Get filedata from stream..
bool ignoreSpace = true; bool ignoreSpace = true;
@ -52,6 +53,14 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
std::ostringstream code; std::ostringstream code;
for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get()) 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.. // Replace assorted special chars with spaces..
if ( ch < 0 ) if ( ch < 0 )
ch = ' '; 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) static std::string getdef(std::string line, bool def)
{ {
// If def is true, the line must start with "#ifdef" // 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 ""; return "";
} }
@ -198,6 +207,8 @@ static std::list<std::string> getcfgs( const std::string &filedata )
std::string def = getdef(line, true) + getdef(line, false); std::string def = getdef(line, true) + getdef(line, false);
if (!def.empty()) if (!def.empty())
{ {
if ( ! deflist.empty() && line.find("#elif ") == 0 )
deflist.pop_back();
deflist.push_back(def); deflist.push_back(def);
def = ""; def = "";
for ( std::list<std::string>::const_iterator it = deflist.begin(); it != deflist.end(); ++it) 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::ostringstream ret;
std::list<bool> matching_ifdef; std::list<bool> matching_ifdef;
std::list<bool> matched_ifdef;
std::istringstream istr(filedata); std::istringstream istr(filedata);
std::string line; 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 def = getdef( line, true );
std::string ndef = getdef( line, false ); 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) ); matching_ifdef.push_back( match_cfg_def(cfg, def) );
matched_ifdef.push_back( matching_ifdef.back() );
}
else if ( ! ndef.empty() ) else if ( ! ndef.empty() )
{
matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) ); matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) );
matched_ifdef.push_back( matching_ifdef.back() );
}
else if ( line == "#else" && !matching_ifdef.empty() ) else if ( line == "#else" )
matching_ifdef.back() = ! matching_ifdef.back(); {
if ( ! matched_ifdef.empty() )
matching_ifdef.back() = ! matched_ifdef.back();
}
else if ( line == "#endif" && !matching_ifdef.empty() ) else if ( line == "#endif" )
{
if ( ! matched_ifdef.empty() )
matched_ifdef.pop_back();
if ( ! matching_ifdef.empty() )
matching_ifdef.pop_back(); matching_ifdef.pop_back();
}
bool match = true; bool match = true;
for ( std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it ) 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 || if ( line.find("#if") == 0 ||
line.find("#else") == 0 || line.find("#else") == 0 ||
line.find("#elif") == 0 ||
line.find("#endif") == 0 ) line.find("#endif") == 0 )
line = ""; line = "";

View File

@ -26,7 +26,7 @@
#include <string> #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 #endif

View File

@ -52,6 +52,8 @@ private:
TEST_CASE( if0 ); TEST_CASE( if0 );
TEST_CASE( if1 ); TEST_CASE( if1 );
TEST_CASE( elif );
TEST_CASE( include1 ); TEST_CASE( include1 );
TEST_CASE( if_cond1 ); 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() void include1()
{ {