"Fossies" - the Fresh Open Source Software Archive

Member "cppcheck-1.89/lib/analyzerinfo.cpp" (1 Sep 2019, 5369 Bytes) of package /windows/misc/cppcheck-1.89.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "analyzerinfo.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.87_vs_1.88.

    1 /*
    2 * Cppcheck - A tool for static C/C++ code analysis
    3 * Copyright (C) 2007-2019 Cppcheck team.
    4 *
    5 * This program is free software: you can redistribute it and/or modify
    6 * it under the terms of the GNU General Public License as published by
    7 * the Free Software Foundation, either version 3 of the License, or
    8 * (at your option) any later version.
    9 *
   10 * This program is distributed in the hope that it will be useful,
   11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 * GNU General Public License for more details.
   14 *
   15 * You should have received a copy of the GNU General Public License
   16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17 */
   18 
   19 #include "analyzerinfo.h"
   20 
   21 #include "path.h"
   22 #include "utils.h"
   23 
   24 #include <tinyxml2.h>
   25 #include <cstring>
   26 #include <map>
   27 #include <sstream>
   28 
   29 AnalyzerInformation::~AnalyzerInformation()
   30 {
   31     close();
   32 }
   33 
   34 static std::string getFilename(const std::string &fullpath)
   35 {
   36     std::string::size_type pos1 = fullpath.find_last_of("/\\");
   37     pos1 = (pos1 == std::string::npos) ? 0U : (pos1 + 1U);
   38     std::string::size_type pos2 = fullpath.rfind('.');
   39     if (pos2 < pos1)
   40         pos2 = std::string::npos;
   41     if (pos2 != std::string::npos)
   42         pos2 = pos2 - pos1;
   43     return fullpath.substr(pos1,pos2);
   44 }
   45 
   46 void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::list<std::string> &sourcefiles, const std::list<ImportProject::FileSettings> &fileSettings)
   47 {
   48     std::map<std::string, unsigned int> fileCount;
   49 
   50     const std::string filesTxt(buildDir + "/files.txt");
   51     std::ofstream fout(filesTxt);
   52     for (const std::string &f : sourcefiles) {
   53         const std::string afile = getFilename(f);
   54         fout << afile << ".a" << (++fileCount[afile]) << "::" << Path::simplifyPath(Path::fromNativeSeparators(f)) << '\n';
   55     }
   56 
   57     for (const ImportProject::FileSettings &fs : fileSettings) {
   58         const std::string afile = getFilename(fs.filename);
   59         fout << afile << ".a" << (++fileCount[afile]) << ":" << fs.cfg << ":" << Path::simplifyPath(Path::fromNativeSeparators(fs.filename)) << std::endl;
   60     }
   61 }
   62 
   63 void AnalyzerInformation::close()
   64 {
   65     mAnalyzerInfoFile.clear();
   66     if (mOutputStream.is_open()) {
   67         mOutputStream << "</analyzerinfo>\n";
   68         mOutputStream.close();
   69     }
   70 }
   71 
   72 static bool skipAnalysis(const std::string &analyzerInfoFile, unsigned long long checksum, std::list<ErrorLogger::ErrorMessage> *errors)
   73 {
   74     tinyxml2::XMLDocument doc;
   75     const tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str());
   76     if (error != tinyxml2::XML_SUCCESS)
   77         return false;
   78 
   79     const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement();
   80     if (rootNode == nullptr)
   81         return false;
   82 
   83     const char *attr = rootNode->Attribute("checksum");
   84     if (!attr || attr != std::to_string(checksum))
   85         return false;
   86 
   87     for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
   88         if (std::strcmp(e->Name(), "error") == 0)
   89             errors->emplace_back(e);
   90     }
   91 
   92     return true;
   93 }
   94 
   95 std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg)
   96 {
   97     const std::string files(buildDir + "/files.txt");
   98     std::ifstream fin(files);
   99     if (fin.is_open()) {
  100         std::string line;
  101         const std::string end(':' + cfg + ':' + sourcefile);
  102         while (std::getline(fin,line)) {
  103             if (line.size() <= end.size() + 2U)
  104                 continue;
  105             if (!endsWith(line, end.c_str(), end.size()))
  106                 continue;
  107             std::ostringstream ostr;
  108             ostr << buildDir << '/' << line.substr(0,line.find(':'));
  109             return ostr.str();
  110         }
  111     }
  112 
  113     std::string filename = Path::fromNativeSeparators(buildDir);
  114     if (!endsWith(filename, '/'))
  115         filename += '/';
  116     const std::string::size_type pos = sourcefile.rfind('/');
  117     if (pos == std::string::npos)
  118         filename += sourcefile;
  119     else
  120         filename += sourcefile.substr(pos+1);
  121     filename += ".analyzerinfo";
  122     return filename;
  123 }
  124 
  125 bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, unsigned long long checksum, std::list<ErrorLogger::ErrorMessage> *errors)
  126 {
  127     if (buildDir.empty() || sourcefile.empty())
  128         return true;
  129     close();
  130 
  131     mAnalyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg);
  132 
  133     if (skipAnalysis(mAnalyzerInfoFile, checksum, errors))
  134         return false;
  135 
  136     mOutputStream.open(mAnalyzerInfoFile);
  137     if (mOutputStream.is_open()) {
  138         mOutputStream << "<?xml version=\"1.0\"?>\n";
  139         mOutputStream << "<analyzerinfo checksum=\"" << checksum << "\">\n";
  140     } else {
  141         mAnalyzerInfoFile.clear();
  142     }
  143 
  144     return true;
  145 }
  146 
  147 void AnalyzerInformation::reportErr(const ErrorLogger::ErrorMessage &msg, bool /*verbose*/)
  148 {
  149     if (mOutputStream.is_open())
  150         mOutputStream << msg.toXML() << '\n';
  151 }
  152 
  153 void AnalyzerInformation::setFileInfo(const std::string &check, const std::string &fileInfo)
  154 {
  155     if (mOutputStream.is_open() && !fileInfo.empty())
  156         mOutputStream << "  <FileInfo check=\"" << check << "\">\n" << fileInfo << "  </FileInfo>\n";
  157 }