diff --git a/preprocessor.cpp b/preprocessor.cpp index 5440f11f3..8f791f87a 100644 --- a/preprocessor.cpp +++ b/preprocessor.cpp @@ -1,4 +1,4 @@ -/* +/* * c++check - c/c++ syntax checking * Copyright (C) 2007 Daniel Marjamäki * @@ -125,6 +125,42 @@ void preprocess(std::istream &istr, std::map &result) +// Get the DEF in this line: "#ifdef DEF" +static std::string getdef(std::string line, bool def) +{ + // Replace tabs with spaces.. + while ( line.find("\t") != std::string::npos ) + line[ line.find("\t") ] = 0; + + // Trim off any leading spaces.. + while (line[0] == ' ') + line.erase(0, 1); + + // If def is true, the line must start with "#ifdef" + if ( def && line.find("#ifdef ") != 0 ) + { + return ""; + } + + // If def is false, the line must start with "#ifndef" + if ( !def && line.find("#ifndef ") != 0 ) + { + return ""; + } + + // Remove the "#ifdef" or "#ifndef" + line.erase( 0, line.find(" ") ); + + // Remove all spaces. + while ( line.find(" ") != std::string::npos ) + line.erase( line.find(" "), 1 ); + + // The remaining string is our result. + return line; +} + + + static std::list getcfgs( const std::string &filedata ) { std::list ret; @@ -134,9 +170,9 @@ static std::list getcfgs( const std::string &filedata ) std::string line; while ( getline(istr, line) ) { - if ( line.find("#ifdef ")==0 || line.find("#ifndef ")==0 ) + std::string def = getdef(line, true) + getdef(line, false); + if (!def.empty()) { - std::string def( line.substr(line.find(" ") + 1) ); if (std::find(ret.begin(), ret.end(), def) == ret.end()) ret.push_back( def ); } @@ -158,11 +194,14 @@ static std::string getcode(const std::string &filedata, std::string cfg) std::string line; while ( getline(istr, line) ) { - if ( line.find("#ifdef ") == 0 ) - matching_ifdef.push_back( !cfg.empty() && line.find(cfg) != std::string::npos ); + std::string def = getdef( line, true ); + std::string ndef = getdef( line, false ); - else if ( line.find("#ifndef ") == 0 ) - matching_ifdef.push_back( cfg.empty() || line.find(cfg) == std::string::npos ); + if ( ! def.empty() ) + matching_ifdef.push_back( cfg == def ); + + else if ( ! ndef.empty() ) + matching_ifdef.push_back( cfg != ndef ); else if ( line.find("#else") == 0) matching_ifdef.back() = ! matching_ifdef.back(); diff --git a/preprocessor.h b/preprocessor.h index a349aba64..89810b132 100644 --- a/preprocessor.h +++ b/preprocessor.h @@ -1,4 +1,4 @@ -/* +/* * c++check - c/c++ syntax checking * Copyright (C) 2007 Daniel Marjamäki * diff --git a/testpreprocessor.cpp b/testpreprocessor.cpp index 40d1a0916..92ac58f15 100644 --- a/testpreprocessor.cpp +++ b/testpreprocessor.cpp @@ -1,111 +1,113 @@ -/* - * c++check - c/c++ syntax checking - * Copyright (C) 2007 Daniel Marjamäki - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see -#include - -class TestPreprocessor : public TestFixture -{ -public: - TestPreprocessor() : TestFixture("TestPreprocessor") - { } - -private: - - void run() - { - TEST_CASE( test1 ); - TEST_CASE( test2 ); - - TEST_CASE( comments1 ); - } - - void check(const char filedata[], const std::map &expected) - { - std::istringstream istr(filedata); - std::map actual; - preprocess( istr, actual ); - - ASSERT_EQUALS( expected.size(), actual.size() ); - for ( std::map::const_iterator it = actual.begin(); it != actual.end(); ++it ) - { - std::map::const_iterator it2 = expected.find(it->first); - if ( it2 == expected.end() ) - assertFail(__FILE__, __LINE__); - else - { - std::string s1 = it->second; - std::string s2 = it2->second; - ASSERT_EQUALS( it->second, it2->second ); - } - } - } - - void test1() - { - const char filedata[] = "#ifdef WIN32\n" - " abcdef\n" - "#else\n" - " qwerty\n" - "#endif\n"; - - std::map expected; - expected[""] = "\n\n\n qwerty\n\n"; - expected["WIN32"] = "\n abcdef\n\n\n\n"; - - check( filedata, expected ); - } - - void test2() - { - const char filedata[] = "#ifndef WIN32\n" - " abcdef\n" - "#else\n" - " qwerty\n" - "#endif\n"; - - std::map expected; - expected[""] = "\n abcdef\n\n\n\n"; - expected["WIN32"] = "\n\n\n qwerty\n\n"; - - check( filedata, expected ); - } - - void comments1() - { - const char filedata[] = "/*\n" - "#ifdef WIN32\n" - "#endif\n" - "*/\n"; - - std::map expected; - expected[""] = "\n\n\n\n"; - check( filedata, expected ); - } - -}; - -REGISTER_TEST( TestPreprocessor ) +/* + * c++check - c/c++ syntax checking + * Copyright (C) 2007 Daniel Marjamäki + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see +#include + +class TestPreprocessor : public TestFixture +{ +public: + TestPreprocessor() : TestFixture("TestPreprocessor") + { } + +private: + + void run() + { + TEST_CASE( test1 ); + TEST_CASE( test2 ); + + TEST_CASE( comments1 ); + } + + void check(const char filedata[], const std::map &expected) + { + std::istringstream istr(filedata); + std::map actual; + preprocess( istr, actual ); + + ASSERT_EQUALS( expected.size(), actual.size() ); + for ( std::map::const_iterator it = actual.begin(); it != actual.end(); ++it ) + { + std::map::const_iterator it2 = expected.find(it->first); + if ( it2 == expected.end() ) + assertFail(__FILE__, __LINE__); + else + { + std::string s1 = it->second; + std::string s2 = it2->second; + ASSERT_EQUALS( it->second, it2->second ); + } + } + } + + void test1() + { + const char filedata[] = "#ifdef WIN32 \n" + " abcdef\n" + "#else\n" + " qwerty\n" + "#endif\n"; + + std::map expected; + expected[""] = "\n\n\n qwerty\n\n"; + expected["WIN32"] = "\n abcdef\n\n\n\n"; + + check( filedata, expected ); + } + + void test2() + { + const char filedata[] = "#ifndef WIN32\n" + " abcdef\n" + "#else\n" + " qwerty\n" + "#endif\n"; + + std::map expected; + expected[""] = "\n abcdef\n\n\n\n"; + expected["WIN32"] = "\n\n\n qwerty\n\n"; + + check( filedata, expected ); + } + + + + void comments1() + { + const char filedata[] = "/*\n" + "#ifdef WIN32\n" + "#endif\n" + "*/\n"; + + std::map expected; + expected[""] = "\n\n\n\n"; + check( filedata, expected ); + } + +}; + +REGISTER_TEST( TestPreprocessor )