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

Annotation of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 92 - (hide annotations)
Wed May 7 04:21:22 2008 UTC (15 years ago) by siliconforks
File MIME type: text/plain
File size: 9085 byte(s)
Add streams; don't use temporary files.

1 siliconforks 2 /*
2     instrument.c - file and directory instrumentation routines
3 siliconforks 87 Copyright (C) 2007, 2008 siliconforks.com
4 siliconforks 2
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 siliconforks 67 fprintf(output, "<link rel=\"stylesheet\" type='text/css' href='%sjscoverage-sh_nedit.css'>\n", relative_path_to_ancestor);
85 siliconforks 2 fprintf(output, "<script src=\"%sjscoverage.js\"></script>\n", relative_path_to_ancestor);
86 siliconforks 67 fprintf(output, "<script src=\"%sjscoverage-sh_main.js\"></script>\n", relative_path_to_ancestor);
87     fprintf(output, "<script src=\"%sjscoverage-sh_javascript.js\"></script>\n", relative_path_to_ancestor);
88 siliconforks 2 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     {
166     FILE * input = xfopen(source_file, "r");
167     FILE * output = xfopen(destination_file, "w");
168 siliconforks 92
169     Stream * input_stream = Stream_new(0);
170     Stream * output_stream = Stream_new(0);
171    
172     Stream_write_file_contents(input_stream, input);
173    
174     jscoverage_instrument_js(id, input_stream, output_stream);
175    
176     if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
177     fatal("cannot write to file: %s", destination_file);
178     }
179    
180     Stream_delete(input_stream);
181     Stream_delete(output_stream);
182    
183 siliconforks 2 fclose(input);
184     fclose(output);
185     }
186 siliconforks 70 highlight_file(source_file, destination_file, id);
187 siliconforks 2 break;
188     }
189     }
190     else {
191     copy_file(source_file, destination_file);
192     }
193     }
194    
195     void jscoverage_instrument(const char * source,
196     const char * destination,
197     int verbose,
198     char ** exclude,
199     int num_exclude,
200     char ** no_instrument,
201     int num_no_instrument)
202     {
203     assert(source != NULL);
204     assert(destination != NULL);
205    
206     g_verbose = verbose;
207    
208     /* check if they are the same */
209     check_same_file(source, destination);
210    
211     /* check if source directory is an ancestor of destination directory */
212     check_contains_file(source, destination);
213    
214     /* check that the source exists and is a directory */
215     struct stat buf;
216     xstat(source, &buf);
217     if (! S_ISDIR(buf.st_mode)) {
218     fatal("not a directory: %s", source);
219     }
220    
221     /* if the destination directory exists, check that it is a jscoverage directory */
222     if (stat(destination, &buf) == 0) {
223     /* it exists */
224     if (! S_ISDIR(buf.st_mode)) {
225     fatal("not a directory: %s", destination);
226     }
227     if (! directory_is_empty(destination)) {
228     char * jscoverage_html = make_path(destination, "jscoverage.html");
229     if (stat(jscoverage_html, &buf) == -1) {
230     fatal("refusing to overwrite directory: %s", destination);
231     }
232     free(jscoverage_html);
233     }
234     }
235     else if (errno == ENOENT) {
236     xmkdir(destination);
237     }
238     else {
239     fatal("cannot stat directory: %s", destination);
240     }
241    
242 siliconforks 69 /* copy the resources */
243     jscoverage_copy_resources(destination);
244    
245 siliconforks 2 /* finally: copy the directory */
246     struct DirListEntry * list = make_recursive_dir_list(source);
247     for (struct DirListEntry * p = list; p != NULL; p = p->next) {
248     char * s = make_path(source, p->name);
249     char * d = make_path(destination, p->name);
250    
251     /* check if it's on the exclude list */
252     for (int i = 0; i < num_exclude; i++) {
253     char * x = make_path(source, exclude[i]);
254     if (is_same_file(x, s) || contains_file(x, s)) {
255     free(x);
256     goto cleanup;
257     }
258     free(x);
259     }
260    
261     char * dd = make_dirname(d);
262     mkdirs(dd);
263     free(dd);
264    
265     int instrument_this = 1;
266    
267     /* check if it's on the no-instrument list */
268     for (int i = 0; i < num_no_instrument; i++) {
269     char * ni = make_path(source, no_instrument[i]);
270     if (is_same_file(ni, s) || contains_file(ni, s)) {
271     instrument_this = 0;
272     }
273     free(ni);
274     }
275    
276     instrument_file(s, d, p->name, instrument_this);
277    
278     cleanup:
279     free(s);
280     free(d);
281     }
282     free_dir_list(list);
283     }
284    
285     void jscoverage_copy_resources(const char * destination_directory) {
286     copy_resource("jscoverage.html", destination_directory);
287     copy_resource("jscoverage.css", destination_directory);
288     copy_resource("jscoverage.js", destination_directory);
289     copy_resource("jscoverage-throbber.gif", destination_directory);
290 siliconforks 67 copy_resource("jscoverage-sh_main.js", destination_directory);
291     copy_resource("jscoverage-sh_javascript.js", destination_directory);
292     copy_resource("jscoverage-sh_nedit.css", destination_directory);
293 siliconforks 2 }

  ViewVC Help
Powered by ViewVC 1.1.24