diff --git a/Makefile b/Makefile index 09aadde1c..5391b67ea 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ CLIOBJ = cli/cmdlineparser.o \ cli/filelister_unix.o \ cli/filelister_win32.o \ cli/main.o \ + cli/pathmatch.o \ cli/threadexecutor.o TESTOBJ = test/options.o \ @@ -74,6 +75,7 @@ TESTOBJ = test/options.o \ test/testoptions.o \ test/testother.o \ test/testpath.o \ + test/testpathmatch.o \ test/testpostfixoperator.o \ test/testpreprocessor.o \ test/testrunner.o \ @@ -103,8 +105,8 @@ cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ) all: cppcheck testrunner -testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o $(LDFLAGS) +testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o $(LDFLAGS) test: all ./testrunner @@ -206,7 +208,7 @@ lib/tokenize.o: lib/tokenize.cpp lib/tokenize.h lib/token.h lib/mathlib.h lib/se cli/cmdlineparser.o: cli/cmdlineparser.cpp lib/cppcheck.h lib/settings.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/timer.h cli/cmdlineparser.h lib/path.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/cmdlineparser.o cli/cmdlineparser.cpp -cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h cli/threadexecutor.h cli/cmdlineparser.h cli/filelister.h lib/path.h +cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h cli/threadexecutor.h cli/cmdlineparser.h cli/filelister.h lib/path.h cli/pathmatch.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/cppcheckexecutor.o cli/cppcheckexecutor.cpp cli/filelister.o: cli/filelister.cpp cli/filelister.h cli/filelister_win32.h cli/filelister_unix.h @@ -221,6 +223,9 @@ cli/filelister_win32.o: cli/filelister_win32.cpp cli/filelister.h cli/filelister cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/main.o cli/main.cpp +cli/pathmatch.o: cli/pathmatch.cpp cli/pathmatch.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/pathmatch.o cli/pathmatch.cpp + cli/threadexecutor.o: cli/threadexecutor.cpp cli/threadexecutor.h lib/settings.h lib/errorlogger.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/threadexecutor.o cli/threadexecutor.cpp @@ -284,6 +289,9 @@ test/testother.o: test/testother.cpp lib/tokenize.h lib/checkother.h lib/check.h test/testpath.o: test/testpath.cpp test/testsuite.h lib/errorlogger.h test/redirect.h lib/path.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpath.o test/testpath.cpp +test/testpathmatch.o: test/testpathmatch.cpp test/testsuite.h lib/errorlogger.h test/redirect.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpathmatch.o test/testpathmatch.cpp + test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/tokenize.h lib/checkpostfixoperator.h lib/check.h lib/token.h lib/settings.h lib/errorlogger.h test/testsuite.h test/redirect.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpostfixoperator.o test/testpostfixoperator.cpp diff --git a/cli/cli.pro b/cli/cli.pro index 85702b9fb..e04e4e158 100644 --- a/cli/cli.pro +++ b/cli/cli.pro @@ -17,12 +17,15 @@ SOURCES += main.cpp \ filelister.cpp \ filelister_unix.cpp \ filelister_win32.cpp \ + pathmatch.cpp \ threadexecutor.cpp + HEADERS += cppcheckexecutor.h \ cmdlineparser.h \ filelister.h \ filelister_unix.h \ filelister_win32.h \ + pathmatch.h \ threadexecutor.h CONFIG(release, debug|release) { diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index c3eaa5764..b64229edf 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -26,6 +26,7 @@ #include "settings.h" #include "cmdlineparser.h" #include "path.h" +#include "filelister.h" // xml is used in rules #include "tinyxml/tinyxml.h" @@ -210,11 +211,28 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) else if (strcmp(argv[i], "--xml") == 0) _settings->_xml = true; - // Write results in xml2 format - else if (strcmp(argv[i], "--xml-version=2") == 0) + // Define the XML file version (and enable XML output) + else if (strncmp(argv[i], "--xml-version=", 14) == 0) { + std::string numberString(argv[i]); + numberString = numberString.substr(14); + + std::istringstream iss(numberString); + if (!(iss >> _settings->_xml_version)) + { + PrintMessage("cppcheck: argument to '--xml-version' is not a number"); + return false; + } + + if (_settings->_xml_version < 0 || _settings->_xml_version > 2) + { + // We only have xml versions 1 and 2 + PrintMessage("cppcheck: --xml-version can only be 1 or 2."); + return false; + } + + // Enable also XML if version is set _settings->_xml = true; - _settings->_xml_version = 2; } // Only print something when there are errors @@ -327,6 +345,44 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) AddFilesToList(12 + argv[i], _pathnames); } + // Ignored paths + else if (strncmp(argv[i], "-i", 2) == 0) + { + std::string path; + + // "-i path/" + if (strcmp(argv[i], "-i") == 0) + { + ++i; + if (i >= argc) + { + PrintMessage("cppcheck: argument to '-i' is missing"); + return false; + } + path = argv[i]; + } + + // "-ipath/" + else + { + path = 2 + argv[i]; + } + + if (!path.empty()) + { + path = Path::fromNativeSeparators(path); + + // If not "known" filename extension then assume it is path + if (!FileLister::acceptFile(path)) + { + // If path doesn't end with / or \, add it + if (path[path.length()-1] != '/') + path += '/'; + } + _ignoredPaths.push_back(path); + } + } + // Report progress else if (strcmp(argv[i], "--report-progress") == 0) { @@ -461,18 +517,18 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) TiXmlDocument doc; if (doc.LoadFile(12+argv[i])) { - TiXmlElement *root = doc.FirstChildElement(); - if (root && root->ValueStr() == "rule") + TiXmlElement *node = doc.FirstChildElement(); + for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) { Settings::Rule rule; - TiXmlElement *pattern = root->FirstChildElement("pattern"); + TiXmlElement *pattern = node->FirstChildElement("pattern"); if (pattern) { rule.pattern = pattern->GetText(); } - TiXmlElement *message = root->FirstChildElement("message"); + TiXmlElement *message = node->FirstChildElement("message"); if (message) { TiXmlElement *severity = message->FirstChildElement("severity"); @@ -589,6 +645,10 @@ void CmdLineParser::PrintHelp() " -I [dir] Give include path. Give several -I parameters to give\n" " several paths. First given path is checked first. If\n" " paths are relative to source files, this is not needed\n" + " -i [dir] Give path to ignore. Give several -i parameters to ignore\n" + " several paths. Give directory name or filename with path\n" + " as parameter. Directory name is matched to all parts of the\n" + " path." " --inline-suppr Enable inline suppressions. Use them by placing one or\n" " more comments, like: // cppcheck-suppress warningId\n" " on the lines before the warning to suppress.\n" @@ -608,6 +668,9 @@ void CmdLineParser::PrintHelp() " -v, --verbose More detailed error reports\n" " --version Print out version number\n" " --xml Write results in xml to error stream.\n" + " --xml-version=[version]\n" + " Select the XML file version. Currently versions 1 and 2\n" + " are available. The default version is 1." "\n" "Example usage:\n" " # Recursively check the current folder. Print the progress on the screen and\n" diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index 7a60e24a6..bfc047cb9 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -92,6 +92,14 @@ public: return _exitAfterPrint; } + /** + * Return a list of paths user wants to ignore. + */ + std::vector GetIgnoredPaths() const + { + return _ignoredPaths; + } + protected: /** @@ -111,6 +119,7 @@ private: bool _showErrorMessages; bool _exitAfterPrint; std::vector _pathnames; + std::vector _ignoredPaths; }; /// @} diff --git a/cli/cppcheck.vcproj b/cli/cppcheck.vcproj index 541363475..37ce7c22a 100755 --- a/cli/cppcheck.vcproj +++ b/cli/cppcheck.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9,00" Name="cppcheck" - ProjectGUID="{7E69D6C6-32B2-32E1-BF56-A5BFBAF5E61F}" + ProjectGUID="{56B0F403-02CE-3F89-9A1B-E03F21240A63}" Keyword="Qt4VSv1.0"> + + - {42BC0E8E-9175-3B2D-B8B3-9EC5C36EF49A} + {A6DACC3F-847F-3498-9415-164FBC746D6B} cppcheck Qt4VSv1.0 @@ -140,6 +140,7 @@ + @@ -176,6 +177,7 @@ + diff --git a/cli/cppcheck.vcxproj.filters b/cli/cppcheck.vcxproj.filters index 4e6b80eca..de87f16e1 100644 --- a/cli/cppcheck.vcxproj.filters +++ b/cli/cppcheck.vcxproj.filters @@ -84,6 +84,9 @@ Source Files + + Source Files + Source Files @@ -188,6 +191,9 @@ Header Files + + Header Files + Header Files diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index fdb886471..c101b6592 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -25,6 +25,7 @@ #include "cmdlineparser.h" #include "filelister.h" #include "path.h" +#include "pathmatch.h" CppCheckExecutor::CppCheckExecutor() { @@ -55,7 +56,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c errorlist = true; std::cout << ErrorLogger::ErrorMessage::getXMLHeader(_settings._xml_version); cppcheck->getErrorMessages(); - std::cout << ErrorLogger::ErrorMessage::getXMLFooter() << std::endl; + std::cout << ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version) << std::endl; } if (parser.ExitAfterPrinting()) @@ -87,19 +88,36 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c std::vector::const_iterator iter; for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) getFileLister()->recursiveAddFiles(filenames, Path::toNativeSeparators(iter->c_str())); - - for (iter = filenames.begin(); iter != filenames.end(); ++iter) - cppcheck->addFile(*iter); } - if (filenames.empty()) + if (!filenames.empty()) + { + PathMatch matcher(parser.GetIgnoredPaths()); + std::vector::iterator iterBegin = filenames.begin(); + for (int i = (int)filenames.size() - 1; i >= 0; i--) + { + if (matcher.Match(filenames[i])) + filenames.erase(iterBegin + i); + } + } + else { std::cout << "cppcheck: error: could not find or open any of the paths given." << std::endl; return false; } + + if (!filenames.empty()) + { + std::vector::iterator iter; + for (iter = filenames.begin(); iter != filenames.end(); ++iter) + cppcheck->addFile(*iter); + + return true; + } else { - return true; + std::cout << "cppcheck: error: no files to check - all paths ignored." << std::endl; + return false; } } @@ -141,7 +159,7 @@ int CppCheckExecutor::check(int argc, const char* const argv[]) if (_settings._xml) { - reportErr(ErrorLogger::ErrorMessage::getXMLFooter()); + reportErr(ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version)); } if (returnValue) diff --git a/cli/filelister.h b/cli/filelister.h index aa292b701..4c6cd7d03 100644 --- a/cli/filelister.h +++ b/cli/filelister.h @@ -55,7 +55,7 @@ public: * @param filename filename to check * @return returns true if the file extension indicates it should be checked */ - virtual bool acceptFile(const std::string &filename); + static bool acceptFile(const std::string &filename); /** * @brief Is given path a directory? diff --git a/cli/filelister_unix.cpp b/cli/filelister_unix.cpp index ed6d12f4b..f9263eb78 100644 --- a/cli/filelister_unix.cpp +++ b/cli/filelister_unix.cpp @@ -72,7 +72,7 @@ void FileListerUnix::recursiveAddFiles2(std::vector &relative, continue; } - if (Path::sameFileName(path,filename) || FileListerUnix::acceptFile(filename)) + if (Path::sameFileName(path,filename) || FileLister::acceptFile(filename)) { relative.push_back(filename); absolute.push_back(fname); diff --git a/cli/pathmatch.cpp b/cli/pathmatch.cpp new file mode 100644 index 000000000..db36d99c9 --- /dev/null +++ b/cli/pathmatch.cpp @@ -0,0 +1,73 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team. + * + * 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 "pathmatch.h" + +PathMatch::PathMatch(const std::vector &masks) + : _masks(masks) +{ +} + +bool PathMatch::Match(const std::string &path) +{ + if (path.empty()) + return false; + + std::vector::const_iterator iterMask; + for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) + { + // Filtering directory name + if ((*iterMask)[(*iterMask).length() - 1] == '/') + { + std::string findpath(path); + if (findpath[findpath.length() - 1] != '/') + findpath = RemoveFilename(findpath); + + if ((*iterMask).length() > findpath.length()) + continue; + // Match relative paths starting with mask + // -isrc matches src/foo.cpp + if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) + return true; + // Match only full directory name in middle or end of the path + // -isrc matches myproject/src/ but does not match + // myproject/srcfiles/ or myproject/mysrc/ + if (findpath.find("/" + *iterMask) != std::string::npos) + return true; + } + // Filtering filename + else + { + if ((*iterMask).length() > path.length()) + continue; + // Check if path ends with mask + // -ifoo.cpp matches (./)foo.c, src/foo.cpp and proj/src/foo.cpp + // -isrc/file.cpp matches src/foo.cpp and proj/src/foo.cpp + if (path.compare(path.size() - (*iterMask).size(), path.size(), *iterMask) == 0) + return true; + + } + } + return false; +} + +std::string PathMatch::RemoveFilename(const std::string &path) +{ + const size_t ind = path.find_last_of('/'); + return path.substr(0, ind + 1); +} diff --git a/cli/pathmatch.h b/cli/pathmatch.h new file mode 100644 index 000000000..5e1a0566c --- /dev/null +++ b/cli/pathmatch.h @@ -0,0 +1,63 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team. + * + * 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 . + */ + +#ifndef PATHMATCH_H +#define PATHMATCH_H + +#include +#include + +/// @addtogroup CLI +/// @{ + +/** + * @brief Simple path matching for ignoring paths in CLI. + */ +class PathMatch +{ +public: + + /** + * The constructor. + * @param masks List of masks. + */ + PathMatch(const std::vector &masks); + + /** + * @brief Match path against list of masks. + * @param path Path to match. + * @return true if any of the masks match the path, false otherwise. + */ + bool Match(const std::string &path); + +protected: + + /** + * @brief Remove filename part from the path. + * @param path Path to edit. + * @return path without filename part. + */ + std::string RemoveFilename(const std::string &path); + +private: + std::vector _masks; +}; + +/// @} + +#endif // PATHMATCH_H diff --git a/htdocs/devinfo/index.php b/htdocs/devinfo/index.php index cb40209f9..efffc6bd8 100644 --- a/htdocs/devinfo/index.php +++ b/htdocs/devinfo/index.php @@ -7,6 +7,8 @@ +