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>
<arg choice="opt"><option>--all</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>--verbose</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>
</listitem>
</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>
<term><option>-q</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>
</listitem>
</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>
</refsect1>
<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)
_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 <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"
" -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;

View File

@ -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<std::string> _includePaths;
};
#endif // CPPCHECK_H

View File

@ -173,12 +173,12 @@ std::string Preprocessor::read(std::istream &istr)
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::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)
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<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);
@ -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<std::string> &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<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;
std::ifstream fin(filename.c_str());
processedFile = Preprocessor::read(fin);
}
if (processedFile.length() > 0)
{
// Replace all tabs with spaces..

View File

@ -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<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
@ -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<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 */
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<std::string> &includePaths);
/**
* Returns the string between double quote characters.