Fix Ticket #30, Need a way to specify include file folders (-I parameter was added)

This commit is contained in:
Reijo Tomperi 2009-01-22 19:59:50 +00:00
parent a9e84c5cd5
commit e897637c7a
5 changed files with 102 additions and 24 deletions

View File

@ -104,6 +104,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
<command>&dhpackage;</command> <command>&dhpackage;</command>
<arg choice="opt"><option>--all</option></arg> <arg choice="opt"><option>--all</option></arg>
<arg choice="opt"><option>--quiet</option></arg> <arg choice="opt"><option>--quiet</option></arg>
<arg choice="opt"><option>-Idir</option></arg>
<arg choice="opt"><option>--style</option></arg> <arg choice="opt"><option>--style</option></arg>
<arg choice="opt"><option>--verbose</option></arg> <arg choice="opt"><option>--verbose</option></arg>
<arg choice="opt"><option>--force</option></arg> <arg choice="opt"><option>--force</option></arg>
@ -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.</para> found a bug. When this option is given, all messages are shown.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>-f</option></term>
<term><option>--force</option></term>
<listitem>
<para>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.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-I <dir></option></term>
<listitem>
<para>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.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-q</option></term> <term><option>-q</option></term>
<term><option>--quiet</option></term> <term><option>--quiet</option></term>
@ -154,14 +170,6 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
<para>More detailed error reports</para> <para>More detailed error reports</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>-f</option></term>
<term><option>--force</option></term>
<listitem>
<para>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.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
<refsect1 id="author"> <refsect1 id="author">

View File

@ -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) else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0)
_settings._force = true; _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 else
pathnames.push_back(argv[i]); 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" "A tool for static C/C++ code analysis\n"
"\n" "\n"
"Syntax:\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" "\n"
"If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n" "If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n"
"are checked recursively from given directory.\n\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" " -a, --all Make the checking more sensitive. More bugs are detected,\n"
" but there are also more false positives\n" " but there are also more false positives\n"
" -f, --force Force checking on files that have \"too many\" configurations\n" " -f, --force Force checking on files that have \"too many\" configurations\n"
" -I <dir> 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" " -q, --quiet Only print error messages\n"
" -s, --style Check coding style\n" " -s, --style Check coding style\n"
" -v, --verbose More detailed error reports\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" " # Recursively check ../myproject/ and print only most fatal errors:\n"
" cppcheck --quiet ../myproject/\n" " cppcheck --quiet ../myproject/\n"
" # Check only files one.cpp and two.cpp and give all information there is:\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(); return oss.str();
} }
@ -159,13 +193,13 @@ unsigned int CppCheck::check()
{ {
// File content was given as a string // File content was given as a string
std::istringstream iss(_fileContents[ _filenames[c] ]); std::istringstream iss(_fileContents[ _filenames[c] ]);
preprocessor.preprocess(iss, filedata, configurations, fname); preprocessor.preprocess(iss, filedata, configurations, fname, _includePaths);
} }
else else
{ {
// Only file name was given, read the content from file // Only file name was given, read the content from file
std::ifstream fin(fname.c_str()); std::ifstream fin(fname.c_str());
preprocessor.preprocess(fin, filedata, configurations, fname); preprocessor.preprocess(fin, filedata, configurations, fname, _includePaths);
} }
int checkCount = 0; int checkCount = 0;

View File

@ -123,6 +123,10 @@ private:
/** Current configuration */ /** Current configuration */
std::string cfg; std::string cfg;
/** List of include paths, e.g. "my/includes/" which should be used
for finding include files inside source files. */
std::list<std::string> _includePaths;
}; };
#endif // CPPCHECK_H #endif // CPPCHECK_H

View File

@ -173,12 +173,12 @@ std::string Preprocessor::read(std::istream &istr)
return code.str(); return code.str();
} }
#include <iostream>
void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename) void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename, const std::list<std::string> &includePaths)
{ {
std::list<std::string> configs; std::list<std::string> configs;
std::string data; std::string data;
preprocess(istr, data, configs, filename); preprocess(istr, data, configs, filename, includePaths);
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it)
result[ *it ] = Preprocessor::getcode(data, *it); result[ *it ] = Preprocessor::getcode(data, *it);
} }
@ -228,7 +228,7 @@ std::string Preprocessor::replaceIfDefined(const std::string &str)
return ret; return ret;
} }
void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, std::list<std::string> &resultConfigurations, const std::string &filename) void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, std::list<std::string> &resultConfigurations, const std::string &filename, const std::list<std::string> &includePaths)
{ {
processedFile = read(istr); 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 // Remove space characters that are after or before new line character
processedFile = removeSpaceNearNL(processedFile); processedFile = removeSpaceNearNL(processedFile);
handleIncludes(processedFile, filename); handleIncludes(processedFile, filename, includePaths);
processedFile = replaceIfDefined(processedFile); processedFile = replaceIfDefined(processedFile);
@ -470,7 +470,7 @@ std::string Preprocessor::getHeaderFileName(const std::string &str)
return result; 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<std::string> &includePaths)
{ {
// std::string line; // std::string line;
std::string path = filename; std::string path = filename;
@ -496,9 +496,26 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filename
continue; continue;
// filename contains now a file name e.g. "menu.h" // filename contains now a file name e.g. "menu.h"
std::string processedFile;
for (std::list<std::string>::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; filename = path + filename;
std::ifstream fin(filename.c_str()); std::ifstream fin(filename.c_str());
std::string processedFile = Preprocessor::read(fin); processedFile = Preprocessor::read(fin);
}
if (processedFile.length() > 0) if (processedFile.length() > 0)
{ {
// Replace all tabs with spaces.. // Replace all tabs with spaces..

View File

@ -38,8 +38,13 @@ public:
* @param istr The (file/string) stream to read from. * @param istr The (file/string) stream to read from.
* @param result The map that will get the results * @param result The map that will get the results
* @param filename The name of the file to check e.g. "src/main.cpp" * @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<std::string, std::string> &result, const std::string &filename); void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename, const std::list<std::string> &includePaths = std::list<std::string>());
/** /**
* Extract the code for each configuration. Use this with getcode() to get the * 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 * @param resultConfigurations List of configurations. Pass these one by one
* to getcode() with processedFile. * to getcode() with processedFile.
* @param filename The name of the file to check e.g. "src/main.cpp" * @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<std::string> &resultConfigurations, const std::string &filename); void preprocess(std::istream &istr, std::string &processedFile, std::list<std::string> &resultConfigurations, const std::string &filename, const std::list<std::string> &includePaths);
/** Just read the code into a string. Perform simple cleanup of the code */ /** Just read the code into a string. Perform simple cleanup of the code */
static std::string read(std::istream &istr); static std::string read(std::istream &istr);
@ -99,9 +109,14 @@ private:
* file * file
* @param code The source code to modify * @param code The source code to modify
* @param filename The name of the file to check e.g. "src/main.cpp" * @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 * @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<std::string> &includePaths);
/** /**
* Returns the string between double quote characters. * Returns the string between double quote characters.