Fix ticket #93 (Write xml results into error stream instead of results.xml file.) and also refactor the

code to use ErrorLogger::reportErr() for all errors, for both xml and plain text. And move xml formatting 
from Cppcheck to CppcheckExecutor.
This commit is contained in:
Reijo Tomperi 2009-02-09 20:51:04 +00:00
parent a5f88862b4
commit 1373e14bc9
15 changed files with 196 additions and 110 deletions

View File

@ -110,7 +110,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
<arg choice="opt"><option>--style</option></arg> <arg choice="opt"><option>--style</option></arg>
<arg choice="opt"><option>--unused-functions</option></arg> <arg choice="opt"><option>--unused-functions</option></arg>
<arg choice="opt"><option>--verbose</option></arg> <arg choice="opt"><option>--verbose</option></arg>
<arg choice="opt"><option>--xml-results</option></arg> <arg choice="opt"><option>--xml</option></arg>
<arg choice="opt"><option>file or path</option></arg> <arg choice="opt"><option>file or path</option></arg>
<arg choice="plain"><option>...</option></arg> <arg choice="plain"><option>...</option></arg>
</cmdsynopsis> </cmdsynopsis>
@ -187,9 +187,9 @@ files, this is not needed.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>--xml-results</option></term> <term><option>--xml</option></term>
<listitem> <listitem>
<para>Write results in results.xml</para> <para>Write results in xml to error stream</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -56,17 +56,17 @@ void CheckDangerousFunctionsClass::dangerousFunctions()
{ {
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
if (Token::Match(tok, "mktemp (")) if (Token::simpleMatch(tok, "mktemp ("))
{ {
std::ostringstream ostr; _errorLogger->dangerousFunctionmktemp(_tokenizer, tok);
ostr << _tokenizer->fileLine(tok) << ": Found 'mktemp'. You should use 'mkstemp' instead";
_errorLogger->reportErr(ostr.str());
} }
else if (Token::Match(tok, "gets|scanf (")) else if (Token::simpleMatch(tok, "gets ("))
{ {
std::ostringstream ostr; _errorLogger->dangerousFunctiongets(_tokenizer, tok);
ostr << _tokenizer->fileLine(tok) << ": Found '" << tok->str() << "'. You should use 'fgets' instead"; }
_errorLogger->reportErr(ostr.str()); else if (Token::simpleMatch(tok, "scanf ("))
{
_errorLogger->dangerousFunctionscanf(_tokenizer, tok);
} }
} }
} }

View File

@ -60,7 +60,13 @@ void CheckHeaders::WarningHeaderWithImplementation()
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << _tokenizer->fileLine(tok) << ": Found implementation in header"; ostr << _tokenizer->fileLine(tok) << ": Found implementation in header";
_errorLogger->reportErr(ostr.str());
// TODO, this check is currently not used, but if it is some day
// it should give correct id and severity by calling proper function
// from errorLogger. It should not call reportErr directly.
std::list<FileLocation> empty;
empty.push_back(FileLocation());
_errorLogger->reportErr(empty, "id", "severity", ostr.str());
// Goto next file.. // Goto next file..
unsigned int fileindex = tok->fileIndex(); unsigned int fileindex = tok->fileIndex();
@ -248,7 +254,13 @@ void CheckHeaders::WarningIncludeHeader()
ostr << _tokenizer->fileLine(includetok) << ": The included header '" << includefile << "' is not needed"; ostr << _tokenizer->fileLine(includetok) << ": The included header '" << includefile << "' is not needed";
if (NeedDeclaration) if (NeedDeclaration)
ostr << " (but a forward declaration is needed)"; ostr << " (but a forward declaration is needed)";
_errorLogger->reportErr(ostr.str());
// TODO, this check is currently not used, but if it is some day
// it should give correct id and severity by calling proper function
// from errorLogger. It should not call reportErr directly.
std::list<FileLocation> empty;
empty.push_back(FileLocation());
_errorLogger->reportErr(empty, "id", "severity", ostr.str()); // TODO
} }
} }
} }

