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

Annotation of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 95 - (hide annotations)
Wed May 7 22:50:00 2008 UTC (11 years, 3 months ago) by siliconforks
File MIME type: text/plain
File size: 6443 byte(s)
Eliminate .jscoverage.js 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 check_same_file(const char * file1, const char * file2) {
58     if (is_same_file(file1, file2)) {
59     fatal("source and destination are the same");
60     }
61     }
62    
63     static void check_contains_file(const char * file1, const char * file2) {
64     if (contains_file(file1, file2)) {
65     fatal("%s contains %s", file1, file2);
66     }
67     }
68    
69     static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
70     if (g_verbose) {
71     printf("Instrumenting file %s\n", id);
72     }
73    
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     case FILE_TYPE_UNKNOWN:
85     case FILE_TYPE_HTML:
86     copy_file(source_file, destination_file);
87     break;
88     case FILE_TYPE_JS:
89     {
90     FILE * input = xfopen(source_file, "r");
91     FILE * output = xfopen(destination_file, "w");
92 siliconforks 92
93     Stream * input_stream = Stream_new(0);
94     Stream * output_stream = Stream_new(0);
95    
96     Stream_write_file_contents(input_stream, input);
97    
98     jscoverage_instrument_js(id, input_stream, output_stream);
99    
100     if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
101     fatal("cannot write to file: %s", destination_file);
102     }
103    
104     Stream_delete(input_stream);
105     Stream_delete(output_stream);
106    
107 siliconforks 2 fclose(input);
108     fclose(output);
109     }
110     break;
111     }
112     }
113     else {
114     copy_file(source_file, destination_file);
115     }
116     }
117    
118     void jscoverage_instrument(const char * source,
119     const char * destination,
120     int verbose,
121     char ** exclude,
122     int num_exclude,
123     char ** no_instrument,
124     int num_no_instrument)
125     {
126     assert(source != NULL);
127     assert(destination != NULL);
128    
129     g_verbose = verbose;
130    
131     /* check if they are the same */
132     check_same_file(source, destination);
133    
134     /* check if source directory is an ancestor of destination directory */
135     check_contains_file(source, destination);
136    
137     /* check that the source exists and is a directory */
138     struct stat buf;
139     xstat(source, &buf);
140     if (! S_ISDIR(buf.st_mode)) {
141     fatal("not a directory: %s", source);
142     }
143    
144     /* if the destination directory exists, check that it is a jscoverage directory */
145     if (stat(destination, &buf) == 0) {
146     /* it exists */
147     if (! S_ISDIR(buf.st_mode)) {
148     fatal("not a directory: %s", destination);
149     }
150     if (! directory_is_empty(destination)) {
151     char * jscoverage_html = make_path(destination, "jscoverage.html");
152     if (stat(jscoverage_html, &buf) == -1) {
153     fatal("refusing to overwrite directory: %s", destination);
154     }
155     free(jscoverage_html);
156     }
157     }
158     else if (errno == ENOENT) {
159     xmkdir(destination);
160     }
161     else {
162     fatal("cannot stat directory: %s", destination);
163     }
164    
165 siliconforks 69 /* copy the resources */
166     jscoverage_copy_resources(destination);
167    
168 siliconforks 2 /* finally: copy the directory */
169     struct DirListEntry * list = make_recursive_dir_list(source);
170     for (struct DirListEntry * p = list; p != NULL; p = p->next) {
171     char * s = make_path(source, p->name);
172     char * d = make_path(destination, p->name);
173    
174     /* check if it's on the exclude list */
175     for (int i = 0; i < num_exclude; i++) {
176     char * x = make_path(source, exclude[i]);
177     if (is_same_file(x, s) || contains_file(x, s)) {
178     free(x);
179     goto cleanup;
180     }
181     free(x);
182     }
183    
184     char * dd = make_dirname(d);
185     mkdirs(dd);
186     free(dd);
187    
188     int instrument_this = 1;
189    
190     /* check if it's on the no-instrument list */
191     for (int i = 0; i < num_no_instrument; i++) {
192     char * ni = make_path(source, no_instrument[i]);
193     if (is_same_file(ni, s) || contains_file(ni, s)) {
194     instrument_this = 0;
195     }
196     free(ni);
197     }
198    
199     instrument_file(s, d, p->name, instrument_this);
200    
201     cleanup:
202     free(s);
203     free(d);
204     }
205     free_dir_list(list);
206     }
207    
208     void jscoverage_copy_resources(const char * destination_directory) {
209     copy_resource("jscoverage.html", destination_directory);
210     copy_resource("jscoverage.css", destination_directory);
211     copy_resource("jscoverage.js", destination_directory);
212     copy_resource("jscoverage-throbber.gif", destination_directory);
213 siliconforks 67 copy_resource("jscoverage-sh_main.js", destination_directory);
214     copy_resource("jscoverage-sh_javascript.js", destination_directory);
215     copy_resource("jscoverage-sh_nedit.css", destination_directory);
216 siliconforks 2 }

  ViewVC Help
Powered by ViewVC 1.1.24