summaryrefslogtreecommitdiff
path: root/Source/CTest/cmParseMumpsCoverage.cxx
blob: 37e8bd0825f527e8a68597ad0d80597406212f4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "cmStandardIncludes.h"
#include <stdio.h>
#include <stdlib.h>
#include "cmSystemTools.h"
#include "cmParseGTMCoverage.h"
#include <cmsys/Directory.hxx>
#include <cmsys/Glob.hxx>


cmParseMumpsCoverage::cmParseMumpsCoverage(
  cmCTestCoverageHandlerContainer& cont,
  cmCTest* ctest)
  :Coverage(cont), CTest(ctest)
{
}

cmParseMumpsCoverage::~cmParseMumpsCoverage()
{
}

bool cmParseMumpsCoverage::ReadCoverageFile(const char* file)
{
  // Read the gtm_coverage.mcov file, that has two lines of data:
  // packages:/full/path/to/Vista/Packages
  // coverage_dir:/full/path/to/dir/with/*.mcov
  std::ifstream in(file);
  if(!in)
    {
    return false;
    }
  std::string line;
  while(cmSystemTools::GetLineFromStream(in, line))
    {
    std::string::size_type pos = line.find(':', 0);
    std::string packages;
    if(pos != std::string::npos)
      {
      std::string type = line.substr(0, pos);
      std::string path = line.substr(pos+1);
      if(type == "packages")
        {
        this->LoadPackages(path.c_str());
        }
      else if(type == "coverage_dir")
        {
        this->LoadCoverageData(path.c_str());
        }
      else
        {
        cmCTestLog(this->CTest, ERROR_MESSAGE,
                   "Parse Error in Mumps coverage file :\n"
                   << file <<
                   "\ntype: [" << type << "]\npath:[" << path << "]\n"
                   "input line: [" << line << "]\n");
        }
      }
    }
  return true;
}

void cmParseMumpsCoverage::InitializeMumpsFile(std::string& file)
{
  // initialize the coverage information for a given mumps file
  std::ifstream in(file.c_str());
  if(!in)
    {
    return;
    }
  std::string line;
  cmCTestCoverageHandlerContainer::SingleFileCoverageVector&
    coverageVector = this->Coverage.TotalCoverage[file];
  if(!cmSystemTools::GetLineFromStream(in, line))
    {
    return;
    }
  // first line of a .m file can never be run
  coverageVector.push_back(-1);
  while( cmSystemTools::GetLineFromStream(in, line) )
    {
    // putting in a 0 for a line means it is executable code
    // putting in a -1 for a line means it is not executable code
    int val = -1; // assume line is not executable
    bool found = false;
    std::string::size_type i = 0;
    // (1) Search for the first whitespace or semicolon character on a line.
    //This will skip over labels if the line starts with one, or will simply
    //be the first character on the line for non-label lines.
    for(; i < line.size(); ++i)
      {
      if(line[i] == ' ' || line[i] == '\t' || line[i] == ';')
        {
        found = true;
        break;
        }
      }
    if(found)
      {
      // (2) If the first character found above is whitespace then continue the
      // search for the first following non-whitespace character.
      if(line[i] == ' ' || line[i] == '\t')
        {
        while(i < line.size() && (line[i] == ' ' || line[i] == '\t'))
          {
          i++;
          }
        }
      // (3) If the character found is not a semicolon then the line counts for
      // coverage.
      if(i < line.size() && line[i] != ';')
        {
        val = 0;
        }
      }
    coverageVector.push_back(val);
    }
}

bool cmParseMumpsCoverage::LoadPackages(const char* d)
{
  cmsys::Glob glob;
  glob.RecurseOn();
  std::string pat = d;
  pat += "/*.m";
  glob.FindFiles(pat.c_str());
  std::vector<std::string>& files = glob.GetFiles();
  std::vector<std::string>::iterator fileIt;
  for ( fileIt = files.begin(); fileIt != files.end();
        ++ fileIt )
    {
    std::string name = cmSystemTools::GetFilenameName(*fileIt);
    this->RoutineToDirectory[name.substr(0, name.size()-2)] = *fileIt;
    // initialze each file, this is left out until CDash is fixed
    // to handle large numbers of files
    this->InitializeMumpsFile(*fileIt);
    }
  return true;
}

bool cmParseMumpsCoverage::FindMumpsFile(std::string const& routine,
                                         std::string& filepath)
{
  std::map<cmStdString, cmStdString>::iterator i =
    this->RoutineToDirectory.find(routine);
  if(i != this->RoutineToDirectory.end())
    {
    filepath = i->second;
    return true;
    }
  else
    {
    // try some alternate names
    const char* tryname[] = {"GUX", "GTM", "ONT", 0};
    for(int k=0; tryname[k] != 0; k++)
      {
      std::string routine2 = routine + tryname[k];
      i = this->RoutineToDirectory.find(routine2);
      if(i != this->RoutineToDirectory.end())
        {
        filepath = i->second;
        return true;
        }
      }
    }
  return false;
}