View File

@ -186,7 +186,7 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
" -s, --style Check coding style\n" " -s, --style Check coding style\n"
" --unused-functions Check if there are unused functions\n" " --unused-functions Check if there are unused functions\n"
" -v, --verbose More detailed error reports\n" " -v, --verbose More detailed error reports\n"
" --xml Write results in results.xml\n" " --xml Write results in xml to error stream.\n"
"\n" "\n"
"Example usage:\n" "Example usage:\n"
" # Recursively check the current folder. Print the progress on the screen and\n" " # Recursively check the current folder. Print the progress on the screen and\n"
@ -284,15 +284,7 @@ unsigned int CppCheck::check()
_checkFunctionUsage.check(); _checkFunctionUsage.check();
} }
if (_settings._xml)
{
std::ofstream fxml("result.xml");
fxml << "<?xml version=\"1.0\"?>\n";
fxml << "<results>\n";
for (std::list<std::string>::const_iterator it = _xmllist.begin(); it != _xmllist.end(); ++it)
fxml << " " << *it << "\n";
fxml << "</results>";
}
unsigned int result = static_cast<unsigned int>(_errorList.size()); unsigned int result = static_cast<unsigned int>(_errorList.size());
_errorList.clear(); _errorList.clear();
@ -416,10 +408,20 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
if (ErrorLogger::strPlusChar()) if (ErrorLogger::strPlusChar())
checkOther.strPlusChar(); checkOther.strPlusChar();
} }
Settings CppCheck::settings() const
{
return _settings;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void CppCheck::reportErr(const std::string &errmsg) void CppCheck::reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg)
{ {
std::ostringstream text;
text << ErrorLogger::callStackToString(callStack) << ": (" << severity << ") " << msg;
std::string errmsg = text.str();
// Alert only about unique errors // Alert only about unique errors
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end()) if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
return; return;
@ -431,8 +433,7 @@ void CppCheck::reportErr(const std::string &errmsg)
errmsg2 += "\n Defines=\'" + cfg + "\'\n"; errmsg2 += "\n Defines=\'" + cfg + "\'\n";
} }
_errorLogger->reportErr(callStack, id, severity, msg);
_errorLogger->reportErr(errmsg2);
_errout << errmsg2 << std::endl; _errout << errmsg2 << std::endl;
} }
@ -442,17 +443,3 @@ void CppCheck::reportOut(const std::string & /*outmsg*/)
// This is currently never called. It is here just to comply with // This is currently never called. It is here just to comply with
// the interface. // the interface.
} }
void CppCheck::reportXml(const std::string &file, const std::string &line, const std::string &id, const std::string &severity, const std::string &msg)
{
std::ostringstream xml;
xml << "<error";
xml << " file=\"" << file << "\"";
xml << " line=\"" << line << "\"";
xml << " id=\"" << id << "\"";
xml << " severity=\"" << severity << "\"";
xml << " msg=\"" << msg << "\"";
xml << "/>";
_xmllist.push_back(xml.str());
}

View File

@ -63,6 +63,12 @@ public:
*/ */
void settings(const Settings &settings); void settings(const Settings &settings);
/**
* Get copy of current settings.
* @return a copy of current settings
*/
Settings settings() const;
/** /**
* Add new file to be checked. * Add new file to be checked.
* *
@ -104,7 +110,7 @@ private:
* "[filepath:line number] Message", e.g. * "[filepath:line number] Message", e.g.
* "[main.cpp:4] Uninitialized member variable" * "[main.cpp:4] Uninitialized member variable"
*/ */
virtual void reportErr(const std::string &errmsg); virtual void reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg);
/** /**
* Information about progress is directed here. * Information about progress is directed here.
@ -113,9 +119,6 @@ private:
*/ */
virtual void reportOut(const std::string &outmsg); virtual void reportOut(const std::string &outmsg);
/** xml output of errors */
virtual void reportXml(const std::string &file, const std::string &line, const std::string &id, const std::string &severity, const std::string &msg);
std::list<std::string> _errorList; std::list<std::string> _errorList;
std::ostringstream _errout; std::ostringstream _errout;
Settings _settings; Settings _settings;

