From 45eaebe4233f0345dc90c25067fc680531f66ad5 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Tue, 31 Aug 2010 21:32:26 +0300 Subject: [PATCH] Move CLI command line parsing to own class. --- cli/cmdlineparser.cpp | 453 +++++++++++++++++++++++++++++++++++ cli/cmdlineparser.h | 57 +++++ cli/cppcheck.vcproj | 8 + cli/cppcheck.vcxproj | 2 + cli/cppcheck.vcxproj.filters | 6 + cli/cppcheckexecutor.cpp | 41 +++- cli/cppcheckexecutor.h | 12 + lib/cppcheck.cpp | 430 --------------------------------- lib/cppcheck.h | 10 - 9 files changed, 578 insertions(+), 441 deletions(-) create mode 100644 cli/cmdlineparser.cpp create mode 100644 cli/cmdlineparser.h diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp new file mode 100644 index 000000000..7104d0981 --- /dev/null +++ b/cli/cmdlineparser.cpp @@ -0,0 +1,453 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2010 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 +#include +#include +#include +#include "cmdlineparser.h" +#include "cppcheck.h" +#include "timer.h" +#include "settings.h" + + +static void AddFilesToList(const std::string& FileList, std::vector& PathNames) +{ + // to keep things initially simple, if the file can't be opened, just be + // silent and move on + // ideas : we could also require this should be an xml file, with the filenames + // specified in an xml structure + // we could elaborate this then, to also include the I-paths, ... + // basically for everything that makes the command line very long + // xml is a bonus then, since we can easily extend it + // we need a good parser then -> suggestion : TinyXml + // drawback : creates a dependency + std::ifstream Files(FileList.c_str()); + if (Files) + { + std::string FileName; + while (std::getline(Files, FileName)) // next line + { + if (!FileName.empty()) + { + PathNames.push_back(FileName); + } + } + } +} + +CmdLineParser::CmdLineParser(Settings *settings) + : _settings(settings) + , _showHelp(false) + , _showVersion(false) + , _showErrorMessages(false) +{ +} + +bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) +{ + for (int i = 1; i < argc; i++) + { + if (strcmp(argv[i], "--version") == 0) + { + _showVersion = true; + return true; + } + // Flag used for various purposes during debugging + else if (strcmp(argv[i], "--debug") == 0) + _settings->debug = _settings->debugwarnings = true; + + // Show debug warnings + else if (strcmp(argv[i], "--debug-warnings") == 0) + _settings->debugwarnings = true; + + // Inconclusive checking - keep this for compatibility but don't + // handle it + else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0) + ; + + // Checking coding style + else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--style") == 0) + { + const std::string errmsg = _settings->addEnabled("style"); + if (!errmsg.empty()) + { + std::cout << errmsg; + return false; + } + } + + // Filter errors + else if (strcmp(argv[i], "--suppressions") == 0) + { + ++i; + + if (i >= argc) + { + std::cout << "cppcheck: No file specified for the --suppressions option"; + return false; + } + + std::ifstream f(argv[i]); + if (!f.is_open()) + { + std::cout << "cppcheck: Couldn't open the file \"" << std::string(argv[i]) << "\""; + return false; + } + const std::string errmsg(_settings->nomsg.parseFile(f)); + if (!errmsg.empty()) + { + std::cout << errmsg; + return false; + } + } + + // Enables inline suppressions. + else if (strcmp(argv[i], "--inline-suppr") == 0) + _settings->_inlineSuppressions = true; + + // Verbose error messages (configuration info) + else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) + _settings->_verbose = true; + + // Force checking of files that have "too many" configurations + else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0) + _settings->_force = true; + + // Write results in results.xml + else if (strcmp(argv[i], "--xml") == 0) + _settings->_xml = true; + + // Only print something when there are errors + else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) + _settings->_errorsOnly = true; + + // Check if there are unused functions + else if (strcmp(argv[i], "--unused-functions") == 0) + { + const std::string errmsg = _settings->addEnabled("unusedFunctions"); + if (!errmsg.empty()) + { + std::cout << errmsg; + return false; + } + } + + // Append userdefined code to checked source code + else if (strncmp(argv[i], "--append=", 9) == 0) + _settings->append(9 + argv[i]); + + else if (strncmp(argv[i], "--enable=", 9) == 0) + { + const std::string errmsg = _settings->addEnabled(argv[i] + 9); + if (!errmsg.empty()) + { + std::cout << errmsg; + return false; + } + } + + // --error-exitcode=1 + else if (strncmp(argv[i], "--error-exitcode=", 17) == 0) + { + std::string temp = argv[i]; + temp = temp.substr(17); + std::istringstream iss(temp); + if (!(iss >> _settings->_exitCode)) + { + _settings->_exitCode = 0; + std::cout << "cppcheck: Argument must be an integer. Try something like '--error-exitcode=1'"; + return false; + } + } + + // User define + else if (strncmp(argv[i], "-D", 2) == 0) + { + if (!_settings->userDefines.empty()) + _settings->userDefines += ";"; + _settings->userDefines += 2 + argv[i]; + } + + // Include paths + else if (strcmp(argv[i], "-I") == 0 || strncmp(argv[i], "-I", 2) == 0) + { + std::string path; + + // "-I path/" + if (strcmp(argv[i], "-I") == 0) + { + ++i; + if (i >= argc) + { + std::cout << "cppcheck: argument to '-I' is missing"; + return false; + } + path = argv[i]; + } + + // "-Ipath/" + else + { + path = argv[i]; + path = path.substr(2); + } + + // If path doesn't end with / or \, add it + if (path[path.length()-1] != '/' && path[path.length()-1] != '\\') + path += '/'; + + _settings->_includePaths.push_back(path); + } + + // file list specified + else if (strncmp(argv[i], "--file-list=", 12) == 0) + { + // open this file and read every input file (1 file name per line) + AddFilesToList(12 + argv[i], _pathnames); + } + + // Report progress + else if (strcmp(argv[i], "--report-progress") == 0) + { + _settings->reportProgress = true; + } + + // Output formatter + else if (strcmp(argv[i], "--template") == 0) + { + // "--template path/" + ++i; + if (i >= argc) + { + std::cout << "cppcheck: argument to '--template' is missing"; + return false; + } + + _settings->_outputFormat = argv[i]; + if (_settings->_outputFormat == "gcc") + _settings->_outputFormat = "{file}:{line}: {severity}: {message}"; + else if (_settings->_outputFormat == "vs") + _settings->_outputFormat = "{file}({line}): {severity}: {message}"; + } + + // Checking threads + else if (strcmp(argv[i], "-j") == 0 || + strncmp(argv[i], "-j", 2) == 0) + { + std::string numberString; + + // "-j 3" + if (strcmp(argv[i], "-j") == 0) + { + ++i; + if (i >= argc) + { + std::cout << "cppcheck: argument to '-j' is missing"; + return false; + } + + numberString = argv[i]; + } + + // "-j3" + else if (strncmp(argv[i], "-j", 2) == 0) + { + numberString = argv[i]; + numberString = numberString.substr(2); + } + + std::istringstream iss(numberString); + if (!(iss >> _settings->_jobs)) + { + std::cout << "cppcheck: argument to '-j' is not a number"; + return false; + } + + if (_settings->_jobs > 1000) + { + std::cout << "cppcheck: argument for '-j' is allowed to be 1000 at max"; + return false; + } + } + + // deprecated: auto deallocated classes.. + else if (strcmp(argv[i], "--auto-dealloc") == 0) + { + ++i; + } + + // print all possible error messages.. + else if (strcmp(argv[i], "--errorlist") == 0) + { + //_cppcheck->getErrorMessages(); + _showErrorMessages = true; + return true; + } + + // documentation.. + else if (strcmp(argv[i], "--doc") == 0) + { + std::ostringstream doc; + // Get documentation.. + for (std::list::iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) + { + doc << "===" << (*it)->name() << "===\n" + << (*it)->classInfo() << "\n\n"; + } + + std::string doc2(doc.str()); + while (doc2.find("\n\n\n") != std::string::npos) + doc2.erase(doc2.find("\n\n\n"), 1); + std::cout << doc2; + return true; + } + + // --test-2-pass Experimental 2-pass checking of files + // This command line flag will be removed + else if (strcmp(argv[i], "--test-2-pass") == 0) + { + _settings->test_2_pass = true; + } + + else if (strncmp(argv[i], "-", 1) == 0 || strncmp(argv[i], "--", 2) == 0) + { + std::cout << "cppcheck: error: unrecognized command line option \"" << argv[i] << "\""; + return false; + } + + // show timing information.. + else if (strncmp(argv[i], "--showtime=", 11) == 0) + { + const std::string showtimeMode = argv[i] + 11; + if (showtimeMode == "file") + _settings->_showtime = SHOWTIME_FILE; + else if (showtimeMode == "summary") + _settings->_showtime = SHOWTIME_SUMMARY; + else if (showtimeMode == "top5") + _settings->_showtime = SHOWTIME_TOP5; + else + _settings->_showtime = SHOWTIME_NONE; + } + + // Print help + else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) + { + _pathnames.clear(); + _showHelp = true; + break; + } + else + _pathnames.push_back(argv[i]); + } + + if (_settings->isEnabled("unusedFunctions") && _settings->_jobs > 1) + { + std::cout << "unusedFunctions check can't be used with -j option, so it was disabled."; + } + + // FIXME: Make the _settings.test_2_pass thread safe + if (_settings->test_2_pass && _settings->_jobs > 1) + { + std::cout << "--test-2-pass doesn't work with -j option yet."; + } + + + if (argc <= 1 || _showHelp) + PrintHelp(); + else if (_pathnames.empty()) + { + std::cout << "cppcheck: No C or C++ source files found."; + return false; + } + + return true; +} + +void CmdLineParser::PrintHelp() +{ + std::cout << "Cppcheck - A tool for static C/C++ code analysis\n" + "\n" + "Syntax:\n" + " cppcheck [--append=file] [-D] [--enable=] [--error-exitcode=[n]]\n" + " [--exitcode-suppressions file] [--file-list=file.txt] [--force]\n" + " [--help] [-Idir] [--inline-suppr] [-j [jobs]] [--quiet]\n" + " [--report-progress] [--style] [--suppressions file.txt]\n" + " [--verbose] [--version] [--xml] [file or path1] [file or path]\n" + "\n" + "If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n" + "are checked recursively from given directory.\n\n" + "Options:\n" + " --append=file This allows you to provide information about\n" + " functions by providing an implementation for these.\n" + " -D By default Cppcheck checks all configurations.\n" + " Use -D to limit the checking. When -D is used the\n" + " checking is limited to the given configuration.\n" + " Example: -DDEBUG=1 -D__cplusplus\n" + " --enable=id Enable additional checks. The available ids are:\n" + " * all - enable all checks\n" + " * style - Check coding style\n" + " * unusedFunctions - check for unused functions\n" + " Several ids can be given if you separate them with commas\n" + " --error-exitcode=[n] If errors are found, integer [n] is returned instead\n" + " of default 0. EXIT_FAILURE is returned\n" + " if arguments are not valid or if no input files are\n" + " provided. Note that your operating system can\n" + " modify this value, e.g. 256 can become 0.\n" + " --exitcode-suppressions file\n" + " Used when certain messages should be displayed but\n" + " should not cause a non-zero exitcode.\n" + " --file-list=file Specify the files to check in a text file. One Filename per line.\n" + " -f, --force Force checking on files that have \"too many\"\n" + " configurations\n" + " -h, --help Print this help\n" + " -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" + " --inline-suppr Enable inline suppressions. Use them by placing one or\n" + " more comments in the form: // cppcheck-suppress memleak\n" + " on the lines before the warning to suppress.\n" + " -j [jobs] Start [jobs] threads to do the checking simultaneously.\n" + " -q, --quiet Only print error messages\n" + " --report-progress Report progress messages while checking a file.\n" + " -s, --style deprecated, use --enable=style\n" + " --suppressions file Suppress warnings listed in the file. Filename and line\n" + " are optional. The format of the single line in file is:\n" + " [error id]:[filename]:[line]\n" + " --template '[text]' Format the error messages. E.g.\n" + " '{file}:{line},{severity},{id},{message}' or\n" + " '{file}({line}):({severity}) {message}'\n" + " Pre-defined templates: gcc, vs\n" + " -v, --verbose More detailed error reports\n" + " --version Print out version number\n" + " --xml Write results in xml to error stream.\n" + "\n" + "Example usage:\n" + " # Recursively check the current folder. Print the progress on the screen and\n" + " write errors in a file:\n" + " cppcheck . 2> err.txt\n" + " # Recursively check ../myproject/ and don't print progress:\n" + " cppcheck --quiet ../myproject/\n" + " # Check only files one.cpp and two.cpp and give all information there is:\n" + " cppcheck -v -s one.cpp two.cpp\n" + " # Check f.cpp and search include files from inc1/ and inc2/:\n" + " cppcheck -I inc1/ -I inc2/ f.cpp\n" + "\n" + "For more information:\n" + " http://cppcheck.sf.net/manual.pdf\n"; +} diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h new file mode 100644 index 000000000..ec8898dee --- /dev/null +++ b/cli/cmdlineparser.h @@ -0,0 +1,57 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2010 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 CMDLINE_PARSER_H +#define CMDLINE_PARSER_H + +#include +#include + +class CppCheck; +class Settings; + +class CmdLineParser +{ +public: + CmdLineParser(Settings *settings); + bool ParseFromArgs(int argc, const char* const argv[]); + bool GetShowVersion() const + { + return _showVersion; + } + bool GetShowErrorMessages() const + { + return _showErrorMessages; + } + std::vector GetPathNames() const + { + return _pathnames; + } + +protected: + void PrintHelp(); + +private: + Settings *_settings; + bool _showHelp; + bool _showVersion; + bool _showErrorMessages; + std::vector _pathnames; +}; + +#endif // CMDLINE_PARSER_H diff --git a/cli/cppcheck.vcproj b/cli/cppcheck.vcproj index 48a52d76c..921a22079 100755 --- a/cli/cppcheck.vcproj +++ b/cli/cppcheck.vcproj @@ -224,6 +224,10 @@ RelativePath="..\lib\checkunusedfunctions.cpp" > + + @@ -330,6 +334,10 @@ RelativePath="..\lib\classinfo.h" > + + diff --git a/cli/cppcheck.vcxproj b/cli/cppcheck.vcxproj index b68daecd9..17cdc0792 100644 --- a/cli/cppcheck.vcxproj +++ b/cli/cppcheck.vcxproj @@ -143,6 +143,7 @@ + @@ -170,6 +171,7 @@ + diff --git a/cli/cppcheck.vcxproj.filters b/cli/cppcheck.vcxproj.filters index 466d3457d..ae2b9ad8b 100644 --- a/cli/cppcheck.vcxproj.filters +++ b/cli/cppcheck.vcxproj.filters @@ -80,6 +80,9 @@ Source Files + + Source Files + @@ -151,6 +154,9 @@ Header Files + + Header Files + diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 113f45b33..df94136db 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -22,6 +22,8 @@ #include #include #include // EXIT_SUCCESS and EXIT_FAILURE +#include "cmdlineparser.h" +#include "filelister.h" CppCheckExecutor::CppCheckExecutor() { @@ -33,10 +35,47 @@ CppCheckExecutor::~CppCheckExecutor() } +bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[]) +{ + CmdLineParser parser(&_settings); + bool success = parser.ParseFromArgs(argc, argv); + + if (success) + { + if (parser.GetShowVersion()) + { + std::cout << "Cppcheck " << cppcheck->version(); + return true; + } + + if (parser.GetShowErrorMessages()) + { + cppcheck->getErrorMessages(); + return true; + } + } + + std::vector pathnames = parser.GetPathNames(); + std::vector filenames; + + if (!pathnames.empty()) + { + // Execute recursiveAddFiles() to each given file parameter + std::vector::const_iterator iter; + for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) + getFileLister()->recursiveAddFiles(filenames, iter->c_str(), true); + + for (iter = filenames.begin(); iter != filenames.end(); ++iter) + cppcheck->addFile(*iter); + } + + return true; +} + int CppCheckExecutor::check(int argc, const char* const argv[]) { CppCheck cppCheck(*this); - if (!cppCheck.parseFromArgs(argc, argv)) + if (!parseFromArgs(&cppCheck, argc, argv)) { return EXIT_FAILURE; } diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index 813a2f196..35ab42a31 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -23,6 +23,8 @@ #include "settings.h" #include +class CppCheck; + /** * This class works as an example of how CppCheck can be used in external * programs without very little knowledge of the internal parts of the @@ -79,6 +81,16 @@ protected: */ virtual void reportErr(const std::string &errmsg); + /** + * @brief Parse command line args and get settings and file lists + * from there. + * + * @param argc argc from main() + * @param argv argv from main() + * @return false when errors are found in the input + */ + bool parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[]); + /** * check() will setup this in the beginning of check(). */ diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 624bfd7ae..40ee70e33 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -101,436 +101,6 @@ static void AddFilesToList(const std::string& FileList, std::vector } } -bool CppCheck::parseFromArgs(int argc, const char* const argv[]) -{ - std::vector pathnames; - bool showHelp = false; - for (int i = 1; i < argc; i++) - { - if (strcmp(argv[i], "--version") == 0) - { - reportOut(std::string("Cppcheck ") + version()); - return true; - } - - // Flag used for various purposes during debugging - else if (strcmp(argv[i], "--debug") == 0) - _settings.debug = _settings.debugwarnings = true; - - // Show debug warnings - else if (strcmp(argv[i], "--debug-warnings") == 0) - _settings.debugwarnings = true; - - // Inconclusive checking - keep this for compatibility but don't - // handle it - else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0) - ; - - // Only print something when there are errors - else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) - _settings._errorsOnly = true; - - // Checking coding style - else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--style") == 0) - { - const std::string errmsg = _settings.addEnabled("style"); - if (!errmsg.empty()) - { - reportOut(errmsg); - return false; - } - } - - // Filter errors - else if (strcmp(argv[i], "--suppressions") == 0) - { - ++i; - - if (i >= argc) - { - reportOut("cppcheck: No file specified for the --suppressions option"); - return false; - } - - std::ifstream f(argv[i]); - if (!f.is_open()) - { - reportOut("cppcheck: Couldn't open the file \"" + std::string(argv[i]) + "\""); - return false; - } - const std::string errmsg(_settings.nomsg.parseFile(f)); - if (!errmsg.empty()) - { - reportOut(errmsg); - return false; - } - } - - // Filter errors - else if (strcmp(argv[i], "--exitcode-suppressions") == 0) - { - ++i; - - if (i >= argc) - { - reportOut("cppcheck: No file specified for the --exitcode-suppressions option"); - return false; - } - - std::ifstream f(argv[i]); - if (!f.is_open()) - { - reportOut("cppcheck: Couldn't open the file \"" + std::string(argv[i]) + "\""); - return false; - } - const std::string errmsg(_settings.nofail.parseFile(f)); - if (!errmsg.empty()) - { - reportOut(errmsg); - return false; - } - } - - // Enables inline suppressions. - else if (strcmp(argv[i], "--inline-suppr") == 0) - _settings._inlineSuppressions = true; - - // Verbose error messages (configuration info) - else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) - _settings._verbose = true; - - // Force checking of files that have "too many" configurations - else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0) - _settings._force = true; - - // Write results in results.xml - else if (strcmp(argv[i], "--xml") == 0) - _settings._xml = true; - - // Check if there are unused functions - else if (strcmp(argv[i], "--unused-functions") == 0) - { - const std::string errmsg = _settings.addEnabled("unusedFunctions"); - if (!errmsg.empty()) - { - reportOut(errmsg); - return false; - } - } - - // Append userdefined code to checked source code - else if (strncmp(argv[i], "--append=", 9) == 0) - _settings.append(9 + argv[i]); - - // show timing information.. - else if (strncmp(argv[i], "--showtime=", 11) == 0) - { - const std::string showtimeMode = argv[i] + 11; - if (showtimeMode == "file") - _settings._showtime = SHOWTIME_FILE; - else if (showtimeMode == "summary") - _settings._showtime = SHOWTIME_SUMMARY; - else if (showtimeMode == "top5") - _settings._showtime = SHOWTIME_TOP5; - else - _settings._showtime = SHOWTIME_NONE; - } - - // Print help - else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) - { - pathnames.clear(); - _filenames.clear(); - showHelp = true; - break; - } - - - else if (strncmp(argv[i], "--enable=", 9) == 0) - { - const std::string errmsg = _settings.addEnabled(argv[i] + 9); - if (!errmsg.empty()) - { - reportOut(errmsg); - return false; - } - } - - // --error-exitcode=1 - else if (strncmp(argv[i], "--error-exitcode=", 17) == 0) - { - std::string temp = argv[i]; - temp = temp.substr(17); - std::istringstream iss(temp); - if (!(iss >> _settings._exitCode)) - { - _settings._exitCode = 0; - reportOut("cppcheck: Argument must be an integer. Try something like '--error-exitcode=1'"); - return false; - } - } - - // User define - else if (strncmp(argv[i], "-D", 2) == 0) - { - if (!_settings.userDefines.empty()) - _settings.userDefines += ";"; - _settings.userDefines += 2 + argv[i]; - } - - // Include paths - else if (strcmp(argv[i], "-I") == 0 || strncmp(argv[i], "-I", 2) == 0) - { - std::string path; - - // "-I path/" - if (strcmp(argv[i], "-I") == 0) - { - ++i; - if (i >= argc) - { - reportOut("cppcheck: argument to '-I' is missing"); - return false; - } - - path = argv[i]; - } - - // "-Ipath/" - else - { - path = argv[i]; - path = path.substr(2); - } - - // If path doesn't end with / or \, add it - if (path[path.length()-1] != '/' && path[path.length()-1] != '\\') - path += '/'; - - _settings._includePaths.push_back(path); - } - - // file list specified - else if (strncmp(argv[i], "--file-list=", 12) == 0) - { - // open this file and read every input file (1 file name per line) - AddFilesToList(12 + argv[i], pathnames); - } - - // Report progress - else if (strcmp(argv[i], "--report-progress") == 0) - { - _settings.reportProgress = true; - } - - // Output formatter - else if (strcmp(argv[i], "--template") == 0) - { - // "--template path/" - ++i; - if (i >= argc) - { - reportOut("cppcheck: argument to '--template' is missing"); - return false; - } - - _settings._outputFormat = argv[i]; - if (_settings._outputFormat == "gcc") - _settings._outputFormat = "{file}:{line}: {severity}: {message}"; - else if (_settings._outputFormat == "vs") - _settings._outputFormat = "{file}({line}): {severity}: {message}"; - } - - // Checking threads - else if (strcmp(argv[i], "-j") == 0 || - strncmp(argv[i], "-j", 2) == 0) - { - std::string numberString; - - // "-j 3" - if (strcmp(argv[i], "-j") == 0) - { - ++i; - if (i >= argc) - { - reportOut("cppcheck: argument to '-j' is missing"); - return false; - } - - numberString = argv[i]; - } - - // "-j3" - else if (strncmp(argv[i], "-j", 2) == 0) - { - numberString = argv[i]; - numberString = numberString.substr(2); - } - - std::istringstream iss(numberString); - if (!(iss >> _settings._jobs)) - { - reportOut("cppcheck: argument to '-j' is not a number"); - return false; - } - - if (_settings._jobs > 1000) - { - reportOut("cppcheck: argument for '-j' is allowed to be 1000 at max"); - return false; - } - } - - // deprecated: auto deallocated classes.. - else if (strcmp(argv[i], "--auto-dealloc") == 0) - { - ++i; - } - - // print all possible error messages.. - else if (strcmp(argv[i], "--errorlist") == 0) - { - getErrorMessages(); - return true; - } - - // documentation.. - else if (strcmp(argv[i], "--doc") == 0) - { - std::ostringstream doc; - // Get documentation.. - for (std::list::iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) - { - doc << "===" << (*it)->name() << "===\n" - << (*it)->classInfo() << "\n\n"; - } - - std::string doc2(doc.str()); - while (doc2.find("\n\n\n") != std::string::npos) - doc2.erase(doc2.find("\n\n\n"), 1); - reportOut(doc2); - return true; - } - - // --test-2-pass Experimental 2-pass checking of files - // This command line flag will be removed - else if (strcmp(argv[i], "--test-2-pass") == 0) - { - _settings.test_2_pass = true; - } - - else if (strncmp(argv[i], "-", 1) == 0 || strncmp(argv[i], "--", 2) == 0) - { - reportOut("cppcheck: error: unrecognized command line option \"" + std::string(argv[i]) + "\""); - return false; - } - - else - pathnames.push_back(argv[i]); - } - - if (_settings.isEnabled("unusedFunctions") && _settings._jobs > 1) - { - reportOut("unusedFunctions check can't be used with -j option, so it was disabled."); - } - - // FIXME: Make the _settings.test_2_pass thread safe - if (_settings.test_2_pass && _settings._jobs > 1) - { - reportOut("--test-2-pass doesn't work with -j option yet."); - } - - if (!pathnames.empty()) - { - // Execute recursiveAddFiles() to each given file parameter - std::vector::const_iterator iter; - for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) - getFileLister()->recursiveAddFiles(_filenames, iter->c_str(), true); - } - - if (argc <= 1 || showHelp) - { - std::ostringstream oss; - oss << "Cppcheck - A tool for static C/C++ code analysis\n" - "\n" - "Syntax:\n" - " cppcheck [--append=file] [-D] [--enable=] [--error-exitcode=[n]]\n" - " [--exitcode-suppressions file] [--file-list=file.txt] [--force]\n" - " [--help] [-Idir] [--inline-suppr] [-j [jobs]] [--quiet]\n" - " [--report-progress] [--style] [--suppressions file.txt]\n" - " [--verbose] [--version] [--xml] [file or path1] [file or path]\n" - "\n" - "If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n" - "are checked recursively from given directory.\n\n" - "Options:\n" - " --append=file This allows you to provide information about\n" - " functions by providing an implementation for these.\n" - " -D By default Cppcheck checks all configurations.\n" - " Use -D to limit the checking. When -D is used the\n" - " checking is limited to the given configuration.\n" - " Example: -DDEBUG=1 -D__cplusplus\n" - " --enable=id Enable additional checks. The available ids are:\n" - " * all - enable all checks\n" - " * style - Check coding style\n" - " * unusedFunctions - check for unused functions\n" - " Several ids can be given if you separate them with commas\n" - " --error-exitcode=[n] If errors are found, integer [n] is returned instead\n" - " of default 0. EXIT_FAILURE is returned\n" - " if arguments are not valid or if no input files are\n" - " provided. Note that your operating system can\n" - " modify this value, e.g. 256 can become 0.\n" - " --exitcode-suppressions file\n" - " Used when certain messages should be displayed but\n" - " should not cause a non-zero exitcode.\n" - " --file-list=file Specify the files to check in a text file. One Filename per line.\n" - " -f, --force Force checking on files that have \"too many\"\n" - " configurations\n" - " -h, --help Print this help\n" - " -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" - " --inline-suppr Enable inline suppressions. Use them by placing one or\n" - " more comments in the form: // cppcheck-suppress memleak\n" - " on the lines before the warning to suppress.\n" - " -j [jobs] Start [jobs] threads to do the checking simultaneously.\n" - " -q, --quiet Only print error messages\n" - " --report-progress Report progress messages while checking a file.\n" - " -s, --style deprecated, use --enable=style\n" - " --suppressions file Suppress warnings listed in the file. Filename and line\n" - " are optional. The format of the single line in file is:\n" - " [error id]:[filename]:[line]\n" - " --template '[text]' Format the error messages. E.g.\n" - " '{file}:{line},{severity},{id},{message}' or\n" - " '{file}({line}):({severity}) {message}'\n" - " Pre-defined templates: gcc, vs\n" - " -v, --verbose More detailed error reports\n" - " --version Print out version number\n" - " --xml Write results in xml to error stream.\n" - "\n" - "Example usage:\n" - " # Recursively check the current folder. Print the progress on the screen and\n" - " write errors in a file:\n" - " cppcheck . 2> err.txt\n" - " # Recursively check ../myproject/ and don't print progress:\n" - " cppcheck --quiet ../myproject/\n" - " # Check only files one.cpp and two.cpp and give all information there is:\n" - " cppcheck -v -s one.cpp two.cpp\n" - " # Check f.cpp and search include files from inc1/ and inc2/:\n" - " cppcheck -I inc1/ -I inc2/ f.cpp\n" - "\n" - "For more information:\n" - " http://cppcheck.sf.net/manual.pdf\n"; - reportOut(oss.str()); - } - else if (_filenames.empty()) - { - reportOut("cppcheck: No C or C++ source files found."); - return false; - } - - return true; -} - unsigned int CppCheck::check() { exitcode = 0; diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 4c48081cd..e24c521b7 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -97,16 +97,6 @@ public: */ void clearFiles(); - /** - * @brief Parse command line args and get settings and file lists - * from there. - * - * @param argc argc from main() - * @param argv argv from main() - * @return false when errors are found in the input - */ - bool parseFromArgs(int argc, const char* const argv[]); - /** * @brief Returns current version number as a string. * @return version, e.g. "1.38"