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

Contents of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 95 - (show annotations)
Wed May 7 22:50:00 2008 UTC (11 years, 7 months ago) by siliconforks
File MIME type: text/plain
File size: 6443 byte(s)
Eliminate .jscoverage.js files.

1 /*
2 instrument.c - file and directory instrumentation routines
3 Copyright (C) 2007, 2008 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 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
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 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 /* copy the resources */
166 jscoverage_copy_resources(destination);
167
168 /* 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 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 }

  ViewVC Help
Powered by ViewVC 1.1.24