Skip to content

Commit f0866e5

Browse files
authored
improved determination if application is Premium / added TODOs (danmar#7346)
1 parent 43be5c3 commit f0866e5

16 files changed

+249
-93
lines changed

cli/cmdlineparser.cpp

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,37 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
324324
// default to --check-level=normal from CLI for now
325325
mSettings.setCheckLevel(Settings::CheckLevel::normal);
326326

327+
// read --debug-lookup early so the option is available for the cppcheck.cfg loading
328+
for (int i = 1; i < argc; i++) {
329+
// Show debug warnings for lookup for configuration files
330+
if (std::strcmp(argv[i], "--debug-lookup") == 0)
331+
mSettings.debuglookup = true;
332+
333+
else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0) {
334+
const std::string lookup = argv[i] + 15;
335+
if (lookup == "all")
336+
mSettings.debuglookup = true;
337+
else if (lookup == "addon")
338+
mSettings.debuglookupAddon = true;
339+
else if (lookup == "config")
340+
mSettings.debuglookupConfig = true;
341+
else if (lookup == "library")
342+
mSettings.debuglookupLibrary = true;
343+
else if (lookup == "platform")
344+
mSettings.debuglookupPlatform = true;
345+
else
346+
{
347+
mLogger.printError("unknown lookup '" + lookup + "'");
348+
return Result::Fail;
349+
}
350+
}
351+
}
352+
353+
if (!loadCppcheckCfg())
354+
return Result::Fail;
355+
327356
if (argc <= 1) {
328-
printHelp();
357+
printHelp(mSettings.premium);
329358
return Result::Exit;
330359
}
331360

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

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

363390
// Print help
364391
if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) {
365-
printHelp();
392+
printHelp(mSettings.premium);
366393
return Result::Exit;
367394
}
368395

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

376403
if (std::strcmp(argv[i], "--version") == 0) {
377-
if (!loadCppcheckCfg())
378-
return Result::Fail;
379404
const std::string version = getVersion();
380405
mLogger.printRaw(version); // TODO: should not include newline
381406
return Result::Exit;
@@ -617,28 +642,11 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
617642
std::strcmp(argv[i], "--debug-normal") == 0)
618643
debug = true;
619644

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

624-
else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0) {
625-
const std::string lookup = argv[i] + 15;
626-
if (lookup == "all")
627-
mSettings.debuglookup = true;
628-
else if (lookup == "addon")
629-
mSettings.debuglookupAddon = true;
630-
else if (lookup == "config")
631-
mSettings.debuglookupConfig = true;
632-
else if (lookup == "library")
633-
mSettings.debuglookupLibrary = true;
634-
else if (lookup == "platform")
635-
mSettings.debuglookupPlatform = true;
636-
else
637-
{
638-
mLogger.printError("unknown lookup '" + lookup + "'");
639-
return Result::Fail;
640-
}
641-
}
648+
else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0)
649+
continue; // already handled above
642650

643651
// Flag used for various purposes during debugging
644652
else if (std::strcmp(argv[i], "--debug-simplified") == 0)
@@ -1008,6 +1016,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
10081016
mSettings.cppHeaderProbe = false;
10091017
}
10101018

1019+
else if (std::strcmp(argv[i], "--no-safety") == 0)
1020+
mSettings.safety = false;
1021+
10111022
// Write results in file
10121023
else if (std::strncmp(argv[i], "--output-file=", 14) == 0)
10131024
mSettings.outputFile = Path::simplifyPath(argv[i] + 14);
@@ -1090,7 +1101,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
10901101
}
10911102

