36 #include <unordered_set>
48 for (std::string i : ipaths) {
49 if (it->filename().size() > i.size() && it->filename().compare(0,i.size(),i)==0) {
59 if (it->filename().size() > i.size() && it->filename().compare(0,i.size(),i)==0) {
84 while (defs.find(
";%(") != std::string::npos) {
85 const std::string::size_type pos1 = defs.find(
";%(");
86 const std::string::size_type pos2 = defs.find(
';', pos1+1);
87 defs.erase(pos1, pos2 == std::string::npos ? pos2 : (pos2-pos1));
89 while (defs.find(
";;") != std::string::npos)
90 defs.erase(defs.find(
";;"),1);
91 while (!defs.empty() && defs[0] ==
';')
93 while (!defs.empty() &&
endsWith(defs,
';'))
94 defs.erase(defs.size() - 1U);
96 for (std::size_t pos = 0; pos < defs.size(); ++pos) {
97 if (defs[pos] ==
'(' || defs[pos] ==
'=')
99 else if (defs[pos] ==
';') {
101 defs.insert(pos,
"=1");
104 if (pos < defs.size())
108 if (!eq && !defs.empty())
115 std::set<std::string, cppcheck::stricmp> expanded;
116 std::string::size_type start = 0;
117 while ((start = s.find(
"$(")) != std::string::npos) {
118 const std::string::size_type end = s.find(
')',start);
119 if (end == std::string::npos)
121 const std::string var = s.substr(start+2,end-start-2);
122 if (expanded.find(var) != expanded.end())
124 expanded.insert(var);
125 std::map<std::string, std::string, cppcheck::stricmp>::const_iterator it1 = variables.find(var);
127 if (it1 == variables.end()) {
128 const char *envValue = std::getenv(var.c_str());
133 variables[var] = std::string(envValue);
134 it1 = variables.find(var);
136 s.replace(start, end - start + 1, it1->second);
138 if (s.find(
"$(") != std::string::npos)
146 std::set<std::string> found;
148 const std::list<std::string> copyIn(in);
150 for (
const std::string &ipath : copyIn) {
156 if (!found.insert(s).second)
158 if (s[0] ==
'/' || (s.size() > 1U && s.compare(1,2,
":/") == 0)) {
166 s.erase(s.size() - 1U);
168 if (s.find(
"$(") == std::string::npos) {
182 std::ifstream fin(filename);
190 const std::vector<std::string> fileFilters =
191 settings ? settings->
fileFilters : std::vector<std::string>();
198 }
else if (
endsWith(filename,
".sln")) {
203 }
else if (
endsWith(filename,
".vcxproj")) {
204 std::map<std::string, std::string, cppcheck::stricmp> variables;
209 }
else if (
endsWith(filename,
".bpr")) {
214 }
else if (settings &&
endsWith(filename,
".cppcheck")) {
225 static std::string
readUntil(
const std::string &command, std::string::size_type *pos,
const char until[])
228 bool escapedString =
false;
231 for (; *pos < command.size() && (str || !std::strchr(until, command[*pos])); (*pos)++) {
234 else if (command[*pos] ==
'\\') {
237 else if (command[*pos + 1] ==
'"') {
240 escapedString =
true;
245 }
else if (command[*pos] ==
'\"')
247 ret += command[*pos];
256 for (
const char c: in) {
259 if (!std::strchr(
"\\\"\'",c))
262 }
else if (c ==
'\\')
275 std::string::size_type pos = 0;
276 while (std::string::npos != (pos = command.find(
' ',pos))) {
277 while (pos < command.size() && command[pos] ==
' ')
279 if (pos >= command.size())
281 if (command[pos] !=
'/' && command[pos] !=
'-')
284 if (pos >= command.size())
286 const char F = command[pos++];
287 if (std::strchr(
"DUI", F)) {
288 while (pos < command.size() && command[pos] ==
' ')
291 const std::string fval =
readUntil(command, &pos,
" =");
293 std::string defval =
readUntil(command, &pos,
" ");
295 if (defval.size() >= 3 &&
startsWith(defval,
"=\"") && defval.back()==
'\"')
296 defval =
"=" +
unescape(defval.substr(2, defval.size() - 3));
297 else if (defval.size() >= 5 &&
startsWith(defval,
"=\\\"") &&
endsWith(defval,
"\\\""))
298 defval =
"=\"" +
unescape(defval.substr(3, defval.size() - 5)) +
"\"";
305 std::string i = fval;
306 if (i.size() > 1 && i[0] ==
'\"' && i.back() ==
'\"')
307 i =
unescape(i.substr(1, i.size() - 2));
313 }
else if (F ==
'i' && fval ==
"system") {
315 std::string isystem =
readUntil(command, &pos,
" ");
318 if (fval ==
"unicode") {
326 }
else if (fval ==
"PIC") {
329 }
else if (fval ==
"pie") {
332 }
else if (fval ==
"PIE") {
345 picojson::value compileCommands;
346 istr >> compileCommands;
347 if (!compileCommands.is<picojson::array>()) {
348 printError(
"compilation database is not a JSON array");
352 for (
const picojson::value &fileInfo : compileCommands.get<picojson::array>()) {
353 picojson::object obj = fileInfo.get<picojson::object>();
361 const std::string directory = std::move(dirpath);
364 if (obj.count(
"arguments")) {
365 if (obj[
"arguments"].is<picojson::array>()) {
366 for (
const picojson::value& arg : obj[
"arguments"].get<picojson::array>()) {
367 if (arg.is<std::string>()) {
368 std::string str = arg.get<std::string>();
369 if (str.find(
' ') != std::string::npos)
370 str =
"\"" + str +
"\"";
371 command += str +
" ";
375 printError(
"'arguments' field in compilation database entry is not a JSON array");
378 }
else if (obj.count(
"command")) {
379 if (obj[
"command"].is<std::string>()) {
380 command = obj[
"command"].get<std::string>();
382 printError(
"'command' field in compilation database entry is not a string");
386 printError(
"no 'arguments' or 'command' field found in compilation database entry");
390 if (!obj.count(
"file") || !obj[
"file"].is<std::string>()) {
391 printError(
"skip compilation database entry because it does not have a proper 'file' field");
405 else if (file[0] ==
'/' && directory.size() > 2 && std::isalpha(directory[0]) && directory[1] ==
':')
414 printError(
"'" + path +
"' from compilation database does not exist");
419 std::map<std::string, std::string, cppcheck::stricmp> variables;
431 if (!std::getline(istr,line)) {
432 printError(
"Visual Studio solution file is empty");
436 if (!
startsWith(line,
"Microsoft Visual Studio Solution File")) {
438 if (!std::getline(istr, line) || !
startsWith(line,
"Microsoft Visual Studio Solution File")) {
439 printError(
"Visual Studio solution file header not found");
444 std::map<std::string,std::string,cppcheck::stricmp> variables;
445 variables[
"SolutionDir"] = path;
449 while (std::getline(istr,line)) {
452 const std::string::size_type pos = line.find(
".vcxproj");
453 if (pos == std::string::npos)
455 const std::string::size_type pos1 = line.rfind(
'\"',pos);
456 if (pos1 == std::string::npos)
458 std::string vcxproj(line.substr(pos1+1, pos-pos1+7));
461 vcxproj = path + vcxproj;
464 printError(
"failed to load '" + vcxproj +
"' from Visual Studio solution");
471 printError(
"no projects found in Visual Studio solution file");
479 struct ProjectConfiguration {
480 explicit ProjectConfiguration(
const tinyxml2::XMLElement *
cfg) {
481 const char *a =
cfg->Attribute(
"Include");
484 for (
const tinyxml2::XMLElement *e =
cfg->FirstChildElement(); e; e = e->NextSiblingElement()) {
487 if (std::strcmp(e->Name(),
"Configuration")==0)
488 configuration = e->GetText();
489 else if (std::strcmp(e->Name(),
"Platform")==0) {
490 platformStr = e->GetText();
491 if (platformStr ==
"Win32")
493 else if (platformStr ==
"x64")
501 std::string configuration;
502 enum { Win32, x64, Unknown } platform = Unknown;
503 std::string platformStr;
506 struct ItemDefinitionGroup {
507 explicit ItemDefinitionGroup(
const tinyxml2::XMLElement *idg, std::string includePaths) : additionalIncludePaths(std::move(includePaths)) {
508 const char *condAttr = idg->Attribute(
"Condition");
510 condition = condAttr;
511 for (
const tinyxml2::XMLElement *e1 = idg->FirstChildElement(); e1; e1 = e1->NextSiblingElement()) {
512 if (std::strcmp(e1->Name(),
"ClCompile") == 0) {
513 enhancedInstructionSet =
"StreamingSIMDExtensions2";
514 for (
const tinyxml2::XMLElement *e = e1->FirstChildElement(); e; e = e->NextSiblingElement()) {
516 if (std::strcmp(e->Name(),
"PreprocessorDefinitions") == 0)
517 preprocessorDefinitions = e->GetText();
518 else if (std::strcmp(e->Name(),
"AdditionalIncludeDirectories") == 0) {
519 if (!additionalIncludePaths.empty())
520 additionalIncludePaths +=
';';
521 additionalIncludePaths += e->GetText();
522 }
else if (std::strcmp(e->Name(),
"LanguageStandard") == 0) {
523 if (std::strcmp(e->GetText(),
"stdcpp14") == 0)
525 else if (std::strcmp(e->GetText(),
"stdcpp17") == 0)
527 else if (std::strcmp(e->GetText(),
"stdcpp20") == 0)
529 else if (std::strcmp(e->GetText(),
"stdcpplatest") == 0)
531 }
else if (std::strcmp(e->Name(),
"EnableEnhancedInstructionSet") == 0) {
532 enhancedInstructionSet = e->GetText();
537 else if (std::strcmp(e1->Name(),
"Link") == 0) {
538 for (
const tinyxml2::XMLElement *e = e1->FirstChildElement(); e; e = e->NextSiblingElement()) {
541 if (std::strcmp(e->Name(),
"EntryPointSymbol") == 0) {
542 entryPointSymbol = e->GetText();
549 static void replaceAll(std::string &c,
const std::string &from,
const std::string &to) {
550 std::string::size_type pos;
551 while ((pos = c.find(from)) != std::string::npos) {
552 c.erase(pos,from.size());
560 if (condition.empty())
562 std::string c =
'(' + condition +
");";
563 replaceAll(c,
"$(Configuration)", p.configuration);
564 replaceAll(c,
"$(Platform)", p.platformStr);
569 std::istringstream istr(c);
570 tokenlist.createTokens(istr, Standards::Language::C);
571 for (
const Token *tok = tokenlist.front(); tok; tok = tok->
next()) {
572 if (tok->str() ==
"(" && tok->astOperand1() && tok->astOperand2()) {
574 if (tok->astOperand1()->expressionString() ==
"Configuration.Contains")
575 return (
'\'' + p.configuration +
'\'') == tok->astOperand2()->str();
577 if (tok->str() ==
"==" && tok->astOperand1() && tok->astOperand2() && tok->astOperand1()->str() == tok->astOperand2()->str())
582 std::string condition;
583 std::string enhancedInstructionSet;
584 std::string preprocessorDefinitions;
585 std::string additionalIncludePaths;
586 std::string entryPointSymbol;
593 std::list<std::string> ret;
594 std::string::size_type pos1 = 0;
595 std::string::size_type pos2;
596 while ((pos2 = s.find(
';',pos1)) != std::string::npos) {
597 ret.push_back(s.substr(pos1, pos2-pos1));
599 if (pos1 >= s.size())
603 ret.push_back(s.substr(pos1));
607 static void importPropertyGroup(
const tinyxml2::XMLElement *node, std::map<std::string,std::string,cppcheck::stricmp> &variables, std::string &includePath,
bool *useOfMfc)
610 for (
const tinyxml2::XMLElement *e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
611 if (std::strcmp(e->Name(),
"UseOfMfc") == 0) {
618 const char* labelAttribute = node->Attribute(
"Label");
619 if (labelAttribute && std::strcmp(labelAttribute,
"UserMacros") == 0) {
620 for (
const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) {
621 const std::string name(propertyGroup->Name());
622 const char *text = propertyGroup->GetText();
623 variables[name] = std::string(text ? text :
"");
626 }
else if (!labelAttribute) {
627 for (
const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) {
628 if (std::strcmp(propertyGroup->Name(),
"IncludePath") != 0)
630 const char *text = propertyGroup->GetText();
633 std::string path(text);
634 const std::string::size_type pos = path.find(
"$(IncludePath)");
635 if (pos != std::string::npos)
636 path.replace(pos, 14U, includePath);
637 includePath = std::move(path);
642 static void loadVisualStudioProperties(
const std::string &props, std::map<std::string,std::string,cppcheck::stricmp> &variables, std::string &includePath,
const std::string &additionalIncludeDirectories, std::list<ItemDefinitionGroup> &itemDefinitionGroupList)
644 std::string filename(props);
653 tinyxml2::XMLDocument doc;
654 if (doc.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS)
656 const tinyxml2::XMLElement *
const rootnode = doc.FirstChildElement();
657 if (rootnode ==
nullptr)
659 for (
const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
660 if (std::strcmp(node->Name(),
"ImportGroup") == 0) {
661 const char *labelAttribute = node->Attribute(
"Label");
662 if (labelAttribute ==
nullptr || std::strcmp(labelAttribute,
"PropertySheets") != 0)
664 for (
const tinyxml2::XMLElement *importGroup = node->FirstChildElement(); importGroup; importGroup = importGroup->NextSiblingElement()) {
665 if (std::strcmp(importGroup->Name(),
"Import") == 0) {
666 const char *projectAttribute = importGroup->Attribute(
"Project");
667 if (projectAttribute ==
nullptr)
669 std::string loadprj(projectAttribute);
670 if (loadprj.find(
'$') == std::string::npos) {
676 }
else if (std::strcmp(node->Name(),
"PropertyGroup")==0) {
678 }
else if (std::strcmp(node->Name(),
"ItemDefinitionGroup")==0) {
679 itemDefinitionGroupList.emplace_back(node, additionalIncludeDirectories);
684 bool ImportProject::importVcxproj(
const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables,
const std::string &additionalIncludeDirectories,
const std::vector<std::string> &fileFilters)
688 std::list<ProjectConfiguration> projectConfigurationList;
689 std::list<std::string> compileList;
690 std::list<ItemDefinitionGroup> itemDefinitionGroupList;
691 std::string includePath;
693 bool useOfMfc =
false;
695 tinyxml2::XMLDocument doc;
696 const tinyxml2::XMLError
error = doc.LoadFile(filename.c_str());
697 if (
error != tinyxml2::XML_SUCCESS) {
698 printError(std::string(
"Visual Studio project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(
error));
701 const tinyxml2::XMLElement *
const rootnode = doc.FirstChildElement();
702 if (rootnode ==
nullptr) {
703 printError(
"Visual Studio project file has no XML root node");
706 for (
const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
707 if (std::strcmp(node->Name(),
"ItemGroup") == 0) {
708 const char *labelAttribute = node->Attribute(
"Label");
709 if (labelAttribute && std::strcmp(labelAttribute,
"ProjectConfigurations") == 0) {
710 for (
const tinyxml2::XMLElement *
cfg = node->FirstChildElement();
cfg;
cfg =
cfg->NextSiblingElement()) {
711 if (std::strcmp(
cfg->Name(),
"ProjectConfiguration") == 0) {
712 const ProjectConfiguration p(
cfg);
713 if (p.platform != ProjectConfiguration::Unknown) {
714 projectConfigurationList.emplace_back(
cfg);
720 for (
const tinyxml2::XMLElement *e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
721 if (std::strcmp(e->Name(),
"ClCompile") == 0) {
722 const char *include = e->Attribute(
"Include");
724 compileList.emplace_back(include);
728 }
else if (std::strcmp(node->Name(),
"ItemDefinitionGroup") == 0) {
729 itemDefinitionGroupList.emplace_back(node, additionalIncludeDirectories);
730 }
else if (std::strcmp(node->Name(),
"PropertyGroup") == 0) {
732 }
else if (std::strcmp(node->Name(),
"ImportGroup") == 0) {
733 const char *labelAttribute = node->Attribute(
"Label");
734 if (labelAttribute && std::strcmp(labelAttribute,
"PropertySheets") == 0) {
735 for (
const tinyxml2::XMLElement *e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
736 if (std::strcmp(e->Name(),
"Import") == 0) {
737 const char *projectAttribute = e->Attribute(
"Project");
738 if (projectAttribute)
748 for (
const std::string &c : compileList) {
750 if (!fileFilters.empty() && !
matchglobs(fileFilters, cfilename))
753 for (
const ProjectConfiguration &p : projectConfigurationList) {
756 const bool doChecking = std::any_of(
guiProject.checkVsConfigs.cbegin(),
guiProject.checkVsConfigs.cend(), [&](
const std::string& c) {
757 return c == p.configuration;
767 fs.useMfc = useOfMfc;
768 fs.defines =
"_WIN32=1";
769 if (p.platform == ProjectConfiguration::Win32)
770 fs.platformType = Platform::Type::Win32W;
771 else if (p.platform == ProjectConfiguration::x64) {
772 fs.platformType = Platform::Type::Win64;
773 fs.defines +=
";_WIN64=1";
775 std::string additionalIncludePaths;
776 for (
const ItemDefinitionGroup &i : itemDefinitionGroupList) {
777 if (!i.conditionIsTrue(p))
780 fs.defines +=
';' + i.preprocessorDefinitions;
781 if (i.enhancedInstructionSet ==
"StreamingSIMDExtensions")
782 fs.defines +=
";__SSE__";
783 else if (i.enhancedInstructionSet ==
"StreamingSIMDExtensions2")
784 fs.defines +=
";__SSE2__";
785 else if (i.enhancedInstructionSet ==
"AdvancedVectorExtensions")
786 fs.defines +=
";__AVX__";
787 else if (i.enhancedInstructionSet ==
"AdvancedVectorExtensions2")
788 fs.defines +=
";__AVX2__";
789 else if (i.enhancedInstructionSet ==
"AdvancedVectorExtensions512")
790 fs.defines +=
";__AVX512__";
791 additionalIncludePaths +=
';' + i.additionalIncludePaths;
804 tinyxml2::XMLDocument doc;
805 const tinyxml2::XMLError
error = doc.LoadFile(projectFilename.c_str());
806 if (
error != tinyxml2::XML_SUCCESS) {
807 printError(std::string(
"Borland project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(
error));
810 const tinyxml2::XMLElement *
const rootnode = doc.FirstChildElement();
811 if (rootnode ==
nullptr) {
812 printError(
"Borland project file has no XML root node");
818 std::list<std::string> compileList;
819 std::string includePath;
820 std::string userdefines;
821 std::string sysdefines;
824 for (
const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
825 if (std::strcmp(node->Name(),
"FILELIST") == 0) {
826 for (
const tinyxml2::XMLElement *f = node->FirstChildElement(); f; f = f->NextSiblingElement()) {
827 if (std::strcmp(f->Name(),
"FILE") == 0) {
828 const char *filename = f->Attribute(
"FILENAME");
830 compileList.emplace_back(filename);
833 }
else if (std::strcmp(node->Name(),
"MACROS") == 0) {
834 for (
const tinyxml2::XMLElement *m = node->FirstChildElement(); m; m = m->NextSiblingElement()) {
835 if (std::strcmp(m->Name(),
"INCLUDEPATH") == 0) {
836 const char *v = m->Attribute(
"value");
839 }
else if (std::strcmp(m->Name(),
"USERDEFINES") == 0) {
840 const char *v = m->Attribute(
"value");
843 }
else if (std::strcmp(m->Name(),
"SYSDEFINES") == 0) {
844 const char *v = m->Attribute(
"value");
849 }
else if (std::strcmp(node->Name(),
"OPTIONS") == 0) {
850 for (
const tinyxml2::XMLElement *m = node->FirstChildElement(); m; m = m->NextSiblingElement()) {
851 if (std::strcmp(m->Name(),
"CFLAG1") == 0) {
852 const char *v = m->Attribute(
"value");
860 std::set<std::string> cflags;
866 for (
const char i : cflag1) {
867 if (i ==
' ' && !arg.empty()) {
882 static const std::map<std::string, std::string> synonyms = {
888 {
"-tWCDR",
"-WCDR" },
889 {
"-tWCDV",
"-WCDV" },
900 for (std::map<std::string, std::string>::const_iterator i = synonyms.cbegin(); i != synonyms.cend(); ++i) {
901 if (cflags.erase(i->first) > 0) {
902 cflags.insert(i->second);
907 std::string predefines;
908 std::string cppPredefines;
916 ";__BCPLUSPLUS__=0x0560"
936 ";__BORLANDC__=0x0560"
937 ";__TCPLUSPLUS__=0x0560"
938 ";__TURBOC__=0x0560";
941 const bool useCdecl = (cflags.find(
"-p") == cflags.end()
942 && cflags.find(
"-pm") == cflags.end()
943 && cflags.find(
"-pr") == cflags.end()
944 && cflags.find(
"-ps") == cflags.end());
946 predefines +=
";__CDECL=1";
949 const bool treatCharAsUnsignedChar = (cflags.find(
"-K") != cflags.end());
950 if (treatCharAsUnsignedChar)
951 predefines +=
";_CHAR_UNSIGNED=1";
954 const bool codeguardUsed = (cflags.find(
"-vGd") != cflags.end()
955 || cflags.find(
"-vGt") != cflags.end()
956 || cflags.find(
"-vGc") != cflags.end());
958 predefines +=
";__CODEGUARD__";
961 const bool isConsoleApp = (cflags.find(
"-WC") != cflags.end());
963 predefines +=
";__CONSOLE__=1";
966 const bool enableStackUnwinding = (cflags.find(
"-xd-") == cflags.end());
967 if (enableStackUnwinding)
968 predefines +=
";_CPPUNWIND=1";
971 const bool isDLL = (cflags.find(
"-WD") != cflags.end());
973 predefines +=
";__DLL__=1";
977 predefines +=
";__FLAT__=1";
980 if (cflags.find(
"-6") != cflags.end())
981 predefines +=
";_M_IX86=600";
982 else if (cflags.find(
"-5") != cflags.end())
983 predefines +=
";_M_IX86=500";
984 else if (cflags.find(
"-4") != cflags.end())
985 predefines +=
";_M_IX86=400";
987 predefines +=
";_M_IX86=300";
990 const bool linkMtLib = (cflags.find(
"-WM") != cflags.end());
992 predefines +=
";__MT__=1";
995 const bool usePascalCallingConvention = (cflags.find(
"-p") != cflags.end());
996 if (usePascalCallingConvention)
997 predefines +=
";__PASCAL__=1";
1000 const bool useAnsiKeywordExtensions = (cflags.find(
"-A") != cflags.end());
1001 if (useAnsiKeywordExtensions)
1002 predefines +=
";__STDC__=1";
1005 predefines +=
";__TLC__=1";
1008 const bool isWindowsTarget = (cflags.find(
"-WC") != cflags.end()
1009 || cflags.find(
"-WCDR") != cflags.end()
1010 || cflags.find(
"-WCDV") != cflags.end()
1011 || cflags.find(
"-WD") != cflags.end()
1012 || cflags.find(
"-WDR") != cflags.end()
1013 || cflags.find(
"-WDV") != cflags.end()
1014 || cflags.find(
"-WM") != cflags.end()
1015 || cflags.find(
"-WP") != cflags.end()
1016 || cflags.find(
"-WR") != cflags.end()
1017 || cflags.find(
"-WU") != cflags.end()
1018 || cflags.find(
"-WV") != cflags.end());
1019 if (isWindowsTarget)
1020 predefines +=
";_Windows";
1029 const bool isConsoleOrGuiApp = isWindowsTarget;
1030 if (isConsoleOrGuiApp)
1031 predefines +=
";__WIN32__=1";
1042 std::map<std::string, std::string, cppcheck::stricmp> variables;
1043 const std::string defines = predefines +
";" + sysdefines +
";" + userdefines;
1044 const std::string cppDefines = cppPredefines +
";" + defines;
1045 const bool forceCppMode = (cflags.find(
"-P") != cflags.end());
1047 for (
const std::string &c : compileList) {
1070 return path1 + path2;
1074 static std::list<std::string>
readXmlStringList(
const tinyxml2::XMLElement *node,
const std::string &path,
const char name[],
const char attribute[])
1076 std::list<std::string> ret;
1077 for (
const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) {
1078 if (strcmp(child->Name(), name) != 0)
1080 const char *attr = attribute ? child->Attribute(attribute) : child->GetText();
1087 static std::string
join(
const std::list<std::string> &strlist,
const char *sep)
1090 for (
const std::string &s : strlist) {
1091 ret += (ret.empty() ?
"" : sep) + s;
1098 std::istreambuf_iterator<char> eos;
1099 return std::string(std::istreambuf_iterator<char>(istr), eos);
1102 static const char *
readSafe(
const char *s,
const char *def) {
1108 tinyxml2::XMLDocument doc;
1110 const tinyxml2::XMLError
error = doc.Parse(xmldata.data(), xmldata.size());
1111 if (
error != tinyxml2::XML_SUCCESS) {
1112 printError(std::string(
"Cppcheck GUI project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(
error));
1115 const tinyxml2::XMLElement *
const rootnode = doc.FirstChildElement();
1117 printError(
"Cppcheck GUI project file has no XML root node");
1121 const std::string &path =
mPath;
1123 std::list<std::string> paths;
1124 std::list<SuppressionList::Suppression> suppressions;
1132 bool checkLevelExhaustive =
false;
1135 for (
const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
1151 const std::string t_str =
readSafe(node->GetText(),
"");
1168 for (
const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) {
1178 s.
hash = strToInt<std::size_t>(
readSafe(child->Attribute(
"hash"),
"0"));
1179 suppressions.push_back(std::move(s));
1191 temp.
addons.insert(addons.cbegin(), addons.cend());
1197 for (
const std::string &toolName : toolList) {
1204 checkLevelExhaustive =
true;
1214 for (
const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) {
1234 temp.
premiumArgs += std::string(
" --cert-c-int-precision=") +
readSafe(node->GetText(),
"0");
1236 for (
const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) {
1238 temp.
premiumArgs += std::string(
" --") + child->GetText();
1244 printError(
"Unknown element '" + std::string(node->Name()) +
"' in Cppcheck project file");
1248 settings->basePaths = temp.basePaths;
1249 settings->relativePaths |= temp.relativePaths;
1250 settings->buildDir = temp.buildDir;
1251 settings->includePaths = temp.includePaths;
1252 settings->userDefines = temp.userDefines;
1253 settings->userUndefs = temp.userUndefs;
1254 settings->addons = temp.addons;
1255 settings->clang = temp.clang;
1256 settings->clangTidy = temp.clangTidy;
1258 if (!settings->premiumArgs.empty())
1259 settings->premiumArgs += temp.premiumArgs;
1260 else if (!temp.premiumArgs.empty())
1261 settings->premiumArgs = temp.premiumArgs.substr(1);
1263 for (
const std::string &p : paths)
1264 guiProject.pathNames.push_back(p);
1265 settings->supprs.nomsg.addSuppressions(std::move(suppressions));
1266 settings->checkHeaders = temp.checkHeaders;
1267 settings->checkUnusedTemplates = temp.checkUnusedTemplates;
1268 settings->maxCtuDepth = temp.maxCtuDepth;
1269 settings->maxTemplateRecursion = temp.maxTemplateRecursion;
1270 settings->safeChecks = temp.safeChecks;
1272 if (checkLevelExhaustive)
1282 std::set<std::string> filenames;
1284 if (it->cfg.empty()) {
1289 bool remove =
false;
1296 else if (filenames.find(fs.
filename()) != filenames.end())
1310 if (it->cfg.empty()) {
1315 const auto config = fs.
cfg.substr(0, fs.
cfg.find(
'|'));
1316 bool remove =
false;
1317 if (std::find(configurations.begin(), configurations.end(), config) == configurations.end())
1343 for (
auto &includePath: fs.includePaths)
1350 std::cout <<
"cppcheck: error: " << message << std::endl;
static void fsParseCommand(FileSettings &fs, const std::string &command)
static void printError(const std::string &message)
std::list< FileSettings > fileSettings
void selectVsConfigurations(Platform::Type platform, const std::vector< std::string > &configurations)
void setRelativePaths(const std::string &filename)
struct ImportProject::@6 guiProject
bool importBcb6Prj(const std::string &projectFilename)
void ignorePaths(const std::vector< std::string > &ipaths)
virtual bool sourceFileExists(const std::string &file)
bool importCppcheckGuiProject(std::istream &istr, Settings *settings)
void selectOneVsConfig(Platform::Type platform)
static void fsSetIncludePaths(FileSettings &fs, const std::string &basepath, const std::list< std::string > &in, std::map< std::string, std::string, cppcheck::stricmp > &variables)
std::list< std::string > getVSConfigs()
bool importVcxproj(const std::string &filename, std::map< std::string, std::string, cppcheck::stricmp > &variables, const std::string &additionalIncludeDirectories, const std::vector< std::string > &fileFilters)
static void fsSetDefines(FileSettings &fs, std::string defs)
void ignoreOtherConfigs(const std::string &cfg)
std::set< std::string > mAllVSConfigs
Type import(const std::string &filename, Settings *settings=nullptr)
bool importCompileCommands(std::istream &istr)
bool importSln(std::istream &istr, const std::string &path, const std::vector< std::string > &fileFilters)
static std::string simplifyPath(std::string originalPath)
Simplify path "foo/bar/.." => "foo".
static bool isFile(const std::string &path)
Checks if given path is a file.
static std::string fromNativeSeparators(std::string path)
Convert path to use internal path separators.
static std::string getCurrentPath()
Returns the absolute path of current working directory.
static std::string toNativeSeparators(std::string path)
Convert path to use native separators.
static std::string getPathFromFilename(const std::string &filename)
Lookup the path part from a filename (e.g., '/tmp/a.h' -> '/tmp/', 'a.h' -> '')
static std::string getAbsoluteFilePath(const std::string &filePath)
Get an absolute file path from a relative one.
static bool acceptFile(const std::string &filename)
Check if the file extension indicates that it's a C/C++ source file.
static std::string getRelativePath(const std::string &absolutePath, const std::vector< std::string > &basePaths)
Create a relative path from an absolute one, if absolute path is inside the basePaths.
static std::string getFilenameExtensionInLowerCase(const std::string &path)
Get an extension of the filename in lower case.
static bool isAbsolute(const std::string &path)
Check if given path is absolute.
This is just a container for general settings so that we don't need to pass individual values to func...
std::set< std::string > userUndefs
undefines given by the user
bool checkHeaders
Check code in the headers, this is on by default but can be turned off to save CPU.
std::vector< std::string > basePaths
Paths used as base for conversion to relative paths.
int maxCtuDepth
–max-ctu-depth
bool relativePaths
Use relative paths in output.
std::unordered_set< std::string > addons
addons, either filename of python/json file or json data
std::string buildDir
–cppcheck-build-dir.
std::string userDefines
defines given by the user
std::string premiumArgs
Extra arguments for Cppcheck Premium addon.
void setCheckLevel(CheckLevel level)
bool clangTidy
Use clang-tidy.
std::list< std::string > includePaths
List of include paths, e.g.
int maxTemplateRecursion
max template recursion
bool checkUnusedTemplates
Check unused/uninstantiated templates.
std::vector< std::string > fileFilters
List of –file-filter for analyzing special files.
The token list that the TokenList generates is a linked-list of this class.
static const std::string emptyString
@ error
Programming error.
static void loadVisualStudioProperties(const std::string &props, std::map< std::string, std::string, cppcheck::stricmp > &variables, std::string &includePath, const std::string &additionalIncludeDirectories, std::list< ItemDefinitionGroup > &itemDefinitionGroupList)
static std::string join(const std::list< std::string > &strlist, const char *sep)
static bool simplifyPathWithVariables(std::string &s, std::map< std::string, std::string, cppcheck::stricmp > &variables)
static std::string istream_to_string(std::istream &istr)
static const char * readSafe(const char *s, const char *def)
static std::string readUntil(const std::string &command, std::string::size_type *pos, const char until[])
static void importPropertyGroup(const tinyxml2::XMLElement *node, std::map< std::string, std::string, cppcheck::stricmp > &variables, std::string &includePath, bool *useOfMfc)
static std::string unescape(const std::string &in)
static std::list< std::string > readXmlStringList(const tinyxml2::XMLElement *node, const std::string &path, const char name[], const char attribute[])
static std::string joinRelativePath(const std::string &path1, const std::string &path2)
static std::list< std::string > toStringList(const std::string &s)
static constexpr char RootPathName[]
static constexpr char VSConfigurationName[]
static constexpr char DirElementName[]
static constexpr char DefineName[]
static constexpr char ExcludePathNameAttrib[]
static constexpr char PathsElementName[]
static constexpr char VariableContractsElementName[]
static constexpr char FunctionContracts[]
static constexpr char DefinesElementName[]
static constexpr char LibrariesElementName[]
static constexpr char ToolsElementName[]
static constexpr char IncludeDirElementName[]
static constexpr char ExcludeElementName[]
static constexpr char ProjectElementName[]
static constexpr char CertIntPrecisionElementName[]
static constexpr char PlatformElementName[]
static constexpr char TagsElementName[]
static constexpr char RootPathNameAttrib[]
static constexpr char CodingStandardElementName[]
static constexpr char IgnorePathNameAttrib[]
static constexpr char CodingStandardsElementName[]
static constexpr char AddonsElementName[]
static constexpr char UndefinesElementName[]
static constexpr char ImportProjectElementName[]
static constexpr char Parser[]
static constexpr char BughuntingElementName[]
static constexpr char AddonElementName[]
static constexpr char CheckUnknownFunctionReturn[]
static constexpr char TagWarningsElementName[]
static constexpr char DefineNameAttrib[]
static constexpr char AnalyzeAllVsConfigsElementName[]
static constexpr char TagElementName[]
static constexpr char ProjectNameElementName[]
static constexpr char BuildDirElementName[]
static constexpr char MaxTemplateRecursionElementName[]
static constexpr char ClangTidy[]
static constexpr char ExcludePathName[]
static constexpr char CheckUnusedTemplatesElementName[]
static constexpr char VSConfigurationElementName[]
static constexpr char CheckLevelExhaustiveElementName[]
static constexpr char DirNameAttrib[]
static constexpr char MaxCtuDepthElementName[]
static constexpr char UndefineName[]
static constexpr char SuppressionElementName[]
static constexpr char IgnoreElementName[]
static constexpr char IgnorePathName[]
static constexpr char ToolElementName[]
static constexpr char SuppressionsElementName[]
static constexpr char CheckHeadersElementName[]
static constexpr char PathName[]
static constexpr char PathNameAttrib[]
static constexpr char LibraryElementName[]
static std::string cfg(const std::vector< std::string > &configs, const std::string &userDefines)
bool conditionIsTrue(const Token *condition, ProgramMemory pm, const Settings &settings)
Is condition always true when variable has given value?
const std::string & filename() const
std::set< std::string > undefs
Platform::Type platformType
std::list< std::string > includePaths
std::list< std::string > systemIncludePaths
bool classes
Public interface of classes.
static const char XmlExternalFunctions[]
static const char XmlInternalFunctions[]
bool externalVariables
Global variables that can be modified outside the TU.
static const char XmlClasses[]
static const char XmlRootName[]
static const char XmlExternalVariables[]
bool externalFunctions
External functions.
bool internalFunctions
Experimental: assume that internal functions can be used in any way This is only available in the GUI...
std::string getCPP() const
cppstd_t
C++ code standard.
bool matchglob(const std::string &pattern, const std::string &name)
bool isValidGlobPattern(const std::string &pattern)
bool matchglobs(const std::vector< std::string > &patterns, const std::string &name)
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
bool endsWith(const std::string &str, char c)