PageRenderTime 85ms CodeModel.GetById 68ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/instrument.c

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C | 226 lines | 166 code | 33 blank | 27 comment | 43 complexity | 9a37774a7c2ec1fc71c4119d45552e8f MD5 | raw file
  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 "encoding.h"
 33#include "global.h"
 34#include "instrument-js.h"
 35#include "resource-manager.h"
 36#include "util.h"
 37
 38static int g_verbose = 0;
 39
 40static 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
 49static 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    return FILE_TYPE_OTHER;
 58  }
 59}
 60
 61static 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
 67static 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
 73static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
 74  if (g_verbose) {
 75    printf("Instrumenting file %s\n", id);
 76  }
 77
 78  /* check if they are the same */
 79  char * canonical_source_file = make_canonical_path(source_file);
 80  char * canonical_destination_file = make_canonical_path(destination_file);
 81  check_same_file(canonical_source_file, canonical_destination_file);
 82  free(canonical_source_file);
 83  free(canonical_destination_file);
 84
 85  if (instrumenting) {
 86    enum FileType file_type = get_file_type(source_file);
 87    switch (file_type) {
 88    case FILE_TYPE_OTHER:
 89    case FILE_TYPE_HTML:
 90      copy_file(source_file, destination_file);
 91      break;
 92    case FILE_TYPE_JS:
 93      {
 94        FILE * input = xfopen(source_file, "rb");
 95        FILE * output = xfopen(destination_file, "wb");
 96
 97        Stream * input_stream = Stream_new(0);
 98        Stream * output_stream = Stream_new(0);
 99
100        Stream_write_file_contents(input_stream, input);
101
102        size_t num_characters = input_stream->length;
103        uint16_t * characters = NULL;
104        int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
105        if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
106          fatal("encoding %s not supported", jscoverage_encoding);
107        }
108        else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
109          fatal("error decoding %s in file %s", jscoverage_encoding, id);
110        }
111        jscoverage_instrument_js(id, characters, num_characters, output_stream);
112        free(characters);
113
114        if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
115          fatal("cannot write to file: %s", destination_file);
116        }
117
118        Stream_delete(input_stream);
119        Stream_delete(output_stream);
120
121        fclose(input);
122        fclose(output);
123      }
124      break;
125    }
126  }
127  else {
128    copy_file(source_file, destination_file);
129  }
130}
131
132void jscoverage_instrument(const char * source,
133                           const char * destination,
134                           int verbose,
135                           char ** exclude,
136                           int num_exclude,
137                           char ** no_instrument,
138                           int num_no_instrument)
139{
140  assert(source != NULL);
141  assert(destination != NULL);
142
143  g_verbose = verbose;
144
145  /* check if they are the same */
146  check_same_file(source, destination);
147
148  /* check if source directory is an ancestor of destination directory */
149  check_contains_file(source, destination);
150
151  /* check that the source exists and is a directory */
152  struct stat buf;
153  xstat(source, &buf);
154  if (! S_ISDIR(buf.st_mode)) {
155    fatal("not a directory: %s", source);
156  }
157
158  /* if the destination directory exists, check that it is a jscoverage directory */
159  if (stat(destination, &buf) == 0) {
160    /* it exists */
161    if (! S_ISDIR(buf.st_mode)) {
162      fatal("not a directory: %s", destination);
163    }
164    if (! directory_is_empty(destination)) {
165      char * expected_file = NULL;
166      if (jscoverage_mozilla) {
167        char * modules_directory = make_path(destination, "modules");
168        expected_file = make_path(modules_directory, "jscoverage.jsm");
169        free(modules_directory);
170      }
171      else {
172        expected_file = make_path(destination, "jscoverage.html");
173      }
174      if (stat(expected_file, &buf) == -1) {
175        fatal("refusing to overwrite directory: %s", destination);
176      }
177      free(expected_file);
178    }
179  }
180  else if (errno == ENOENT) {
181    xmkdir(destination);
182  }
183  else {
184    fatal("cannot stat directory: %s", destination);
185  }
186
187  /* finally: copy the directory */
188  struct DirListEntry * list = make_recursive_dir_list(source);
189  for (struct DirListEntry * p = list; p != NULL; p = p->next) {
190    char * s = make_path(source, p->name);
191    char * d = make_path(destination, p->name);
192
193    /* check if it's on the exclude list */
194    for (int i = 0; i < num_exclude; i++) {
195      char * x = make_path(source, exclude[i]);
196      if (is_same_file(x, s) || contains_file(x, s)) {
197        free(x);
198        goto cleanup;
199      }
200      free(x);
201    }
202
203    char * dd = make_dirname(d);
204    mkdirs(dd);
205    free(dd);
206
207    int instrument_this = 1;
208
209    /* check if it's on the no-instrument list */
210    for (int i = 0; i < num_no_instrument; i++) {
211      char * ni = make_path(source, no_instrument[i]);
212      if (is_same_file(ni, s) || contains_file(ni, s)) {
213        instrument_this = 0;
214      }
215      free(ni);
216    }
217
218    instrument_file(s, d, p->name, instrument_this);
219
220  cleanup:
221    free(s);
222    free(d);
223  }
224
225  free_dir_list(list);
226}