diff options
Diffstat (limited to 'tools/node_modules/expresso/deps/jscoverage/instrument.c')
-rw-r--r-- | tools/node_modules/expresso/deps/jscoverage/instrument.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument.c b/tools/node_modules/expresso/deps/jscoverage/instrument.c new file mode 100644 index 0000000..d19b690 --- /dev/null +++ b/tools/node_modules/expresso/deps/jscoverage/instrument.c @@ -0,0 +1,226 @@ +/* + instrument.c - file and directory instrumentation routines + Copyright (C) 2007, 2008 siliconforks.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include <config.h> + +#include "instrument.h" + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <dirent.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "encoding.h" +#include "global.h" +#include "instrument-js.h" +#include "resource-manager.h" +#include "util.h" + +static int g_verbose = 0; + +static int string_ends_with(const char * s, const char * suffix) { + size_t length = strlen(s); + size_t suffix_length = strlen(suffix); + if (length < suffix_length) { + return 0; + } + return strcasecmp(s + (length - suffix_length), suffix) == 0; +} + +static enum FileType get_file_type(const char * file) { + if (string_ends_with(file, ".js")) { + return FILE_TYPE_JS; + } + else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) { + return FILE_TYPE_HTML; + } + else { + return FILE_TYPE_OTHER; + } +} + +static void check_same_file(const char * file1, const char * file2) { + if (is_same_file(file1, file2)) { + fatal("source and destination are the same"); + } +} + +static void check_contains_file(const char * file1, const char * file2) { + if (contains_file(file1, file2)) { + fatal("%s contains %s", file1, file2); + } +} + +static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) { + if (g_verbose) { + printf("Instrumenting file %s\n", id); + } + + /* check if they are the same */ + char * canonical_source_file = make_canonical_path(source_file); + char * canonical_destination_file = make_canonical_path(destination_file); + check_same_file(canonical_source_file, canonical_destination_file); + free(canonical_source_file); + free(canonical_destination_file); + + if (instrumenting) { + enum FileType file_type = get_file_type(source_file); + switch (file_type) { + case FILE_TYPE_OTHER: + case FILE_TYPE_HTML: + copy_file(source_file, destination_file); + break; + case FILE_TYPE_JS: + { + FILE * input = xfopen(source_file, "rb"); + FILE * output = xfopen(destination_file, "wb"); + + Stream * input_stream = Stream_new(0); + Stream * output_stream = Stream_new(0); + + Stream_write_file_contents(input_stream, input); + + size_t num_characters = input_stream->length; + uint16_t * characters = NULL; + int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters); + if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) { + fatal("encoding %s not supported", jscoverage_encoding); + } + else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) { + fatal("error decoding %s in file %s", jscoverage_encoding, id); + } + jscoverage_instrument_js(id, characters, num_characters, output_stream); + free(characters); + + if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) { + fatal("cannot write to file: %s", destination_file); + } + + Stream_delete(input_stream); + Stream_delete(output_stream); + + fclose(input); + fclose(output); + } + break; + } + } + else { + copy_file(source_file, destination_file); + } +} + +void jscoverage_instrument(const char * source, + const char * destination, + int verbose, + char ** exclude, + int num_exclude, + char ** no_instrument, + int num_no_instrument) +{ + assert(source != NULL); + assert(destination != NULL); + + g_verbose = verbose; + + /* check if they are the same */ + check_same_file(source, destination); + + /* check if source directory is an ancestor of destination directory */ + check_contains_file(source, destination); + + /* check that the source exists and is a directory */ + struct stat buf; + xstat(source, &buf); + if (! S_ISDIR(buf.st_mode)) { + fatal("not a directory: %s", source); + } + + /* if the destination directory exists, check that it is a jscoverage directory */ + if (stat(destination, &buf) == 0) { + /* it exists */ + if (! S_ISDIR(buf.st_mode)) { + fatal("not a directory: %s", destination); + } + if (! directory_is_empty(destination)) { + char * expected_file = NULL; + if (jscoverage_mozilla) { + char * modules_directory = make_path(destination, "modules"); + expected_file = make_path(modules_directory, "jscoverage.jsm"); + free(modules_directory); + } + else { + expected_file = make_path(destination, "jscoverage.html"); + } + if (stat(expected_file, &buf) == -1) { + fatal("refusing to overwrite directory: %s", destination); + } + free(expected_file); + } + } + else if (errno == ENOENT) { + xmkdir(destination); + } + else { + fatal("cannot stat directory: %s", destination); + } + + /* finally: copy the directory */ + struct DirListEntry * list = make_recursive_dir_list(source); + for (struct DirListEntry * p = list; p != NULL; p = p->next) { + char * s = make_path(source, p->name); + char * d = make_path(destination, p->name); + + /* check if it's on the exclude list */ + for (int i = 0; i < num_exclude; i++) { + char * x = make_path(source, exclude[i]); + if (is_same_file(x, s) || contains_file(x, s)) { + free(x); + goto cleanup; + } + free(x); + } + + char * dd = make_dirname(d); + mkdirs(dd); + free(dd); + + int instrument_this = 1; + + /* check if it's on the no-instrument list */ + for (int i = 0; i < num_no_instrument; i++) { + char * ni = make_path(source, no_instrument[i]); + if (is_same_file(ni, s) || contains_file(ni, s)) { + instrument_this = 0; + } + free(ni); + } + + instrument_file(s, d, p->name, instrument_this); + + cleanup: + free(s); + free(d); + } + + free_dir_list(list); +} |