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

Contents of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 124 - (show annotations)
Sun Jun 1 14:35:47 2008 UTC (11 years, 5 months ago) by siliconforks
File MIME type: text/plain
File size: 5944 byte(s)
Don't use FILE_TYPE_UNKNOWN; Windows defines it.

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 <config.h>
21
22 #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 #include "instrument-js.h"
33 #include "resource-manager.h"
34 #include "util.h"
35
36 static int g_verbose = 0;
37
38 static int string_ends_with(const char * s, const char * suffix) {
39 size_t length = strlen(s);
40 size_t suffix_length = strlen(suffix);
41 if (length < suffix_length) {
42 return 0;
43 }
44 return strcasecmp(s + (length - suffix_length), suffix) == 0;
45 }
46
47 static enum FileType get_file_type(const char * file) {
48 if (string_ends_with(file, ".js")) {
49 return FILE_TYPE_JS;
50 }
51 else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
52 return FILE_TYPE_HTML;
53 }
54 else {
55 return FILE_TYPE_OTHER;
56 }
57 }
58
59 static void check_same_file(const char * file1, const char * file2) {
60 if (is_same_file(file1, file2)) {
61 fatal("source and destination are the same");
62 }
63 }
64
65 static void check_contains_file(const char * file1, const char * file2) {
66 if (contains_file(file1, file2)) {
67 fatal("%s contains %s", file1, file2);
68 }
69 }
70
71 static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
72 if (g_verbose) {
73 printf("Instrumenting file %s\n", id);
74 }
75
76 /* check if they are the same */
77 char * canonical_source_file = make_canonical_path(source_file);
78 char * canonical_destination_file = make_canonical_path(destination_file);
79 check_same_file(canonical_source_file, canonical_destination_file);
80 free(canonical_source_file);
81 free(canonical_destination_file);
82
83 if (instrumenting) {
84 enum FileType file_type = get_file_type(source_file);
85 switch (file_type) {
86 case FILE_TYPE_OTHER:
87 case FILE_TYPE_HTML:
88 copy_file(source_file, destination_file);
89 break;
90 case FILE_TYPE_JS:
91 {
92 FILE * input = xfopen(source_file, "r");
93 FILE * output = xfopen(destination_file, "w");
94
95 Stream * input_stream = Stream_new(0);
96 Stream * output_stream = Stream_new(0);
97
98 Stream_write_file_contents(input_stream, input);
99
100 jscoverage_instrument_js(id, input_stream, output_stream);
101
102 if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
103 fatal("cannot write to file: %s", destination_file);
104 }
105
106 Stream_delete(input_stream);
107 Stream_delete(output_stream);
108
109 fclose(input);
110 fclose(output);
111 }
112 break;
113 }
114 }
115 else {
116 copy_file(source_file, destination_file);
117 }
118 }
119
120 void jscoverage_instrument(const char * source,
121 const char * destination,
122 int verbose,
123 char ** exclude,
124 int num_exclude,
125 char ** no_instrument,
126 int num_no_instrument)
127 {
128 assert(source != NULL);
129 assert(destination != NULL);
130
131 g_verbose = verbose;
132
133 /* check if they are the same */
134 check_same_file(source, destination);
135
136 /* check if source directory is an ancestor of destination directory */
137 check_contains_file(source, destination);
138
139 /* check that the source exists and is a directory */
140 struct stat buf;
141 xstat(source, &buf);
142 if (! S_ISDIR(buf.st_mode)) {
143 fatal("not a directory: %s", source);
144 }
145
146 /* if the destination directory exists, check that it is a jscoverage directory */
147 if (stat(destination, &buf) == 0) {
148 /* it exists */
149 if (! S_ISDIR(buf.st_mode)) {
150 fatal("not a directory: %s", destination);
151 }
152 if (! directory_is_empty(destination)) {
153 char * jscoverage_html = make_path(destination, "jscoverage.html");
154 if (stat(jscoverage_html, &buf) == -1) {
155 fatal("refusing to overwrite directory: %s", destination);
156 }
157 free(jscoverage_html);
158 }
159 }
160 else if (errno == ENOENT) {
161 xmkdir(destination);
162 }
163 else {
164 fatal("cannot stat directory: %s", destination);
165 }
166
167 /* copy the resources */
168 jscoverage_copy_resources(destination);
169
170 /* finally: copy the directory */
171 struct DirListEntry * list = make_recursive_dir_list(source);
172 for (struct DirListEntry * p = list; p != NULL; p = p->next) {
173 char * s = make_path(source, p->name);
174 char * d = make_path(destination, p->name);
175
176 /* check if it's on the exclude list */
177 for (int i = 0; i < num_exclude; i++) {
178 char * x = make_path(source, exclude[i]);
179 if (is_same_file(x, s) || contains_file(x, s)) {
180 free(x);
181 goto cleanup;
182 }
183 free(x);
184 }
185
186 char * dd = make_dirname(d);
187 mkdirs(dd);
188 free(dd);
189
190 int instrument_this = 1;
191
192 /* check if it's on the no-instrument list */
193 for (int i = 0; i < num_no_instrument; i++) {
194 char * ni = make_path(source, no_instrument[i]);
195 if (is_same_file(ni, s) || contains_file(ni, s)) {
196 instrument_this = 0;
197 }
198 free(ni);
199 }
200
201 instrument_file(s, d, p->name, instrument_this);
202
203 cleanup:
204 free(s);
205 free(d);
206 }
207 free_dir_list(list);
208 }

  ViewVC Help
Powered by ViewVC 1.1.24