/[jscoverage]/trunk/instrument.c
ViewVC logotype

Contents of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Sun Aug 19 04:14:05 2007 UTC (15 years, 9 months ago) by siliconforks
File MIME type: text/plain
File size: 8521 byte(s)
New sh_javascript.js.

1 /*
2 instrument.c - file and directory instrumentation routines
3 Copyright (C) 2007 siliconforks.com
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 2 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 along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "instrument.h"
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <string.h>
25
26 #include <dirent.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29
30 #include "instrument-js.h"
31 #include "resource-manager.h"
32 #include "util.h"
33
34 static int g_verbose = 0;
35
36 static int string_ends_with(const char * s, const char * suffix) {
37 size_t length = strlen(s);
38 size_t suffix_length = strlen(suffix);
39 if (length < suffix_length) {
40 return 0;
41 }
42 return strcasecmp(s + (length - suffix_length), suffix) == 0;
43 }
44
45 static enum FileType get_file_type(const char * file) {
46 if (string_ends_with(file, ".js")) {
47 return FILE_TYPE_JS;
48 }
49 else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
50 return FILE_TYPE_HTML;
51 }
52 else {
53 return FILE_TYPE_UNKNOWN;
54 }
55 }
56
57 static void highlight_file(const char * source_file, const char * destination_file, const char * relative_path) {
58 int depth = 0;
59 for (const char * p = relative_path; *p != '\0'; p++) {
60 if (*p == '/' || *p == '\\') {
61 depth++;
62 }
63 }
64
65 enum FileType file_type = get_file_type(relative_path);
66 const char * suffix = ".jscoverage.html";
67 char * highlighted_file = xmalloc(strlen(destination_file) + strlen(suffix) + 1);
68 strcpy(highlighted_file, destination_file);
69 strcat(highlighted_file, suffix);
70
71 FILE * input = xfopen(source_file, "r");
72 FILE * output = xfopen(highlighted_file, "w");
73
74 free(highlighted_file);
75
76 char * relative_path_to_ancestor = xmalloc(depth * 3 + 1);
77 for (int i = 0; i < depth; i++) {
78 strcpy(relative_path_to_ancestor + i * 3, "../");
79 }
80 relative_path_to_ancestor[depth * 3] = '\0';
81
82 fprintf(output, "<html><head><title>%s</title>\n", relative_path);
83 fprintf(output, "<link rel=\"stylesheet\" type='text/css' href='%sjscoverage.css'>\n", relative_path_to_ancestor);
84 fprintf(output, "<link rel=\"stylesheet\" type='text/css' href='%ssh_nedit.css'>\n", relative_path_to_ancestor);
85 fprintf(output, "<script src=\"%sjscoverage.js\"></script>\n", relative_path_to_ancestor);
86 fprintf(output, "<script src=\"%ssh_main.js\"></script>\n", relative_path_to_ancestor);
87 fprintf(output, "<script src=\"%ssh_javascript.js\"></script>\n", relative_path_to_ancestor);
88 fprintf(output, "<script>\n");
89 fprintf(output, "var gCurrentFile = \"%s\";\n", relative_path);
90 fprintf(output, "</script>\n");
91 fprintf(output, "</head><body onload=\"source_load();\">\n");
92 fprintf(output, "<h1>%s</h1>\n", relative_path);
93 fprintf(output, "<pre id=\"sourceDiv\" class='sh_%s'>", file_type == FILE_TYPE_JS? "javascript": "html");
94 free(relative_path_to_ancestor);
95
96 int c;
97 int atLineStart = 1;
98 int line = 1;
99 while ((c = fgetc(input)) != EOF) {
100 if (atLineStart) {
101 atLineStart = 0;
102 }
103
104 if (c == '<') {
105 fprintf(output, "&lt;");
106 }
107 else if (c == '>') {
108 fprintf(output, "&gt;");
109 }
110 else if (c == '&') {
111 fprintf(output, "&amp;");
112 }
113 else {
114 if (c == '\n') {
115 line++;
116 atLineStart = 1;
117 }
118 fputc(c, output);
119 }
120 }
121 fprintf(output, "</pre></body></html>\n");
122
123 fclose(output);
124 fclose(input);
125
126 suffix = ".jscoverage.js";
127 char original_file[strlen(destination_file) + strlen(suffix) + 1];
128 strcpy(original_file, destination_file);
129 strcat(original_file, suffix);
130 copy_file(source_file, original_file);
131 }
132
133 static void check_same_file(const char * file1, const char * file2) {
134 if (is_same_file(file1, file2)) {
135 fatal("source and destination are the same");
136 }
137 }
138
139 static void check_contains_file(const char * file1, const char * file2) {
140 if (contains_file(file1, file2)) {
141 fatal("%s contains %s", file1, file2);
142 }
143 }
144
145 static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
146 if (g_verbose) {
147 printf("Instrumenting file %s\n", id);
148 }
149
150 /* check if they are the same */
151 char * canonical_source_file = make_canonical_path(source_file);
152 char * canonical_destination_file = make_canonical_path(destination_file);
153 check_same_file(canonical_source_file, canonical_destination_file);
154 free(canonical_source_file);
155 free(canonical_destination_file);
156
157 if (instrumenting) {
158 enum FileType file_type = get_file_type(source_file);
159 switch (file_type) {
160 case FILE_TYPE_UNKNOWN:
161 case FILE_TYPE_HTML:
162 copy_file(source_file, destination_file);
163 break;
164 case FILE_TYPE_JS:
165 highlight_file(source_file, destination_file, id);
166 {
167 FILE * input = xfopen(source_file, "r");
168 FILE * output = xfopen(destination_file, "w");
169 jscoverage_instrument_js(id, input, output);
170 fclose(input);
171 fclose(output);
172 }
173 break;
174 }
175 }
176 else {
177 copy_file(source_file, destination_file);
178 }
179 }
180
181 void jscoverage_instrument(const char * source,
182 const char * destination,
183 int verbose,
184 char ** exclude,
185 int num_exclude,
186 char ** no_instrument,
187 int num_no_instrument)
188 {
189 assert(source != NULL);
190 assert(destination != NULL);
191
192 g_verbose = verbose;
193
194 /* check if they are the same */
195 check_same_file(source, destination);
196
197 /* check if source directory is an ancestor of destination directory */
198 check_contains_file(source, destination);
199
200 /* check that the source exists and is a directory */
201 struct stat buf;
202 xstat(source, &buf);
203 if (! S_ISDIR(buf.st_mode)) {
204 fatal("not a directory: %s", source);
205 }
206
207 /* if the destination directory exists, check that it is a jscoverage directory */
208 if (stat(destination, &buf) == 0) {
209 /* it exists */
210 if (! S_ISDIR(buf.st_mode)) {
211 fatal("not a directory: %s", destination);
212 }
213 if (! directory_is_empty(destination)) {
214 char * jscoverage_html = make_path(destination, "jscoverage.html");
215 if (stat(jscoverage_html, &buf) == -1) {
216 fatal("refusing to overwrite directory: %s", destination);
217 }
218 free(jscoverage_html);
219 }
220 }
221 else if (errno == ENOENT) {
222 xmkdir(destination);
223 }
224 else {
225 fatal("cannot stat directory: %s", destination);
226 }
227
228 /* finally: copy the directory */
229 struct DirListEntry * list = make_recursive_dir_list(source);
230 for (struct DirListEntry * p = list; p != NULL; p = p->next) {
231 char * s = make_path(source, p->name);
232 char * d = make_path(destination, p->name);
233
234 /* check if it's on the exclude list */
235 for (int i = 0; i < num_exclude; i++) {
236 char * x = make_path(source, exclude[i]);
237 if (is_same_file(x, s) || contains_file(x, s)) {
238 free(x);
239 goto cleanup;
240 }
241 free(x);
242 }
243
244 char * dd = make_dirname(d);
245 mkdirs(dd);
246 free(dd);
247
248 int instrument_this = 1;
249
250 /* check if it's on the no-instrument list */
251 for (int i = 0; i < num_no_instrument; i++) {
252 char * ni = make_path(source, no_instrument[i]);
253 if (is_same_file(ni, s) || contains_file(ni, s)) {
254 instrument_this = 0;
255 }
256 free(ni);
257 }
258
259 instrument_file(s, d, p->name, instrument_this);
260
261 cleanup:
262 free(s);
263 free(d);
264 }
265 free_dir_list(list);
266 }
267
268 void jscoverage_copy_resources(const char * destination_directory) {
269 copy_resource("jscoverage.html", destination_directory);
270 copy_resource("jscoverage.css", destination_directory);
271 copy_resource("jscoverage.js", destination_directory);
272 copy_resource("jscoverage-throbber.gif", destination_directory);
273 copy_resource("sh_main.js", destination_directory);
274 copy_resource("sh_javascript.js", destination_directory);
275 copy_resource("sh_nedit.css", destination_directory);
276 }

  ViewVC Help
Powered by ViewVC 1.1.24