View File

@ -24,7 +24,7 @@
CppCheckExecutor::CppCheckExecutor() CppCheckExecutor::CppCheckExecutor()
{ {
//ctor _useXML = false;
} }
CppCheckExecutor::~CppCheckExecutor() CppCheckExecutor::~CppCheckExecutor()
@ -38,7 +38,20 @@ unsigned int CppCheckExecutor::check(int argc, const char* const argv[])
std::string result = cppCheck.parseFromArgs(argc, argv); std::string result = cppCheck.parseFromArgs(argc, argv);
if (result.length() == 0) if (result.length() == 0)
{ {
return cppCheck.check(); if (cppCheck.settings()._xml)
{
_useXML = true;
reportErr("<?xml version=\"1.0\"?>");
reportErr("<results>");
}
unsigned int returnValue = cppCheck.check();
if (_useXML)
{
reportErr("</results>");
}
return returnValue;
} }
else else
{ {
@ -57,7 +70,25 @@ void CppCheckExecutor::reportOut(const std::string &outmsg)
std::cout << outmsg << std::endl; std::cout << outmsg << std::endl;
} }
void CppCheckExecutor::reportXml(const std::string & /*file*/, const std::string & /*line*/, const std::string & /*id*/, const std::string & /*severity*/, const std::string & /*msg*/) void CppCheckExecutor::reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg)
{ {
// never used if (_useXML)
{
std::ostringstream xml;
xml << "<error";
xml << " file=\"" << callStack.back().file << "\"";
xml << " line=\"" << callStack.back().line << "\"";
xml << " id=\"" << id << "\"";
xml << " severity=\"" << severity << "\"";
xml << " msg=\"" << msg << "\"";
xml << "/>";
reportErr(xml.str());
}
else
{
std::ostringstream text;
text << ErrorLogger::callStackToString(callStack) << ": (" << severity << ") " << msg;
reportErr(text.str());
}
} }

View File

@ -54,15 +54,7 @@ public:
*/ */
unsigned int check(int argc, const char* const argv[]); unsigned int check(int argc, const char* const argv[]);
/**
* Errors and warnings are directed here. This should be
* called by the CppCheck class only.
*
* @param errmsg Errors messages are normally in format
* "[filepath:line number] Message", e.g.
* "[main.cpp:4] Uninitialized member variable"
*/
virtual void reportErr(const std::string &errmsg);
/** /**
* Information about progress is directed here. This should be * Information about progress is directed here. This should be
@ -73,7 +65,17 @@ public:
virtual void reportOut(const std::string &outmsg); virtual void reportOut(const std::string &outmsg);
/** xml output of errors */ /** xml output of errors */
virtual void reportXml(const std::string &file, const std::string &line, const std::string &id, const std::string &severity, const std::string &msg); virtual void reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg);
private:
/**
* Helper function to print out errors. Appends a line change.
* @param errmsg, string to printed to error stream
*/
void reportErr(const std::string &errmsg);
bool _useXML;
}; };
#endif // CPPCHECKEXECUTOR_H #endif // CPPCHECKEXECUTOR_H

View File

