diff --git a/cli/cppcheck.vcproj b/cli/cppcheck.vcproj index 9f49e54eb..fe7319d19 100755 --- a/cli/cppcheck.vcproj +++ b/cli/cppcheck.vcproj @@ -268,6 +268,10 @@ RelativePath="..\lib\filelister.cpp" > + + @@ -370,6 +374,10 @@ RelativePath="..\lib\filelister.h" > + + diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 6e92366c2..1508f62bb 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -379,7 +379,7 @@ QStringList MainWindow::RemoveUnacceptedFiles(const QStringList &list) QString str; foreach(str, list) { - if (FileLister::acceptFile(str.toStdString())) + if (getFileLister()->acceptFile(str.toStdString())) { result << str; } diff --git a/lib/checkheaders.cpp b/lib/checkheaders.cpp index 3125e3016..36c0cabbf 100644 --- a/lib/checkheaders.cpp +++ b/lib/checkheaders.cpp @@ -100,7 +100,7 @@ void CheckHeaders::warningIncludeHeader() const std::string includefile = includetok->strAt(1); while (hfile < _tokenizer->getFiles()->size()) { - if (FileLister::sameFileName(_tokenizer->getFiles()->at(hfile), includefile)) + if (getFileLister()->sameFileName(_tokenizer->getFiles()->at(hfile), includefile)) break; ++hfile; } diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 33c47e3ec..e9e8d5119 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -61,7 +61,7 @@ void CppCheck::settings(const Settings &settings) void CppCheck::addFile(const std::string &path) { - FileLister::recursiveAddFiles(_filenames, path.c_str(), true); + getFileLister()->recursiveAddFiles(_filenames, path.c_str(), true); } void CppCheck::addFile(const std::string &path, const std::string &content) @@ -373,7 +373,7 @@ void CppCheck::parseFromArgs(int argc, const char* const argv[]) // Execute recursiveAddFiles() to each given file parameter std::vector::const_iterator iter; for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) - FileLister::recursiveAddFiles(_filenames, iter->c_str(), true); + getFileLister()->recursiveAddFiles(_filenames, iter->c_str(), true); } if (argc <= 1 || showHelp) diff --git a/lib/filelister.cpp b/lib/filelister.cpp index 615dcdce0..1aa7da105 100644 --- a/lib/filelister.cpp +++ b/lib/filelister.cpp @@ -17,6 +17,7 @@ */ #include "filelister.h" +#include "fileLister_win32.h" #include #include #include @@ -34,6 +35,18 @@ #include #endif +static FileLister *fileLister; + +FileLister * getFileLister() +{ + if (fileLister == NULL) + { + fileLister = new FileListerWin32; + return fileLister; + } + return fileLister; +} + std::string FileLister::simplifyPath(const char *originalPath) { std::string subPath = ""; diff --git a/lib/filelister.h b/lib/filelister.h index 181c5840a..879fa839c 100644 --- a/lib/filelister.h +++ b/lib/filelister.h @@ -29,14 +29,16 @@ class FileLister { public: - static void recursiveAddFiles(std::vector &filenames, const std::string &path, bool recursive); - static std::string simplifyPath(const char *originalPath); - static bool sameFileName(const std::string &fname1, const std::string &fname2); - static bool acceptFile(const std::string &filename); + virtual void recursiveAddFiles(std::vector &filenames, const std::string &path, bool recursive); + virtual std::string simplifyPath(const char *originalPath); + virtual bool sameFileName(const std::string &fname1, const std::string &fname2); + virtual bool acceptFile(const std::string &filename); private: }; +FileLister * getFileLister(); + /// @} -#endif // #ifndef FILELISTER_H +#endif // #ifndef FileListerH diff --git a/lib/filelister_win32.cpp b/lib/filelister_win32.cpp new file mode 100644 index 000000000..8ef5b37ad --- /dev/null +++ b/lib/filelister_win32.cpp @@ -0,0 +1,201 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team. + * + * 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 . + */ + +#include "filelister_win32.h" +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#ifndef __BORLANDC__ +#include +#endif +#endif + + + + + +/////////////////////////////////////////////////////////////////////////////// +////// This code is for Microsoft Windows ///////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +// Here is the catch: cppcheck core is Ansi code (using char type). +// When compiling Unicode targets WinAPI automatically uses *W Unicode versions +// of called functions. So we must convert data given to WinAPI functions from +// ANSI to Unicode. Likewise we must convert data we get from WinAPI from +// Unicode to ANSI. + +#if defined(UNICODE) + +static bool TransformUcs2ToAnsi(LPCWSTR psUcs, LPSTR psAnsi, int nAnsi) +{ + WideCharToMultiByte(CP_ACP, 0, psUcs, -1, psAnsi, nAnsi, NULL, NULL); + return true; +} + +static bool TransformAnsiToUcs2(LPCSTR psAnsi, LPWSTR psUcs, UINT nUcs) +{ + MultiByteToWideChar(CP_ACP, 0, psAnsi, -1, psUcs, nUcs); + return true; +} + +static BOOL MyIsDirectory(std::string path) +{ + WCHAR * unicodeCleanPath = new WCHAR[path.size() + 1]; + TransformAnsiToUcs2(path.c_str(), unicodeCleanPath, + (path.size() * sizeof(WCHAR)) + 1); + // See http://msdn.microsoft.com/en-us/library/bb773621(VS.85).aspx + BOOL res = PathIsDirectory(unicodeCleanPath); + delete [] unicodeCleanPath; + return res; +} + +static HANDLE MyFindFirstFile(std::string path, LPWIN32_FIND_DATA findData) +{ + WCHAR * unicodeOss = new wchar_t[path.size() + 1]; + TransformAnsiToUcs2(path.c_str(), unicodeOss, (path.size() + 1) * sizeof(WCHAR)); + HANDLE hFind = FindFirstFile(unicodeOss, findData); + delete [] unicodeOss; + return hFind; +} + +#else // defined(UNICODE) + +static BOOL MyIsDirectory(std::string path) +{ +#ifdef __BORLANDC__ + return (GetFileAttributes(path.c_str()) & FILE_ATTRIBUTE_DIRECTORY); +#else +// See http://msdn.microsoft.com/en-us/library/bb773621(VS.85).aspx +return PathIsDirectory(path.c_str()); +#endif +} + +static HANDLE MyFindFirstFile(std::string path, LPWIN32_FIND_DATA findData) +{ + HANDLE hFind = FindFirstFile(path.c_str(), findData); + return hFind; +} + +#endif // defined(UNICODE) + +void FileListerWin32::recursiveAddFiles(std::vector &filenames, const std::string &path, bool recursive) +{ + // oss is the search string passed into FindFirst and FindNext. + // bdir is the base directory which is used to form pathnames. + // It always has a trailing backslash available for concatenation. + std::ostringstream bdir, oss; + + std::string cleanedPath = path; + std::replace(cleanedPath.begin(), cleanedPath.end(), '/', '\\'); + + oss << cleanedPath; + + if (MyIsDirectory(cleanedPath.c_str())) + { + char c = cleanedPath[ cleanedPath.size()-1 ]; + switch (c) + { + case '\\': + oss << '*'; + bdir << cleanedPath; + break; + case '*': + bdir << cleanedPath.substr(0, cleanedPath.length() - 1); + break; + default: + oss << "\\*"; + bdir << cleanedPath << '\\'; + } + } + else + { + std::string::size_type pos; + pos = cleanedPath.find_last_of('\\'); + if (std::string::npos != pos) + { + bdir << cleanedPath.substr(0, pos + 1); + } + } + + WIN32_FIND_DATA ffd; + HANDLE hFind = MyFindFirstFile(oss.str(), &ffd); + if (INVALID_HANDLE_VALUE == hFind) + return; + + do + { + if (ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0') + continue; + +#if defined(UNICODE) + char * ansiFfd = new char[wcslen(ffd.cFileName) + 1]; + TransformUcs2ToAnsi(ffd.cFileName, ansiFfd, wcslen(ffd.cFileName) + 1); +#else // defined(UNICODE) + char * ansiFfd = &ffd.cFileName[0]; +#endif // defined(UNICODE) + + std::ostringstream fname; + fname << bdir.str().c_str() << ansiFfd; + + if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + { + // File + + // If recursive is not used, accept all files given by user + if (!recursive || FileLister::acceptFile(ansiFfd)) + filenames.push_back(fname.str()); + } + else if (recursive) + { + // Directory + FileLister::recursiveAddFiles(filenames, fname.str().c_str(), recursive); + } +#if defined(UNICODE) + delete [] ansiFfd; +#endif // defined(UNICODE) + } + while (FindNextFile(hFind, &ffd) != FALSE); + + if (INVALID_HANDLE_VALUE != hFind) + { + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + } +} + +#endif + +//--------------------------------------------------------------------------- + +bool FileListerWin32::sameFileName(const std::string &fname1, const std::string &fname2) +{ +#ifdef __BORLANDC__ + return bool(stricmp(fname1.c_str(), fname2.c_str()) == 0); +#endif +#ifdef _MSC_VER + return bool(_stricmp(fname1.c_str(), fname2.c_str()) == 0); +#endif +} diff --git a/lib/filelister_win32.h b/lib/filelister_win32.h new file mode 100644 index 000000000..467ccca0d --- /dev/null +++ b/lib/filelister_win32.h @@ -0,0 +1,43 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team. + * + * 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 . + */ + +#ifndef FileListerWin32H +#define FileListerWin32H + +#include +#include +#include "filelister.h" + +/// @addtogroup Core +/// @{ + + +class FileListerWin32 : public FileLister +{ +public: + virtual void recursiveAddFiles(std::vector &filenames, const std::string &path, bool recursive); +// virtual static std::string simplifyPath(const char *originalPath); + virtual bool sameFileName(const std::string &fname1, const std::string &fname2); +// virtual static bool acceptFile(const std::string &filename); +private: + +}; + +/// @} + +#endif // #ifndef FileListerWin32H diff --git a/lib/lib.pri b/lib/lib.pri index 24e2ca24e..d56336bbb 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -21,6 +21,10 @@ HEADERS += $$PWD/check.h \ $$PWD/token.h \ $$PWD/tokenize.h +win32 { +HEADERS += $$PWD/filelister_win32.h +} + SOURCES += $$PWD/checkautovariables.cpp \ $$PWD/checkbufferoverrun.cpp \ $$PWD/checkclass.cpp \ @@ -40,3 +44,7 @@ SOURCES += $$PWD/checkautovariables.cpp \ $$PWD/settings.cpp \ $$PWD/token.cpp \ $$PWD/tokenize.cpp + +win32 { +SOURCES += $$PWD/filelister_win32.cpp +} diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 5f296e730..df960aea2 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -1325,7 +1325,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filename if (fileOpened) { - std::string tempFile = FileLister::simplifyPath(filename.c_str()); + std::string tempFile = getFileLister()->simplifyPath(filename.c_str()); std::transform(tempFile.begin(), tempFile.end(), tempFile.begin(), tolowerWrapper); if (handledFiles.find(tempFile) != handledFiles.end()) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 30ded2a40..289778808 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -230,7 +230,7 @@ void Tokenizer::createTokens(std::istream &code) fileIndexes.push_back(FileIndex); for (unsigned int i = 0; i < _files.size(); i++) { - if (FileLister::sameFileName(_files[i].c_str(), line.c_str())) + if (getFileLister()->sameFileName(_files[i].c_str(), line.c_str())) { // Use this index foundOurfile = true; @@ -241,7 +241,7 @@ void Tokenizer::createTokens(std::istream &code) if (!foundOurfile) { // The "_files" vector remembers what files have been tokenized.. - _files.push_back(FileLister::simplifyPath(line.c_str())); + _files.push_back(getFileLister()->simplifyPath(line.c_str())); FileIndex = static_cast(_files.size() - 1); } @@ -1094,7 +1094,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s _configuration = configuration; // The "_files" vector remembers what files have been tokenized.. - _files.push_back(FileLister::simplifyPath(FileName)); + _files.push_back(getFileLister()->simplifyPath(FileName)); createTokens(code);