Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 56 additions & 45 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,37 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
// default to --check-level=normal from CLI for now
mSettings.setCheckLevel(Settings::CheckLevel::normal);

// read --debug-lookup early so the option is available for the cppcheck.cfg loading
for (int i = 1; i < argc; i++) {
// Show debug warnings for lookup for configuration files
if (std::strcmp(argv[i], "--debug-lookup") == 0)
mSettings.debuglookup = true;

else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0) {
const std::string lookup = argv[i] + 15;
if (lookup == "all")
mSettings.debuglookup = true;
else if (lookup == "addon")
mSettings.debuglookupAddon = true;
else if (lookup == "config")
mSettings.debuglookupConfig = true;
else if (lookup == "library")
mSettings.debuglookupLibrary = true;
else if (lookup == "platform")
mSettings.debuglookupPlatform = true;
else
{
mLogger.printError("unknown lookup '" + lookup + "'");
return Result::Fail;
}
}
}

if (!loadCppcheckCfg())
return Result::Fail;

if (argc <= 1) {
printHelp();
printHelp(mSettings.premium);
return Result::Exit;
}

Expand All @@ -349,8 +378,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a

// print all possible error messages..
if (std::strcmp(argv[i], "--errorlist") == 0) {
if (!loadCppcheckCfg())
return Result::Fail;
{
XMLErrorMessagesLogger xmlLogger;
std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName, 2);
Expand All @@ -362,7 +389,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a

// Print help
if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) {
printHelp();
printHelp(mSettings.premium);
return Result::Exit;
}

Expand All @@ -374,8 +401,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
}

if (std::strcmp(argv[i], "--version") == 0) {
if (!loadCppcheckCfg())
return Result::Fail;
const std::string version = getVersion();
mLogger.printRaw(version); // TODO: should not include newline
return Result::Exit;
Expand Down Expand Up @@ -614,28 +639,11 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
std::strcmp(argv[i], "--debug-normal") == 0)
debug = true;

// Show debug warnings for lookup for configuration files
else if (std::strcmp(argv[i], "--debug-lookup") == 0)
mSettings.debuglookup = true;
continue; // already handled above

else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0) {
const std::string lookup = argv[i] + 15;
if (lookup == "all")
mSettings.debuglookup = true;
else if (lookup == "addon")
mSettings.debuglookupAddon = true;
else if (lookup == "config")
mSettings.debuglookupConfig = true;
else if (lookup == "library")
mSettings.debuglookupLibrary = true;
else if (lookup == "platform")
mSettings.debuglookupPlatform = true;
else
{
mLogger.printError("unknown lookup '" + lookup + "'");
return Result::Fail;
}
}
else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0)
continue; // already handled above

// Flag used for various purposes during debugging
else if (std::strcmp(argv[i], "--debug-simplified") == 0)
Expand Down Expand Up @@ -1005,6 +1013,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
mSettings.cppHeaderProbe = false;
}

else if (std::strcmp(argv[i], "--no-safety") == 0)
mSettings.safety = false;

// Write results in file
else if (std::strncmp(argv[i], "--output-file=", 14) == 0)
mSettings.outputFile = Path::simplifyPath(argv[i] + 14);
Expand Down Expand Up @@ -1087,7 +1098,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
}

// Special Cppcheck Premium options
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && isCppcheckPremium()) {
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && mSettings.premium) {
// valid options --premium=..
const std::set<std::string> valid{
"autosar",
Expand All @@ -1105,7 +1116,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
"misra-c++-2023",
"misra-cpp-2023",
"bughunting",
"safety",
"safety", // TODO: deprecate in favor of the regular --saftey/--no-safety
"debug-progress"};
// valid options --premium-..=
const std::set<std::string> valid2{
Expand Down Expand Up @@ -1148,7 +1159,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a

mSettings.checkAllConfigurations = false; // Can be overridden with --max-configs or --force
std::string projectFile = argv[i]+10;
projectType = project.import(projectFile, &mSettings, &mSuppressions, isCppcheckPremium());
projectType = project.import(projectFile, &mSettings, &mSuppressions);
if (projectType == ImportProject::Type::CPPCHECK_GUI) {
for (const std::string &lib : project.guiProject.libraries)
mSettings.libraries.emplace_back(lib);
Expand Down Expand Up @@ -1561,9 +1572,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
}
}

if (!loadCppcheckCfg())
return Result::Fail;

// TODO: bail out?
if (!executorAuto && mSettings.useSingleJob())
mLogger.printMessage("'--executor' has no effect as only a single job will be used.");
Expand Down Expand Up @@ -1687,13 +1695,15 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
return Result::Success;
}