@ -32,20 +32,19 @@ void ErrorLogger::_writemsg(const Tokenizer *tokenizer, const Token *tok, const
void ErrorLogger::_writemsg(const Tokenizer *tokenizer, const std::list<const Token *> &callstack, const char severity[], const std::string msg, const std::string &id) void ErrorLogger::_writemsg(const Tokenizer *tokenizer, const std::list<const Token *> &callstack, const char severity[], const std::string msg, const std::string &id)
{ {
// Todo.. callstack handling std::list<FileLocation> locationList;
const std::string &file(tokenizer->getFiles()->at(callstack.back()->fileIndex())); for (std::list<const Token *>::const_iterator tok = callstack.begin(); tok != callstack.end(); ++tok)
std::ostringstream linenr; {
linenr << callstack.back()->linenr(); FileLocation loc;
reportXml(file, loc.file = tokenizer->file(*tok);
linenr.str(), loc.line = (*tok)->linenr();
locationList.push_back(loc);
}
reportErr(locationList,
id, id,
severity, severity,
msg); msg);
std::ostringstream ostr;
for (std::list<const Token *>::const_iterator tok = callstack.begin(); tok != callstack.end(); ++tok)
ostr << (tok == callstack.begin() ? "" : " -> ") << tokenizer->fileLine(*tok);
reportErr(ostr.str() + ": (" + severity + ") " + msg);
} }
@ -57,5 +56,15 @@ void ErrorLogger::_writemsg(const std::string msg, const std::string &id)
xml << " msg=\"" << msg << "\""; xml << " msg=\"" << msg << "\"";
xml << ">"; xml << ">";
reportErr(msg); std::list<FileLocation> empty;
empty.push_back(FileLocation());
reportErr(empty, "id", "severity", msg);
}
std::string ErrorLogger::callStackToString(const std::list<FileLocation> &callStack)
{
std::ostringstream ostr;
for (std::list<FileLocation>::const_iterator tok = callStack.begin(); tok != callStack.end(); ++tok)
ostr << (tok == callStack.begin() ? "" : " -> ") << "[" << (*tok).file << ":" << (*tok).line << "]";
return ostr.str();
} }

View File

@ -27,6 +27,16 @@
class Token; class Token;
class Tokenizer; class Tokenizer;
/**
* File name and line number.
*/
class FileLocation
{
public:
std::string file;
unsigned int line;
};
/** /**
* This is an interface, which the class responsible of error logging * This is an interface, which the class responsible of error logging
* should implement. * should implement.
@ -38,15 +48,6 @@ public:
ErrorLogger() { } ErrorLogger() { }
virtual ~ErrorLogger() { } virtual ~ErrorLogger() { }
/**
* Errors and warnings are directed here.
*
* @param errmsg Errors messages are normally in format
* "[filepath:line number] Message", e.g.
* "[main.cpp:4] Uninitialized member variable"
*/
virtual void reportErr(const std::string &errmsg) = 0;
/** /**
* Information about progress is directed here. * Information about progress is directed here.
* *
@ -55,16 +56,17 @@ public:
virtual void reportOut(const std::string &outmsg) = 0; virtual void reportOut(const std::string &outmsg) = 0;
/** /**
* XML output of error / warning * Output of error / warning
* Todo: callstack handling * Todo: callstack handling
* *
* @param file filepath (can be "") * @param callStack File names and line numbers where the error
* @param line line (can be "") * was found and where it was called from. Error location is last
* element in the list
* @param id error id (function name) * @param id error id (function name)
* @param severity severity of error (always, all, style, all+style, never) * @param severity severity of error (always, all, style, all+style, never)
* @param msg error message in plain text * @param msg error message in plain text
*/ */
virtual void reportXml(const std::string &file, const std::string &line, const std::string &id, const std::string &severity, const std::string &msg) = 0; virtual void reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg) = 0;
void arrayIndexOutOfBounds(const Tokenizer *tokenizer, const std::list<const Token *> &Location) void arrayIndexOutOfBounds(const Tokenizer *tokenizer, const std::list<const Token *> &Location)
{ {
@ -381,6 +383,35 @@ public:
return true; return true;
} }
void dangerousFunctionmktemp(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Found 'mktemp'. You should use 'mkstemp' instead", "dangerousFunctionmktemp");
}
static bool dangerousFunctionmktemp(const Settings &s)
{
return s._checkCodingStyle;
}
void dangerousFunctiongets(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Found 'gets'. You should use 'fgets' instead", "dangerousFunctiongets");
}
static bool dangerousFunctiongets(const Settings &s)
{
return s._checkCodingStyle;
}
void dangerousFunctionscanf(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Found 'scanf'. You should use 'fgets' instead", "dangerousFunctionscanf");
}
static bool dangerousFunctionscanf(const Settings &s)
{
return s._checkCodingStyle;
}
static std::string callStackToString(const std::list<FileLocation> &callStack);
private: private:
void _writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string msg, const std::string &id); void _writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string msg, const std::string &id);

