aboutsummaryrefslogtreecommitdiffstats
path: root/tools/node_modules/expresso/deps/jscoverage/instrument.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/expresso/deps/jscoverage/instrument.c')
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument.c226
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);
+}