void CmdLineParser::printHelp() const
void CmdLineParser::printHelp(bool premium) const
{
const std::string manualUrl(isCppcheckPremium() ?
"https://cppcheck.sourceforge.io/manual.pdf" :
"https://files.cppchecksolutions.com/manual.pdf");
// TODO: fetch URL from config like product name?
const std::string manualUrl(premium ?
"https://files.cppchecksolutions.com/manual.pdf" :
"https://cppcheck.sourceforge.io/manual.pdf");
Comment on lines +1701 to +1703
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were switched.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also we should not have the custom URL hardcoded and read it from cppcheck.cfg like the product name instead. I files https://trac.cppcheck.net/ticket/14208 about this.


std::ostringstream oss;
// TODO: display product name
oss << "Cppcheck - A tool for static C/C++ code analysis\n"
"\n"
"Syntax:\n"
Expand Down Expand Up @@ -1894,7 +1904,7 @@ void CmdLineParser::printHelp() const
" --plist-output=<path>\n"
" Generate Clang-plist output files in folder.\n";

if (isCppcheckPremium()) {
if (premium) {
oss <<
" --premium=<option>\n"
" Coding standards:\n"
Expand Down Expand Up @@ -2077,6 +2087,7 @@ void CmdLineParser::printHelp() const
}

std::string CmdLineParser::getVersion() const {
// TODO: this should not contain the version - it should set the extraVersion
if (!mSettings.cppcheckCfgProductName.empty())
return mSettings.cppcheckCfgProductName;
const char * const extraVersion = CppCheck::extraVersion();
Expand All @@ -2085,12 +2096,6 @@ std::string CmdLineParser::getVersion() const {
return std::string("Cppcheck ") + CppCheck::version();
}

bool CmdLineParser::isCppcheckPremium() const {
if (mSettings.cppcheckCfgProductName.empty())
Settings::loadCppcheckCfg(mSettings, mSuppressions, mSettings.debuglookup || mSettings.debuglookupConfig);
return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
}

bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool debug)
{
const Library::Error err = destination.load(basepath.c_str(), filename, debug);
Expand Down Expand Up @@ -2183,13 +2188,19 @@ bool CmdLineParser::loadAddons(Settings& settings)

bool CmdLineParser::loadCppcheckCfg()
{
if (!mSettings.cppcheckCfgProductName.empty())
return true;
if (!mSettings.settingsFiles.empty())
{
// should never happen - programming error
mLogger.printError("cppcheck.cfg has already been loaded from " + mSettings.settingsFiles[0]);
return false;
}
const std::string cfgErr = Settings::loadCppcheckCfg(mSettings, mSuppressions, mSettings.debuglookup || mSettings.debuglookupConfig);
if (!cfgErr.empty()) {
// TODO: log full path
mLogger.printError("could not load cppcheck.cfg - " + cfgErr);
return false;
}
mSettings.premium = startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
return true;
}

Expand Down
4 changes: 1 addition & 3 deletions cli/cmdlineparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,9 @@ class CmdLineParser {
/**
* Print help text to the console.
*/
void printHelp() const;
void printHelp(bool premium) const;

private:
bool isCppcheckPremium() const;

template<typename T>
bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false)
{
Expand Down
1 change: 1 addition & 0 deletions gui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ static void ShowUsage()

static void ShowVersion()
{
// TODO: should only *not* show a dialog when we are on a commnd-line
#if defined(_WIN32)
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), 0);
dlg->exec();
Expand Down
5 changes: 5 additions & 0 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,8 @@ bool MainWindow::getCppcheckSettings(Settings& settings, Suppressions& supprs)
return false;
}

settings.premium = startsWith(settings.cppcheckCfgProductName, "Cppcheck Premium");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it feels like this line of code belongs in LIB?


const auto cfgAddons = settings.addons;
settings.addons.clear();
for (const std::string& addon : cfgAddons) {
Expand Down Expand Up @@ -1754,6 +1756,7 @@ void MainWindow::formatAndSetTitle(const QString &text)
nameWithVersion += " (" + extraVersion + ")";
}

// TODO: should not contain the version
if (!mCppcheckCfgProductName.isEmpty())
nameWithVersion = mCppcheckCfgProductName;

Expand Down Expand Up @@ -2282,7 +2285,9 @@ void MainWindow::replyFinished(QNetworkReply *reply) {
const QString str = reply->readAll();
qDebug() << "Response: " << str;
if (reply->url().fileName() == "version.txt") {
// TODO: lacks extra version
QString nameWithVersion = QString("Cppcheck %1").arg(CppCheck::version());
// TODO: this should not contain the version
if (!mCppcheckCfgProductName.isEmpty())
nameWithVersion = mCppcheckCfgProductName;
const int appVersion = getVersion(nameWithVersion);
Expand Down
1 change: 1 addition & 0 deletions gui/xmlreportv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ void XmlReportV2::writeHeader()
{
const auto nameAndVersion = Settings::getNameAndVersion(mProductName.toStdString());
const QString name = QString::fromStdString(nameAndVersion.first);
// TODO: lacks extraVersion
const QString version = nameAndVersion.first.empty() ? CppCheck::version() : QString::fromStdString(nameAndVersion.second);

mXmlWriter->setAutoFormatting(true);
Expand Down
1 change: 1 addition & 0 deletions lib/errorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ std::string ErrorMessage::getXMLHeader(std::string productName, int xmlVersion)
{
const auto nameAndVersion = Settings::getNameAndVersion(productName);
productName = nameAndVersion.first;
// TODO: lacks extra version
const std::string version = nameAndVersion.first.empty() ? CppCheck::version() : nameAndVersion.second;

tinyxml2::XMLPrinter printer;
Expand Down
8 changes: 4 additions & 4 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void ImportProject::fsSetIncludePaths(FileSettings& fs, const std::string &basep
}
}

ImportProject::Type ImportProject::import(const std::string &filename, Settings *settings, Suppressions *supprs, bool premium)
ImportProject::Type ImportProject::import(const std::string &filename, Settings *settings, Suppressions *supprs)
{
std::ifstream fin(filename);
if (!fin.is_open())
Expand Down Expand Up @@ -201,7 +201,7 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
return ImportProject::Type::BORLAND;
}
} else if (settings && supprs && endsWith(filename, ".cppcheck")) {
if (importCppcheckGuiProject(fin, *settings, *supprs, premium)) {
if (importCppcheckGuiProject(fin, *settings, *supprs)) {
setRelativePaths(filename);
return ImportProject::Type::CPPCHECK_GUI;
}
Expand Down Expand Up @@ -1291,7 +1291,7 @@ static std::string istream_to_string(std::istream &istr)
return std::string(std::istreambuf_iterator<char>(istr), eos);
}

bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs, bool premium)
bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs)
{
tinyxml2::XMLDocument doc;
const std::string xmldata = istream_to_string(istr);
Expand Down Expand Up @@ -1375,7 +1375,7 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
else if (strcmp(name, CppcheckXml::AddonsElementName) == 0) {
const auto& addons = readXmlStringList(node, "", CppcheckXml::AddonElementName, nullptr);
temp.addons.insert(addons.cbegin(), addons.cend());
if (premium) {
if (settings.premium) {
auto it = temp.addons.find("misra");
if (it != temp.addons.end()) {
temp.addons.erase(it);
Expand Down
4 changes: 2 additions & 2 deletions lib/importproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
void ignorePaths(const std::vector<std::string> &ipaths, bool debug = false);
void ignoreOtherConfigs(const std::string &cfg);

Type import(const std::string &filename, Settings *settings=nullptr, Suppressions *supprs=nullptr, bool premium=false);
Type import(const std::string &filename, Settings *settings=nullptr, Suppressions *supprs=nullptr);
protected:
bool importCompileCommands(std::istream &istr);
bool importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs, bool premium);
bool importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs);

private:
struct SharedItemsProject {
Expand Down
7 changes: 4 additions & 3 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ Settings::Settings()

std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppressions, bool debug)
{
// TODO: this always needs to be run *after* the Settings has been filled
static const std::string cfgFilename = "cppcheck.cfg";
std::string fileName;
#ifdef FILESDIR
Expand All @@ -82,7 +81,7 @@ std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppress
// cppcheck-suppress knownConditionTrueFalse
if (fileName.empty()) {
// TODO: make sure that exename is set
fileName = Path::getPathFromFilename(settings.exename) + cfgFilename;
fileName = Path::join(Path::getPathFromFilename(settings.exename), cfgFilename);
if (debug)
std::cout << "looking for '" << fileName << "'" << std::endl;
if (!Path::isFile(fileName))
Expand Down Expand Up @@ -163,10 +162,12 @@ std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppress
const auto& v = it->second;
if (!v.is<bool>())
return "'safety' is not a bool";
settings.safety = settings.safety || v.get<bool>();
settings.safety = v.get<bool>();
}
}

settings.settingsFiles.emplace_back(std::move(fileName));

return "";
}

Expand Down
6 changes: 6 additions & 0 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
/** @brief plist output (--plist-output=&lt;dir&gt;) */
std::string plistOutput;

/** @brief Are we Cppcheck Premium */
bool premium{};

/** @brief Extra arguments for Cppcheck Premium addon */
std::string premiumArgs;

Expand Down Expand Up @@ -405,6 +408,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {

SafeChecks safeChecks;

/** @brief the files we successfully loaded settings from */
std::vector<std::string> settingsFiles;

SimpleEnableGroup<Severity> severity;
SimpleEnableGroup<Certainty> certainty;
SimpleEnableGroup<Checks> checks;
Expand Down
Loading