1 // COVTOOL -- test coverage analysis tool.
2 // Copyright (C) 2002, Lowell Boggs Jr.
3 // mailto:lowell.boggs@attbi.com
4 
5 // This file contains free software.  You can redistribute it
6 // and/or modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2, or
8 // (at your option) any later version.
9 
10 // This source code 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 // Write to the Free Software Foundation, 59 Temple Place - Suite 330,
16 // Boston, MA  02111-1307, USA for a copy of the GNU General Public License.
17 //
18 
19 #include <covstream.h>
20 #include <read_database.h>
21 #include <stdlib.h>
22 
23 //
24 // This program annotates a .c or .h file for which instrumentation
25 // data has been collected.  It produces an output file of the
26 // following form:
27 //
28 //    lines without instrumentation begin with a space
29 //    lines which have been executed begin with a +
30 //    lines which were intrumented but not executed begin with -
31 //
32 // Here is a realistic example
33 //
34 //   #include <stdio.h>
35 //
36 //   extern void CvT_StartRecording____();
37 //
38 //   int main(int argc, char **argv)
39 //  -{
40 //  -   CvT_StartRecording____();     // recording starts after this line
41 //
42 //  +   if(argc < 0)                  // got executed
43 //      {
44 //  -      exit(100);                 // this will never happen
45 //      }
46 //
47 //  +   exit(1);                      // got executed
48 //  -   return 0;                     // never executed
49 //   }
50 //
51 // In this example, all executable lines of the program
52 // show up has having either a - or a + in column 1.
53 // Data collection doesn't start until the call to CvT_StartRecording____()
54 // and thus the first line of the program (the open {) and the line
55 // containing CvT_StartRecording____() dont' show up as being executed
56 // even though they were -- again because the instrumentation was turned off.
57 //
58 // To get this annotation, instrument the above program and execute it.  Then
59 // use covannotate.exe to print the source code with the -/+ from the data
60 // collected during the run.  Here's an example invocation of covannotate:
61 //
62 //   covannotate.exe main.c *.covexp >main.c.annotated
63 //
64 // the following block must not be separated, it defines the
65 // version string
66 
67 char const*
68 #include "covtool_version"
69 ;
70 // do not separate this from the #include of covtool_version!
71 
72 
main(int argc,char ** argv)73 int main(int argc, char **argv)
74 {
75 
76   if( argc > 1 && string("-v") == argv[1])
77   {
78     cout << covtool_version << endl;
79     exit(1);
80   }
81 
82    if(argc < 3 )
83    {
84       cerr << "Error:  expected 'source-file-name merged-covtool-database ...'"
85 	   << endl;
86 
87       exit(1);
88    }
89 
90    CvT_Database db;
91 
92    int db_file=2;
93 
94    //
95    // merge all the covexp files into a single database
96    //
97 
98    while( db_file < argc )
99    {
100     if( db.insert(argv[db_file++]) )
101       cerr << "Error reading file "
102 	   << argv[db_file-1] << endl;
103    }
104 
105    int count=0;
106 
107    string filename = argv[1];
108 
109    ifstream src(argv[1]);
110 
111    if(src.bad())
112    {
113      cerr << "Error reading file " << argv[1] << endl;
114    }
115 
116    // look up the coverage data for this file in the merged
117    // database
118 
119    string s = string("\"") + filename + "\"";
120 
121    s = CovStream::fullname(s);
122 
123    string::iterator first = s.begin(); ++first;
124    string::iterator last = s.end();   --last;
125 
126    s = string(first, last);
127 
128    CvT_Database::const_iterator fileinfo = db.find(s);
129 
130    bool data_available=true;
131 
132    if(fileinfo == db.end())
133    {
134      cerr << "No instrumented lines found for  " << s << endl;
135      data_available = false;
136    }
137 
138    //
139    // for each line in the file, see if it has instrumentation
140    // data and if so, interpret executed versus only instrumented
141    //
142 
143    while(!src.bad() && !src.eof() && !src.fail())
144    {
145      ++count;         // line number
146 
147      string line;
148 
149      getline(src, line);
150 
151      char const * prefix = " ";
152 
153      if(data_available)
154      {
155 	if(fileinfo->second.executed_lines.find(count) !=
156 	   fileinfo->second.executed_lines.end()
157 	  )
158 	{
159 	  prefix = "+";
160 	}
161 	else
162 	{
163 	  if(fileinfo->second.instrumented_lines.find(count) !=
164 	     fileinfo->second.instrumented_lines.end()
165 	    )
166 	  {
167 	    prefix = "-";
168 	  }
169 	}
170 
171      }
172 
173      // Jam in the annotation in front of the extant
174      // line of text.  When dealing with tabs, convert
175      // them to space to avoid mis-allignment.s
176 
177 
178      if(line.size() && line[0] == '\t')
179      {
180        line.erase(0,1);
181        cout << prefix << "       " << line << endl;
182      }
183      else
184        cout << prefix << line << endl;
185 
186    }
187 
188 
189 }
190