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

Annotation of /trunk/instrument.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.24