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

Annotation of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Thu Sep 9 22:39:11 2010 UTC (8 years, 7 months ago) by siliconforks
File MIME type: text/plain
File size: 8498 byte(s)
Improve --verbose output.

1 siliconforks 2 /*
2     instrument.c - file and directory instrumentation routines
3 siliconforks 505 Copyright (C) 2007, 2008, 2009, 2010 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 siliconforks 116 #include <config.h>
21    
22 siliconforks 2 #include "instrument.h"
23    
24     #include <assert.h>
25     #include <errno.h>
26     #include <string.h>
27    
28     #include <dirent.h>
29     #include <sys/stat.h>
30     #include <sys/types.h>
31    
32 siliconforks 179 #include "encoding.h"
33 siliconforks 174 #include "global.h"
34 siliconforks 2 #include "instrument-js.h"
35     #include "resource-manager.h"
36     #include "util.h"
37    
38     static int g_verbose = 0;
39    
40     static int string_ends_with(const char * s, const char * suffix) {
41     size_t length = strlen(s);
42     size_t suffix_length = strlen(suffix);
43     if (length < suffix_length) {
44     return 0;
45     }
46     return strcasecmp(s + (length - suffix_length), suffix) == 0;
47     }
48    
49     static enum FileType get_file_type(const char * file) {
50     if (string_ends_with(file, ".js")) {
51     return FILE_TYPE_JS;
52     }
53     else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
54     return FILE_TYPE_HTML;
55     }
56     else {
57 siliconforks 124 return FILE_TYPE_OTHER;
58 siliconforks 2 }
59     }
60    
61     static void check_same_file(const char * file1, const char * file2) {
62     if (is_same_file(file1, file2)) {
63     fatal("source and destination are the same");
64     }
65     }
66    
67     static void check_contains_file(const char * file1, const char * file2) {
68     if (contains_file(file1, file2)) {
69     fatal("%s contains %s", file1, file2);
70     }
71     }
72    
73     static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
74     /* check if they are the same */
75     char * canonical_source_file = make_canonical_path(source_file);
76     char * canonical_destination_file = make_canonical_path(destination_file);
77     check_same_file(canonical_source_file, canonical_destination_file);
78     free(canonical_source_file);
79     free(canonical_destination_file);
80    
81     if (instrumenting) {
82     enum FileType file_type = get_file_type(source_file);
83     switch (file_type) {
84 siliconforks 124 case FILE_TYPE_OTHER:
85 siliconforks 2 case FILE_TYPE_HTML:
86 siliconforks 577 if (g_verbose) {
87     printf("Copying file %s\n", id);
88     }
89 siliconforks 2 copy_file(source_file, destination_file);
90     break;
91     case FILE_TYPE_JS:
92     {
93 siliconforks 577 if (g_verbose) {
94     printf("Instrumenting file %s\n", id);
95     }
96    
97 siliconforks 241 FILE * input = xfopen(source_file, "rb");
98     FILE * output = xfopen(destination_file, "wb");
99 siliconforks 92
100     Stream * input_stream = Stream_new(0);
101     Stream * output_stream = Stream_new(0);
102    
103     Stream_write_file_contents(input_stream, input);
104    
105 siliconforks 444 /*
106     Check if the source file looks like an instrumented JavaScript file.
107     */
108     if (input_stream->length >= JSCOVERAGE_INSTRUMENTED_HEADER_LENGTH &&
109     memcmp(input_stream->data, JSCOVERAGE_INSTRUMENTED_HEADER, JSCOVERAGE_INSTRUMENTED_HEADER_LENGTH) == 0) {
110     fatal_command_line("file %s in the source directory appears to be already instrumented", id);
111     }
112    
113 siliconforks 179 size_t num_characters = input_stream->length;
114     uint16_t * characters = NULL;
115     int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
116     if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
117     fatal("encoding %s not supported", jscoverage_encoding);
118     }
119     else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
120     fatal("error decoding %s in file %s", jscoverage_encoding, id);
121     }
122     jscoverage_instrument_js(id, characters, num_characters, output_stream);
123     free(characters);
124 siliconforks 92
125     if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
126     fatal("cannot write to file: %s", destination_file);
127     }
128    
129     Stream_delete(input_stream);
130     Stream_delete(output_stream);
131    
132 siliconforks 2 fclose(input);
133     fclose(output);
134     }
135     break;
136     }
137     }
138     else {
139 siliconforks 577 if (g_verbose) {
140     printf("Copying file %s (on --no-instrument list)\n", id);
141     }
142    
143 siliconforks 2 copy_file(source_file, destination_file);
144     }
145     }
146    
147     void jscoverage_instrument(const char * source,
148     const char * destination,
149     int verbose,
150     char ** exclude,
151     int num_exclude,
152     char ** no_instrument,
153     int num_no_instrument)
154     {
155     assert(source != NULL);
156     assert(destination != NULL);
157    
158     g_verbose = verbose;
159    
160     /* check if they are the same */
161     check_same_file(source, destination);
162    
163     /* check if source directory is an ancestor of destination directory */
164     check_contains_file(source, destination);
165    
166     /* check that the source exists and is a directory */
167     struct stat buf;
168     xstat(source, &buf);
169     if (! S_ISDIR(buf.st_mode)) {
170     fatal("not a directory: %s", source);
171     }
172    
173     /* if the destination directory exists, check that it is a jscoverage directory */
174     if (stat(destination, &buf) == 0) {
175     /* it exists */
176     if (! S_ISDIR(buf.st_mode)) {
177     fatal("not a directory: %s", destination);
178     }
179     if (! directory_is_empty(destination)) {
180 siliconforks 361 char * expected_file = NULL;
181 siliconforks 431 if (jscoverage_mode == JSCOVERAGE_MOZILLA) {
182 siliconforks 361 char * modules_directory = make_path(destination, "modules");
183     expected_file = make_path(modules_directory, "jscoverage.jsm");
184     free(modules_directory);
185     }
186     else {
187     expected_file = make_path(destination, "jscoverage.html");
188     }
189     if (stat(expected_file, &buf) == -1) {
190 siliconforks 2 fatal("refusing to overwrite directory: %s", destination);
191     }
192 siliconforks 361 free(expected_file);
193 siliconforks 2 }
194     }
195     else if (errno == ENOENT) {
196     xmkdir(destination);
197     }
198     else {
199     fatal("cannot stat directory: %s", destination);
200     }
201    
202 siliconforks 388 /* copy the resources */
203 siliconforks 431 if (jscoverage_mode == JSCOVERAGE_MOZILLA) {
204 siliconforks 388 char * chrome_directory = make_path(destination, "chrome");
205     char * jscoverage_chrome_directory = make_path(chrome_directory, "jscoverage");
206     mkdirs(jscoverage_chrome_directory);
207     copy_resource("jscoverage.manifest", chrome_directory);
208     copy_resource("jscoverage.html", jscoverage_chrome_directory);
209     copy_resource("jscoverage.css", jscoverage_chrome_directory);
210     copy_resource("jscoverage.js", jscoverage_chrome_directory);
211     copy_resource("jscoverage-throbber.gif", jscoverage_chrome_directory);
212     copy_resource("jscoverage-highlight.css", jscoverage_chrome_directory);
213     copy_resource("jscoverage.xul", jscoverage_chrome_directory);
214     copy_resource("jscoverage-overlay.js", jscoverage_chrome_directory);
215     free(jscoverage_chrome_directory);
216     free(chrome_directory);
217    
218     char * modules_directory = make_path(destination, "modules");
219     mkdirs(modules_directory);
220     copy_resource("jscoverage.jsm", modules_directory);
221     free(modules_directory);
222     }
223     else {
224     jscoverage_copy_resources(destination);
225     }
226    
227 siliconforks 2 /* finally: copy the directory */
228     struct DirListEntry * list = make_recursive_dir_list(source);
229     for (struct DirListEntry * p = list; p != NULL; p = p->next) {
230     char * s = make_path(source, p->name);
231     char * d = make_path(destination, p->name);
232    
233     /* check if it's on the exclude list */
234     for (int i = 0; i < num_exclude; i++) {
235     char * x = make_path(source, exclude[i]);
236     if (is_same_file(x, s) || contains_file(x, s)) {
237     free(x);
238     goto cleanup;
239     }
240     free(x);
241     }
242    
243     char * dd = make_dirname(d);
244     mkdirs(dd);
245     free(dd);
246    
247     int instrument_this = 1;
248    
249     /* check if it's on the no-instrument list */
250     for (int i = 0; i < num_no_instrument; i++) {
251     char * ni = make_path(source, no_instrument[i]);
252     if (is_same_file(ni, s) || contains_file(ni, s)) {
253     instrument_this = 0;
254     }
255     free(ni);
256     }
257    
258     instrument_file(s, d, p->name, instrument_this);
259    
260     cleanup:
261     free(s);
262     free(d);
263     }
264 siliconforks 361
265 siliconforks 2 free_dir_list(list);
266     }

  ViewVC Help
Powered by ViewVC 1.1.24