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