10921103
// Special Cppcheck Premium options
1093-
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && isCppcheckPremium()) {
1104+
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && mSettings.premium) {
10941105
// valid options --premium=..
10951106
const std::set<std::string> valid{
10961107
"autosar",
@@ -1108,7 +1119,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
11081119
"misra-c++-2023",
11091120
"misra-cpp-2023",
11101121
"bughunting",
1111-
"safety",
1122+
"safety", // TODO: deprecate in favor of the regular --saftey/--no-safety
11121123
"debug-progress"};
11131124
// valid options --premium-..=
11141125
const std::set<std::string> valid2{
@@ -1151,7 +1162,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
11511162

11521163
mSettings.checkAllConfigurations = false; // Can be overridden with --max-configs or --force
11531164
std::string projectFile = argv[i]+10;
1154-
projectType = project.import(projectFile, &mSettings, &mSuppressions, isCppcheckPremium());
1165+
projectType = project.import(projectFile, &mSettings, &mSuppressions);
11551166
if (projectType == ImportProject::Type::CPPCHECK_GUI) {
11561167
for (const std::string &lib : project.guiProject.libraries)
11571168
mSettings.libraries.emplace_back(lib);
@@ -1564,9 +1575,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
15641575
}
15651576
}
15661577

1567-
if (!loadCppcheckCfg())
1568-
return Result::Fail;
1569-
15701578
// TODO: bail out?
15711579
if (!executorAuto && mSettings.useSingleJob())
15721580
mLogger.printMessage("'--executor' has no effect as only a single job will be used.");
@@ -1690,13 +1698,15 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
16901698
return Result::Success;
16911699
}
16921700

