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("");
|
||||
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;
|
||||
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() )
|
||||
{
|
||||
// File content was given as a string
|
||||
std::istringstream iss( _fileContents[ _filenames[c] ] );
|
||||
preprocessor.preprocess(iss, code, fname);
|
||||
preprocessor.preprocess(iss, fname, filedata, configurations );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only file name was given, read the content from file
|
||||
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;
|
||||
checkFile(it->second, _filenames[c].c_str());
|
||||
cfg = *it;
|
||||
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() )
|
||||
|
|
|
@ -140,55 +140,52 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename)
|
|||
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)
|
||||
{
|
||||
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..
|
||||
std::string::size_type loc = 0;
|
||||
while ( (loc = codestr.find("\t", loc)) != std::string::npos )
|
||||
codestr[loc] = ' ';
|
||||
while ( (loc = processedFile.find("\t", loc)) != std::string::npos )
|
||||
processedFile[loc] = ' ';
|
||||
|
||||
// Remove all indentation..
|
||||
if ( !codestr.empty() && codestr[0] == ' ' )
|
||||
codestr.erase( 0, codestr.find_first_not_of(" ") );
|
||||
if ( !processedFile.empty() && processedFile[0] == ' ' )
|
||||
processedFile.erase( 0, processedFile.find_first_not_of(" ") );
|
||||
loc = 0;
|
||||
while ( (loc = codestr.find("\n ", loc)) != std::string::npos )
|
||||
codestr.erase( 1 + loc, 1 );
|
||||
while ( (loc = processedFile.find("\n ", loc)) != std::string::npos )
|
||||
processedFile.erase( 1 + loc, 1 );
|
||||
|
||||
// Remove all trailing spaces..
|
||||
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 )
|
||||
--loc;
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (loc > 0 && codestr[loc-1] != ' ')
|
||||
codestr.insert(loc, " ");
|
||||
if ( (loc = codestr.find("\n", loc)) != std::string::npos)
|
||||
codestr.insert( loc, "\n" );
|
||||
processedFile.erase(loc, 2);
|
||||
if (loc > 0 && processedFile[loc-1] != ' ')
|
||||
processedFile.insert(loc, " ");
|
||||
if ( (loc = processedFile.find("\n", loc)) != std::string::npos)
|
||||
processedFile.insert( loc, "\n" );
|
||||
}
|
||||
|
||||
// Get all possible configurations..
|
||||
std::list<std::string> cfgs = getcfgs( codestr );
|
||||
|
||||
// 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 );
|
||||
}
|
||||
resultConfigurations = getcfgs( processedFile );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,25 +32,45 @@ class Preprocessor
|
|||
public:
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
std::string read(std::istream &istr, const std::string &filename);
|
||||
|
||||
private:
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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