2009-01-08 07:22:14 +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
2009-01-08 07:22:14 +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/
*/
2009-01-06 16:02:34 +01:00
2009-01-08 18:29:44 +01:00
# include <fstream>
2009-01-06 16:02:34 +01:00
# include <iostream>
# include <list>
# include <string>
class Message
{
2009-01-13 07:25:36 +01:00
public :
2009-02-05 22:06:32 +01:00
enum Settings { error , all , style , style_all , never } ;
2009-01-13 07:25:36 +01:00
Message ( std : : string funcname , Settings settings , std : : string msg ) ;
Message ( std : : string funcname , Settings settings , std : : string msg , std : : string par1 ) ;
Message ( std : : string funcname , Settings settings , std : : string msg , std : : string par1 , std : : string par2 ) ;
2009-01-26 20:14:46 +01:00
Message ( std : : string funcname , Settings settings , std : : string msg , std : : string par1 , std : : string par2 , std : : string details ) ;
2009-01-13 07:25:36 +01:00
void generateCode ( std : : ostream & ostr ) const ;
void generateDoc ( std : : ostream & ostr , Settings i ) const ;
2009-01-31 09:33:31 +01:00
std : : string stringifySettings ( bool text ) const ;
2009-01-06 16:02:34 +01:00
private :
std : : string _funcname ;
std : : string _msg ;
std : : string _par1 ;
2009-01-10 18:11:47 +01:00
std : : string _par2 ;
2009-01-13 07:25:36 +01:00
Settings _settings ;
2009-01-26 20:14:46 +01:00
std : : string _details ;
2009-01-06 16:02:34 +01:00
2009-01-08 21:56:51 +01:00
std : : string msg ( bool code ) const ;
2009-01-06 16:02:34 +01:00
} ;
int main ( )
{
// Error messages..
std : : list < Message > err ;
2009-01-08 21:56:51 +01:00
2009-01-10 20:23:21 +01:00
// checkbufferoverrun.cpp
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " arrayIndexOutOfBounds " , Message : : all , " Array index out of bounds " ) ) ;
err . push_back ( Message ( " bufferOverrun " , Message : : all , " Buffer overrun " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " outOfBounds " , Message : : error , " %1 is out of bounds " , " what " ) ) ;
2009-02-10 20:36:49 +01:00
err . push_back ( Message ( " stlOutOfBounds " , Message : : error , " %1 is out of bounds " , " what " ) ) ;
2009-01-10 20:23:21 +01:00
2009-01-10 15:29:59 +01:00
// checkclass.cpp..
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " noConstructor " , Message : : style , " The class '%1' has no constructor " , " classname " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " uninitVar " , Message : : error , " Uninitialized member variable '%1::%2' " , " classname " , " varname " ) ) ;
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " unusedPrivateFunction " , Message : : style , " Unused private function '%1::%2' " , " classname " , " funcname " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " memsetClass " , Message : : error , " Using '%1' on class " , " memfunc " ) ) ;
err . push_back ( Message ( " memsetStruct " , Message : : error , " Using '%1' on struct that contains a 'std::%2' " , " memfunc " , " classname " ) ) ;
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " operatorEq " , Message : : style , " 'operator=' should return something " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " virtualDestructor " , Message : : error , " Class %1 which is inherited by class %2 does not have a virtual destructor " , " Base " , " Derived " ) ) ;
2009-01-10 14:08:44 +01:00
2009-01-11 07:44:32 +01:00
// checkfunctionusage.cpp..
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " unusedFunction " , Message : : style_all , " [%1]: The function '%2' is never used " , " filename " , " funcname " ) ) ;
2009-01-11 07:44:32 +01:00
2009-01-08 21:56:51 +01:00
// checkmemoryleak.cpp..
2009-02-06 19:24:01 +01:00
err . push_back ( Message ( " mismatchAllocDealloc " , Message : : error , " Mismatching allocation and deallocation: %1 " , " varname " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " memleak " , Message : : error , " Memory leak: %1 " , " varname " ) ) ;
2009-01-31 14:57:27 +01:00
err . push_back ( Message ( " memleakall " , Message : : all , " Memory leak: %1 " , " varname " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " resourceLeak " , Message : : error , " Resource leak: %1 " , " varname " ) ) ;
err . push_back ( Message ( " deallocDealloc " , Message : : error , " Deallocating a deallocated pointer: %1 " , " varname " ) ) ;
err . push_back ( Message ( " deallocuse " , Message : : error , " Using '%1' after it is deallocated / released " , " varname " ) ) ;
2009-02-08 19:34:04 +01:00
err . push_back ( Message ( " mismatchSize " , Message : : error , " The given size %1 is mismatching " , " sz " ) ) ;
2009-01-06 16:02:34 +01:00
2009-01-08 21:56:51 +01:00
// checkother.cpp..
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " cstyleCast " , Message : : style , " C-style pointer casting " ) ) ;
err . push_back ( Message ( " redundantIfDelete0 " , Message : : style , " Redundant condition. It is safe to deallocate a NULL pointer " ) ) ;
err . push_back ( Message ( " redundantIfRemove " , Message : : style , " Redundant condition. The remove function in the STL will not do anything if element doesn't exist " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " dangerousUsageStrtol " , Message : : error , " Invalid radix in call to strtol or strtoul. Must be 0 or 2-36 " ) ) ;
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " ifNoAction " , Message : : style , " Found redundant if condition - 'if (condition);' " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " sprintfOverlappingData " , Message : : error , " Overlapping data buffer %1 " , " varname " , " " ,
2009-01-26 20:14:46 +01:00
" -- If copying takes place between objects that overlap as a result of a \n "
" call to sprintf() or snprintf(), the results are undefined. \n "
" http://www.opengroup.org/onlinepubs/000095399/functions/printf.html " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " udivError " , Message : : error , " Unsigned division. The result will be wrong. " ) ) ;
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " udivWarning " , Message : : style_all , " Warning: Division with signed and unsigned operators " ) ) ;
err . push_back ( Message ( " unusedStructMember " , Message : : style , " struct or union member '%1::%2' is never used " , " structname " , " varname " ) ) ;
2009-01-26 19:32:00 +01:00
err . push_back ( Message ( " passedByValue " , Message : : style , " Function parameter '%1' is passed by value. It could be passed by reference instead. " , " parname " ) ) ;
2009-01-13 07:25:36 +01:00
err . push_back ( Message ( " constStatement " , Message : : style , " Redundant code: Found a statement that begins with %1 constant " , " type " ) ) ;
err . push_back ( Message ( " charArrayIndex " , Message : : style , " Warning - using char variable as array index " ) ) ;
err . push_back ( Message ( " charBitOp " , Message : : style , " Warning - using char variable in bit operation " ) ) ;
err . push_back ( Message ( " variableScope " , Message : : never , " The scope of the variable %1 can be limited " , " varname " ) ) ;
2009-01-14 20:43:28 +01:00
err . push_back ( Message ( " conditionAlwaysTrueFalse " , Message : : style , " Condition is always %1 " , " truefalse " ) ) ;
2009-02-05 22:06:32 +01:00
err . push_back ( Message ( " strPlusChar " , Message : : error , " Unusual pointer arithmetic " ) ) ;
err . push_back ( Message ( " returnLocalVariable " , Message : : error , " Returning pointer to local array variable " ) ) ;
2009-01-08 21:56:51 +01:00
2009-02-09 21:51:04 +01:00
// checkdangerousfunctions.cpp..
err . push_back ( Message ( " dangerousFunctionmktemp " , Message : : style , " Found 'mktemp'. You should use 'mkstemp' instead " ) ) ;
err . push_back ( Message ( " dangerousFunctiongets " , Message : : style , " Found 'gets'. You should use 'fgets' instead " ) ) ;
err . push_back ( Message ( " dangerousFunctionscanf " , Message : : style , " Found 'scanf'. You should use 'fgets' instead " ) ) ;
2009-02-10 20:40:21 +01:00
// checkstl.cpp..
err . push_back ( Message ( " iteratorUsage " , Message : : error , " Same iterator is used with both %1 and %2 " , " container1 " , " container2 " ) ) ;
2009-02-11 06:08:29 +01:00
err . push_back ( Message ( " erase " , Message : : error , " Dangerous usage of erase " ) ) ;
2009-02-10 20:40:21 +01:00
2009-02-09 21:51:04 +01:00
2009-01-06 16:02:34 +01:00
// Generate code..
2009-01-07 16:17:02 +01:00
std : : cout < < " Generate code.. " < < std : : endl ;
2009-02-08 22:20:35 +01:00
std : : ofstream fout ( " errorlogger.h " ) ;
2009-01-08 21:51:07 +01:00
fout < < " /* \n " ;
2009-01-21 21:04:20 +01:00
fout < < " * Cppcheck - A tool for static C/C++ code analysis \n " ;
fout < < " * Copyright (C) 2007-2009 Daniel Marjamäki, Reijo Tomperi, Nicolas Le Cam, \n " ;
fout < < " * Leandro Penz, Kimmo Varis \n " ;
2009-01-08 21:51:07 +01:00
fout < < " * \n " ;
fout < < " * This program is free software: you can redistribute it and/or modify \n " ;
fout < < " * it under the terms of the GNU General Public License as published by \n " ;
fout < < " * the Free Software Foundation, either version 3 of the License, or \n " ;
fout < < " * (at your option) any later version. \n " ;
fout < < " * \n " ;
fout < < " * This program is distributed in the hope that it will be useful, \n " ;
fout < < " * but WITHOUT ANY WARRANTY; without even the implied warranty of \n " ;
fout < < " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n " ;
fout < < " * GNU General Public License for more details. \n " ;
fout < < " * \n " ;
fout < < " * You should have received a copy of the GNU General Public License \n " ;
fout < < " * along with this program. If not, see <http://www.gnu.org/licenses/ \n " ;
fout < < " */ \n \n " ;
fout < < " // THIS FILE IS GENERATED BY MACHINE, SEE ../tools/errmsg.cpp ! \n \n " ;
2009-02-08 22:20:35 +01:00
fout < < " #ifndef errorloggerH \n " ;
fout < < " #define errorloggerH \n " ;
2009-02-01 16:47:36 +01:00
fout < < " #include <list> \n " ;
2009-01-08 18:29:44 +01:00
fout < < " #include <string> \n " ;
fout < < " #include \" settings.h \" \n " ;
fout < < " class Token; \n " ;
fout < < " class Tokenizer; \n " ;
2009-02-08 22:20:35 +01:00
fout < < " \n " ;
fout < < " /** \n " ;
fout < < " * This is an interface, which the class responsible of error logging \n " ;
fout < < " * should implement. \n " ;
fout < < " */ \n " ;
fout < < " class ErrorLogger \n " ;
2009-01-08 18:29:44 +01:00
fout < < " { \n " ;
fout < < " public: \n " ;
2009-02-08 22:20:35 +01:00
fout < < " \n " ;
2009-02-10 22:51:52 +01:00
fout < < " /** \n " ;
fout < < " * reportErr() \n " ;
fout < < " */ \n " ;
fout < < " class ErrorMessage \n " ;
fout < < " { \n " ;
fout < < " public: \n " ;
fout < < " /** \n " ;
fout < < " * File name and line number. \n " ;
fout < < " */ \n " ;
fout < < " class FileLocation \n " ;
fout < < " { \n " ;
fout < < " public: \n " ;
fout < < " std::string file; \n " ;
fout < < " unsigned int line; \n " ;
fout < < " }; \n " ;
fout < < " \n " ;
fout < < " ErrorMessage(const std::list<FileLocation> &callStack, const std::string &severity, const std::string &msg, const std::string &id); \n " ;
fout < < " std::string toXML() const; \n " ;
fout < < " std::string toText() const; \n " ;
fout < < " private: \n " ;
fout < < " std::list<FileLocation> _callStack; \n " ;
fout < < " std::string _severity; \n " ;
fout < < " std::string _msg; \n " ;
fout < < " std::string _id; \n " ;
fout < < " }; \n " ;
fout < < " \n " ;
2009-02-08 22:20:35 +01:00
fout < < " ErrorLogger() { } \n " ;
fout < < " virtual ~ErrorLogger() { } \n " ;
fout < < " \n " ;
fout < < " /** \n " ;
fout < < " * Information about progress is directed here. \n " ;
fout < < " * \n " ;
fout < < " * @param outmsg, E.g. \" Checking main.cpp... \" \n " ;
fout < < " */ \n " ;
fout < < " virtual void reportOut(const std::string &outmsg) = 0; \n " ;
fout < < " \n " ;
fout < < " /** \n " ;
2009-02-09 21:51:04 +01:00
fout < < " * Output of error / warning \n " ;
2009-02-08 22:20:35 +01:00
fout < < " * Todo: callstack handling \n " ;
fout < < " * \n " ;
2009-02-09 21:51:04 +01:00
fout < < " * @param callStack File names and line numbers where the error \n " ;
fout < < " * was found and where it was called from. Error location is last \n " ;
fout < < " * element in the list \n " ;
2009-02-08 22:20:35 +01:00
fout < < " * @param id error id (function name) \n " ;
fout < < " * @param severity severity of error (always, all, style, all+style, never) \n " ;
fout < < " * @param msg error message in plain text \n " ;
fout < < " */ \n " ;
2009-02-10 22:51:52 +01:00
fout < < " virtual void reportErr(const ErrorLogger::ErrorMessage &msg) = 0; \n " ;
2009-02-08 22:20:35 +01:00
fout < < " \n " ;
2009-01-06 16:02:34 +01:00
for ( std : : list < Message > : : const_iterator it = err . begin ( ) ; it ! = err . end ( ) ; + + it )
2009-01-08 18:29:44 +01:00
it - > generateCode ( fout ) ;
2009-02-09 21:51:04 +01:00
fout < < " \n " ;
2009-02-10 22:51:52 +01:00
fout < < " static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack); \n " ;
2009-02-08 22:20:35 +01:00
fout < < " \n " ;
fout < < " private: \n " ;
fout < < " void _writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string msg, const std::string &id); \n " ;
fout < < " void _writemsg(const Tokenizer *tokenizer, const std::list<const Token *> &callstack, const char severity[], const std::string msg, const std::string &id); \n " ;
fout < < " void _writemsg(const std::string msg, const std::string &id); \n " ;
2009-01-08 18:29:44 +01:00
fout < < " }; \n " ;
fout < < " #endif \n " ;
2009-01-07 16:17:02 +01:00
std : : cout < < std : : endl ;
// Generate documentation..
std : : cout < < " Generate doc.. " < < std : : endl ;
for ( unsigned int i = 0 ; i < 4 ; + + i )
{
2009-02-05 22:06:32 +01:00
const char * suite [ 4 ] = { " error " , " all " , " style " , " all + style " } ;
const Message : : Settings settings [ 4 ] = { Message : : error , Message : : all , Message : : style , Message : : style_all } ;
2009-01-07 16:17:02 +01:00
std : : cout < < " = " < < suite [ i ] < < " = " < < std : : endl ;
for ( std : : list < Message > : : const_iterator it = err . begin ( ) ; it ! = err . end ( ) ; + + it )
2009-01-13 07:25:36 +01:00
it - > generateDoc ( std : : cout , settings [ i ] ) ;
2009-01-07 16:17:02 +01:00
}
std : : cout < < std : : endl ;
2009-01-06 16:02:34 +01:00
return 0 ;
}
2009-01-08 21:56:51 +01:00
2009-01-13 07:25:36 +01:00
Message : : Message ( std : : string funcname , Settings settings , std : : string msg )
2009-01-26 20:14:46 +01:00
: _funcname ( funcname ) , _msg ( msg ) , _par1 ( " " ) , _par2 ( " " ) , _settings ( settings ) , _details ( " " )
2009-01-10 18:11:47 +01:00
{ }
2009-01-13 07:25:36 +01:00
Message : : Message ( std : : string funcname , Settings settings , std : : string msg , std : : string par1 )
2009-01-26 20:14:46 +01:00
: _funcname ( funcname ) , _msg ( msg ) , _par1 ( par1 ) , _par2 ( " " ) , _settings ( settings ) , _details ( " " )
2009-01-10 18:11:47 +01:00
{ }
2009-01-13 07:25:36 +01:00
Message : : Message ( std : : string funcname , Settings settings , std : : string msg , std : : string par1 , std : : string par2 )
2009-01-26 20:14:46 +01:00
: _funcname ( funcname ) , _msg ( msg ) , _par1 ( par1 ) , _par2 ( par2 ) , _settings ( settings ) , _details ( " " )
{ }
Message : : Message ( std : : string funcname , Settings settings , std : : string msg , std : : string par1 , std : : string par2 , std : : string details )
: _funcname ( funcname ) , _msg ( msg ) , _par1 ( par1 ) , _par2 ( par2 ) , _settings ( settings ) , _details ( details )
2009-01-08 21:56:51 +01:00
{ }
std : : string Message : : msg ( bool code ) const
{
const char * str = code ? " \" " : " " ;
std : : string ret ( str + _msg + str ) ;
2009-01-10 18:11:47 +01:00
2009-01-08 21:56:51 +01:00
if ( ! _par1 . empty ( ) )
{
std : : string : : size_type pos = 0 ;
while ( ( pos = ret . find ( " %1 " , pos ) ) ! = std : : string : : npos )
{
ret . erase ( pos , 2 ) ;
if ( code )
ret . insert ( pos , " \" + " + _par1 + " + \" " ) ;
else
ret . insert ( pos , _par1 ) ;
}
}
2009-01-10 18:11:47 +01:00
if ( ! _par2 . empty ( ) )
{
std : : string : : size_type pos = 0 ;
while ( ( pos = ret . find ( " %2 " , pos ) ) ! = std : : string : : npos )
{
ret . erase ( pos , 2 ) ;
if ( code )
ret . insert ( pos , " \" + " + _par2 + " + \" " ) ;
else
ret . insert ( pos , _par2 ) ;
}
}
2009-01-08 21:56:51 +01:00
return ret ;
}
void Message : : generateCode ( std : : ostream & ostr ) const
{
2009-01-11 09:10:51 +01:00
bool loc = bool ( _msg . substr ( 0 , 4 ) ! = " [%1] " ) ;
2009-01-08 21:56:51 +01:00
// Error message..
2009-02-08 22:20:35 +01:00
ostr < < " void " < < _funcname < < " ( " ;
2009-01-11 09:10:51 +01:00
if ( loc )
2009-02-01 16:47:36 +01:00
{
ostr < < " const Tokenizer *tokenizer, " ;
if ( _funcname = = " mismatchAllocDealloc " | |
_funcname = = " arrayIndexOutOfBounds " )
ostr < < " const std::list<const Token *> &Location " ;
else
ostr < < " const Token *Location " ;
}
/*
2009-01-26 20:14:46 +01:00
if ( _details . size ( ) )
ostr < < " , const Settings &settings " ;
2009-02-01 16:47:36 +01:00
*/
2009-01-08 21:56:51 +01:00
if ( ! _par1 . empty ( ) )
2009-01-11 09:10:51 +01:00
ostr < < ( loc ? " , " : " " ) < < " const std::string & " < < _par1 ;
2009-01-10 18:11:47 +01:00
if ( ! _par2 . empty ( ) )
ostr < < " , const std::string & " < < _par2 ;
2009-01-08 21:56:51 +01:00
ostr < < " ) \n " ;
2009-01-10 08:43:15 +01:00
ostr < < " { \n " ;
2009-02-08 22:20:35 +01:00
ostr < < " _writemsg( " ;
2009-02-01 16:47:36 +01:00
if ( loc )
ostr < < " tokenizer, Location, \" " < < stringifySettings ( true ) < < " \" , " ;
2009-02-01 19:00:47 +01:00
ostr < < msg ( true ) < < " , \" " < < _funcname < < " \" ); \n " ;
2009-02-01 17:39:29 +01:00
/*
ostr < < " return " ;
if ( loc )
ostr < < " msg1(tokenizer, Location) + " ;
ostr < < " std::string( \" ( " < < stringifySettings ( true ) < < " ) \" ) + " ;
ostr < < msg ( true ) ;
if ( _details . empty ( ) )
ostr < < " ; \n " ;
else
2009-01-26 20:14:46 +01:00
{
2009-02-01 17:39:29 +01:00
ostr < < " + std::string(settings._verbose ? \" \\ n " ;
for ( std : : string : : size_type pos = 0 ; pos < _details . length ( ) ; + + pos )
{
if ( _details [ pos ] = = ' \n ' )
ostr < < " \\ n " ;
else
ostr < < _details [ pos ] ;
}
ostr < < " \" : \" \" ); \n " ;
2009-01-26 20:14:46 +01:00
}
2009-02-01 17:39:29 +01:00
*/
2009-01-10 08:43:15 +01:00
ostr < < " } \n " ;
2009-01-08 21:56:51 +01:00
// Settings..
2009-01-19 20:50:00 +01:00
ostr < < " static bool " < < _funcname < < " ( " ;
2009-02-05 22:06:32 +01:00
if ( _settings ! = error & & _settings ! = never )
2009-01-19 20:50:00 +01:00
ostr < < " const Settings &s " ;
ostr < < " ) " < < std : : endl ;
2009-01-10 08:43:15 +01:00
ostr < < " { \n " ;
2009-01-31 09:33:31 +01:00
ostr < < " return " < < stringifySettings ( false ) < < " ; \n " ;
2009-01-10 12:17:00 +01:00
ostr < < " } \n \n " ;
2009-01-08 21:56:51 +01:00
}
2009-01-13 07:25:36 +01:00
void Message : : generateDoc ( std : : ostream & ostr , Message : : Settings i ) const
2009-01-08 21:56:51 +01:00
{
if ( _settings = = i )
{
ostr < < " " < < msg ( false ) < < std : : endl ;
}
}
2009-01-31 09:33:31 +01:00
std : : string Message : : stringifySettings ( bool text ) const
{
switch ( _settings )
{
2009-02-05 22:06:32 +01:00
case error :
return text ? " error " : " true " ;
2009-01-31 09:33:31 +01:00
case all :
return text ? " all " : " s._showAll " ;
case style :
return text ? " style " : " s._checkCodingStyle " ;
case style_all :
return text ? " all style " : " s._checkCodingStyle || s._showAll " ;
case never :
return text ? " never " : " false " ;
}
return " " ;
}
2009-01-08 21:56:51 +01:00