View File

@ -1740,6 +1740,9 @@ std::string Tokenizer::fileLine(const Token *tok) const
return ostr.str(); return ostr.str();
} }
std::string Tokenizer::file(const Token *tok) const
{
return _files.at(tok->fileIndex());
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -75,6 +75,8 @@ public:
const Token *GetFunctionTokenByName(const char funcname[]) const; const Token *GetFunctionTokenByName(const char funcname[]) const;
const Token *tokens() const; const Token *tokens() const;
std::string file(const Token *tok) const;
protected: protected:
/** Add braces to an if-block /** Add braces to an if-block

View File

@ -75,7 +75,7 @@ private:
"{\n" "{\n"
" char *x = mktemp(\"/tmp/zxcv\");\n" " char *x = mktemp(\"/tmp/zxcv\");\n"
"}\n"); "}\n");
ASSERT_EQUALS(std::string("[test.cpp:3]: Found 'mktemp'. You should use 'mkstemp' instead\n"), errout.str()); ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Found 'mktemp'. You should use 'mkstemp' instead\n"), errout.str());
} }
void testgets() void testgets()
@ -84,7 +84,7 @@ private:
"{\n" "{\n"
" char *x = gets();\n" " char *x = gets();\n"
"}\n"); "}\n");
ASSERT_EQUALS(std::string("[test.cpp:3]: Found 'gets'. You should use 'fgets' instead\n"), errout.str()); ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Found 'gets'. You should use 'fgets' instead\n"), errout.str());
} }
void testscanf() void testscanf()
@ -94,7 +94,7 @@ private:
" char *x;\n" " char *x;\n"
" scanf(\"%s\", x);\n" " scanf(\"%s\", x);\n"
"}\n"); "}\n");
ASSERT_EQUALS(std::string("[test.cpp:4]: Found 'scanf'. You should use 'fgets' instead\n"), errout.str()); ASSERT_EQUALS(std::string("[test.cpp:4]: (style) Found 'scanf'. You should use 'fgets' instead\n"), errout.str());
} }
}; };

View File

@ -167,18 +167,14 @@ void TestFixture::runTests(const char cmd[])
std::cerr << errmsg.str(); std::cerr << errmsg.str();
} }
void TestFixture::reportErr(const std::string &errmsg)
{
errout << errmsg << std::endl;
}
void TestFixture::reportOut(const std::string & /*outmsg*/) void TestFixture::reportOut(const std::string & /*outmsg*/)
{ {
// These can probably be ignored // These can probably be ignored
} }
void TestFixture::reportXml(const std::string & /*file*/, const std::string & /*line*/, const std::string & /*id*/, const std::string & /*severity*/, const std::string & /*msg*/) void TestFixture::reportErr(const std::list<FileLocation> &callStack, const std::string & /*id*/, const std::string &severity, const std::string &msg)
{ {
// These can probably be ignored std::ostringstream text;
text << ErrorLogger::callStackToString(callStack) << ": (" << severity << ") " << msg;
errout << text.str() << std::endl;
} }

View File

@ -42,9 +42,8 @@ protected:
void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual); void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual);
public: public:
virtual void reportErr(const std::string &errmsg);
virtual void reportOut(const std::string &outmsg); virtual void reportOut(const std::string &outmsg);
virtual void reportXml(const std::string &file, const std::string &line, const std::string &id, const std::string &severity, const std::string &msg); virtual void reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg);
void run(const std::string &str); void run(const std::string &str);

View File

@ -105,6 +105,12 @@ int main()
err.push_back(Message("strPlusChar", Message::error, "Unusual pointer arithmetic")); err.push_back(Message("strPlusChar", Message::error, "Unusual pointer arithmetic"));
err.push_back(Message("returnLocalVariable", Message::error, "Returning pointer to local array variable")); err.push_back(Message("returnLocalVariable", Message::error, "Returning pointer to local array variable"));
// 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"));
// Generate code.. // Generate code..
std::cout << "Generate code.." << std::endl; std::cout << "Generate code.." << std::endl;
std::ofstream fout("errorlogger.h"); std::ofstream fout("errorlogger.h");
@ -137,6 +143,16 @@ int main()
fout << "class Tokenizer;\n"; fout << "class Tokenizer;\n";
fout << "\n"; fout << "\n";
fout << "/**\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 << "/**\n";
fout << " * This is an interface, which the class responsible of error logging\n"; fout << " * This is an interface, which the class responsible of error logging\n";
fout << " * should implement.\n"; fout << " * should implement.\n";
fout << " */\n"; fout << " */\n";
@ -148,15 +164,6 @@ int main()
fout << " virtual ~ErrorLogger() { }\n"; fout << " virtual ~ErrorLogger() { }\n";
fout << "\n"; fout << "\n";
fout << " /**\n"; fout << " /**\n";
fout << " * Errors and warnings are directed here.\n";
fout << " *\n";
fout << " * @param errmsg Errors messages are normally in format\n";
fout << " * \"[filepath:line number] Message\", e.g.\n";
fout << " * \"[main.cpp:4] Uninitialized member variable\"\n";
fout << " */\n";
fout << " virtual void reportErr(const std::string &errmsg) = 0;\n";
fout << "\n";
fout << " /**\n";
fout << " * Information about progress is directed here.\n"; fout << " * Information about progress is directed here.\n";
fout << " *\n"; fout << " *\n";
fout << " * @param outmsg, E.g. \"Checking main.cpp...\"\n"; fout << " * @param outmsg, E.g. \"Checking main.cpp...\"\n";
@ -164,20 +171,24 @@ int main()
fout << " virtual void reportOut(const std::string &outmsg) = 0;\n"; fout << " virtual void reportOut(const std::string &outmsg) = 0;\n";
fout << "\n"; fout << "\n";
fout << " /**\n"; fout << " /**\n";
fout << " * XML output of error / warning\n"; fout << " * Output of error / warning\n";
fout << " * Todo: callstack handling\n"; fout << " * Todo: callstack handling\n";
fout << " *\n"; fout << " *\n";
fout << " * @param file filepath (can be \"\")\n"; fout << " * @param callStack File names and line numbers where the error\n";
fout << " * @param line line (can be \"\")\n"; fout << " * was found and where it was called from. Error location is last\n";
fout << " * element in the list\n";
fout << " * @param id error id (function name)\n"; fout << " * @param id error id (function name)\n";
fout << " * @param severity severity of error (always, all, style, all+style, never)\n"; fout << " * @param severity severity of error (always, all, style, all+style, never)\n";
fout << " * @param msg error message in plain text\n"; fout << " * @param msg error message in plain text\n";
fout << " */\n"; fout << " */\n";
fout << " virtual void reportXml(const std::string &file, const std::string &line, const std::string &id, const std::string &severity, const std::string &msg) = 0;\n"; fout << " virtual void reportErr(const std::list<FileLocation> &callStack, const std::string &id, const std::string &severity, const std::string &msg) = 0;\n";
fout << "\n"; fout << "\n";
for (std::list<Message>::const_iterator it = err.begin(); it != err.end(); ++it) for (std::list<Message>::const_iterator it = err.begin(); it != err.end(); ++it)
it->generateCode(fout); it->generateCode(fout);
fout << "\n";
fout << " static std::string callStackToString(const std::list<FileLocation> &callStack);\n";
fout << "\n"; fout << "\n";
fout << "private:\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 Token *tok, const char severity[], const std::string msg, const std::string &id);\n";