diff --git a/man/cppcheck.1.xml b/man/cppcheck.1.xml
index f1f5d801b..445d2dc11 100644
--- a/man/cppcheck.1.xml
+++ b/man/cppcheck.1.xml
@@ -104,6 +104,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
&dhpackage;
+
@@ -133,6 +134,21 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
found a bug. When this option is given, all messages are shown.
+
+
+
+
+ Force checking of files that have a lot of configurations. Error is printed if such a file is found so there is no reason to use this by
+default.
+
+
+
+
+
+ Give include path. Give several -I parameters to give several paths. First given path is checked first. If paths are relative to source
+files, this is not needed.
+
+
@@ -154,14 +170,6 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
More detailed error reports
-
-
-
-
- Force checking of files that have a lot of configurations. Error is printed if such a file is found so there is no reason to use this by
-default.
-
-
diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp
index 2860e5e65..c536cde75 100644
--- a/src/cppcheck.cpp
+++ b/src/cppcheck.cpp
@@ -95,6 +95,35 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0)
_settings._force = true;
+ // Include paths
+ else if (strcmp(argv[i], "-I") == 0 || strncmp(argv[i], "-I", 2) == 0)
+ {
+ std::string path;
+
+ // "-I path/"
+ if (strcmp(argv[i], "-I") == 0)
+ {
+ ++i;
+ if (i >= argc)
+ return "cppcheck: argument to '-I' is missing\n";
+
+ path = argv[i];
+ }
+
+ // "-Ipath/"
+ else
+ {
+ path = argv[i];
+ path = path.substr(2);
+ }
+
+ // If path doesn't end with / or \, add it
+ if (path[path.length()-1] != '/' && path[path.length()-1] != '\\')
+ path += '/';
+
+ _includePaths.push_back(path);
+ }
+
else
pathnames.push_back(argv[i]);
}
@@ -115,7 +144,7 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
"A tool for static C/C++ code analysis\n"
"\n"
"Syntax:\n"
- " cppcheck [--all] [--force] [--quiet] [--style] [--verbose] [file or path1] [file or path]\n"
+ " cppcheck [--all] [--force] [-Idir] [--quiet] [--style] [--verbose] [file or path1] [file or path]\n"
"\n"
"If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n"
"are checked recursively from given directory.\n\n"
@@ -123,6 +152,9 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
" -a, --all Make the checking more sensitive. More bugs are detected,\n"
" but there are also more false positives\n"
" -f, --force Force checking on files that have \"too many\" configurations\n"
+ " -I Give include path. Give several -I parameters to give several\n"
+ " paths. First given path is checked first. If paths are\n"
+ " relative to source files, this is not needed.\n"
" -q, --quiet Only print error messages\n"
" -s, --style Check coding style\n"
" -v, --verbose More detailed error reports\n"
@@ -133,7 +165,9 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
" # Recursively check ../myproject/ and print only most fatal errors:\n"
" cppcheck --quiet ../myproject/\n"
" # Check only files one.cpp and two.cpp and give all information there is:\n"
- " cppcheck -v -a -s one.cpp two.cpp\n";
+ " cppcheck -v -a -s one.cpp two.cpp\n"
+ " # Check f.cpp and search include files from inc1/ and inc2/:\n"
+ " cppcheck -I inc1/ -I inc2/ f.cpp\n";
return oss.str();
}
@@ -159,13 +193,13 @@ unsigned int CppCheck::check()
{
// File content was given as a string
std::istringstream iss(_fileContents[ _filenames[c] ]);
- preprocessor.preprocess(iss, filedata, configurations, fname);
+ preprocessor.preprocess(iss, filedata, configurations, fname, _includePaths);
}
else
{
// Only file name was given, read the content from file
std::ifstream fin(fname.c_str());
- preprocessor.preprocess(fin, filedata, configurations, fname);
+ preprocessor.preprocess(fin, filedata, configurations, fname, _includePaths);
}
int checkCount = 0;
diff --git a/src/cppcheck.h b/src/cppcheck.h
index 7480eb35f..b226eaa2f 100644
--- a/src/cppcheck.h
+++ b/src/cppcheck.h
@@ -123,6 +123,10 @@ private:
/** Current configuration */
std::string cfg;
+
+ /** List of include paths, e.g. "my/includes/" which should be used
+ for finding include files inside source files. */
+ std::list _includePaths;
};
#endif // CPPCHECK_H
diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp
index 0a8d20d7c..6e97d750f 100644
--- a/src/preprocessor.cpp
+++ b/src/preprocessor.cpp
@@ -173,12 +173,12 @@ std::string Preprocessor::read(std::istream &istr)
return code.str();
}
-#include
-void Preprocessor::preprocess(std::istream &istr, std::map &result, const std::string &filename)
+
+void Preprocessor::preprocess(std::istream &istr, std::map &result, const std::string &filename, const std::list &includePaths)
{
std::list configs;
std::string data;
- preprocess(istr, data, configs, filename);
+ preprocess(istr, data, configs, filename, includePaths);
for (std::list::const_iterator it = configs.begin(); it != configs.end(); ++it)
result[ *it ] = Preprocessor::getcode(data, *it);
}
@@ -228,7 +228,7 @@ std::string Preprocessor::replaceIfDefined(const std::string &str)
return ret;
}
-void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, std::list &resultConfigurations, const std::string &filename)
+void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, std::list &resultConfigurations, const std::string &filename, const std::list &includePaths)
{
processedFile = read(istr);
@@ -242,7 +242,7 @@ void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, st
// Remove space characters that are after or before new line character
processedFile = removeSpaceNearNL(processedFile);
- handleIncludes(processedFile, filename);
+ handleIncludes(processedFile, filename, includePaths);
processedFile = replaceIfDefined(processedFile);
@@ -470,7 +470,7 @@ std::string Preprocessor::getHeaderFileName(const std::string &str)
return result;
}
-void Preprocessor::handleIncludes(std::string &code, const std::string &filename)
+void Preprocessor::handleIncludes(std::string &code, const std::string &filename, const std::list &includePaths)
{
// std::string line;
std::string path = filename;
@@ -496,9 +496,26 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filename
continue;
// filename contains now a file name e.g. "menu.h"
- filename = path + filename;
- std::ifstream fin(filename.c_str());
- std::string processedFile = Preprocessor::read(fin);
+ std::string processedFile;
+ for (std::list::const_iterator iter = includePaths.begin(); iter != includePaths.end(); ++iter)
+ {
+ std::ifstream fin;
+ fin.open((*iter + filename).c_str());
+ if (fin.is_open())
+ {
+ filename = *iter + filename;
+ processedFile = Preprocessor::read(fin);
+ break;
+ }
+ }
+
+ if (processedFile.length() == 0)
+ {
+ filename = path + filename;
+ std::ifstream fin(filename.c_str());
+ processedFile = Preprocessor::read(fin);
+ }
+
if (processedFile.length() > 0)
{
// Replace all tabs with spaces..
diff --git a/src/preprocessor.h b/src/preprocessor.h
index 87c8e6af5..455a62e67 100644
--- a/src/preprocessor.h
+++ b/src/preprocessor.h
@@ -38,8 +38,13 @@ public:
* @param istr The (file/string) stream to read from.
* @param result The map that will get the results
* @param filename The name of the file to check e.g. "src/main.cpp"
+ * @param includePaths List of paths where incude files should be searched from,
+ * single path can be e.g. in format "include/".
+ * There must be a path separator at the end. Default parameter is empty list.
+ * Note that if path from given filename is also extracted and that is used as
+ * a last include path if include file was not found from earlier paths.
*/
- void preprocess(std::istream &istr, std::map &result, const std::string &filename);
+ void preprocess(std::istream &istr, std::map &result, const std::string &filename, const std::list &includePaths = std::list());
/**
* Extract the code for each configuration. Use this with getcode() to get the
@@ -52,8 +57,13 @@ public:
* @param resultConfigurations List of configurations. Pass these one by one
* to getcode() with processedFile.
* @param filename The name of the file to check e.g. "src/main.cpp"
+ * @param includePaths List of paths where incude files should be searched from,
+ * single path can be e.g. in format "include/".
+ * There must be a path separator at the end. Default parameter is empty list.
+ * Note that if path from given filename is also extracted and that is used as
+ * a last include path if include file was not found from earlier paths.
*/
- void preprocess(std::istream &istr, std::string &processedFile, std::list &resultConfigurations, const std::string &filename);
+ void preprocess(std::istream &istr, std::string &processedFile, std::list &resultConfigurations, const std::string &filename, const std::list &includePaths);
/** Just read the code into a string. Perform simple cleanup of the code */
static std::string read(std::istream &istr);
@@ -99,9 +109,14 @@ private:
* file
* @param code The source code to modify
* @param filename The name of the file to check e.g. "src/main.cpp"
+ * @param includePaths List of paths where incude files should be searched from,
+ * single path can be e.g. in format "include/".
+ * There must be a path separator at the end. Default parameter is empty list.
+ * Note that if path from given filename is also extracted and that is used as
+ * a last include path if include file was not found from earlier paths.
* @return modified source code
*/
- static void handleIncludes(std::string &code, const std::string &filename);
+ static void handleIncludes(std::string &code, const std::string &filename, const std::list &includePaths);
/**
* Returns the string between double quote characters.