1693-
void CmdLineParser::printHelp() const
1701+
void CmdLineParser::printHelp(bool premium) const
16941702
{
1695-
const std::string manualUrl(isCppcheckPremium() ?
1696-
"https://cppcheck.sourceforge.io/manual.pdf" :
1697-
"https://files.cppchecksolutions.com/manual.pdf");
1703+
// TODO: fetch URL from config like product name?
1704+
const std::string manualUrl(premium ?
1705+
"https://files.cppchecksolutions.com/manual.pdf" :
1706+
"https://cppcheck.sourceforge.io/manual.pdf");
16981707

16991708
std::ostringstream oss;
1709+
// TODO: display product name
17001710
oss << "Cppcheck - A tool for static C/C++ code analysis\n"
17011711
"\n"
17021712
"Syntax:\n"
@@ -1890,7 +1900,7 @@ void CmdLineParser::printHelp() const
18901900
" --plist-output=<path>\n"
18911901
" Generate Clang-plist output files in folder.\n";
18921902

1893-
if (isCppcheckPremium()) {
1903+
if (premium) {
18941904
oss <<
18951905
" --premium=<option>\n"
18961906
" Coding standards:\n"
@@ -2073,6 +2083,7 @@ void CmdLineParser::printHelp() const
20732083
}
20742084

20752085
std::string CmdLineParser::getVersion() const {
2086+
// TODO: this should not contain the version - it should set the extraVersion
20762087
if (!mSettings.cppcheckCfgProductName.empty())
20772088
return mSettings.cppcheckCfgProductName;
20782089
const char * const extraVersion = CppCheck::extraVersion();
@@ -2081,12 +2092,6 @@ std::string CmdLineParser::getVersion() const {
20812092
return std::string("Cppcheck ") + CppCheck::version();
20822093
}
20832094

2084-
bool CmdLineParser::isCppcheckPremium() const {
2085-
if (mSettings.cppcheckCfgProductName.empty())
2086-
Settings::loadCppcheckCfg(mSettings, mSuppressions, mSettings.debuglookup || mSettings.debuglookupConfig);
2087-
return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
2088-
}
2089-
20902095
bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool debug)
20912096
{
20922097
const Library::Error err = destination.load(basepath.c_str(), filename, debug);
@@ -2179,13 +2184,19 @@ bool CmdLineParser::loadAddons(Settings& settings)
21792184

21802185
bool CmdLineParser::loadCppcheckCfg()
21812186
{
2182-
if (!mSettings.cppcheckCfgProductName.empty())
2183-
return true;
2187+
if (!mSettings.settingsFiles.empty())
2188+
{
2189+
// should never happen - programming error
2190+
mLogger.printError("cppcheck.cfg has already been loaded from " + mSettings.settingsFiles[0]);
2191+
return false;
2192+
}
21842193
const std::string cfgErr = Settings::loadCppcheckCfg(mSettings, mSuppressions, mSettings.debuglookup || mSettings.debuglookupConfig);
21852194
if (!cfgErr.empty()) {
2195+
// TODO: log full path
21862196
mLogger.printError("could not load cppcheck.cfg - " + cfgErr);
21872197
return false;
21882198
}
2199+
mSettings.premium = startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
21892200
return true;
21902201
}
21912202

cli/cmdlineparser.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,7 @@ class CmdLineParser {
109109
/**
110110
* Print help text to the console.
111111
*/
112-
void printHelp() const;
113-
114-
bool isCppcheckPremium() const;
112+
void printHelp(bool premium) const;
115113

116114
template<typename T>
117115
bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false)

gui/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ static void ShowUsage()
124124

125125
static void ShowVersion()
126126
{
127+
// TODO: should only *not* show a dialog when we are on a commnd-line
127128
#if defined(_WIN32)
128129
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), 0);
129130
dlg->exec();

gui/mainwindow.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,8 @@ bool MainWindow::getCppcheckSettings(Settings& settings, Suppressions& supprs)
10911091
return false;
10921092
}
10931093

1094+
settings.premium = startsWith(settings.cppcheckCfgProductName, "Cppcheck Premium");
1095+
10941096
const auto cfgAddons = settings.addons;
10951097
settings.addons.clear();
10961098
for (const std::string& addon : cfgAddons) {
@@ -1757,6 +1759,7 @@ void MainWindow::formatAndSetTitle(const QString &text)
17571759
nameWithVersion += " (" + extraVersion + ")";
17581760
}
17591761

1762+
// TODO: should not contain the version
17601763
if (!mCppcheckCfgProductName.isEmpty())
17611764
nameWithVersion = mCppcheckCfgProductName;
17621765

@@ -2285,7 +2288,9 @@ void MainWindow::replyFinished(QNetworkReply *reply) {
22852288
const QString str = reply->readAll();
22862289
qDebug() << "Response: " << str;
22872290
if (reply->url().fileName() == "version.txt") {
2291+
// TODO: lacks extra version
22882292
QString nameWithVersion = QString("Cppcheck %1").arg(CppCheck::version());
2293+
// TODO: this should not contain the version
22892294
if (!mCppcheckCfgProductName.isEmpty())
22902295
nameWithVersion = mCppcheckCfgProductName;
22912296
const int appVersion = getVersion(nameWithVersion);

gui/xmlreportv2.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ void XmlReportV2::writeHeader()
9494
{
9595
const auto nameAndVersion = Settings::getNameAndVersion(mProductName.toStdString());
9696
const QString name = QString::fromStdString(nameAndVersion.first);
97+
// TODO: lacks extraVersion
9798
const QString version = nameAndVersion.first.empty() ? CppCheck::version() : QString::fromStdString(nameAndVersion.second);
9899

99100
mXmlWriter->setAutoFormatting(true);

lib/errorlogger.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ std::string ErrorMessage::getXMLHeader(std::string productName, int xmlVersion)
437437
{
438438
const auto nameAndVersion = Settings::getNameAndVersion(productName);
439439
productName = nameAndVersion.first;
440+
// TODO: lacks extra version
440441
const std::string version = nameAndVersion.first.empty() ? CppCheck::version() : nameAndVersion.second;
441442

442443
tinyxml2::XMLPrinter printer;

lib/importproject.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ void ImportProject::fsSetIncludePaths(FileSettings& fs, const std::string &basep
164164
}
165165
}
166166

167-
ImportProject::Type ImportProject::import(const std::string &filename, Settings *settings, Suppressions *supprs, bool premium)
167+
ImportProject::Type ImportProject::import(const std::string &filename, Settings *settings, Suppressions *supprs)
168168
{
169169
std::ifstream fin(filename);
170170
if (!fin.is_open())
@@ -200,7 +200,7 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
200200
return ImportProject::Type::BORLAND;
201201
}
202202
} else if (settings && supprs && endsWith(filename, ".cppcheck")) {
203-
if (importCppcheckGuiProject(fin, *settings, *supprs, premium)) {
203+
if (importCppcheckGuiProject(fin, *settings, *supprs)) {
204204
setRelativePaths(filename);
205205
return ImportProject::Type::CPPCHECK_GUI;
206206
}
@@ -1290,7 +1290,7 @@ static std::string istream_to_string(std::istream &istr)
12901290
return std::string(std::istreambuf_iterator<char>(istr), eos);
12911291
}
12921292

1293-
bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs, bool premium)
1293+
bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs)
12941294
{
12951295
tinyxml2::XMLDocument doc;
12961296
const std::string xmldata = istream_to_string(istr);
@@ -1374,7 +1374,7 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings &setti
13741374
else if (strcmp(name, CppcheckXml::AddonsElementName) == 0) {
13751375
const auto& addons = readXmlStringList(node, "", CppcheckXml::AddonElementName, nullptr);
13761376
temp.addons.insert(addons.cbegin(), addons.cend());
1377-
if (premium) {
1377+
if (settings.premium) {
13781378
auto it = temp.addons.find("misra");
13791379
if (it != temp.addons.end()) {
13801380
temp.addons.erase(it);

lib/importproject.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
9898
void ignorePaths(const std::vector<std::string> &ipaths, bool debug = false);
9999
void ignoreOtherConfigs(const std::string &cfg);
100100

101-
Type import(const std::string &filename, Settings *settings=nullptr, Suppressions *supprs=nullptr, bool premium=false);
101+
Type import(const std::string &filename, Settings *settings=nullptr, Suppressions *supprs=nullptr);
102102
protected:
103103
bool importCompileCommands(std::istream &istr);
104-
bool importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs, bool premium);
104+
bool importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs);
105105

106106
private:
107107
struct SharedItemsProject {

lib/settings.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ Settings::Settings()
6767

6868
std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppressions, bool debug)
6969
{
70-
// TODO: this always needs to be run *after* the Settings has been filled
7170
static const std::string cfgFilename = "cppcheck.cfg";
7271
std::string fileName;
7372
#ifdef FILESDIR
@@ -82,7 +81,7 @@ std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppress
8281
// cppcheck-suppress knownConditionTrueFalse
8382
if (fileName.empty()) {
8483
// TODO: make sure that exename is set
85-
fileName = Path::getPathFromFilename(settings.exename) + cfgFilename;
84+
fileName = Path::join(Path::getPathFromFilename(settings.exename), cfgFilename);
8685
if (debug)
8786
std::cout << "looking for '" << fileName << "'" << std::endl;
8887
if (!Path::isFile(fileName))
@@ -163,10 +162,12 @@ std::string Settings::loadCppcheckCfg(Settings& settings, Suppressions& suppress
163162
const auto& v = it->second;
164163
if (!v.is<bool>())
165164
return "'safety' is not a bool";
166-
settings.safety = settings.safety || v.get<bool>();
165+
settings.safety = v.get<bool>();
167166
}
168167
}
169168

169+
settings.settingsFiles.emplace_back(std::move(fileName));
170+
170171
return "";
171172
}
172173

lib/settings.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
318318
/** @brief plist output (--plist-output=&lt;dir&gt;) */
319319
std::string plistOutput;
320320

321+
/** @brief Are we Cppcheck Premium */
322+
bool premium{};
323+
321324
/** @brief Extra arguments for Cppcheck Premium addon */
322325
std::string premiumArgs;
323326

@@ -405,6 +408,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
405408

406409
SafeChecks safeChecks;
407410

411+
/** @brief the files we successfully loaded settings from */
412+
std::vector<std::string> settingsFiles;
413+
408414
SimpleEnableGroup<Severity> severity;
409415
SimpleEnableGroup<Certainty> certainty;
410416
SimpleEnableGroup<Checks> checks;

0 commit comments

Comments
 (0)