GitHub Viewer
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2022 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 "cmdlineparser.h"
#include "check.h"
#include "config.h"
#include "cppcheckexecutor.h"
#include "errortypes.h"
#include "filelister.h"
#include "importproject.h"
#include "path.h"
#include "platform.h"
#include "settings.h"
#include "standards.h"
#include "suppressions.h"
#include "timer.h"
#include "utils.h"
#include
#include
#include
#include // EXIT_FAILURE
#include
#include
#include
#include
#include
#include
#ifdef HAVE_RULES
// xml is used for rules
#include
#endif
#ifdef __linux__
#include
#endif
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.
std::istream *files;
std::ifstream infile;
if (fileList == "-") { // read from stdin
files = &std::cin;
} else {
infile.open(fileList);
files = &infile;
}
if (files && *files) {
std::string fileName;
while (std::getline(*files, fileName)) { // next line
if (!fileName.empty()) {
pathNames.emplace_back(fileName);
}
}
}
}
static bool addIncludePathsToList(const std::string& fileList, std::list* pathNames)
{
std::ifstream files(fileList);
if (files) {
std::string pathName;
while (std::getline(files, pathName)) { // next line
if (!pathName.empty()) {
pathName = Path::removeQuotationMarks(pathName);
pathName = Path::fromNativeSeparators(pathName);
// If path doesn't end with / or \, add it
if (!endsWith(pathName, '/'))
pathName += '/';
pathNames->emplace_back(pathName);
}
}
return true;
}
return false;
}
static bool addPathsToSet(const std::string& fileName, std::set* set)
{
std::list templist;
if (!addIncludePathsToList(fileName, &templist))
return false;
set->insert(templist.begin(), templist.end());
return true;
}
CmdLineParser::CmdLineParser(Settings *settings)
: mSettings(settings)
, mShowHelp(false)
, mShowVersion(false)
, mShowErrorMessages(false)
, mExitAfterPrint(false)
{}
void CmdLineParser::printMessage(const std::string &message)
{
std::cout 0)
mSettings->exename = buf;
}
#endif
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
// User define
if (std::strncmp(argv[i], "-D", 2) == 0) {
std::string define;
// "-D define"
if (std::strcmp(argv[i], "-D") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-D' is missing.");
return false;
}
define = argv[i];
}
// "-Ddefine"
else {
define = 2 + argv[i];
}
// No "=", append a "=1"
if (define.find('=') == std::string::npos)
define += "=1";
if (!mSettings->userDefines.empty())
mSettings->userDefines += ";";
mSettings->userDefines += define;
def = true;
}
// -E
else if (std::strcmp(argv[i], "-E") == 0) {
mSettings->preprocessOnly = true;
mSettings->quiet = true;
}
// Include paths
else if (std::strncmp(argv[i], "-I", 2) == 0) {
std::string path;
// "-I path/"
if (std::strcmp(argv[i], "-I") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-I' is missing.");
return false;
}
path = argv[i];
}
// "-Ipath/"
else {
path = 2 + argv[i];
}
path = Path::removeQuotationMarks(path);
path = Path::fromNativeSeparators(path);
// If path doesn't end with / or \, add it
if (!endsWith(path,'/'))
path += '/';
mSettings->includePaths.emplace_back(path);
}
// User undef
else if (std::strncmp(argv[i], "-U", 2) == 0) {
std::string undef;
// "-U undef"
if (std::strcmp(argv[i], "-U") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-U' is missing.");
return false;
}
undef = argv[i];
}
// "-Uundef"
else {
undef = 2 + argv[i];
}
mSettings->userUndefs.insert(std::move(undef));
}
else if (std::strncmp(argv[i], "--addon=", 8) == 0)
mSettings->addons.emplace(argv[i]+8);
else if (std::strncmp(argv[i],"--addon-python=", 15) == 0)
mSettings->addonPython.assign(argv[i]+15);
// Check configuration
else if (std::strcmp(argv[i], "--check-config") == 0)
mSettings->checkConfiguration = true;
// Check library definitions
else if (std::strcmp(argv[i], "--check-library") == 0) {
mSettings->checkLibrary = true;
// need to add "information" or no messages will be shown at all
mSettings->addEnabled("information");
}
else if (std::strcmp(argv[i], "--clang") == 0) {
mSettings->clang = true;
}
else if (std::strncmp(argv[i], "--clang=", 8) == 0) {
mSettings->clang = true;
mSettings->clangExecutable = argv[i] + 8;
}
else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) {
mSettings->configExcludePaths.insert(Path::fromNativeSeparators(argv[i] + 17));
}
else if (std::strncmp(argv[i], "--config-excludes-file=", 23) == 0) {
// open this file and read every input file (1 file name per line)
const std::string cfgExcludesFile(23 + argv[i]);
if (!addPathsToSet(cfgExcludesFile, &mSettings->configExcludePaths)) {
printError("unable to open config excludes file at '" + cfgExcludesFile + "'");
return false;
}
}
else if (std::strncmp(argv[i], "--cppcheck-build-dir=", 21) == 0) {
mSettings->buildDir = Path::fromNativeSeparators(argv[i] + 21);
if (endsWith(mSettings->buildDir, '/'))
mSettings->buildDir.pop_back();
}
// Show --debug output after the first simplifications
else if (std::strcmp(argv[i], "--debug") == 0 ||
std::strcmp(argv[i], "--debug-normal") == 0)
mSettings->debugnormal = true;
// Flag used for various purposes during debugging
else if (std::strcmp(argv[i], "--debug-simplified") == 0)
mSettings->debugSimplified = true;
// Show template information
else if (std::strcmp(argv[i], "--debug-template") == 0)
mSettings->debugtemplate = true;
// Show debug warnings
else if (std::strcmp(argv[i], "--debug-warnings") == 0)
mSettings->debugwarnings = true;
// documentation..
else if (std::strcmp(argv[i], "--doc") == 0) {
std::ostringstream doc;
// Get documentation..
for (const Check * it : Check::instances()) {
const std::string& name(it->name());
const std::string info(it->classInfo());
if (!name.empty() && !info.empty())
doc addEnabled("portability");
}
}
// print all possible error messages..
else if (std::strcmp(argv[i], "--errorlist") == 0) {
mShowErrorMessages = true;
mSettings->xml = true;
mExitAfterPrint = true;
}
// --error-exitcode=1
else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) {
const std::string temp = argv[i]+17;
std::istringstream iss(temp);
if (!(iss >> mSettings->exitCode)) {
mSettings->exitCode = 0;
printError("argument must be an integer. Try something like '--error-exitcode=1'.");
return false;
}
}
// Exception handling inside cppcheck client
else if (std::strcmp(argv[i], "--exception-handling") == 0) {
mSettings->exceptionHandling = true;
}
// Exception handling inside cppcheck client
else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) {
const std::string exceptionOutfilename = argv[i] + 21;
if (exceptionOutfilename != "stderr" && exceptionOutfilename != "stdout") {
printError("invalid '--exception-handling' argument");
return false;
}
mSettings->exceptionHandling = true;
CppCheckExecutor::setExceptionOutput((exceptionOutfilename == "stderr") ? stderr : stdout);
}
// Filter errors
else if (std::strncmp(argv[i], "--exitcode-suppressions=", 24) == 0) {
// exitcode-suppressions=filename.txt
std::string filename = 24 + argv[i];
std::ifstream f(filename);
if (!f.is_open()) {
printError("couldn't open the file: \"" + filename + "\".");
return false;
}
const std::string errmsg(mSettings->nofail.parseFile(f));
if (!errmsg.empty()) {
printError(errmsg);
return false;
}
}
// use a file filter
else if (std::strncmp(argv[i], "--file-filter=", 14) == 0)
mSettings->fileFilters.emplace_back(argv[i] + 14);
// file list specified
else if (std::strncmp(argv[i], "--file-list=", 12) == 0)
// open this file and read every input file (1 file name per line)
addFilesToList(12 + argv[i], mPathNames);
// Force checking of files that have "too many" configurations
else if (std::strcmp(argv[i], "-f") == 0 || std::strcmp(argv[i], "--force") == 0)
mSettings->force = true;
// Print help
else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) {
mPathNames.clear();
mShowHelp = true;
mExitAfterPrint = true;
break;
}
// Ignored paths
else if (std::strncmp(argv[i], "-i", 2) == 0) {
std::string path;
// "-i path/"
if (std::strcmp(argv[i], "-i") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-i' is missing.");
return false;
}
path = argv[i];
}
// "-ipath/"
else {
path = 2 + argv[i];
}
if (!path.empty()) {
path = Path::removeQuotationMarks(path);
path = Path::fromNativeSeparators(path);
path = Path::simplifyPath(path);
if (FileLister::isDirectory(path)) {
// If directory name doesn't end with / or \, add it
if (!endsWith(path, '/'))
path += '/';
}
mIgnoredPaths.emplace_back(path);
}
}
else if (std::strncmp(argv[i], "--include=", 10) == 0) {
mSettings->userIncludes.emplace_back(Path::fromNativeSeparators(argv[i] + 10));
}
else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) {
// open this file and read every input file (1 file name per line)
const std::string includesFile(16 + argv[i]);
if (!addIncludePathsToList(includesFile, &mSettings->includePaths)) {
printError("unable to open includes file at '" + includesFile + "'");
return false;
}
}
// Inconclusive checking
else if (std::strcmp(argv[i], "--inconclusive") == 0)
mSettings->certainty.enable(Certainty::inconclusive);
// Enables inline suppressions.
else if (std::strcmp(argv[i], "--inline-suppr") == 0)
mSettings->inlineSuppressions = true;
// Checking threads
else if (std::strncmp(argv[i], "-j", 2) == 0) {
std::string numberString;
// "-j 3"
if (std::strcmp(argv[i], "-j") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-j' is missing.");
return false;
}
numberString = argv[i];
}
// "-j3"
else
numberString = argv[i]+2;
std::istringstream iss(numberString);
if (!(iss >> mSettings->jobs)) {
printError("argument to '-j' is not a number.");
return false;
}
if (mSettings->jobs > 10000) {
// This limit is here just to catch typos. If someone has
// need for more jobs, this value should be increased.
printError("argument for '-j' is allowed to be 10000 at max.");
return false;
}
}
#ifdef THREADING_MODEL_FORK
else if (std::strncmp(argv[i], "-l", 2) == 0) {
std::string numberString;
// "-l 3"
if (std::strcmp(argv[i], "-l") == 0) {
++i;
if (i >= argc || argv[i][0] == '-') {
printError("argument to '-l' is missing.");
return false;
}
numberString = argv[i];
}
// "-l3"
else
numberString = argv[i]+2;
std::istringstream iss(numberString);
if (!(iss >> mSettings->loadAverage)) {
printError("argument to '-l' is not a number.");
return false;
}
}
#endif
// Enforce language (--language=, -x)
else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) {
std::string str;
if (argv[i][2]) {
str = argv[i]+11;
} else {
i++;
if (i >= argc || argv[i][0] == '-') {
printError("no language given to '-x' option.");
return false;
}
str = argv[i];
}
if (str == "c")
mSettings->enforcedLang = Settings::C;
else if (str == "c++")
mSettings->enforcedLang = Settings::CPP;
else {
printError("unknown language '" + str + "' enforced.");
return false;
}
}
// --library
else if (std::strncmp(argv[i], "--library=", 10) == 0) {
mSettings->libraries.emplace_back(argv[i] + 10);
}
// Set maximum number of #ifdef configurations to check
else if (std::strncmp(argv[i], "--max-configs=", 14) == 0) {
mSettings->force = false;
std::istringstream iss(14+argv[i]);
if (!(iss >> mSettings->maxConfigs)) {
printError("argument to '--max-configs=' is not a number.");
return false;
}
if (mSettings->maxConfigs < 1) {
printError("argument to '--max-configs=' must be greater than 0.");
return false;
}
maxconfigs = true;
}
// max ctu depth
else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0)
mSettings->maxCtuDepth = std::atoi(argv[i] + 16);
// Write results in file
else if (std::strncmp(argv[i], "--output-file=", 14) == 0)
mSettings->outputFile = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 14));
// Specify platform
else if (std::strncmp(argv[i], "--platform=", 11) == 0) {
const std::string platform(11+argv[i]);
if (platform == "win32A")
mSettings->platform(Settings::Win32A);
else if (platform == "win32W")
mSettings->platform(Settings::Win32W);
else if (platform == "win64")
mSettings->platform(Settings::Win64);
else if (platform == "unix32")
mSettings->platform(Settings::Unix32);
else if (platform == "unix64")
mSettings->platform(Settings::Unix64);
else if (platform == "native")
mSettings->platform(Settings::Native);
else if (platform == "unspecified")
mSettings->platform(Settings::Unspecified);
else if (!mSettings->loadPlatformFile(argv[0], platform)) {
std::string message("unrecognized platform: \"");
message += platform;
message += "\".";
printError(message);
return false;
}
}
// Write results in results.plist
else if (std::strncmp(argv[i], "--plist-output=", 15) == 0) {
mSettings->plistOutput = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 15));
if (mSettings->plistOutput.empty())
mSettings->plistOutput = "./";
else if (!endsWith(mSettings->plistOutput,'/'))
mSettings->plistOutput += '/';
const std::string plistOutput = Path::toNativeSeparators(mSettings->plistOutput);
if (!FileLister::isDirectory(plistOutput)) {
std::string message("plist folder does not exist: \"");
message += plistOutput;
message += "\".";
printError(message);
return false;
}
}
// Special Cppcheck Premium options
else if (std::strncmp(argv[i], "--premium=", 10) == 0 && isCppcheckPremium()) {
if (!mSettings->premiumArgs.empty())
mSettings->premiumArgs += " ";
const std::string p(argv[i] + 10);
mSettings->premiumArgs += "--" + p;
if (p == "misra-c-2012")
mSettings->addons.emplace("misra");
}
// --project
else if (std::strncmp(argv[i], "--project=", 10) == 0) {
mSettings->checkAllConfigurations = false; // Can be overridden with --max-configs or --force
const std::string projectFile = argv[i]+10;
ImportProject::Type projType = mSettings->project.import(projectFile, mSettings);
mSettings->project.projectType = projType;
if (projType == ImportProject::Type::CPPCHECK_GUI) {
mPathNames = mSettings->project.guiProject.pathNames;
for (const std::string &lib : mSettings->project.guiProject.libraries)
mSettings->libraries.emplace_back(lib);
for (const std::string &ignorePath : mSettings->project.guiProject.excludedPaths)
mIgnoredPaths.emplace_back(ignorePath);
const std::string platform(mSettings->project.guiProject.platform);
if (platform == "win32A")
mSettings->platform(Settings::Win32A);
else if (platform == "win32W")
mSettings->platform(Settings::Win32W);
else if (platform == "win64")
mSettings->platform(Settings::Win64);
else if (platform == "unix32")
mSettings->platform(Settings::Unix32);
else if (platform == "unix64")
mSettings->platform(Settings::Unix64);
else if (platform == "native")
mSettings->platform(Settings::Native);
else if (platform == "unspecified" || platform == "Unspecified" || platform.empty())
;
else if (!mSettings->loadPlatformFile(projectFile.c_str(), platform) && !mSettings->loadPlatformFile(argv[0], platform)) {
std::string message("unrecognized platform: \"");
message += platform;
message += "\".";
printError(message);
return false;
}
if (!mSettings->project.guiProject.projectFile.empty())
projType = mSettings->project.import(mSettings->project.guiProject.projectFile, mSettings);
}
if (projType == ImportProject::Type::VS_SLN || projType == ImportProject::Type::VS_VCXPROJ) {
if (mSettings->project.guiProject.analyzeAllVsConfigs == "false")
mSettings->project.selectOneVsConfig(mSettings->platformType);
if (!CppCheckExecutor::tryLoadLibrary(mSettings->library, argv[0], "windows.cfg")) {
// This shouldn't happen normally.
printError("failed to load 'windows.cfg'. Your Cppcheck installation is broken. Please re-install.");
return false;
}
}
if (projType == ImportProject::Type::MISSING) {
printError("failed to open project '" + projectFile + "'. The file does not exist.");
return false;
}
if (projType == ImportProject::Type::UNKNOWN) {
printError("failed to load project '" + projectFile + "'. The format is unknown.");
return false;
}
if (projType == ImportProject::Type::FAILURE) {
printError("failed to load project '" + projectFile + "'. An error occurred.");
return false;
}
}
// --project-configuration
else if (std::strncmp(argv[i], "--project-configuration=", 24) == 0) {
mVSConfig = argv[i] + 24;
if (!mVSConfig.empty() && (mSettings->project.projectType == ImportProject::Type::VS_SLN || mSettings->project.projectType == ImportProject::Type::VS_VCXPROJ))
mSettings->project.ignoreOtherConfigs(mVSConfig);
}
// Only print something when there are errors
else if (std::strcmp(argv[i], "-q") == 0 || std::strcmp(argv[i], "--quiet") == 0)
mSettings->quiet = true;
// Output relative paths
else if (std::strcmp(argv[i], "-rp") == 0 || std::strcmp(argv[i], "--relative-paths") == 0)
mSettings->relativePaths = true;
else if (std::strncmp(argv[i], "-rp=", 4) == 0 || std::strncmp(argv[i], "--relative-paths=", 17) == 0) {
mSettings->relativePaths = true;
if (argv[i][argv[i][3]=='='?4:17] != 0) {
std::string paths = argv[i]+(argv[i][3]=='='?4:17);
for (;;) {
const std::string::size_type pos = paths.find(';');
if (pos == std::string::npos) {
mSettings->basePaths.emplace_back(Path::fromNativeSeparators(paths));
break;
}
mSettings->basePaths.emplace_back(Path::fromNativeSeparators(paths.substr(0, pos)));
paths.erase(0, pos + 1);
}
} else {
printError("no paths specified for the '" + std::string(argv[i]) + "' option.");
return false;
}
}
// Report progress
else if (std::strcmp(argv[i], "--report-progress") == 0) {
mSettings->reportProgress = true;
}
#ifdef HAVE_RULES
// Rule given at command line
else if (std::strncmp(argv[i], "--rule=", 7) == 0) {
Settings::Rule rule;
rule.pattern = 7 + argv[i];
mSettings->rules.emplace_back(rule);
}
// Rule file
else if (std::strncmp(argv[i], "--rule-file=", 12) == 0) {
tinyxml2::XMLDocument doc;
if (doc.LoadFile(12+argv[i]) == tinyxml2::XML_SUCCESS) {
tinyxml2::XMLElement *node = doc.FirstChildElement();
if (node && strcmp(node->Value(), "rules") == 0)
node = node->FirstChildElement("rule");
for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) {
Settings::Rule rule;
tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist");
if (tokenlist)
rule.tokenlist = tokenlist->GetText();
tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern");
if (pattern) {
rule.pattern = pattern->GetText();
}
tinyxml2::XMLElement *message = node->FirstChildElement("message");
if (message) {
tinyxml2::XMLElement *severity = message->FirstChildElement("severity");
if (severity)
rule.severity = Severity::fromString(severity->GetText());
tinyxml2::XMLElement *id = message->FirstChildElement("id");
if (id)
rule.id = id->GetText();
tinyxml2::XMLElement *summary = message->FirstChildElement("summary");
if (summary)
rule.summary = summary->GetText() ? summary->GetText() : "";
}
if (!rule.pattern.empty())
mSettings->rules.emplace_back(rule);
}
} else {
printError("unable to load rule-file: " + std::string(12+argv[i]));
return false;
}
}
#endif
// show timing information..
else if (std::strncmp(argv[i], "--showtime=", 11) == 0) {
const std::string showtimeMode = argv[i] + 11;
if (showtimeMode == "file")
mSettings->showtime = SHOWTIME_MODES::SHOWTIME_FILE;
else if (showtimeMode == "summary")
mSettings->showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY;
else if (showtimeMode == "top5")
mSettings->showtime = SHOWTIME_MODES::SHOWTIME_TOP5;
else if (showtimeMode.empty())
mSettings->showtime = SHOWTIME_MODES::SHOWTIME_NONE;
else {
printError("unrecognized showtime mode: \"" + showtimeMode + "\". Supported modes: file, summary, top5.");
return false;
}
}
// --std
else if (std::strncmp(argv[i], "--std=", 6) == 0) {
const std::string std = argv[i] + 6;
// TODO: print error when standard is unknown
if (std::strncmp(std.c_str(), "c++", 3) == 0) {
mSettings->standards.cpp = Standards::getCPP(std);
}
else if (std::strncmp(std.c_str(), "c", 1) == 0) {
mSettings->standards.c = Standards::getC(std);
}
else {
printError("unknown --std value '" + std + "'");
return false;
}
}
else if (std::strncmp(argv[i], "--suppress=", 11) == 0) {
const std::string suppression = argv[i]+11;
const std::string errmsg(mSettings->nomsg.addSuppressionLine(suppression));
if (!errmsg.empty()) {
printError(errmsg);
return false;
}
}
// Filter errors
else if (std::strncmp(argv[i], "--suppressions-list=", 20) == 0) {
std::string filename = argv[i]+20;
std::ifstream f(filename);
if (!f.is_open()) {
std::string message("couldn't open the file: \"");
message += filename;
message += "\".";
if (std::count(filename.begin(), filename.end(), ',') > 0 ||
std::count(filename.begin(), filename.end(), '.') > 1) {
// If user tried to pass multiple files (we can only guess that)
// e.g. like this: --suppressions-list=a.txt,b.txt
// print more detailed error message to tell user how he can solve the problem
message += "\nIf you want to pass two files, you can do it e.g. like this:";
message += "\n cppcheck --suppressions-list=a.txt --suppressions-list=b.txt file.cpp";
}
printError(message);
return false;
}
const std::string errmsg(mSettings->nomsg.parseFile(f));
if (!errmsg.empty()) {
printError(errmsg);
return false;
}
}
else if (std::strncmp(argv[i], "--suppress-xml=", 15) == 0) {
const char * filename = argv[i] + 15;
const std::string errmsg(mSettings->nomsg.parseXmlFile(filename));
if (!errmsg.empty()) {
printError(errmsg);
return false;
}
}
// Output formatter
else if (std::strcmp(argv[i], "--template") == 0 ||
std::strncmp(argv[i], "--template=", 11) == 0) {
// "--template format"
if (argv[i][10] == '=')
mSettings->templateFormat = argv[i] + 11;
else if ((i+1) < argc && argv[i+1][0] != '-') {
++i;
mSettings->templateFormat = argv[i];
} else {
printError("argument to '--template' is missing.");
return false;
}
if (mSettings->templateFormat == "gcc") {
mSettings->templateFormat = "{bold}{file}:{line}:{column}: {magenta}warning:{default} {message} [{id}]{reset}\\n{code}";
mSettings->templateLocation = "{bold}{file}:{line}:{column}: {dim}note:{reset} {info}\\n{code}";
} else if (mSettings->templateFormat == "daca2") {
mSettings->daca = true;
mSettings->templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]";
mSettings->templateLocation = "{file}:{line}:{column}: note: {info}";
} else if (mSettings->templateFormat == "vs")
mSettings->templateFormat = "{file}({line}): {severity}: {message}";
else if (mSettings->templateFormat == "edit")
mSettings->templateFormat = "{file} +{line}: {severity}: {message}";
else if (mSettings->templateFormat == "cppcheck1")
mSettings->templateFormat = "{callstack}: ({severity}{inconclusive:, inconclusive}) {message}";
else if (mSettings->templateFormat == "selfcheck") {
mSettings->templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}";
mSettings->templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}";
mSettings->daca = true;
}
}
else if (std::strcmp(argv[i], "--template-location") == 0 ||
std::strncmp(argv[i], "--template-location=", 20) == 0) {
// "--template-location format"
if (argv[i][19] == '=')
mSettings->templateLocation = argv[i] + 20;
else if ((i+1) < argc && argv[i+1][0] != '-') {
++i;
mSettings->templateLocation = argv[i];
} else {
printError("argument to '--template' is missing.");
return false;
}
}
else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0)
mSettings->verbose = true;
else if (std::strcmp(argv[i], "--version") == 0) {
mShowVersion = true;
mExitAfterPrint = true;
mSettings->loadCppcheckCfg();
return true;
}
// Write results in results.xml
else if (std::strcmp(argv[i], "--xml") == 0)
mSettings->xml = true;
// Define the XML file version (and enable XML output)
else if (std::strncmp(argv[i], "--xml-version=", 14) == 0) {
const std::string numberString(argv[i]+14);
std::istringstream iss(numberString);
if (!(iss >> mSettings->xml_version)) {
printError("argument to '--xml-version' is not a number.");
return false;
}
if (mSettings->xml_version != 2) {
// We only have xml version 2
printError("'--xml-version' can only be 2.");
return false;
}
// Enable also XML if version is set
mSettings->xml = true;
}
else {
std::string message("unrecognized command line option: \"");
message += argv[i];
message += "\".";
printError(message);
return false;
}
}
else {
mPathNames.emplace_back(Path::fromNativeSeparators(Path::removeQuotationMarks(argv[i])));
}
}
mSettings->loadCppcheckCfg();
// Default template format..
if (mSettings->templateFormat.empty()) {
mSettings->templateFormat = "{bold}{file}:{line}:{column}: {red}{inconclusive:{magenta}}{severity}:{inconclusive: inconclusive:}{default} {message} [{id}]{reset}\\n{code}";
if (mSettings->templateLocation.empty())
mSettings->templateLocation = "{bold}{file}:{line}:{column}: {dim}note:{reset} {info}\\n{code}";
}
mSettings->project.ignorePaths(mIgnoredPaths);
if (mSettings->force || maxconfigs)
mSettings->checkAllConfigurations = true;
if (mSettings->force)
mSettings->maxConfigs = INT_MAX;
else if ((def || mSettings->preprocessOnly) && !maxconfigs)
mSettings->maxConfigs = 1U;
if (mSettings->checks.isEnabled(Checks::unusedFunction) && mSettings->jobs > 1) {
printMessage("unusedFunction check can't be used with '-j' option. Disabling unusedFunction check.");
}
if (argc project.fileSettings.empty()) {
printError("no C or C++ source files found.");
return false;
}
// Use paths _pathnames if no base paths for relative path output are given
if (mSettings->basePaths.empty() && mSettings->relativePaths)
mSettings->basePaths = mPathNames;
return true;
}
void CmdLineParser::printHelp()
{
std::cout cppcheckCfgProductName.empty())
mSettings->loadCppcheckCfg();
return mSettings->cppcheckCfgProductName.compare(0, 16, "Cppcheck Premium") == 0;
}