Added preprocessor a way to retrieve configurations and file content one configuration at time, because large files could consume 500 MB or even more memory.
This commit is contained in:
parent
6ef11f3f49
commit
c850901536
22
cppcheck.cpp
22
cppcheck.cpp
|
@ -144,29 +144,33 @@ void CppCheck::check()
|
||||||
_errout.str("");
|
_errout.str("");
|
||||||
std::string fname = _filenames[c];
|
std::string fname = _filenames[c];
|
||||||
|
|
||||||
// If only errors are printed, print filename after the check
|
|
||||||
if ( _settings._errorsOnly == false )
|
|
||||||
_errorLogger->reportOut( std::string( "Checking " ) + fname + std::string( "..." ) );
|
|
||||||
|
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
std::map<std::string, std::string> code;
|
std::list<std::string> configurations;
|
||||||
|
std::string filedata = "";
|
||||||
if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() )
|
if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() )
|
||||||
{
|
{
|
||||||
// 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, code, fname);
|
preprocessor.preprocess(iss, fname, filedata, configurations );
|
||||||
}
|
}
|
||||||
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, code, fname);
|
preprocessor.preprocess(fin, fname, filedata, configurations );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
|
for ( std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it )
|
||||||
{
|
{
|
||||||
cfg = it->first;
|
cfg = *it;
|
||||||
checkFile(it->second, _filenames[c].c_str());
|
std::string codeWithoutCfg = Preprocessor::getcode( filedata, *it );
|
||||||
|
|
||||||
|
// If only errors are printed, print filename after the check
|
||||||
|
if ( _settings._errorsOnly == false )
|
||||||
|
_errorLogger->reportOut( std::string( "Checking " ) + fname + ": "+cfg+std::string( "..." ) );
|
||||||
|
|
||||||
|
checkFile( codeWithoutCfg, _filenames[c].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _settings._errorsOnly == false && _errout.str().empty() )
|
if ( _settings._errorsOnly == false && _errout.str().empty() )
|
||||||
|
|
|
@ -140,55 +140,52 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename)
|
||||||
return code.str();
|
return code.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the code for each configuration
|
|
||||||
* \param istr The (file/string) stream to read from.
|
|
||||||
* \param result The map that will get the results
|
|
||||||
*/
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
std::string codestr( read(istr, filename) );
|
std::list<std::string> configs;
|
||||||
|
std::string data;
|
||||||
|
preprocess( istr, filename, data, configs );
|
||||||
|
for ( std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it )
|
||||||
|
result[ *it ] = Preprocessor::getcode( data, *it );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preprocessor::preprocess(std::istream &istr, const std::string &filename, std::string &processedFile, std::list<std::string> &resultConfigurations)
|
||||||
|
{
|
||||||
|
processedFile = read(istr, filename);
|
||||||
|
|
||||||
// Replace all tabs with spaces..
|
// Replace all tabs with spaces..
|
||||||
std::string::size_type loc = 0;
|
std::string::size_type loc = 0;
|
||||||
while ( (loc = codestr.find("\t", loc)) != std::string::npos )
|
while ( (loc = processedFile.find("\t", loc)) != std::string::npos )
|
||||||
codestr[loc] = ' ';
|
processedFile[loc] = ' ';
|
||||||
|
|
||||||
// Remove all indentation..
|
// Remove all indentation..
|
||||||
if ( !codestr.empty() && codestr[0] == ' ' )
|
if ( !processedFile.empty() && processedFile[0] == ' ' )
|
||||||
codestr.erase( 0, codestr.find_first_not_of(" ") );
|
processedFile.erase( 0, processedFile.find_first_not_of(" ") );
|
||||||
loc = 0;
|
loc = 0;
|
||||||
while ( (loc = codestr.find("\n ", loc)) != std::string::npos )
|
while ( (loc = processedFile.find("\n ", loc)) != std::string::npos )
|
||||||
codestr.erase( 1 + loc, 1 );
|
processedFile.erase( 1 + loc, 1 );
|
||||||
|
|
||||||
// Remove all trailing spaces..
|
// Remove all trailing spaces..
|
||||||
loc = 0;
|
loc = 0;
|
||||||
while ( (loc = codestr.find(" \n", loc)) != std::string::npos )
|
while ( (loc = processedFile.find(" \n", loc)) != std::string::npos )
|
||||||
{
|
{
|
||||||
codestr.erase( loc, 1 );
|
processedFile.erase( loc, 1 );
|
||||||
if ( loc > 0 )
|
if ( loc > 0 )
|
||||||
--loc;
|
--loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using the backslash at the end of a line..
|
// Using the backslash at the end of a line..
|
||||||
while ( (loc = codestr.rfind("\\\n")) != std::string::npos )
|
while ( (loc = processedFile.rfind("\\\n")) != std::string::npos )
|
||||||
{
|
{
|
||||||
codestr.erase(loc, 2);
|
processedFile.erase(loc, 2);
|
||||||
if (loc > 0 && codestr[loc-1] != ' ')
|
if (loc > 0 && processedFile[loc-1] != ' ')
|
||||||
codestr.insert(loc, " ");
|
processedFile.insert(loc, " ");
|
||||||
if ( (loc = codestr.find("\n", loc)) != std::string::npos)
|
if ( (loc = processedFile.find("\n", loc)) != std::string::npos)
|
||||||
codestr.insert( loc, "\n" );
|
processedFile.insert( loc, "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all possible configurations..
|
// Get all possible configurations..
|
||||||
std::list<std::string> cfgs = getcfgs( codestr );
|
resultConfigurations = getcfgs( processedFile );
|
||||||
|
|
||||||
// Extract the code for each possible configuration..
|
|
||||||
result.clear();
|
|
||||||
for ( std::list<std::string>::const_iterator it = cfgs.begin(); it != cfgs.end(); ++it )
|
|
||||||
{
|
|
||||||
result[ *it ] = getcode( codestr, *it );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,25 +32,45 @@ class Preprocessor
|
||||||
public:
|
public:
|
||||||
Preprocessor();
|
Preprocessor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the code for each configuration
|
||||||
|
* \param istr The (file/string) stream to read from.
|
||||||
|
* \param result The map that will get the results
|
||||||
|
*/
|
||||||
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the code for each configuration. Use this with getcode() to get the
|
||||||
|
* file data for each individual configuration.
|
||||||
|
*
|
||||||
|
* @param istr The (file/string) stream to read from.
|
||||||
|
* @param filename
|
||||||
|
* @param processedFile Give reference to empty string as a parameter,
|
||||||
|
* function will fill processed file here. Use this also as a filedata parameter
|
||||||
|
* to getcode() if you recieved more than once configurations.
|
||||||
|
* @param resultConfigurations List of configurations. Pass these one by one
|
||||||
|
* to getcode() with processedFile.
|
||||||
|
*/
|
||||||
|
void preprocess(std::istream &istr, const std::string &filename, std::string &processedFile, std::list<std::string> &resultConfigurations );
|
||||||
|
|
||||||
/** 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 */
|
||||||
std::string read(std::istream &istr, const std::string &filename);
|
std::string read(std::istream &istr, const std::string &filename);
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
/**
|
||||||
* Get preprocessed code for a given configuration
|
* Get preprocessed code for a given configuration
|
||||||
*/
|
*/
|
||||||
std::string getcode(const std::string &filedata, std::string cfg);
|
static std::string getcode(const std::string &filedata, std::string cfg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all possible configurations. By looking at the ifdefs and ifndefs in filedata
|
* Get all possible configurations. By looking at the ifdefs and ifndefs in filedata
|
||||||
*/
|
*/
|
||||||
std::list<std::string> getcfgs( const std::string &filedata );
|
std::list<std::string> getcfgs( const std::string &filedata );
|
||||||
|
|
||||||
std::string getdef(std::string line, bool def);
|
static std::string getdef(std::string line, bool def);
|
||||||
|
|
||||||
bool match_cfg_def( std::string cfg, const std::string &def );
|
static bool match_cfg_def( std::string cfg, const std::string &def );
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue