Fixed #439 (Patch: Cppcheck reports wrong filename for filenames containing 8-bit ASCII)
This commit is contained in:
parent
bce1d83550
commit
04bcc86d59
|
@ -197,6 +197,11 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppCheckExecutor::setSettings(const Settings &settings)
|
||||||
|
{
|
||||||
|
_settings = &settings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple helper function:
|
* Simple helper function:
|
||||||
* \return size of array
|
* \return size of array
|
||||||
|
@ -937,6 +942,29 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// fix trac ticket #439 'Cppcheck reports wrong filename for filenames containing 8-bit ASCII'
|
||||||
|
static const std::string ansiToOEM(std::string msg, bool doConvert)
|
||||||
|
{
|
||||||
|
if (doConvert) {
|
||||||
|
// convert ANSI strings to OEM strings in two steps
|
||||||
|
std::vector<WCHAR> wcContainer(msg.length());
|
||||||
|
std::vector<char> cContainer(msg.begin(), msg.end());
|
||||||
|
|
||||||
|
// ansi code page characters to wide characters
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, cContainer.data(), msg.length(), wcContainer.data(), msg.length());
|
||||||
|
// wide characters to oem codepage characters
|
||||||
|
WideCharToMultiByte(CP_OEMCP, 0, wcContainer.data(), msg.length(), cContainer.data(), msg.length(), NULL, NULL);
|
||||||
|
|
||||||
|
msg.assign(cContainer.begin(), cContainer.end());
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// no performance regression on non-windows systems
|
||||||
|
#define ansiToOEM(msg, doConvert) msg
|
||||||
|
#endif
|
||||||
|
|
||||||
void CppCheckExecutor::reportErr(const std::string &errmsg)
|
void CppCheckExecutor::reportErr(const std::string &errmsg)
|
||||||
{
|
{
|
||||||
// Alert only about unique errors
|
// Alert only about unique errors
|
||||||
|
@ -947,12 +975,12 @@ void CppCheckExecutor::reportErr(const std::string &errmsg)
|
||||||
if (errorOutput)
|
if (errorOutput)
|
||||||
*errorOutput << errmsg << std::endl;
|
*errorOutput << errmsg << std::endl;
|
||||||
else
|
else
|
||||||
std::cerr << errmsg << std::endl;
|
std::cerr << ansiToOEM(errmsg, _settings ? !_settings->xml : true) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::reportOut(const std::string &outmsg)
|
void CppCheckExecutor::reportOut(const std::string &outmsg)
|
||||||
{
|
{
|
||||||
std::cout << outmsg << std::endl;
|
std::cout << ansiToOEM(outmsg, true) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
|
void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
|
||||||
|
|
|
@ -125,6 +125,12 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[]);
|
bool parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to supply settings. This can be used for testing.
|
||||||
|
* @param settings Reference to an Settings instance
|
||||||
|
*/
|
||||||
|
void setSettings(const Settings &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Cppcheck - A tool for static C/C++ code analysis
|
* Cppcheck - A tool for static C/C++ code analysis
|
||||||
* Copyright (C) 2007-2016 Cppcheck team.
|
* Copyright (C) 2007-2016 Cppcheck team.
|
||||||
*
|
*
|
||||||
|
@ -17,6 +17,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cppcheckexecutor.h"
|
#include "cppcheckexecutor.h"
|
||||||
|
#include "errorlogger.h"
|
||||||
|
#include "cppcheck.h"
|
||||||
#include "filelister.h"
|
#include "filelister.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "pathmatch.h"
|
#include "pathmatch.h"
|
||||||
|
@ -44,6 +46,7 @@ private:
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
TEST_CASE(runSamples);
|
TEST_CASE(runSamples);
|
||||||
|
TEST_CASE(runConsoleCodePageTranslationOnWindows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSamples() const {
|
void runSamples() const {
|
||||||
|
@ -90,6 +93,91 @@ private:
|
||||||
delete[] path;
|
delete[] path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CppCheckExecutor2 : public CppCheckExecutor {
|
||||||
|
public:
|
||||||
|
void settings(const Settings &set) {
|
||||||
|
setSettings(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void runConsoleCodePageTranslationOnWindows() const {
|
||||||
|
REDIRECT;
|
||||||
|
|
||||||
|
std::vector<std::string> msgs;
|
||||||
|
msgs.push_back("ASCII"); // first entry should be using only ASCII
|
||||||
|
msgs.push_back("kääk");
|
||||||
|
msgs.push_back("Português");
|
||||||
|
// msgs.push_back("日本語");
|
||||||
|
// msgs.push_back("한국어");
|
||||||
|
// msgs.push_back("Русский");
|
||||||
|
// msgs.push_back("中文");
|
||||||
|
|
||||||
|
Settings set1;
|
||||||
|
Settings setXML;
|
||||||
|
setXML.xml = true;
|
||||||
|
setXML.xml_version = 2;
|
||||||
|
CppCheckExecutor2 exec;
|
||||||
|
exec.settings(set1);
|
||||||
|
CppCheckExecutor2 execXML;
|
||||||
|
execXML.settings(setXML);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator i = msgs.begin(); i != msgs.end(); ++i) {
|
||||||
|
CLEAR_REDIRECT_OUTPUT;
|
||||||
|
CLEAR_REDIRECT_ERROUT;
|
||||||
|
|
||||||
|
exec.reportOut(*i);
|
||||||
|
|
||||||
|
ErrorLogger::ErrorMessage errMessage;
|
||||||
|
errMessage.setmsg(*i);
|
||||||
|
|
||||||
|
// no xml option
|
||||||
|
exec.reportInfo(errMessage);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// expect changes through code page translation except for the 'ASCII' case
|
||||||
|
if (i == msgs.begin()) {
|
||||||
|
ASSERT_EQUALS(*i + "\n", GET_REDIRECT_OUTPUT);
|
||||||
|
ASSERT_EQUALS(*i + "\n", GET_REDIRECT_ERROUT);
|
||||||
|
} else {
|
||||||
|
ASSERT(*i + "\n" != GET_REDIRECT_OUTPUT);
|
||||||
|
ASSERT(*i + "\n" != GET_REDIRECT_ERROUT);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// do not expect any code page translation
|
||||||
|
ASSERT_EQUALS(*i + "\n", GET_REDIRECT_OUTPUT);
|
||||||
|
ASSERT_EQUALS(*i + "\n", GET_REDIRECT_ERROUT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CLEAR_REDIRECT_ERROUT;
|
||||||
|
// possible change of msg for xml option
|
||||||
|
// with ErrorLogger::ErrorMessage::fixInvalidChars(), plus additional XML formatting
|
||||||
|
execXML.reportInfo(errMessage);
|
||||||
|
// undo the effects of "ErrorLogger::ErrorMessage::fixInvalidChars()"
|
||||||
|
// replacing octal constants with characters
|
||||||
|
std::string myErr;
|
||||||
|
std::string myErrOrg = GET_REDIRECT_ERROUT;
|
||||||
|
std::string::const_iterator from = myErrOrg.begin();
|
||||||
|
while (from != myErrOrg.end()) {
|
||||||
|
if (*from == '\\') {
|
||||||
|
++from;
|
||||||
|
unsigned c;
|
||||||
|
// expect three digits
|
||||||
|
std::istringstream es(std::string(from, from + 3));
|
||||||
|
es >> std::oct >> c;
|
||||||
|
++from;
|
||||||
|
++from;
|
||||||
|
myErr.push_back(c);
|
||||||
|
} else {
|
||||||
|
myErr.push_back(*from);
|
||||||
|
}
|
||||||
|
++from;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(std::string::npos != myErr.find(*i));
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestSamples)
|
REGISTER_TEST(TestSamples)
|
||||||
|
|
Loading…
Reference in New Issue