2008-12-18 22:28:57 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
* Copyright ( C ) 2007 - 2009 Daniel Marjamäki , Reijo Tomperi , Nicolas Le Cam ,
* Leandro Penz , Kimmo Varis
2008-12-18 22:28:57 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/
*/
# include "cppcheck.h"
# include "preprocessor.h" // preprocessor.
# include "tokenize.h" // <- Tokenizer
# include "checkmemoryleak.h"
# include "checkbufferoverrun.h"
# include "checkclass.h"
# include "checkheaders.h"
# include "checkother.h"
# include "checkfunctionusage.h"
# include "filelister.h"
2009-01-08 18:32:33 +01:00
# include "errormessage.h"
2008-12-18 22:28:57 +01:00
# include <algorithm>
# include <sstream>
# include <cstring>
# include <fstream>
# include <map>
//---------------------------------------------------------------------------
2009-01-05 16:49:57 +01:00
CppCheck : : CppCheck ( ErrorLogger & errorLogger )
2008-12-18 22:28:57 +01:00
{
_errorLogger = & errorLogger ;
}
CppCheck : : ~ CppCheck ( )
{
}
2009-01-05 16:49:57 +01:00
void CppCheck : : settings ( const Settings & settings )
2008-12-18 22:28:57 +01:00
{
_settings = settings ;
}
2009-01-05 16:49:57 +01:00
void CppCheck : : addFile ( const std : : string & path )
2008-12-18 22:28:57 +01:00
{
2009-01-05 16:49:57 +01:00
_filenames . push_back ( path ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-05 16:49:57 +01:00
void CppCheck : : addFile ( const std : : string & path , const std : : string & content )
2008-12-18 22:28:57 +01:00
{
2009-01-05 16:49:57 +01:00
_filenames . push_back ( path ) ;
2008-12-18 22:28:57 +01:00
_fileContents [ path ] = content ;
}
2009-01-05 16:49:57 +01:00
std : : string CppCheck : : parseFromArgs ( int argc , const char * const argv [ ] )
2008-12-18 22:28:57 +01:00
{
std : : vector < std : : string > pathnames ;
2009-01-25 12:05:51 +01:00
bool showHelp = false ;
2008-12-18 22:28:57 +01:00
for ( int i = 1 ; i < argc ; i + + )
{
// Flag used for various purposes during debugging
2009-01-05 16:49:57 +01:00
if ( strcmp ( argv [ i ] , " --debug " ) = = 0 )
2008-12-18 22:28:57 +01:00
_settings . _debug = true ;
// Show all messages
2009-01-05 16:49:57 +01:00
else if ( strcmp ( argv [ i ] , " -a " ) = = 0 | | strcmp ( argv [ i ] , " --all " ) = = 0 )
2008-12-18 22:28:57 +01:00
_settings . _showAll = true ;
// Only print something when there are errors
2009-01-05 16:49:57 +01:00
else if ( strcmp ( argv [ i ] , " -q " ) = = 0 | | strcmp ( argv [ i ] , " --quiet " ) = = 0 )
2008-12-18 22:28:57 +01:00
_settings . _errorsOnly = true ;
// Checking coding style
2009-01-05 16:49:57 +01:00
else if ( strcmp ( argv [ i ] , " -s " ) = = 0 | | strcmp ( argv [ i ] , " --style " ) = = 0 )
2008-12-18 22:28:57 +01:00
_settings . _checkCodingStyle = true ;
// Verbose error messages (configuration info)
2009-01-05 16:49:57 +01:00
else if ( strcmp ( argv [ i ] , " -v " ) = = 0 | | strcmp ( argv [ i ] , " --verbose " ) = = 0 )
2008-12-18 22:28:57 +01:00
_settings . _verbose = true ;
2008-12-27 08:52:07 +01:00
// Force checking of files that have "too many" configurations
2009-01-05 16:49:57 +01:00
else if ( strcmp ( argv [ i ] , " -f " ) = = 0 | | strcmp ( argv [ i ] , " --force " ) = = 0 )
2008-12-27 08:52:07 +01:00
_settings . _force = true ;
2009-01-28 18:12:43 +01:00
// Write results in results.xml
else if ( strcmp ( argv [ i ] , " --xml-results " ) = = 0 )
_settings . _xmlResults = true ;
2009-01-22 21:26:04 +01:00
// Print help
else if ( strcmp ( argv [ i ] , " -h " ) = = 0 | | strcmp ( argv [ i ] , " --help " ) = = 0 )
{
pathnames . clear ( ) ;
_filenames . clear ( ) ;
2009-01-25 12:05:51 +01:00
showHelp = true ;
2009-01-22 21:26:04 +01:00
break ;
}
2009-01-22 20:59:50 +01:00
// 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 ) ;
}
2009-01-22 21:26:04 +01:00
else if ( strncmp ( argv [ i ] , " - " , 1 ) = = 0 | | strncmp ( argv [ i ] , " -- " , 2 ) = = 0 )
{
return " cppcheck: error: unrecognized command line option \" " + std : : string ( argv [ i ] ) + " \" \n " ;
}
2008-12-18 22:28:57 +01:00
else
2009-01-05 16:49:57 +01:00
pathnames . push_back ( argv [ i ] ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-05 16:49:57 +01:00
if ( pathnames . size ( ) > 0 )
2008-12-18 22:28:57 +01:00
{
2008-12-19 19:18:29 +01:00
// Execute RecursiveAddFiles() to each given file parameter
2008-12-18 22:28:57 +01:00
std : : vector < std : : string > : : const_iterator iter ;
2009-01-05 16:49:57 +01:00
for ( iter = pathnames . begin ( ) ; iter ! = pathnames . end ( ) ; iter + + )
FileLister : : RecursiveAddFiles ( _filenames , iter - > c_str ( ) , true ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-25 12:05:51 +01:00
if ( argc < = 1 | | showHelp )
2008-12-18 22:28:57 +01:00
{
std : : ostringstream oss ;
2009-01-21 21:04:20 +01:00
oss < < " Cppcheck 1.27 \n "
2009-01-05 16:49:57 +01:00
" \n "
2009-01-21 21:04:20 +01:00
" A tool for static C/C++ code analysis \n "
2009-01-05 16:49:57 +01:00
" \n "
" Syntax: \n "
2009-01-22 21:26:04 +01:00
" cppcheck [--all] [--force] [--help] [-Idir] [--quiet] [--style] \n "
" [--verbose] [file or path1] [file or path] \n "
2009-01-05 16:49:57 +01:00
" \n "
2009-01-16 23:42:08 +01:00
" If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files \n "
" are checked recursively from given directory. \n \n "
2009-01-05 16:49:57 +01:00
" Options: \n "
" -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 "
2009-01-22 21:26:04 +01:00
" -h, --help Print this help \n "
2009-01-24 19:24:04 +01:00
" -I <dir> Give include path. Give several -I parameters to give \n "
" several paths. First given path is checked first. If paths \n "
" are relative to source files, this is not needed. \n "
2009-01-05 16:49:57 +01:00
" -q, --quiet Only print error messages \n "
" -s, --style Check coding style \n "
" -v, --verbose More detailed error reports \n "
" \n "
" Example usage: \n "
2009-01-24 19:24:04 +01:00
" # Recursively check the current folder. Print the progress on the screen and \n "
" write errors in a file: \n "
2009-01-05 16:49:57 +01:00
" cppcheck . 2> err.txt \n "
" # 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 "
2009-01-22 20:59:50 +01:00
" 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 " ;
2008-12-18 22:28:57 +01:00
return oss . str ( ) ;
}
2009-01-25 12:05:51 +01:00
else if ( _filenames . empty ( ) )
{
return " cppcheck: No C or C++ source files found. \n " ;
}
2008-12-18 22:28:57 +01:00
return " " ;
}
2009-01-08 22:30:25 +01:00
unsigned int CppCheck : : check ( )
2008-12-18 22:28:57 +01:00
{
2009-01-05 16:49:57 +01:00
_checkFunctionUsage . setErrorLogger ( this ) ;
std : : sort ( _filenames . begin ( ) , _filenames . end ( ) ) ;
2008-12-18 22:28:57 +01:00
for ( unsigned int c = 0 ; c < _filenames . size ( ) ; c + + )
{
_errout . str ( " " ) ;
std : : string fname = _filenames [ c ] ;
2009-01-19 20:00:36 +01:00
if ( _settings . _errorsOnly = = false )
_errorLogger - > reportOut ( std : : string ( " Checking " ) + fname + std : : string ( " ... " ) ) ;
2008-12-18 22:28:57 +01:00
Preprocessor preprocessor ;
2008-12-26 23:52:27 +01:00
std : : list < std : : string > configurations ;
std : : string filedata = " " ;
2009-01-05 16:49:57 +01:00
if ( _fileContents . size ( ) > 0 & & _fileContents . find ( _filenames [ c ] ) ! = _fileContents . end ( ) )
2008-12-18 22:28:57 +01:00
{
// File content was given as a string
2009-01-05 16:49:57 +01:00
std : : istringstream iss ( _fileContents [ _filenames [ c ] ] ) ;
2009-01-22 20:59:50 +01:00
preprocessor . preprocess ( iss , filedata , configurations , fname , _includePaths ) ;
2008-12-18 22:28:57 +01:00
}
else
{
// Only file name was given, read the content from file
2009-01-05 16:49:57 +01:00
std : : ifstream fin ( fname . c_str ( ) ) ;
2009-01-22 20:59:50 +01:00
preprocessor . preprocess ( fin , filedata , configurations , fname , _includePaths ) ;
2008-12-18 22:28:57 +01:00
}
2008-12-27 08:52:07 +01:00
int checkCount = 0 ;
2009-01-05 16:49:57 +01:00
for ( std : : list < std : : string > : : const_iterator it = configurations . begin ( ) ; it ! = configurations . end ( ) ; + + it )
2008-12-18 22:28:57 +01:00
{
2008-12-27 08:52:07 +01:00
// Check only 12 first configurations, after that bail out, unless --force
// was used.
2009-01-05 16:49:57 +01:00
if ( ! _settings . _force & & checkCount > 11 )
2008-12-27 08:52:07 +01:00
{
2009-01-05 16:49:57 +01:00
if ( _settings . _errorsOnly = = false )
_errorLogger - > reportOut ( std : : string ( " Bailing out from checking " ) + fname + " : Too many configurations. Recheck this file with --force if you want to check them all. " ) ;
2008-12-28 21:13:03 +01:00
2008-12-27 08:52:07 +01:00
break ;
}
2008-12-26 23:52:27 +01:00
cfg = * it ;
2009-01-05 16:49:57 +01:00
std : : string codeWithoutCfg = Preprocessor : : getcode ( filedata , * it ) ;
2008-12-26 23:52:27 +01:00
// If only errors are printed, print filename after the check
2009-01-19 20:00:36 +01:00
if ( _settings . _errorsOnly = = false & & it ! = configurations . begin ( ) )
2009-01-05 16:49:57 +01:00
_errorLogger - > reportOut ( std : : string ( " Checking " ) + fname + " : " + cfg + std : : string ( " ... " ) ) ;
2008-12-26 23:52:27 +01:00
2009-01-05 16:49:57 +01:00
checkFile ( codeWithoutCfg , _filenames [ c ] . c_str ( ) ) ;
2009-01-01 23:22:28 +01:00
+ + checkCount ;
2008-12-18 22:28:57 +01:00
}
2009-01-05 16:49:57 +01:00
if ( _settings . _errorsOnly = = false & & _errout . str ( ) . empty ( ) )
2009-01-24 09:06:40 +01:00
{
std : : ostringstream oss ;
oss < < " No errors found ( "
< < ( c + 1 ) < < " / " < < _filenames . size ( )
< < " files checked " < <
static_cast < int > ( static_cast < double > ( ( c + 1 ) ) / _filenames . size ( ) * 100 )
< < " % done) " ;
_errorLogger - > reportOut ( oss . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
}
// This generates false positives - especially for libraries
_settings . _verbose = false ;
2009-01-11 07:44:32 +01:00
if ( ErrorMessage : : unusedFunction ( _settings ) )
2008-12-18 22:28:57 +01:00
{
_errout . str ( " " ) ;
2009-01-05 16:49:57 +01:00
if ( _settings . _errorsOnly = = false )
_errorLogger - > reportOut ( " Checking usage of global functions (this may take several minutes).. " ) ;
2008-12-18 22:28:57 +01:00
_checkFunctionUsage . check ( ) ;
}
2009-01-28 18:12:43 +01:00
// xml results..
if ( _settings . _xmlResults )
{
std : : ofstream fxml ( " results.xml " ) ;
fxml < < " <cppcheckResults> \n "
< < " <test result= \" " < < ( _errorList . empty ( ) ? " OK " : " ERROR " ) < < " \" /> \n "
< < " <name>cppcheck</name> \n " ;
if ( _errorList . size ( ) )
{
fxml < < " <message> \n " ;
for ( std : : list < std : : string > : : const_iterator it = _errorList . begin ( ) ; it ! = _errorList . end ( ) ; + + it )
fxml < < * it < < " \n " ;
fxml < < " </message> \n " ;
}
fxml < < " </test> \n "
< < " </cppcheckResults> \n " ;
}
2009-01-08 22:30:25 +01:00
unsigned int result = _errorList . size ( ) ;
2008-12-18 22:28:57 +01:00
_errorList . clear ( ) ;
2009-01-08 22:30:25 +01:00
return result ;
2008-12-18 22:28:57 +01:00
}
//---------------------------------------------------------------------------
// CppCheck - A function that checks a specified file
//---------------------------------------------------------------------------
void CppCheck : : checkFile ( const std : : string & code , const char FileName [ ] )
{
2009-01-24 14:53:53 +01:00
/* For debugging: Write the code into a file and exit
{
std : : ofstream f ( " temp.txt " ) ;
f < < code ;
exit ( 0 ) ;
}
*/
2008-12-18 22:28:57 +01:00
Tokenizer _tokenizer ;
// Tokenize the file
{
2009-01-05 16:49:57 +01:00
std : : istringstream istr ( code ) ;
_tokenizer . tokenize ( istr , FileName ) ;
2008-12-18 22:28:57 +01:00
}
// Set variable id
_tokenizer . setVarId ( ) ;
_tokenizer . fillFunctionList ( ) ;
// Check that the memsets are valid.
// The 'memset' function can do dangerous things if used wrong.
// Important: The checking doesn't work on simplified tokens list.
2009-01-05 16:49:57 +01:00
CheckClass checkClass ( & _tokenizer , _settings , this ) ;
2009-01-19 20:50:59 +01:00
if ( ErrorMessage : : memsetClass ( ) )
2009-01-10 18:51:03 +01:00
checkClass . noMemset ( ) ;
2008-12-18 22:28:57 +01:00
2009-01-04 19:28:05 +01:00
// Coding style checks that must be run before the simplifyTokenList
2009-01-12 18:12:14 +01:00
CheckOther checkOther ( & _tokenizer , _settings , this ) ;
// Check for unsigned divisions where one operand is signed
2009-01-19 20:50:59 +01:00
if ( ErrorMessage : : udivWarning ( _settings ) | | ErrorMessage : : udivError ( ) )
2008-12-18 22:28:57 +01:00
checkOther . CheckUnsignedDivision ( ) ;
2009-01-12 19:52:43 +01:00
// Give warning when using char variable as array index
if ( ErrorMessage : : charArrayIndex ( _settings ) | | ErrorMessage : : charBitOp ( _settings ) )
2008-12-18 22:28:57 +01:00
checkOther . CheckCharVariable ( ) ;
2009-01-12 18:40:20 +01:00
2009-01-04 19:28:05 +01:00
2008-12-18 22:28:57 +01:00
_tokenizer . simplifyTokenList ( ) ;
2009-01-11 07:44:32 +01:00
if ( ErrorMessage : : unusedFunction ( _settings ) )
2008-12-18 22:28:57 +01:00
_checkFunctionUsage . parseTokens ( _tokenizer ) ;
2009-01-03 16:22:53 +01:00
// Class for detecting buffer overruns and related problems
2009-01-05 16:49:57 +01:00
CheckBufferOverrunClass checkBufferOverrun ( & _tokenizer , _settings , this ) ;
2009-01-03 16:22:53 +01:00
2008-12-18 22:28:57 +01:00
// Memory leak
2009-01-05 16:49:57 +01:00
CheckMemoryLeakClass checkMemoryLeak ( & _tokenizer , _settings , this ) ;
2009-01-22 22:20:40 +01:00
if ( ErrorMessage : : memleak ( ) | | ErrorMessage : : mismatchAllocDealloc ( ) )
2009-01-08 18:32:33 +01:00
checkMemoryLeak . CheckMemoryLeak ( ) ;
2008-12-18 22:28:57 +01:00
// Check that all class constructors are ok.
2009-01-21 20:11:27 +01:00
if ( ErrorMessage : : noConstructor ( _settings ) | | ErrorMessage : : uninitVar ( ) )
2009-01-10 14:08:44 +01:00
checkClass . constructors ( ) ;
2008-12-18 22:28:57 +01:00
// Check that all base classes have virtual destructors
2009-01-19 20:50:59 +01:00
if ( ErrorMessage : : virtualDestructor ( ) )
2009-01-10 19:03:56 +01:00
checkClass . virtualDestructor ( ) ;
2008-12-18 22:28:57 +01:00
2009-01-10 20:23:21 +01:00
// Array index out of bounds / Buffer overruns..
2009-01-22 22:20:40 +01:00
if ( ErrorMessage : : arrayIndexOutOfBounds ( _settings ) | | ErrorMessage : : bufferOverrun ( _settings ) )
2009-01-10 20:23:21 +01:00
checkBufferOverrun . bufferOverrun ( ) ;
2008-12-18 22:28:57 +01:00
// Dangerous functions, such as 'gets' and 'scanf'
2008-12-20 09:53:42 +01:00
checkBufferOverrun . dangerousFunctions ( ) ;
2008-12-18 22:28:57 +01:00
2009-01-08 21:56:51 +01:00
// Warning upon c-style pointer casts
2009-01-08 22:08:14 +01:00
if ( ErrorMessage : : cstyleCast ( _settings ) )
2008-12-18 22:28:57 +01:00
{
const char * ext = strrchr ( FileName , ' . ' ) ;
2009-01-05 16:49:57 +01:00
if ( ext & & strcmp ( ext , " .cpp " ) = = 0 )
2008-12-18 22:28:57 +01:00
checkOther . WarningOldStylePointerCast ( ) ;
2009-01-08 21:56:51 +01:00
}
2008-12-18 22:28:57 +01:00
2009-01-08 21:56:51 +01:00
// if (a) delete a;
2009-01-08 22:08:14 +01:00
if ( ErrorMessage : : redundantIfDelete0 ( _settings ) )
2008-12-18 22:28:57 +01:00
checkOther . WarningRedundantCode ( ) ;
2009-01-09 20:15:54 +01:00
// strtol and strtoul usage
2009-01-19 20:50:59 +01:00
if ( ErrorMessage : : dangerousUsageStrtol ( ) | |
ErrorMessage : : sprintfOverlappingData ( ) )
2009-01-09 20:15:54 +01:00
checkOther . InvalidFunctionUsage ( ) ;
2009-01-08 21:56:51 +01:00
2009-01-10 18:35:41 +01:00
// Check that all private functions are called.
if ( ErrorMessage : : unusedPrivateFunction ( _settings ) )
2009-01-08 21:56:51 +01:00
checkClass . privateFunctions ( ) ;
2009-01-10 18:57:31 +01:00
// 'operator=' should return something..
if ( ErrorMessage : : operatorEq ( _settings ) )
checkClass . operatorEq ( ) ;
2009-01-10 18:35:41 +01:00
2009-01-12 07:44:47 +01:00
// if (condition);
2009-01-14 20:43:28 +01:00
if ( ErrorMessage : : ifNoAction ( _settings ) | | ErrorMessage : : conditionAlwaysTrueFalse ( _settings ) )
2008-12-18 22:28:57 +01:00
checkOther . WarningIf ( ) ;
2009-01-12 18:21:25 +01:00
// Unused struct members..
if ( ErrorMessage : : unusedStructMember ( _settings ) )
checkOther . CheckStructMemberUsage ( ) ;
2009-01-12 18:32:53 +01:00
// Check if a constant function parameter is passed by value
2009-01-26 19:32:00 +01:00
if ( ErrorMessage : : passedByValue ( _settings ) )
2009-01-12 18:32:53 +01:00
checkOther . CheckConstantFunctionParameter ( ) ;
2009-01-12 18:28:04 +01:00
2009-01-13 07:25:36 +01:00
// Variable scope (check if the scope could be limited)
2009-01-19 20:50:59 +01:00
if ( ErrorMessage : : variableScope ( ) )
2009-01-14 08:43:46 +01:00
checkOther . CheckVariableScope ( ) ;
2008-12-18 22:28:57 +01:00
2009-01-12 18:46:24 +01:00
// Check for various types of incomplete statements that could for example
// mean that an ';' has been added by accident
if ( ErrorMessage : : constStatement ( _settings ) )
2008-12-18 22:28:57 +01:00
checkOther . CheckIncompleteStatement ( ) ;
2009-01-15 17:57:51 +01:00
// Unusual pointer arithmetic
2009-01-19 20:50:59 +01:00
if ( ErrorMessage : : strPlusChar ( ) )
2009-01-15 17:57:51 +01:00
checkOther . strPlusChar ( ) ;
2008-12-18 22:28:57 +01:00
}
//---------------------------------------------------------------------------
2009-01-05 16:49:57 +01:00
void CppCheck : : reportErr ( const std : : string & errmsg )
2008-12-18 22:28:57 +01:00
{
2009-01-05 16:49:57 +01:00
if ( /*OnlyReportUniqueErrors*/ true )
2008-12-18 22:28:57 +01:00
{
2009-01-05 16:49:57 +01:00
if ( std : : find ( _errorList . begin ( ) , _errorList . end ( ) , errmsg ) ! = _errorList . end ( ) )
2008-12-18 22:28:57 +01:00
return ;
2009-01-05 16:49:57 +01:00
_errorList . push_back ( errmsg ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-05 16:49:57 +01:00
std : : string errmsg2 ( errmsg ) ;
if ( _settings . _verbose )
2008-12-18 22:28:57 +01:00
{
errmsg2 + = " \n Defines= \' " + cfg + " \' \n " ;
}
2009-01-05 16:49:57 +01:00
_errorLogger - > reportErr ( errmsg2 ) ;
2008-12-18 22:28:57 +01:00
_errout < < errmsg2 < < std : : endl ;
}
2009-01-23 19:37:28 +01:00
void CppCheck : : reportOut ( const std : : string & /*outmsg*/ )
2008-12-18 22:28:57 +01:00
{
// This is currently never called. It is here just to comply with
// the interface.
}