http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-logging/log2gnuplot.py ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-logging/log2gnuplot.py b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-logging/log2gnuplot.py new file mode 100644 index 0000000..0528259 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-logging/log2gnuplot.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python2 +# +# Analyze allocator logs and write total-bytes-in-use after every +# operation to stdout. The output can be gnuplotted as: +# +# $ python log2gnuplot.py </tmp/duk-alloc-log.txt >/tmp/output.txt +# $ gnuplot +# > plot "output.txt" with lines +# + +import os +import sys + +def main(): + allocated = 0 + + for line in sys.stdin: + line = line.strip() + parts = line.split(' ') + + # A ptr/NULL/FAIL size + # F ptr/NULL size + # R ptr/NULL oldsize ptr/NULL/FAIL newsize + + # Note: ajduk doesn't log oldsize (uses -1 instead) + + if parts[0] == 'A': + if parts[1] != 'NULL' and parts[1] != 'FAIL': + allocated += long(parts[2]) + elif parts[0] == 'F': + allocated -= long(parts[2]) + elif parts[0] == 'R': + allocated -= long(parts[2]) + if parts[3] != 'NULL' and parts[3] != 'FAIL': + allocated += long(parts[4]) + print(allocated) + + print(allocated) + +if __name__ == '__main__': + main()
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/README.rst b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/README.rst new file mode 100644 index 0000000..f3278bb --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/README.rst @@ -0,0 +1,10 @@ +========================================== +Allocator with memory wiping and red zones +========================================== + +Example allocator that wipes memory on free and checks that no out-of-bounds +writes have been made to bytes just before and after the allocated area. + +Valgrind is a better tool for detecting these memory issues, but it's not +available for all targets so you can use something like this to detect +memory lifecycle or out-of-bounds issues. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.c new file mode 100644 index 0000000..abca2f7 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.c @@ -0,0 +1,182 @@ +/* + * Example torture memory allocator with memory wiping and check for + * out-of-bounds writes. + * + * Allocation structure: + * + * [ alloc_hdr | red zone before | user area | red zone after ] + * + * ^ ^ + * | `--- pointer returned to Duktape + * `--- underlying malloc ptr + */ + +#include "duktape.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#define RED_ZONE_SIZE 16 +#define RED_ZONE_BYTE 0x5a +#define INIT_BYTE 0xa5 +#define WIPE_BYTE 0x27 + +typedef struct { + /* The double value in the union is there to ensure alignment is + * good for IEEE doubles too. In many 32-bit environments 4 bytes + * would be sufficiently aligned and the double value is unnecessary. + */ + union { + size_t sz; + double d; + } u; +} alloc_hdr; + +static void check_red_zone(alloc_hdr *hdr) { + size_t size; + int i; + int err; + unsigned char *p; + unsigned char *userptr; + + size = hdr->u.sz; + userptr = (unsigned char *) hdr + sizeof(alloc_hdr) + RED_ZONE_SIZE; + + err = 0; + p = (unsigned char *) hdr + sizeof(alloc_hdr); + for (i = 0; i < RED_ZONE_SIZE; i++) { + if (p[i] != RED_ZONE_BYTE) { + err = 1; + } + } + if (err) { + fprintf(stderr, "RED ZONE CORRUPTED BEFORE ALLOC: hdr=%p ptr=%p size=%ld\n", + (void *) hdr, (void *) userptr, (long) size); + fflush(stderr); + } + + err = 0; + p = (unsigned char *) hdr + sizeof(alloc_hdr) + RED_ZONE_SIZE + size; + for (i = 0; i < RED_ZONE_SIZE; i++) { + if (p[i] != RED_ZONE_BYTE) { + err = 1; + } + } + if (err) { + fprintf(stderr, "RED ZONE CORRUPTED AFTER ALLOC: hdr=%p ptr=%p size=%ld\n", + (void *) hdr, (void *) userptr, (long) size); + fflush(stderr); + } +} + +void *duk_alloc_torture(void *udata, duk_size_t size) { + unsigned char *p; + + (void) udata; /* Suppress warning. */ + + if (size == 0) { + return NULL; + } + + p = (unsigned char *) malloc(size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); + if (!p) { + return NULL; + } + + ((alloc_hdr *) (void *) p)->u.sz = size; + p += sizeof(alloc_hdr); + memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); + p += RED_ZONE_SIZE; + memset((void *) p, INIT_BYTE, size); + p += size; + memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); + p -= size; + return (void *) p; +} + +void *duk_realloc_torture(void *udata, void *ptr, duk_size_t size) { + unsigned char *p, *old_p; + size_t old_size; + + (void) udata; /* Suppress warning. */ + + /* Handle the ptr-NULL vs. size-zero cases explicitly to minimize + * platform assumptions. You can get away with much less in specific + * well-behaving environments. + */ + + if (ptr) { + old_p = (unsigned char *) ptr - sizeof(alloc_hdr) - RED_ZONE_SIZE; + old_size = ((alloc_hdr *) (void *) old_p)->u.sz; + check_red_zone((alloc_hdr *) (void *) old_p); + + if (size == 0) { + memset((void *) old_p, WIPE_BYTE, old_size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); + free((void *) old_p); + return NULL; + } else { + /* Force address change on every realloc. */ + p = (unsigned char *) malloc(size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); + if (!p) { + return NULL; + } + + ((alloc_hdr *) (void *) p)->u.sz = size; + p += sizeof(alloc_hdr); + memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); + p += RED_ZONE_SIZE; + if (size > old_size) { + memcpy((void *) p, (void *) (old_p + sizeof(alloc_hdr) + RED_ZONE_SIZE), old_size); + memset((void *) (p + old_size), INIT_BYTE, size - old_size); + } else { + memcpy((void *) p, (void *) (old_p + sizeof(alloc_hdr) + RED_ZONE_SIZE), size); + } + p += size; + memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); + p -= size; + + memset((void *) old_p, WIPE_BYTE, old_size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); + free((void *) old_p); + + return (void *) p; + } + } else { + if (size == 0) { + return NULL; + } else { + p = (unsigned char *) malloc(size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); + if (!p) { + return NULL; + } + + ((alloc_hdr *) (void *) p)->u.sz = size; + p += sizeof(alloc_hdr); + memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); + p += RED_ZONE_SIZE; + memset((void *) p, INIT_BYTE, size); + p += size; + memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); + p -= size; + return (void *) p; + } + } +} + +void duk_free_torture(void *udata, void *ptr) { + unsigned char *p; + size_t old_size; + + (void) udata; /* Suppress warning. */ + + if (!ptr) { + return; + } + + p = (unsigned char *) ptr - sizeof(alloc_hdr) - RED_ZONE_SIZE; + old_size = ((alloc_hdr *) (void *) p)->u.sz; + + check_red_zone((alloc_hdr *) (void *) p); + memset((void *) p, WIPE_BYTE, old_size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); + free((void *) p); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.h ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.h b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.h new file mode 100644 index 0000000..a12153a --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.h @@ -0,0 +1,10 @@ +#ifndef DUK_ALLOC_TORTURE_H_INCLUDED +#define DUK_ALLOC_TORTURE_H_INCLUDED + +#include "duktape.h" + +void *duk_alloc_torture(void *udata, duk_size_t size); +void *duk_realloc_torture(void *udata, void *ptr, duk_size_t size); +void duk_free_torture(void *udata, void *ptr); + +#endif /* DUK_ALLOC_TORTURE_H_INCLUDED */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/README.rst b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/README.rst new file mode 100644 index 0000000..e0c6bce --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/README.rst @@ -0,0 +1,6 @@ +==================== +Duktape command line +==================== + +Ecmascript command line execution tool, useful for running Ecmascript code +from a file, stdin, or interactively. Also used by automatic testing. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline.c new file mode 100644 index 0000000..ea5af55 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline.c @@ -0,0 +1,1463 @@ +/* + * Command line execution tool. Useful for test cases and manual testing. + * + * To enable linenoise and other fancy stuff, compile with -DDUK_CMDLINE_FANCY. + * It is not the default to maximize portability. You can also compile in + * support for example allocators, grep for DUK_CMDLINE_*. + */ + +/* Helper define to enable a feature set; can also use separate defines. */ +#if defined(DUK_CMDLINE_FANCY) +#define DUK_CMDLINE_LINENOISE +#define DUK_CMDLINE_LINENOISE_COMPLETION +#define DUK_CMDLINE_RLIMIT +#define DUK_CMDLINE_SIGNAL +#endif + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ + defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +/* Suppress warnings about plain fopen() etc. */ +#define _CRT_SECURE_NO_WARNINGS +#if defined(_MSC_VER) && (_MSC_VER < 1900) +/* Workaround for snprintf() missing in older MSVC versions. + * Note that _snprintf() may not NUL terminate the string, but + * this difference does not matter here as a NUL terminator is + * always explicitly added. + */ +#define snprintf _snprintf +#endif +#endif + +#define GREET_CODE(variant) \ + "print('((o) Duktape" variant " ' + " \ + "Math.floor(Duktape.version / 10000) + '.' + " \ + "Math.floor(Duktape.version / 100) % 100 + '.' + " \ + "Duktape.version % 100" \ + ", '(" DUK_GIT_DESCRIBE ")');" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if defined(DUK_CMDLINE_SIGNAL) +#include <signal.h> +#endif +#if defined(DUK_CMDLINE_RLIMIT) +#include <sys/resource.h> +#endif +#if defined(DUK_CMDLINE_LINENOISE) +#include "linenoise.h" +#endif +#if defined(DUK_CMDLINE_FILEIO) +#include <errno.h> +#endif +#if defined(EMSCRIPTEN) +#include <emscripten.h> +#endif +#if defined(DUK_CMDLINE_ALLOC_LOGGING) +#include "duk_alloc_logging.h" +#endif +#if defined(DUK_CMDLINE_ALLOC_TORTURE) +#include "duk_alloc_torture.h" +#endif +#if defined(DUK_CMDLINE_ALLOC_HYBRID) +#include "duk_alloc_hybrid.h" +#endif +#include "duktape.h" + +#if defined(DUK_CMDLINE_AJSHEAP) +/* Defined in duk_cmdline_ajduk.c or alljoyn.js headers. */ +void ajsheap_init(void); +void ajsheap_free(void); +void ajsheap_dump(void); +void ajsheap_register(duk_context *ctx); +void ajsheap_start_exec_timeout(void); +void ajsheap_clear_exec_timeout(void); +void *ajsheap_alloc_wrapped(void *udata, duk_size_t size); +void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size); +void ajsheap_free_wrapped(void *udata, void *ptr); +void *AJS_Alloc(void *udata, duk_size_t size); +void *AJS_Realloc(void *udata, void *ptr, duk_size_t size); +void AJS_Free(void *udata, void *ptr); +#endif + +#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT) +#include "duk_trans_socket.h" +#endif + +#define MEM_LIMIT_NORMAL (128*1024*1024) /* 128 MB */ +#define MEM_LIMIT_HIGH (2047*1024*1024) /* ~2 GB */ +#define LINEBUF_SIZE 65536 + +static int main_argc = 0; +static char **main_argv = NULL; +static int interactive_mode = 0; +#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT) +static int debugger_reattach = 0; +#endif + +/* + * Misc helpers + */ + +#if defined(DUK_CMDLINE_RLIMIT) +static void set_resource_limits(rlim_t mem_limit_value) { + int rc; + struct rlimit lim; + + rc = getrlimit(RLIMIT_AS, &lim); + if (rc != 0) { + fprintf(stderr, "Warning: cannot read RLIMIT_AS\n"); + return; + } + + if (lim.rlim_max < mem_limit_value) { + fprintf(stderr, "Warning: rlim_max < mem_limit_value (%d < %d)\n", (int) lim.rlim_max, (int) mem_limit_value); + return; + } + + lim.rlim_cur = mem_limit_value; + lim.rlim_max = mem_limit_value; + + rc = setrlimit(RLIMIT_AS, &lim); + if (rc != 0) { + fprintf(stderr, "Warning: setrlimit failed\n"); + return; + } + +#if 0 + fprintf(stderr, "Set RLIMIT_AS to %d\n", (int) mem_limit_value); +#endif +} +#endif /* DUK_CMDLINE_RLIMIT */ + +#if defined(DUK_CMDLINE_SIGNAL) +static void my_sighandler(int x) { + fprintf(stderr, "Got signal %d\n", x); + fflush(stderr); +} +static void set_sigint_handler(void) { + (void) signal(SIGINT, my_sighandler); + (void) signal(SIGPIPE, SIG_IGN); /* avoid SIGPIPE killing process */ +} +#endif /* DUK_CMDLINE_SIGNAL */ + +static int get_stack_raw(duk_context *ctx) { + if (!duk_is_object(ctx, -1)) { + return 1; + } + if (!duk_has_prop_string(ctx, -1, "stack")) { + return 1; + } + if (!duk_is_error(ctx, -1)) { + /* Not an Error instance, don't read "stack". */ + return 1; + } + + duk_get_prop_string(ctx, -1, "stack"); /* caller coerces */ + duk_remove(ctx, -2); + return 1; +} + +/* Print error to stderr and pop error. */ +static void print_pop_error(duk_context *ctx, FILE *f) { + /* Print error objects with a stack trace specially. + * Note that getting the stack trace may throw an error + * so this also needs to be safe call wrapped. + */ + (void) duk_safe_call(ctx, get_stack_raw, 1 /*nargs*/, 1 /*nrets*/); + fprintf(f, "%s\n", duk_safe_to_string(ctx, -1)); + fflush(f); + duk_pop(ctx); +} + +static int wrapped_compile_execute(duk_context *ctx) { + const char *src_data; + duk_size_t src_len; + int comp_flags; + + /* XXX: Here it'd be nice to get some stats for the compilation result + * when a suitable command line is given (e.g. code size, constant + * count, function count. These are available internally but not through + * the public API. + */ + + /* Use duk_compile_lstring_filename() variant which avoids interning + * the source code. This only really matters for low memory environments. + */ + + /* [ ... bytecode_filename src_data src_len filename ] */ + + src_data = (const char *) duk_require_pointer(ctx, -3); + src_len = (duk_size_t) duk_require_uint(ctx, -2); + + if (src_data != NULL && src_len >= 2 && src_data[0] == (char) 0xff) { + /* Bytecode. */ + duk_push_lstring(ctx, src_data, src_len); + duk_to_buffer(ctx, -1, NULL); + duk_load_function(ctx); + } else { + /* Source code. */ + comp_flags = 0; + duk_compile_lstring_filename(ctx, comp_flags, src_data, src_len); + } + + /* [ ... bytecode_filename src_data src_len function ] */ + + /* Optional bytecode dump. */ + if (duk_is_string(ctx, -4)) { + FILE *f; + void *bc_ptr; + duk_size_t bc_len; + size_t wrote; + char fnbuf[256]; + const char *filename; + + duk_dup_top(ctx); + duk_dump_function(ctx); + bc_ptr = duk_require_buffer(ctx, -1, &bc_len); + filename = duk_require_string(ctx, -5); +#if defined(EMSCRIPTEN) + if (filename[0] == '/') { + snprintf(fnbuf, sizeof(fnbuf), "%s", filename); + } else { + snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename); + } +#else + snprintf(fnbuf, sizeof(fnbuf), "%s", filename); +#endif + fnbuf[sizeof(fnbuf) - 1] = (char) 0; + + f = fopen(fnbuf, "wb"); + if (!f) { + duk_error(ctx, DUK_ERR_ERROR, "failed to open bytecode output file"); + } + wrote = fwrite(bc_ptr, 1, (size_t) bc_len, f); /* XXX: handle partial writes */ + (void) fclose(f); + if (wrote != bc_len) { + duk_error(ctx, DUK_ERR_ERROR, "failed to write all bytecode"); + } + + return 0; /* duk_safe_call() cleans up */ + } + +#if 0 + /* Manual test for bytecode dump/load cycle: dump and load before + * execution. Enable manually, then run "make qecmatest" for a + * reasonably good coverage of different functions and programs. + */ + duk_dump_function(ctx); + duk_load_function(ctx); +#endif + +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_start_exec_timeout(); +#endif + + duk_push_global_object(ctx); /* 'this' binding */ + duk_call_method(ctx, 0); + +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_clear_exec_timeout(); +#endif + + if (interactive_mode) { + /* + * In interactive mode, write to stdout so output won't + * interleave as easily. + * + * NOTE: the ToString() coercion may fail in some cases; + * for instance, if you evaluate: + * + * ( {valueOf: function() {return {}}, + * toString: function() {return {}}}); + * + * The error is: + * + * TypeError: failed to coerce with [[DefaultValue]] + * duk_api.c:1420 + * + * These are handled now by the caller which also has stack + * trace printing support. User code can print out errors + * safely using duk_safe_to_string(). + */ + + fprintf(stdout, "= %s\n", duk_to_string(ctx, -1)); + fflush(stdout); + } else { + /* In non-interactive mode, success results are not written at all. + * It is important that the result value is not string coerced, + * as the string coercion may cause an error in some cases. + */ + } + + return 0; /* duk_safe_call() cleans up */ +} + +/* + * Minimal Linenoise completion support + */ + +#if defined(DUK_CMDLINE_LINENOISE_COMPLETION) +static duk_context *completion_ctx; + +static int completion_idpart(unsigned char c) { + /* Very simplified "is identifier part" check. */ + if ((c >= (unsigned char) 'a' && c <= (unsigned char) 'z') || + (c >= (unsigned char) 'A' && c <= (unsigned char) 'Z') || + (c >= (unsigned char) '0' && c <= (unsigned char) '9') || + c == (unsigned char) '$' || c == (unsigned char) '_') { + return 1; + } + return 0; +} + +static int completion_digit(unsigned char c) { + return (c >= (unsigned char) '0' && c <= (unsigned char) '9'); +} + +static duk_ret_t linenoise_completion_lookup(duk_context *ctx) { + duk_size_t len; + const char *orig; + const unsigned char *p; + const unsigned char *p_curr; + const unsigned char *p_end; + const char *key; + const char *prefix; + linenoiseCompletions *lc; + duk_idx_t idx_obj; + + orig = duk_require_string(ctx, -3); + p_curr = (const unsigned char *) duk_require_lstring(ctx, -2, &len); + p_end = p_curr + len; + lc = duk_require_pointer(ctx, -1); + + duk_push_global_object(ctx); + idx_obj = duk_require_top_index(ctx); + + while (p_curr <= p_end) { + /* p_curr == p_end allowed on purpose, to handle 'Math.' for example. */ + p = p_curr; + while (p < p_end && p[0] != (unsigned char) '.') { + p++; + } + /* 'p' points to a NUL (p == p_end) or a period. */ + prefix = duk_push_lstring(ctx, (const char *) p_curr, (duk_size_t) (p - p_curr)); + +#if 0 + fprintf(stderr, "Completion check: '%s'\n", prefix); + fflush(stderr); +#endif + + if (p == p_end) { + /* 'idx_obj' points to the object matching the last + * full component, use [p_curr,p[ as a filter for + * that object. + */ + + duk_enum(ctx, idx_obj, DUK_ENUM_INCLUDE_NONENUMERABLE); + while (duk_next(ctx, -1, 0 /*get_value*/)) { + key = duk_get_string(ctx, -1); +#if 0 + fprintf(stderr, "Key: %s\n", key ? key : ""); + fflush(stderr); +#endif + if (!key) { + /* Should never happen, just in case. */ + goto next; + } + + /* Ignore array index keys: usually not desirable, and would + * also require ['0'] quoting. + */ + if (completion_digit(key[0])) { + goto next; + } + + /* XXX: There's no key quoting now, it would require replacing the + * last component with a ['foo\nbar'] style lookup when appropriate. + */ + + if (strlen(prefix) == 0) { + /* Partial ends in a period, e.g. 'Math.' -> complete all Math properties. */ + duk_push_string(ctx, orig); /* original, e.g. 'Math.' */ + duk_push_string(ctx, key); + duk_concat(ctx, 2); + linenoiseAddCompletion(lc, duk_require_string(ctx, -1)); + duk_pop(ctx); + } else if (prefix && strcmp(key, prefix) == 0) { + /* Full completion, add a period, e.g. input 'Math' -> 'Math.'. */ + duk_push_string(ctx, orig); /* original, including partial last component */ + duk_push_string(ctx, "."); + duk_concat(ctx, 2); + linenoiseAddCompletion(lc, duk_require_string(ctx, -1)); + duk_pop(ctx); + } else if (prefix && strncmp(key, prefix, strlen(prefix)) == 0) { + /* Last component is partial, complete. */ + duk_push_string(ctx, orig); /* original, including partial last component */ + duk_push_string(ctx, key + strlen(prefix)); /* completion to last component */ + duk_concat(ctx, 2); + linenoiseAddCompletion(lc, duk_require_string(ctx, -1)); + duk_pop(ctx); + } + + next: + duk_pop(ctx); + } + return 0; + } else { + if (duk_get_prop(ctx, idx_obj)) { + duk_to_object(ctx, -1); /* for properties of plain strings etc */ + duk_replace(ctx, idx_obj); + p_curr = p + 1; + } else { + /* Not found. */ + return 0; + } + } + } + + return 0; +} + +static void linenoise_completion(const char *buf, linenoiseCompletions *lc) { + duk_context *ctx; + const unsigned char *p_start; + const unsigned char *p_end; + const unsigned char *p; + duk_int_t rc; + + if (!buf) { + return; + } + ctx = completion_ctx; + if (!ctx) { + return; + } + + p_start = (const unsigned char *) buf; + p_end = (const unsigned char *) (buf + strlen(buf)); + p = p_end; + + /* Scan backwards for a maximal string which looks like a property + * chain (e.g. foo.bar.quux). + */ + + while (--p >= p_start) { + if (p[0] == (unsigned char) '.') { + if (p <= p_start) { + break; + } + if (!completion_idpart(p[-1])) { + /* Catches e.g. 'foo..bar' -> we want 'bar' only. */ + break; + } + } else if (!completion_idpart(p[0])) { + break; + } + } + /* 'p' will either be p_start - 1 (ran out of buffer) or point to + * the first offending character. + */ + p++; + if (p < p_start || p >= p_end) { + return; /* should never happen, but just in case */ + } + + /* 'p' now points to a string of the form 'foo.bar.quux'. Look up + * all the components except the last; treat the last component as + * a partial name which is used as a filter for the previous full + * component. All lookups are from the global object now. + */ + +#if 0 + fprintf(stderr, "Completion starting point: '%s'\n", p); + fflush(stderr); +#endif + + duk_push_string(ctx, (const char *) buf); + duk_push_lstring(ctx, (const char *) p, (duk_size_t) (p_end - p)); + duk_push_pointer(ctx, (void *) lc); + + rc = duk_safe_call(ctx, linenoise_completion_lookup, 3 /*nargs*/, 1 /*nrets*/); + if (rc != DUK_EXEC_SUCCESS) { + fprintf(stderr, "Completion handling failure: %s\n", duk_safe_to_string(ctx, -1)); + } + duk_pop(ctx); +} +#endif /* DUK_CMDLINE_LINENOISE_COMPLETION */ + +/* + * Execute from file handle etc + */ + +static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename) { + char *buf = NULL; + size_t bufsz; + size_t bufoff; + size_t got; + int rc; + int retval = -1; + + buf = (char *) malloc(1024); + if (!buf) { + goto error; + } + bufsz = 1024; + bufoff = 0; + + /* Read until EOF, avoid fseek/stat because it won't work with stdin. */ + for (;;) { + size_t avail; + + avail = bufsz - bufoff; + if (avail < 1024) { + size_t newsz; + char *buf_new; +#if 0 + fprintf(stderr, "resizing read buffer: %ld -> %ld\n", (long) bufsz, (long) (bufsz * 2)); +#endif + newsz = bufsz + (bufsz >> 2) + 1024; /* +25% and some extra */ + buf_new = (char *) realloc(buf, newsz); + if (!buf_new) { + goto error; + } + buf = buf_new; + bufsz = newsz; + } + + avail = bufsz - bufoff; +#if 0 + fprintf(stderr, "reading input: buf=%p bufsz=%ld bufoff=%ld avail=%ld\n", + (void *) buf, (long) bufsz, (long) bufoff, (long) avail); +#endif + + got = fread((void *) (buf + bufoff), (size_t) 1, avail, f); +#if 0 + fprintf(stderr, "got=%ld\n", (long) got); +#endif + if (got == 0) { + break; + } + bufoff += got; + + /* Emscripten specific: stdin EOF doesn't work as expected. + * Instead, when 'emduk' is executed using Node.js, a file + * piped to stdin repeats (!). Detect that repeat and cut off + * the stdin read. Ensure the loop repeats enough times to + * avoid detecting spurious loops. + * + * This only seems to work for inputs up to 256 bytes long. + */ +#if defined(EMSCRIPTEN) + if (bufoff >= 16384) { + size_t i, j, nloops; + int looped = 0; + + for (i = 16; i < bufoff / 8; i++) { + int ok; + + nloops = bufoff / i; + ok = 1; + for (j = 1; j < nloops; j++) { + if (memcmp((void *) buf, (void *) (buf + i * j), i) != 0) { + ok = 0; + break; + } + } + if (ok) { + fprintf(stderr, "emscripten workaround: detect looping at index %ld, verified with %ld loops\n", (long) i, (long) (nloops - 1)); + bufoff = i; + looped = 1; + break; + } + } + + if (looped) { + break; + } + } +#endif + } + + duk_push_string(ctx, bytecode_filename); + duk_push_pointer(ctx, (void *) buf); + duk_push_uint(ctx, (duk_uint_t) bufoff); + duk_push_string(ctx, filename); + + interactive_mode = 0; /* global */ + + rc = duk_safe_call(ctx, wrapped_compile_execute, 4 /*nargs*/, 1 /*nret*/); + +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_clear_exec_timeout(); +#endif + + free(buf); + buf = NULL; + + if (rc != DUK_EXEC_SUCCESS) { + print_pop_error(ctx, stderr); + goto error; + } else { + duk_pop(ctx); + retval = 0; + } + /* fall thru */ + + cleanup: + if (buf) { + free(buf); + buf = NULL; + } + return retval; + + error: + fprintf(stderr, "error in executing file %s\n", filename); + fflush(stderr); + goto cleanup; +} + +static int handle_file(duk_context *ctx, const char *filename, const char *bytecode_filename) { + FILE *f = NULL; + int retval; + char fnbuf[256]; + + /* Example of sending an application specific debugger notification. */ + duk_push_string(ctx, "DebuggerHandleFile"); + duk_push_string(ctx, filename); + duk_debugger_notify(ctx, 2); + +#if defined(EMSCRIPTEN) + if (filename[0] == '/') { + snprintf(fnbuf, sizeof(fnbuf), "%s", filename); + } else { + snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename); + } +#else + snprintf(fnbuf, sizeof(fnbuf), "%s", filename); +#endif + fnbuf[sizeof(fnbuf) - 1] = (char) 0; + + f = fopen(fnbuf, "rb"); + if (!f) { + fprintf(stderr, "failed to open source file: %s\n", filename); + fflush(stderr); + goto error; + } + + retval = handle_fh(ctx, f, filename, bytecode_filename); + + fclose(f); + return retval; + + error: + return -1; +} + +static int handle_eval(duk_context *ctx, char *code) { + int rc; + int retval = -1; + + duk_push_pointer(ctx, (void *) code); + duk_push_uint(ctx, (duk_uint_t) strlen(code)); + duk_push_string(ctx, "eval"); + + interactive_mode = 0; /* global */ + + rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); + +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_clear_exec_timeout(); +#endif + + if (rc != DUK_EXEC_SUCCESS) { + print_pop_error(ctx, stderr); + } else { + duk_pop(ctx); + retval = 0; + } + + return retval; +} + +#if defined(DUK_CMDLINE_LINENOISE) +static int handle_interactive(duk_context *ctx) { + const char *prompt = "duk> "; + char *buffer = NULL; + int retval = 0; + int rc; + + duk_eval_string(ctx, GREET_CODE(" [linenoise]")); + duk_pop(ctx); + + linenoiseSetMultiLine(1); + linenoiseHistorySetMaxLen(64); +#if defined(DUK_CMDLINE_LINENOISE_COMPLETION) + linenoiseSetCompletionCallback(linenoise_completion); +#endif + + for (;;) { + if (buffer) { + linenoiseFree(buffer); + buffer = NULL; + } + +#if defined(DUK_CMDLINE_LINENOISE_COMPLETION) + completion_ctx = ctx; +#endif + buffer = linenoise(prompt); +#if defined(DUK_CMDLINE_LINENOISE_COMPLETION) + completion_ctx = NULL; +#endif + + if (!buffer) { + break; + } + + if (buffer && buffer[0] != (char) 0) { + linenoiseHistoryAdd(buffer); + } + + duk_push_pointer(ctx, (void *) buffer); + duk_push_uint(ctx, (duk_uint_t) strlen(buffer)); + duk_push_string(ctx, "input"); + + interactive_mode = 1; /* global */ + + rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); + +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_clear_exec_timeout(); +#endif + + if (buffer) { + linenoiseFree(buffer); + buffer = NULL; + } + + if (rc != DUK_EXEC_SUCCESS) { + /* in interactive mode, write to stdout */ + print_pop_error(ctx, stdout); + retval = -1; /* an error 'taints' the execution */ + } else { + duk_pop(ctx); + } + } + + if (buffer) { + linenoiseFree(buffer); + buffer = NULL; + } + + return retval; +} +#else /* DUK_CMDLINE_LINENOISE */ +static int handle_interactive(duk_context *ctx) { + const char *prompt = "duk> "; + char *buffer = NULL; + int retval = 0; + int rc; + int got_eof = 0; + + duk_eval_string(ctx, GREET_CODE("")); + duk_pop(ctx); + + buffer = (char *) malloc(LINEBUF_SIZE); + if (!buffer) { + fprintf(stderr, "failed to allocated a line buffer\n"); + fflush(stderr); + retval = -1; + goto done; + } + + while (!got_eof) { + size_t idx = 0; + + fwrite(prompt, 1, strlen(prompt), stdout); + fflush(stdout); + + for (;;) { + int c = fgetc(stdin); + if (c == EOF) { + got_eof = 1; + break; + } else if (c == '\n') { + break; + } else if (idx >= LINEBUF_SIZE) { + fprintf(stderr, "line too long\n"); + fflush(stderr); + retval = -1; + goto done; + } else { + buffer[idx++] = (char) c; + } + } + + duk_push_pointer(ctx, (void *) buffer); + duk_push_uint(ctx, (duk_uint_t) idx); + duk_push_string(ctx, "input"); + + interactive_mode = 1; /* global */ + + rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); + +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_clear_exec_timeout(); +#endif + + if (rc != DUK_EXEC_SUCCESS) { + /* in interactive mode, write to stdout */ + print_pop_error(ctx, stdout); + retval = -1; /* an error 'taints' the execution */ + } else { + duk_pop(ctx); + } + } + + done: + if (buffer) { + free(buffer); + buffer = NULL; + } + + return retval; +} +#endif /* DUK_CMDLINE_LINENOISE */ + +/* + * Simple file read/write bindings + */ + +#if defined(DUK_CMDLINE_FILEIO) +static duk_ret_t fileio_read_file(duk_context *ctx) { + const char *fn; + char *buf; + size_t len; + size_t off; + int rc; + FILE *f; + + fn = duk_require_string(ctx, 0); + f = fopen(fn, "rb"); + if (!f) { + duk_error(ctx, DUK_ERR_TYPE_ERROR, "cannot open file %s for reading, errno %ld: %s", + fn, (long) errno, strerror(errno)); + } + + rc = fseek(f, 0, SEEK_END); + if (rc < 0) { + (void) fclose(f); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "fseek() failed for %s, errno %ld: %s", + fn, (long) errno, strerror(errno)); + } + len = (size_t) ftell(f); + rc = fseek(f, 0, SEEK_SET); + if (rc < 0) { + (void) fclose(f); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "fseek() failed for %s, errno %ld: %s", + fn, (long) errno, strerror(errno)); + } + + buf = (char *) duk_push_fixed_buffer(ctx, (duk_size_t) len); + for (off = 0; off < len;) { + size_t got; + got = fread((void *) (buf + off), 1, len - off, f); + if (ferror(f)) { + (void) fclose(f); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while reading %s", fn); + } + if (got == 0) { + if (feof(f)) { + break; + } else { + (void) fclose(f); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while reading %s", fn); + } + } + off += got; + } + + if (f) { + (void) fclose(f); + } + + return 1; +} + +static duk_ret_t fileio_write_file(duk_context *ctx) { + const char *fn; + const char *buf; + size_t len; + size_t off; + FILE *f; + + fn = duk_require_string(ctx, 0); + f = fopen(fn, "wb"); + if (!f) { + duk_error(ctx, DUK_ERR_TYPE_ERROR, "cannot open file %s for writing, errno %ld: %s", + fn, (long) errno, strerror(errno)); + } + + len = 0; + buf = (char *) duk_to_buffer(ctx, 1, &len); + for (off = 0; off < len;) { + size_t got; + got = fwrite((const void *) (buf + off), 1, len - off, f); + if (ferror(f)) { + (void) fclose(f); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while writing %s", fn); + } + if (got == 0) { + (void) fclose(f); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while writing %s", fn); + } + off += got; + } + + if (f) { + (void) fclose(f); + } + + return 0; +} +#endif /* DUK_CMDLINE_FILEIO */ + +/* + * Duktape heap lifecycle + */ + +#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT) +static duk_idx_t debugger_request(duk_context *ctx, void *udata, duk_idx_t nvalues) { + const char *cmd; + int i; + + (void) udata; + + if (nvalues < 1) { + duk_push_string(ctx, "missing AppRequest argument(s)"); + return -1; + } + + cmd = duk_get_string(ctx, -nvalues + 0); + + if (cmd && strcmp(cmd, "CommandLine") == 0) { + if (!duk_check_stack(ctx, main_argc)) { + /* Callback should avoid errors for now, so use + * duk_check_stack() rather than duk_require_stack(). + */ + duk_push_string(ctx, "failed to extend stack"); + return -1; + } + for (i = 0; i < main_argc; i++) { + duk_push_string(ctx, main_argv[i]); + } + return main_argc; + } + duk_push_sprintf(ctx, "command not supported"); + return -1; +} + +static void debugger_detached(void *udata) { + duk_context *ctx = (duk_context *) udata; + (void) ctx; + fprintf(stderr, "Debugger detached, udata: %p\n", (void *) udata); + fflush(stderr); + + /* Ensure socket is closed even when detach is initiated by Duktape + * rather than debug client. + */ + duk_trans_socket_finish(); + + if (debugger_reattach) { + /* For automatic reattach testing. */ + duk_trans_socket_init(); + duk_trans_socket_waitconn(); + fprintf(stderr, "Debugger reconnected, call duk_debugger_attach()\n"); + fflush(stderr); +#if 0 + /* This is not necessary but should be harmless. */ + duk_debugger_detach(ctx); +#endif + duk_debugger_attach_custom(ctx, + duk_trans_socket_read_cb, + duk_trans_socket_write_cb, + duk_trans_socket_peek_cb, + duk_trans_socket_read_flush_cb, + duk_trans_socket_write_flush_cb, + debugger_request, + debugger_detached, + (void *) ctx); + } +} +#endif + +#define ALLOC_DEFAULT 0 +#define ALLOC_LOGGING 1 +#define ALLOC_TORTURE 2 +#define ALLOC_HYBRID 3 +#define ALLOC_AJSHEAP 4 + +static duk_context *create_duktape_heap(int alloc_provider, int debugger, int ajsheap_log) { + duk_context *ctx; + + (void) ajsheap_log; /* suppress warning */ + + ctx = NULL; + if (!ctx && alloc_provider == ALLOC_LOGGING) { +#if defined(DUK_CMDLINE_ALLOC_LOGGING) + ctx = duk_create_heap(duk_alloc_logging, + duk_realloc_logging, + duk_free_logging, + (void *) 0xdeadbeef, + NULL); +#else + fprintf(stderr, "Warning: option --alloc-logging ignored, no logging allocator support\n"); + fflush(stderr); +#endif + } + if (!ctx && alloc_provider == ALLOC_TORTURE) { +#if defined(DUK_CMDLINE_ALLOC_TORTURE) + ctx = duk_create_heap(duk_alloc_torture, + duk_realloc_torture, + duk_free_torture, + (void *) 0xdeadbeef, + NULL); +#else + fprintf(stderr, "Warning: option --alloc-torture ignored, no torture allocator support\n"); + fflush(stderr); +#endif + } + if (!ctx && alloc_provider == ALLOC_HYBRID) { +#if defined(DUK_CMDLINE_ALLOC_HYBRID) + void *udata = duk_alloc_hybrid_init(); + if (!udata) { + fprintf(stderr, "Failed to init hybrid allocator\n"); + fflush(stderr); + } else { + ctx = duk_create_heap(duk_alloc_hybrid, + duk_realloc_hybrid, + duk_free_hybrid, + udata, + NULL); + } +#else + fprintf(stderr, "Warning: option --alloc-hybrid ignored, no hybrid allocator support\n"); + fflush(stderr); +#endif + } + if (!ctx && alloc_provider == ALLOC_AJSHEAP) { +#if defined(DUK_CMDLINE_AJSHEAP) + ajsheap_init(); + + ctx = duk_create_heap( + ajsheap_log ? ajsheap_alloc_wrapped : AJS_Alloc, + ajsheap_log ? ajsheap_realloc_wrapped : AJS_Realloc, + ajsheap_log ? ajsheap_free_wrapped : AJS_Free, + (void *) 0xdeadbeef, /* heap_udata: ignored by AjsHeap, use as marker */ + NULL + ); /* fatal_handler */ +#else + fprintf(stderr, "Warning: option --alloc-ajsheap ignored, no ajsheap allocator support\n"); + fflush(stderr); +#endif + } + if (!ctx && alloc_provider == ALLOC_DEFAULT) { + ctx = duk_create_heap_default(); + } + + if (!ctx) { + fprintf(stderr, "Failed to create Duktape heap\n"); + fflush(stderr); + exit(-1); + } + +#if defined(DUK_CMDLINE_AJSHEAP) + if (alloc_provider == ALLOC_AJSHEAP) { + fprintf(stdout, "Pool dump after heap creation\n"); + ajsheap_dump(); + } +#endif + +#if defined(DUK_CMDLINE_AJSHEAP) + if (alloc_provider == ALLOC_AJSHEAP) { + ajsheap_register(ctx); + } +#endif + +#if defined(DUK_CMDLINE_FILEIO) + duk_push_c_function(ctx, fileio_read_file, 1 /*nargs*/); + duk_put_global_string(ctx, "readFile"); + duk_push_c_function(ctx, fileio_write_file, 2 /*nargs*/); + duk_put_global_string(ctx, "writeFile"); +#endif + + if (debugger) { +#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT) + fprintf(stderr, "Debugger enabled, create socket and wait for connection\n"); + fflush(stderr); + duk_trans_socket_init(); + duk_trans_socket_waitconn(); + fprintf(stderr, "Debugger connected, call duk_debugger_attach() and then execute requested file(s)/eval\n"); + fflush(stderr); + duk_debugger_attach_custom(ctx, + duk_trans_socket_read_cb, + duk_trans_socket_write_cb, + duk_trans_socket_peek_cb, + duk_trans_socket_read_flush_cb, + duk_trans_socket_write_flush_cb, + debugger_request, + debugger_detached, + (void *) ctx); +#else + fprintf(stderr, "Warning: option --debugger ignored, no debugger support\n"); + fflush(stderr); +#endif + } + +#if 0 + /* Manual test for duk_debugger_cooperate() */ + { + for (i = 0; i < 60; i++) { + printf("cooperate: %d\n", i); + usleep(1000000); + duk_debugger_cooperate(ctx); + } + } +#endif + + return ctx; +} + +static void destroy_duktape_heap(duk_context *ctx, int alloc_provider) { + (void) alloc_provider; + +#if defined(DUK_CMDLINE_AJSHEAP) + if (alloc_provider == ALLOC_AJSHEAP) { + fprintf(stdout, "Pool dump before duk_destroy_heap(), before forced gc\n"); + ajsheap_dump(); + + duk_gc(ctx, 0); + + fprintf(stdout, "Pool dump before duk_destroy_heap(), after forced gc\n"); + ajsheap_dump(); + } +#endif + + if (ctx) { + duk_destroy_heap(ctx); + } + +#if defined(DUK_CMDLINE_AJSHEAP) + if (alloc_provider == ALLOC_AJSHEAP) { + fprintf(stdout, "Pool dump after duk_destroy_heap() (should have zero allocs)\n"); + ajsheap_dump(); + } + ajsheap_free(); +#endif +} + +/* + * Main + */ + +int main(int argc, char *argv[]) { + duk_context *ctx = NULL; + int retval = 0; + int have_files = 0; + int have_eval = 0; + int interactive = 0; + int memlimit_high = 1; + int alloc_provider = ALLOC_DEFAULT; + int ajsheap_log = 0; + int debugger = 0; + int recreate_heap = 0; + int no_heap_destroy = 0; + int verbose = 0; + int run_stdin = 0; + const char *compile_filename = NULL; + int i; + + main_argc = argc; + main_argv = (char **) argv; + +#if defined(EMSCRIPTEN) + /* Try to use NODEFS to provide access to local files. Mount the + * CWD as /working, and then prepend "/working/" to relative native + * paths in file calls to get something that works reasonably for + * relative paths. Emscripten doesn't support replacing virtual + * "/" with host "/" (the default MEMFS at "/" can't be unmounted) + * but we can mount "/tmp" as host "/tmp" to allow testcase runs. + * + * https://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.html#filesystem-api-nodefs + * https://github.com/kripken/emscripten/blob/master/tests/fs/test_nodefs_rw.c + */ + EM_ASM( + /* At the moment it's not possible to replace the default MEMFS mounted at '/': + * https://github.com/kripken/emscripten/issues/2040 + * https://github.com/kripken/emscripten/blob/incoming/src/library_fs.js#L1341-L1358 + */ + /* + try { + FS.unmount("/"); + } catch (e) { + console.log("Failed to unmount default '/' MEMFS mount: " + e); + } + */ + try { + FS.mkdir("/working"); + FS.mount(NODEFS, { root: "." }, "/working"); + } catch (e) { + console.log("Failed to mount NODEFS /working: " + e); + } + /* A virtual '/tmp' exists by default: + * https://gist.github.com/evanw/e6be28094f34451bd5bd#file-temp-js-L3806-L3809 + */ + /* + try { + FS.mkdir("/tmp"); + } catch (e) { + console.log("Failed to create virtual /tmp: " + e); + } + */ + try { + FS.mount(NODEFS, { root: "/tmp" }, "/tmp"); + } catch (e) { + console.log("Failed to mount NODEFS /tmp: " + e); + } + ); +#endif /* EMSCRIPTEN */ + +#if defined(DUK_CMDLINE_AJSHEAP) + alloc_provider = ALLOC_AJSHEAP; +#endif + (void) ajsheap_log; + + /* + * Signal handling setup + */ + +#if defined(DUK_CMDLINE_SIGNAL) + set_sigint_handler(); + + /* This is useful at the global level; libraries should avoid SIGPIPE though */ + /*signal(SIGPIPE, SIG_IGN);*/ +#endif + + /* + * Parse options + */ + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + if (!arg) { + goto usage; + } + if (strcmp(arg, "--restrict-memory") == 0) { + memlimit_high = 0; + } else if (strcmp(arg, "-i") == 0) { + interactive = 1; + } else if (strcmp(arg, "-c") == 0) { + if (i == argc - 1) { + goto usage; + } + i++; + compile_filename = argv[i]; + } else if (strcmp(arg, "-e") == 0) { + have_eval = 1; + if (i == argc - 1) { + goto usage; + } + i++; /* skip code */ + } else if (strcmp(arg, "--alloc-default") == 0) { + alloc_provider = ALLOC_DEFAULT; + } else if (strcmp(arg, "--alloc-logging") == 0) { + alloc_provider = ALLOC_LOGGING; + } else if (strcmp(arg, "--alloc-torture") == 0) { + alloc_provider = ALLOC_TORTURE; + } else if (strcmp(arg, "--alloc-hybrid") == 0) { + alloc_provider = ALLOC_HYBRID; + } else if (strcmp(arg, "--alloc-ajsheap") == 0) { + alloc_provider = ALLOC_AJSHEAP; + } else if (strcmp(arg, "--ajsheap-log") == 0) { + ajsheap_log = 1; + } else if (strcmp(arg, "--debugger") == 0) { + debugger = 1; +#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT) + } else if (strcmp(arg, "--reattach") == 0) { + debugger_reattach = 1; +#endif + } else if (strcmp(arg, "--recreate-heap") == 0) { + recreate_heap = 1; + } else if (strcmp(arg, "--no-heap-destroy") == 0) { + no_heap_destroy = 1; + } else if (strcmp(arg, "--verbose") == 0) { + verbose = 1; + } else if (strcmp(arg, "--run-stdin") == 0) { + run_stdin = 1; + } else if (strlen(arg) >= 1 && arg[0] == '-') { + goto usage; + } else { + have_files = 1; + } + } + if (!have_files && !have_eval && !run_stdin) { + interactive = 1; + } + + /* + * Memory limit + */ + +#if defined(DUK_CMDLINE_RLIMIT) + set_resource_limits(memlimit_high ? MEM_LIMIT_HIGH : MEM_LIMIT_NORMAL); +#else + if (memlimit_high == 0) { + fprintf(stderr, "Warning: option --restrict-memory ignored, no rlimit support\n"); + fflush(stderr); + } +#endif + + /* + * Create heap + */ + + ctx = create_duktape_heap(alloc_provider, debugger, ajsheap_log); + + /* + * Execute any argument file(s) + */ + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + if (!arg) { + continue; + } else if (strlen(arg) == 2 && strcmp(arg, "-e") == 0) { + /* Here we know the eval arg exists but check anyway */ + if (i == argc - 1) { + retval = 1; + goto cleanup; + } + if (handle_eval(ctx, argv[i + 1]) != 0) { + retval = 1; + goto cleanup; + } + i++; /* skip code */ + continue; + } else if (strlen(arg) == 2 && strcmp(arg, "-c") == 0) { + i++; /* skip filename */ + continue; + } else if (strlen(arg) >= 1 && arg[0] == '-') { + continue; + } + + if (verbose) { + fprintf(stderr, "*** Executing file: %s\n", arg); + fflush(stderr); + } + + if (handle_file(ctx, arg, compile_filename) != 0) { + retval = 1; + goto cleanup; + } + + if (recreate_heap) { + if (verbose) { + fprintf(stderr, "*** Recreating heap...\n"); + fflush(stderr); + } + + destroy_duktape_heap(ctx, alloc_provider); + ctx = create_duktape_heap(alloc_provider, debugger, ajsheap_log); + } + } + + if (run_stdin) { + /* Running stdin like a full file (reading all lines before + * compiling) is useful with emduk: + * cat test.js | ./emduk --run-stdin + */ + if (handle_fh(ctx, stdin, "stdin", compile_filename) != 0) { + retval = 1; + goto cleanup; + } + + if (recreate_heap) { + if (verbose) { + fprintf(stderr, "*** Recreating heap...\n"); + fflush(stderr); + } + + destroy_duktape_heap(ctx, alloc_provider); + ctx = create_duktape_heap(alloc_provider, debugger, ajsheap_log); + } + } + + /* + * Enter interactive mode if options indicate it + */ + + if (interactive) { + if (handle_interactive(ctx) != 0) { + retval = 1; + goto cleanup; + } + } + + /* + * Cleanup and exit + */ + + cleanup: + if (interactive) { + fprintf(stderr, "Cleaning up...\n"); + fflush(stderr); + } + + if (ctx && no_heap_destroy) { + duk_gc(ctx, 0); + } + if (ctx && !no_heap_destroy) { + destroy_duktape_heap(ctx, alloc_provider); + } + ctx = NULL; + + return retval; + + /* + * Usage + */ + + usage: + fprintf(stderr, "Usage: duk [options] [<filenames>]\n" + "\n" + " -i enter interactive mode after executing argument file(s) / eval code\n" + " -e CODE evaluate code\n" + " -c FILE compile into bytecode (use with only one file argument)\n" + " --run-stdin treat stdin like a file, i.e. compile full input (not line by line)\n" + " --verbose verbose messages to stderr\n" + " --restrict-memory use lower memory limit (used by test runner)\n" + " --alloc-default use Duktape default allocator\n" +#if defined(DUK_CMDLINE_ALLOC_LOGGING) + " --alloc-logging use logging allocator (writes to /tmp)\n" +#endif +#if defined(DUK_CMDLINE_ALLOC_TORTURE) + " --alloc-torture use torture allocator\n" +#endif +#if defined(DUK_CMDLINE_ALLOC_HYBRID) + " --alloc-hybrid use hybrid allocator\n" +#endif +#if defined(DUK_CMDLINE_AJSHEAP) + " --alloc-ajsheap use ajsheap allocator (enabled by default with 'ajduk')\n" + " --ajsheap-log write alloc log to /tmp/ajduk-alloc-log.txt\n" +#endif +#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT) + " --debugger start example debugger\n" + " --reattach automatically reattach debugger on detach\n" +#endif + " --recreate-heap recreate heap after every file\n" + " --no-heap-destroy force GC, but don't destroy heap at end (leak testing)\n" + "\n" + "If <filename> is omitted, interactive mode is started automatically.\n"); + fflush(stderr); + exit(1); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline_ajduk.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline_ajduk.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline_ajduk.c new file mode 100644 index 0000000..ae28ede --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline_ajduk.c @@ -0,0 +1,1008 @@ +/* + * 'ajduk' specific functionality, examples for low memory techniques + */ + +#ifdef DUK_CMDLINE_AJSHEAP + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ajs.h" +#include "ajs_heap.h" +#include "duktape.h" + +extern uint8_t dbgHEAPDUMP; + +#if defined(DUK_USE_ROM_OBJECTS) && defined(DUK_USE_HEAPPTR16) +/* Pointer compression with ROM strings/objects: + * + * For now, use DUK_USE_ROM_OBJECTS to signal the need for compressed ROM + * pointers. DUK_USE_ROM_PTRCOMP_FIRST is provided for the ROM pointer + * compression range minimum to avoid duplication in user code. + */ +#if 0 /* This extern declaration is provided by duktape.h, array provided by duktape.c. */ +extern const void * const duk_rom_compressed_pointers[]; +#endif +static const void *duk__romptr_low = NULL; +static const void *duk__romptr_high = NULL; +#define DUK__ROMPTR_COMPRESSION +#define DUK__ROMPTR_FIRST DUK_USE_ROM_PTRCOMP_FIRST +#endif + +/* + * Helpers + */ + +static void *ajduk__lose_const(const void *ptr) { + /* Somewhat portable way of losing a const without warnings. + * Another approach is to cast through intptr_t, but that + * type is not always available. + */ + union { + const void *p; + void *q; + } u; + u.p = ptr; + return u.q; +} + +static void safe_print_chars(const char *p, duk_size_t len, int until_nul) { + duk_size_t i; + + printf("\""); + for (i = 0; i < len; i++) { + unsigned char x = (unsigned char) p[i]; + if (until_nul && x == 0U) { + break; + } + if (x < 0x20 || x >= 0x7e || x == '"' || x == '\'' || x == '\\') { + printf("\\x%02x", (int) x); + } else { + printf("%c", (char) x); + } + } + printf("\""); +} + +/* + * Heap initialization when using AllJoyn.js pool allocator (without any + * other AllJoyn.js integration). This serves as an example of how to + * integrate Duktape with a pool allocator and is useful for low memory + * testing. + * + * The pool sizes are not optimized here. The sizes are chosen so that + * you can look at the high water mark (hwm) and use counts (use) and see + * how much allocations are needed for each pool size. To optimize pool + * sizes more accurately, you can use --alloc-logging and inspect the memory + * allocation log which provides exact byte counts etc. + * + * https://git.allseenalliance.org/cgit/core/alljoyn-js.git + * https://git.allseenalliance.org/cgit/core/alljoyn-js.git/tree/ajs.c + */ + +static const AJS_HeapConfig ajsheap_config[] = { + { 8, 10, AJS_POOL_BORROW, 0 }, + { 12, 600, AJS_POOL_BORROW, 0 }, + { 16, 300, AJS_POOL_BORROW, 0 }, + { 20, 300, AJS_POOL_BORROW, 0 }, + { 24, 300, AJS_POOL_BORROW, 0 }, + { 28, 150, AJS_POOL_BORROW, 0 }, + { 32, 150, AJS_POOL_BORROW, 0 }, + { 40, 150, AJS_POOL_BORROW, 0 }, + { 48, 50, AJS_POOL_BORROW, 0 }, + { 52, 50, AJS_POOL_BORROW, 0 }, + { 56, 50, AJS_POOL_BORROW, 0 }, + { 60, 50, AJS_POOL_BORROW, 0 }, + { 64, 50, AJS_POOL_BORROW, 0 }, + { 128, 80, AJS_POOL_BORROW, 0 }, + { 256, 16, AJS_POOL_BORROW, 0 }, + { 320, 1, AJS_POOL_BORROW, 0 }, + { 392, 1, AJS_POOL_BORROW, 0 }, /* duk_hthread, with heap ptr compression, ROM strings+objects */ + { 512, 16, AJS_POOL_BORROW, 0 }, + { 964, 1, AJS_POOL_BORROW, 0 }, /* duk_heap, with heap ptr compression, ROM strings+objects */ + { 1024, 6, AJS_POOL_BORROW, 0 }, + { 1344, 1, AJS_POOL_BORROW, 0 }, /* duk_heap, with heap ptr compression, RAM strings+objects */ + { 2048, 5, AJS_POOL_BORROW, 0 }, + { 4096, 3, 0, 0 }, + { 8192, 3, 0, 0 }, + { 16384, 1, 0, 0 }, + { 32768, 1, 0, 0 } +}; + +uint8_t *ajsheap_ram = NULL; + +void ajsheap_init(void) { + size_t heap_sz[1]; + uint8_t *heap_array[1]; + uint8_t num_pools, i; + AJ_Status ret; + + num_pools = (uint8_t) (sizeof(ajsheap_config) / sizeof(AJS_HeapConfig)); + heap_sz[0] = AJS_HeapRequired(ajsheap_config, /* heapConfig */ + num_pools, /* numPools */ + 0); /* heapNum */ + ajsheap_ram = (uint8_t *) malloc(heap_sz[0]); + if (ajsheap_ram == NULL) { + fprintf(stderr, "Failed to allocate AJS heap\n"); + fflush(stderr); + exit(1); + } + heap_array[0] = ajsheap_ram; + + fprintf(stderr, "Allocated AJS heap of %ld bytes, pools:", (long) heap_sz[0]); + for (i = 0; i < num_pools; i++) { + fprintf(stderr, " (sz:%ld,num:%ld,brw:%ld,idx:%ld)", + (long) ajsheap_config[i].size, (long) ajsheap_config[i].entries, + (long) ajsheap_config[i].borrow, (long) ajsheap_config[i].heapIndex); + } + fprintf(stderr, "\n"); + fflush(stderr); + + ret = AJS_HeapInit((void **) heap_array, /* heap */ + (size_t *) heap_sz, /* heapSz */ + ajsheap_config, /* heapConfig */ + num_pools, /* numPools */ + 1); /* numHeaps */ + fprintf(stderr, "AJS_HeapInit() -> %ld\n", (long) ret); + fflush(stderr); + + /* Enable heap dumps */ + dbgHEAPDUMP = 1; + +#if defined(DUK__ROMPTR_COMPRESSION) + /* Scan ROM pointer range for faster detection of "is 'p' a ROM pointer" + * later on. + */ + if (1) { + const void * const * ptrs = (const void * const *) duk_rom_compressed_pointers; + duk__romptr_low = duk__romptr_high = (const void *) *ptrs; + while (*ptrs) { + if (*ptrs > duk__romptr_high) { + duk__romptr_high = (const void *) *ptrs; + } + if (*ptrs < duk__romptr_low) { + duk__romptr_low = (const void *) *ptrs; + } + ptrs++; + } + fprintf(stderr, "romptrs: low=%p high=%p\n", + (const void *) duk__romptr_low, (const void *) duk__romptr_high); + fflush(stderr); + } +#endif +} + +void ajsheap_free(void) { + if (ajsheap_ram != NULL) { + free(ajsheap_ram); + ajsheap_ram = NULL; + } +} + +/* AjsHeap.dump(), allows Ecmascript code to dump heap status at suitable + * points. + */ +duk_ret_t ajsheap_dump_binding(duk_context *ctx) { + AJS_HeapDump(); + fflush(stdout); + return 0; +} + +void ajsheap_dump(void) { + AJS_HeapDump(); + fflush(stdout); +} + +void ajsheap_register(duk_context *ctx) { + duk_push_object(ctx); + duk_push_c_function(ctx, ajsheap_dump_binding, 0); + duk_put_prop_string(ctx, -2, "dump"); + duk_put_global_string(ctx, "AjsHeap"); +} + +/* + * Wrapped ajs_heap.c alloc functions + * + * Used to write an alloc log. + */ + +static FILE *ajsheap_alloc_log = NULL; + +static void ajsheap_write_alloc_log(const char *fmt, ...) { + va_list ap; + char buf[256]; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + buf[sizeof(buf) - 1] = (char) 0; + va_end(ap); + + if (ajsheap_alloc_log == NULL) { + ajsheap_alloc_log = fopen("/tmp/ajduk-alloc-log.txt", "wb"); + if (ajsheap_alloc_log == NULL) { + fprintf(stderr, "WARNING: failed to write alloc log, ignoring\n"); + fflush(stderr); + return; + } + } + + (void) fwrite((const void *) buf, 1, strlen(buf), ajsheap_alloc_log); + (void) fflush(ajsheap_alloc_log); +} + +void *ajsheap_alloc_wrapped(void *udata, duk_size_t size) { + void *ret = AJS_Alloc(udata, size); + if (size > 0 && ret == NULL) { + ajsheap_write_alloc_log("A FAIL %ld\n", (long) size); + } else if (ret == NULL) { + ajsheap_write_alloc_log("A NULL %ld\n", (long) size); + } else { + ajsheap_write_alloc_log("A %p %ld\n", ret, (long) size); + } + return ret; +} + +void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size) { + void *ret = AJS_Realloc(udata, ptr, size); + if (size > 0 && ret == NULL) { + if (ptr == NULL) { + ajsheap_write_alloc_log("R NULL -1 FAIL %ld\n", (long) size); + } else { + ajsheap_write_alloc_log("R %p -1 FAIL %ld\n", ptr, (long) size); + } + } else if (ret == NULL) { + if (ptr == NULL) { + ajsheap_write_alloc_log("R NULL -1 NULL %ld\n", (long) size); + } else { + ajsheap_write_alloc_log("R %p -1 NULL %ld\n", ptr, (long) size); + } + } else { + if (ptr == NULL) { + ajsheap_write_alloc_log("R NULL -1 %p %ld\n", ret, (long) size); + } else { + ajsheap_write_alloc_log("R %p -1 %p %ld\n", ptr, ret, (long) size); + } + } + return ret; +} + +void ajsheap_free_wrapped(void *udata, void *ptr) { + AJS_Free(udata, ptr); + if (ptr == NULL) { + } else { + ajsheap_write_alloc_log("F %p -1\n", ptr); + } +} + +/* + * Example pointer compression functions. + * + * 'base' is chosen so that no non-NULL pointer results in a zero result + * which is reserved for NULL pointers. + */ + +duk_uint16_t ajsheap_enc16(void *ud, void *p) { + duk_uint32_t ret; + char *base = (char *) ajsheap_ram - 4; + +#if defined(DUK__ROMPTR_COMPRESSION) + if (p >= duk__romptr_low && p <= duk__romptr_high) { + /* The if-condition should be the fastest possible check + * for "is 'p' in ROM?". If pointer is in ROM, we'd like + * to compress it quickly. Here we just scan a ~1K array + * which is very bad for performance and for illustration + * only. + */ + const void * const * ptrs = duk_rom_compressed_pointers; + while (*ptrs) { + if (*ptrs == p) { + ret = DUK__ROMPTR_FIRST + (ptrs - duk_rom_compressed_pointers); +#if 0 + fprintf(stderr, "ajsheap_enc16: rom pointer: %p -> 0x%04lx\n", (void *) p, (long) ret); + fflush(stderr); +#endif + return (duk_uint16_t) ret; + } + ptrs++; + } + + /* We should really never be here: Duktape should only be + * compressing pointers which are in the ROM compressed + * pointers list, which are known at 'make dist' time. + * We go on, causing a pointer compression error. + */ + fprintf(stderr, "ajsheap_enc16: rom pointer: %p could not be compressed, should never happen\n", (void *) p); + fflush(stderr); + } +#endif + + /* Userdata is not needed in this case but would be useful if heap + * pointer compression were used for multiple heaps. The userdata + * allows the callback to distinguish between heaps and their base + * pointers. + * + * If not needed, the userdata can be left out during compilation + * by simply ignoring the userdata argument of the pointer encode + * and decode macros. It is kept here so that any bugs in actually + * providing the value inside Duktape are revealed during compilation. + */ + (void) ud; +#if 1 + /* Ensure that we always get the heap_udata given in heap creation. + * (Useful for Duktape development, not needed for user programs.) + */ + if (ud != (void *) 0xdeadbeef) { + fprintf(stderr, "invalid udata for ajsheap_enc16: %p\n", ud); + fflush(stderr); + } +#endif + + if (p == NULL) { + ret = 0; + } else { + ret = (duk_uint32_t) (((char *) p - base) >> 2); + } +#if 0 + printf("ajsheap_enc16: %p -> %u\n", p, (unsigned int) ret); +#endif + if (ret > 0xffffUL) { + fprintf(stderr, "Failed to compress pointer: %p (ret was %ld)\n", (void *) p, (long) ret); + fflush(stderr); + abort(); + } +#if defined(DUK__ROMPTR_COMPRESSION) + if (ret >= DUK__ROMPTR_FIRST) { + fprintf(stderr, "Failed to compress pointer, in 16-bit range but matches romptr range: %p (ret was %ld)\n", (void *) p, (long) ret); + fflush(stderr); + abort(); + } +#endif + return (duk_uint16_t) ret; +} + +void *ajsheap_dec16(void *ud, duk_uint16_t x) { + void *ret; + char *base = (char *) ajsheap_ram - 4; + +#if defined(DUK__ROMPTR_COMPRESSION) + if (x >= DUK__ROMPTR_FIRST) { + /* This is a blind lookup, could check index validity. + * Duktape should never decompress a pointer which would + * be out-of-bounds here. + */ + ret = (void *) ajduk__lose_const(duk_rom_compressed_pointers[x - DUK__ROMPTR_FIRST]); +#if 0 + fprintf(stderr, "ajsheap_dec16: rom pointer: 0x%04lx -> %p\n", (long) x, ret); + fflush(stderr); +#endif + return ret; + } +#endif + + /* See userdata discussion in ajsheap_enc16(). */ + (void) ud; +#if 1 + /* Ensure that we always get the heap_udata given in heap creation. */ + if (ud != (void *) 0xdeadbeef) { + fprintf(stderr, "invalid udata for ajsheap_dec16: %p\n", ud); + fflush(stderr); + } +#endif + + if (x == 0) { + ret = NULL; + } else { + ret = (void *) (base + (((duk_uint32_t) x) << 2)); + } +#if 0 + printf("ajsheap_dec16: %u -> %p\n", (unsigned int) x, ret); +#endif + return ret; +} + +/* + * Simplified example of an external strings strategy where incoming strings + * are written sequentially into a fixed, memory mapped flash area. + * + * The example first scans if the string is already in the flash (which may + * happen if the same string is interned multiple times), then adds it to + * flash if there is space. + * + * This example is too slow to be used in a real world application: there + * should be e.g. a hash table to quickly check for strings that are already + * present in the string data (similarly to how string interning works in + * Duktape itself). + */ + +static uint8_t ajsheap_strdata[65536]; +static size_t ajsheap_strdata_used = 0; + +const void *ajsheap_extstr_check_1(const void *ptr, duk_size_t len) { + uint8_t *p, *p_end; + uint8_t initial; + uint8_t *ret; + size_t left; + + (void) safe_print_chars; /* potentially unused */ + + if (len <= 3) { + /* It's not worth it to make very small strings external, as + * they would take the same space anyway. Also avoids zero + * length degenerate case. + */ + return NULL; + } + + /* + * Check if we already have the string. Be careful to compare for + * NUL terminator too, it is NOT present in 'ptr'. This algorithm + * is too simplistic and way too slow for actual use. + */ + + initial = ((const uint8_t *) ptr)[0]; + for (p = ajsheap_strdata, p_end = p + ajsheap_strdata_used; p != p_end; p++) { + if (*p != initial) { + continue; + } + left = (size_t) (p_end - p); + if (left >= len + 1 && + memcmp(p, ptr, len) == 0 && + p[len] == 0) { + ret = p; +#if 0 + printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", + (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> existing %p (used=%ld)\n", + (void *) ret, (long) ajsheap_strdata_used); +#endif + return ret; + } + } + + /* + * Not present yet, check if we have space. Again, be careful to + * ensure there is space for a NUL following the input data. + */ + + if (ajsheap_strdata_used + len + 1 > sizeof(ajsheap_strdata)) { +#if 0 + printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> no space (used=%ld)\n", (long) ajsheap_strdata_used); +#endif + return NULL; + } + + /* + * There is space, add the string to our collection, being careful + * to append the NUL. + */ + + ret = ajsheap_strdata + ajsheap_strdata_used; + memcpy(ret, ptr, len); + ret[len] = (uint8_t) 0; + ajsheap_strdata_used += len + 1; + +#if 0 + printf("ajsheap_extstr_check_1: ptr=%p, len=%ld -> ", (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> %p (used=%ld)\n", (void *) ret, (long) ajsheap_strdata_used); +#endif + return (const void *) ret; +} + +void ajsheap_extstr_free_1(const void *ptr) { + (void) ptr; +#if 0 + printf("ajsheap_extstr_free_1: freeing extstr %p -> ", ptr); + safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/); + printf("\n"); +#endif +} + +/* + * Simplified example of an external strings strategy where a set of strings + * is gathered during application compile time and baked into the application + * binary. + * + * Duktape built-in strings are available from duk_build_meta.json, see + * util/duk_meta_to_strarray.py. There may also be a lot of application + * specific strings, e.g. those used by application specific APIs. These + * must be gathered through some other means, see e.g. util/scan_strings.py. + */ + +static const char *strdata_duk_builtin_strings[] = { + /* + * These strings are from util/duk_meta_to_strarray.py + */ + + "Logger", + "Thread", + "Pointer", + "Buffer", + "DecEnv", + "ObjEnv", + "", + "global", + "Arguments", + "JSON", + "Math", + "Error", + "RegExp", + "Date", + "Number", + "Boolean", + "String", + "Array", + "Function", + "Object", + "Null", + "Undefined", + "{_func:true}", + "{\x22" "_func\x22" ":true}", + "{\x22" "_ninf\x22" ":true}", + "{\x22" "_inf\x22" ":true}", + "{\x22" "_nan\x22" ":true}", + "{\x22" "_undef\x22" ":true}", + "toLogString", + "clog", + "l", + "n", + "fatal", + "error", + "warn", + "debug", + "trace", + "raw", + "fmt", + "current", + "resume", + "compact", + "jc", + "jx", + "base64", + "hex", + "dec", + "enc", + "fin", + "gc", + "act", + "info", + "version", + "env", + "modLoaded", + "modSearch", + "errThrow", + "errCreate", + "compile", + "\xff" "Regbase", + "\xff" "Thread", + "\xff" "Handler", + "\xff" "Finalizer", + "\xff" "Callee", + "\xff" "Map", + "\xff" "Args", + "\xff" "This", + "\xff" "Pc2line", + "\xff" "Source", + "\xff" "Varenv", + "\xff" "Lexenv", + "\xff" "Varmap", + "\xff" "Formals", + "\xff" "Bytecode", + "\xff" "Next", + "\xff" "Target", + "\xff" "Value", + "pointer", + "buffer", + "\xff" "Tracedata", + "lineNumber", + "fileName", + "pc", + "stack", + "ThrowTypeError", + "Duktape", + "id", + "require", + "__proto__", + "setPrototypeOf", + "ownKeys", + "enumerate", + "deleteProperty", + "has", + "Proxy", + "callee", + "Invalid Date", + "[...]", + "\x0a" "\x09", + " ", + ",", + "-0", + "+0", + "0", + "-Infinity", + "+Infinity", + "Infinity", + "object", + "string", + "number", + "boolean", + "undefined", + "stringify", + "tan", + "sqrt", + "sin", + "round", + "random", + "pow", + "min", + "max", + "log", + "floor", + "exp", + "cos", + "ceil", + "atan2", + "atan", + "asin", + "acos", + "abs", + "SQRT2", + "SQRT1_2", + "PI", + "LOG10E", + "LOG2E", + "LN2", + "LN10", + "E", + "message", + "name", + "input", + "index", + "(?:)", + "lastIndex", + "multiline", + "ignoreCase", + "source", + "test", + "exec", + "toGMTString", + "setYear", + "getYear", + "toJSON", + "toISOString", + "toUTCString", + "setUTCFullYear", + "setFullYear", + "setUTCMonth", + "setMonth", + "setUTCDate", + "setDate", + "setUTCHours", + "setHours", + "setUTCMinutes", + "setMinutes", + "setUTCSeconds", + "setSeconds", + "setUTCMilliseconds", + "setMilliseconds", + "setTime", + "getTimezoneOffset", + "getUTCMilliseconds", + "getMilliseconds", + "getUTCSeconds", + "getSeconds", + "getUTCMinutes", + "getMinutes", + "getUTCHours", + "getHours", + "getUTCDay", + "getDay", + "getUTCDate", + "getDate", + "getUTCMonth", + "getMonth", + "getUTCFullYear", + "getFullYear", + "getTime", + "toLocaleTimeString", + "toLocaleDateString", + "toTimeString", + "toDateString", + "now", + "UTC", + "parse", + "toPrecision", + "toExponential", + "toFixed", + "POSITIVE_INFINITY", + "NEGATIVE_INFINITY", + "NaN", + "MIN_VALUE", + "MAX_VALUE", + "substr", + "trim", + "toLocaleUpperCase", + "toUpperCase", + "toLocaleLowerCase", + "toLowerCase", + "substring", + "split", + "search", + "replace", + "match", + "localeCompare", + "charCodeAt", + "charAt", + "fromCharCode", + "reduceRight", + "reduce", + "filter", + "map", + "forEach", + "some", + "every", + "lastIndexOf", + "indexOf", + "unshift", + "splice", + "sort", + "slice", + "shift", + "reverse", + "push", + "pop", + "join", + "concat", + "isArray", + "arguments", + "caller", + "bind", + "call", + "apply", + "propertyIsEnumerable", + "isPrototypeOf", + "hasOwnProperty", + "valueOf", + "toLocaleString", + "toString", + "constructor", + "set", + "get", + "enumerable", + "configurable", + "writable", + "value", + "keys", + "isExtensible", + "isFrozen", + "isSealed", + "preventExtensions", + "freeze", + "seal", + "defineProperties", + "defineProperty", + "create", + "getOwnPropertyNames", + "getOwnPropertyDescriptor", + "getPrototypeOf", + "prototype", + "length", + "alert", + "print", + "unescape", + "escape", + "encodeURIComponent", + "encodeURI", + "decodeURIComponent", + "decodeURI", + "isFinite", + "isNaN", + "parseFloat", + "parseInt", + "eval", + "URIError", + "TypeError", + "SyntaxError", + "ReferenceError", + "RangeError", + "EvalError", + "break", + "case", + "catch", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "finally", + "for", + "function", + "if", + "in", + "instanceof", + "new", + "return", + "switch", + "this", + "throw", + "try", + "typeof", + "var", + "void", + "while", + "with", + "class", + "const", + "enum", + "export", + "extends", + "import", + "super", + "null", + "true", + "false", + "implements", + "interface", + "let", + "package", + "private", + "protected", + "public", + "static", + "yield", + + /* + * These strings are manually added, and would be gathered in some + * application specific manner. + */ + + "foo", + "bar", + "quux", + "enableFrob", + "disableFrob" + /* ... */ +}; + +const void *ajsheap_extstr_check_2(const void *ptr, duk_size_t len) { + int i, n; + + (void) safe_print_chars; /* potentially unused */ + + /* Linear scan. An actual implementation would need some acceleration + * structure, e.g. select a sublist based on first character. + * + * NOTE: input string (behind 'ptr' with 'len' bytes) DOES NOT have a + * trailing NUL character. Any strings returned from this function + * MUST have a trailing NUL character. + */ + + n = (int) (sizeof(strdata_duk_builtin_strings) / sizeof(const char *)); + for (i = 0; i < n; i++) { + const char *str; + + str = strdata_duk_builtin_strings[i]; + if (strlen(str) == len && memcmp(ptr, (const void *) str, len) == 0) { +#if 0 + printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ", + (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> constant string index %ld\n", (long) i); +#endif + return (void *) ajduk__lose_const(strdata_duk_builtin_strings[i]); + } + } + +#if 0 + printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ", + (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> not found\n"); +#endif + return NULL; +} + +void ajsheap_extstr_free_2(const void *ptr) { + (void) ptr; +#if 0 + printf("ajsheap_extstr_free_2: freeing extstr %p -> ", ptr); + safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/); + printf("\n"); +#endif +} + +/* + * External strings strategy intended for valgrind testing: external strings + * are allocated using malloc()/free() so that valgrind can be used to ensure + * that strings are e.g. freed exactly once. + */ + +const void *ajsheap_extstr_check_3(const void *ptr, duk_size_t len) { + duk_uint8_t *ret; + + (void) safe_print_chars; /* potentially unused */ + + ret = malloc((size_t) len + 1); + if (ret == NULL) { +#if 0 + printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ", + (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> malloc failed, return NULL\n"); +#endif + return (const void *) NULL; + } + + if (len > 0) { + memcpy((void *) ret, ptr, (size_t) len); + } + ret[len] = (duk_uint8_t) 0; + +#if 0 + printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ", + (void *) ptr, (long) len); + safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); + printf(" -> %p\n", (void *) ret); +#endif + return (const void *) ret; +} + +void ajsheap_extstr_free_3(const void *ptr) { + (void) ptr; +#if 0 + printf("ajsheap_extstr_free_3: freeing extstr %p -> ", ptr); + safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/); + printf("\n"); +#endif + free((void *) ajduk__lose_const(ptr)); +} + +/* + * Execution timeout example + */ + +#define AJSHEAP_EXEC_TIMEOUT 5 /* seconds */ + +static time_t curr_pcall_start = 0; +static long exec_timeout_check_counter = 0; + +void ajsheap_start_exec_timeout(void) { + curr_pcall_start = time(NULL); +} + +void ajsheap_clear_exec_timeout(void) { + curr_pcall_start = 0; +} + +duk_bool_t ajsheap_exec_timeout_check(void *udata) { + time_t now = time(NULL); + time_t diff = now - curr_pcall_start; + + (void) udata; /* not needed */ + + exec_timeout_check_counter++; +#if 0 + printf("exec timeout check %ld: now=%ld, start=%ld, diff=%ld\n", + (long) exec_timeout_check_counter, (long) now, (long) curr_pcall_start, (long) diff); + fflush(stdout); +#endif + + if (curr_pcall_start == 0) { + /* protected call not yet running */ + return 0; + } + if (diff > AJSHEAP_EXEC_TIMEOUT) { + return 1; + } + return 0; +} + +#else /* DUK_CMDLINE_AJSHEAP */ + +int ajs_dummy = 0; /* to avoid empty source file */ + +#endif /* DUK_CMDLINE_AJSHEAP */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/README.rst b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/README.rst new file mode 100644 index 0000000..98b53d2 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/README.rst @@ -0,0 +1,8 @@ +Codepage conversion example +=========================== + +Example of how to convert an 8-bit input string (e.g. ISO-8859-1 or Windows +codepage 1252) into CESU-8 without using an external library like iconv. + +This is useful e.g. when compiling non-UTF-8 source code which cannot be +converted to UTF-8 (CESU-8) at build time. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.c new file mode 100644 index 0000000..932e9a6 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.c @@ -0,0 +1,54 @@ +/* + * Convert an 8-bit input string (e.g. ISO-8859-1) into CESU-8. + * Calling code supplies the "code page" as a 256-entry array of + * codepoints for the conversion. + * + * This is useful when input data is in non-UTF-8 format and must + * be converted at runtime, e.g. when compiling non-UTF-8 source + * code. Another alternative is to use e.g. iconv. + */ + +#include "duktape.h" + +/* Decode an 8-bit string using 'codepage' into Unicode codepoints and + * re-encode into CESU-8. Codepage argument must point to a 256-entry + * table. Only supports BMP (codepoints U+0000 to U+FFFF). + */ +void duk_decode_string_codepage(duk_context *ctx, const char *str, size_t len, unsigned int *codepage) { + unsigned char *tmp; + size_t tmplen, i; + unsigned char *p; + unsigned int cp; + + tmplen = 3 * len; /* max expansion is 1 input byte -> 3 output bytes */ + if (tmplen / 3 != len) { + /* Temporary buffer length wraps. */ + duk_error(ctx, DUK_ERR_RANGE_ERROR, "input string too long"); + return; + } + + tmp = (unsigned char *) duk_push_fixed_buffer(ctx, tmplen); + + for (i = 0, p = tmp; i < len; i++) { + cp = codepage[((unsigned char *) str)[i]] & 0xffffUL; + if (cp < 0x80UL) { + *p++ = (unsigned char) cp; + } else if (cp < 0x800UL) { + *p++ = (unsigned char) (0xc0 + ((cp >> 6) & 0x1f)); + *p++ = (unsigned char) (0x80 + (cp & 0x3f)); + } else { + /* In CESU-8 all codepoints in [0x0000,0xFFFF] are + * allowed, including surrogates. + */ + *p++ = (unsigned char) (0xe0 + ((cp >> 12) & 0x0f)); + *p++ = (unsigned char) (0x80 + ((cp >> 6) & 0x3f)); + *p++ = (unsigned char) (0x80 + (cp & 0x3f)); + } + } + + duk_push_lstring(ctx, (const char *) tmp, (duk_size_t) (p - tmp)); + + /* [ ... tmp res ] */ + + duk_remove(ctx, -2); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.h ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.h b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.h new file mode 100644 index 0000000..d2705a0 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.h @@ -0,0 +1,8 @@ +#ifndef DUK_CODEPAGE_CONV_H_INCLUDED +#define DUK_CODEPAGE_CONV_H_INCLUDED + +#include "duktape.h" + +void duk_decode_string_codepage(duk_context *ctx, const char *str, size_t len, unsigned int *codepage); + +#endif /* DUK_CODEPAGE_CONV_H_INCLUDED */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/test.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/test.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/test.c new file mode 100644 index 0000000..c34299a --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/codepage-conv/test.c @@ -0,0 +1,286 @@ +#include "duktape.h" +#include "duk_codepage_conv.h" + +/* http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT */ +unsigned int cp1252[256] = { + (unsigned int) 0x0000, + (unsigned int) 0x0001, + (unsigned int) 0x0002, + (unsigned int) 0x0003, + (unsigned int) 0x0004, + (unsigned int) 0x0005, + (unsigned int) 0x0006, + (unsigned int) 0x0007, + (unsigned int) 0x0008, + (unsigned int) 0x0009, + (unsigned int) 0x000A, + (unsigned int) 0x000B, + (unsigned int) 0x000C, + (unsigned int) 0x000D, + (unsigned int) 0x000E, + (unsigned int) 0x000F, + (unsigned int) 0x0010, + (unsigned int) 0x0011, + (unsigned int) 0x0012, + (unsigned int) 0x0013, + (unsigned int) 0x0014, + (unsigned int) 0x0015, + (unsigned int) 0x0016, + (unsigned int) 0x0017, + (unsigned int) 0x0018, + (unsigned int) 0x0019, + (unsigned int) 0x001A, + (unsigned int) 0x001B, + (unsigned int) 0x001C, + (unsigned int) 0x001D, + (unsigned int) 0x001E, + (unsigned int) 0x001F, + (unsigned int) 0x0020, + (unsigned int) 0x0021, + (unsigned int) 0x0022, + (unsigned int) 0x0023, + (unsigned int) 0x0024, + (unsigned int) 0x0025, + (unsigned int) 0x0026, + (unsigned int) 0x0027, + (unsigned int) 0x0028, + (unsigned int) 0x0029, + (unsigned int) 0x002A, + (unsigned int) 0x002B, + (unsigned int) 0x002C, + (unsigned int) 0x002D, + (unsigned int) 0x002E, + (unsigned int) 0x002F, + (unsigned int) 0x0030, + (unsigned int) 0x0031, + (unsigned int) 0x0032, + (unsigned int) 0x0033, + (unsigned int) 0x0034, + (unsigned int) 0x0035, + (unsigned int) 0x0036, + (unsigned int) 0x0037, + (unsigned int) 0x0038, + (unsigned int) 0x0039, + (unsigned int) 0x003A, + (unsigned int) 0x003B, + (unsigned int) 0x003C, + (unsigned int) 0x003D, + (unsigned int) 0x003E, + (unsigned int) 0x003F, + (unsigned int) 0x0040, + (unsigned int) 0x0041, + (unsigned int) 0x0042, + (unsigned int) 0x0043, + (unsigned int) 0x0044, + (unsigned int) 0x0045, + (unsigned int) 0x0046, + (unsigned int) 0x0047, + (unsigned int) 0x0048, + (unsigned int) 0x0049, + (unsigned int) 0x004A, + (unsigned int) 0x004B, + (unsigned int) 0x004C, + (unsigned int) 0x004D, + (unsigned int) 0x004E, + (unsigned int) 0x004F, + (unsigned int) 0x0050, + (unsigned int) 0x0051, + (unsigned int) 0x0052, + (unsigned int) 0x0053, + (unsigned int) 0x0054, + (unsigned int) 0x0055, + (unsigned int) 0x0056, + (unsigned int) 0x0057, + (unsigned int) 0x0058, + (unsigned int) 0x0059, + (unsigned int) 0x005A, + (unsigned int) 0x005B, + (unsigned int) 0x005C, + (unsigned int) 0x005D, + (unsigned int) 0x005E, + (unsigned int) 0x005F, + (unsigned int) 0x0060, + (unsigned int) 0x0061, + (unsigned int) 0x0062, + (unsigned int) 0x0063, + (unsigned int) 0x0064, + (unsigned int) 0x0065, + (unsigned int) 0x0066, + (unsigned int) 0x0067, + (unsigned int) 0x0068, + (unsigned int) 0x0069, + (unsigned int) 0x006A, + (unsigned int) 0x006B, + (unsigned int) 0x006C, + (unsigned int) 0x006D, + (unsigned int) 0x006E, + (unsigned int) 0x006F, + (unsigned int) 0x0070, + (unsigned int) 0x0071, + (unsigned int) 0x0072, + (unsigned int) 0x0073, + (unsigned int) 0x0074, + (unsigned int) 0x0075, + (unsigned int) 0x0076, + (unsigned int) 0x0077, + (unsigned int) 0x0078, + (unsigned int) 0x0079, + (unsigned int) 0x007A, + (unsigned int) 0x007B, + (unsigned int) 0x007C, + (unsigned int) 0x007D, + (unsigned int) 0x007E, + (unsigned int) 0x007F, + (unsigned int) 0x20AC, + (unsigned int) 0xFFFD, /* undefined */ + (unsigned int) 0x201A, + (unsigned int) 0x0192, + (unsigned int) 0x201E, + (unsigned int) 0x2026, + (unsigned int) 0x2020, + (unsigned int) 0x2021, + (unsigned int) 0x02C6, + (unsigned int) 0x2030, + (unsigned int) 0x0160, + (unsigned int) 0x2039, + (unsigned int) 0x0152, + (unsigned int) 0xFFFD, /* undefined */ + (unsigned int) 0x017D, + (unsigned int) 0xFFFD, /* undefined */ + (unsigned int) 0xFFFD, /* undefined */ + (unsigned int) 0x2018, + (unsigned int) 0x2019, + (unsigned int) 0x201C, + (unsigned int) 0x201D, + (unsigned int) 0x2022, + (unsigned int) 0x2013, + (unsigned int) 0x2014, + (unsigned int) 0x02DC, + (unsigned int) 0x2122, + (unsigned int) 0x0161, + (unsigned int) 0x203A, + (unsigned int) 0x0153, + (unsigned int) 0xFFFD, /* undefined */ + (unsigned int) 0x017E, + (unsigned int) 0x0178, + (unsigned int) 0x00A0, + (unsigned int) 0x00A1, + (unsigned int) 0x00A2, + (unsigned int) 0x00A3, + (unsigned int) 0x00A4, + (unsigned int) 0x00A5, + (unsigned int) 0x00A6, + (unsigned int) 0x00A7, + (unsigned int) 0x00A8, + (unsigned int) 0x00A9, + (unsigned int) 0x00AA, + (unsigned int) 0x00AB, + (unsigned int) 0x00AC, + (unsigned int) 0x00AD, + (unsigned int) 0x00AE, + (unsigned int) 0x00AF, + (unsigned int) 0x00B0, + (unsigned int) 0x00B1, + (unsigned int) 0x00B2, + (unsigned int) 0x00B3, + (unsigned int) 0x00B4, + (unsigned int) 0x00B5, + (unsigned int) 0x00B6, + (unsigned int) 0x00B7, + (unsigned int) 0x00B8, + (unsigned int) 0x00B9, + (unsigned int) 0x00BA, + (unsigned int) 0x00BB, + (unsigned int) 0x00BC, + (unsigned int) 0x00BD, + (unsigned int) 0x00BE, + (unsigned int) 0x00BF, + (unsigned int) 0x00C0, + (unsigned int) 0x00C1, + (unsigned int) 0x00C2, + (unsigned int) 0x00C3, + (unsigned int) 0x00C4, + (unsigned int) 0x00C5, + (unsigned int) 0x00C6, + (unsigned int) 0x00C7, + (unsigned int) 0x00C8, + (unsigned int) 0x00C9, + (unsigned int) 0x00CA, + (unsigned int) 0x00CB, + (unsigned int) 0x00CC, + (unsigned int) 0x00CD, + (unsigned int) 0x00CE, + (unsigned int) 0x00CF, + (unsigned int) 0x00D0, + (unsigned int) 0x00D1, + (unsigned int) 0x00D2, + (unsigned int) 0x00D3, + (unsigned int) 0x00D4, + (unsigned int) 0x00D5, + (unsigned int) 0x00D6, + (unsigned int) 0x00D7, + (unsigned int) 0x00D8, + (unsigned int) 0x00D9, + (unsigned int) 0x00DA, + (unsigned int) 0x00DB, + (unsigned int) 0x00DC, + (unsigned int) 0x00DD, + (unsigned int) 0x00DE, + (unsigned int) 0x00DF, + (unsigned int) 0x00E0, + (unsigned int) 0x00E1, + (unsigned int) 0x00E2, + (unsigned int) 0x00E3, + (unsigned int) 0x00E4, + (unsigned int) 0x00E5, + (unsigned int) 0x00E6, + (unsigned int) 0x00E7, + (unsigned int) 0x00E8, + (unsigned int) 0x00E9, + (unsigned int) 0x00EA, + (unsigned int) 0x00EB, + (unsigned int) 0x00EC, + (unsigned int) 0x00ED, + (unsigned int) 0x00EE, + (unsigned int) 0x00EF, + (unsigned int) 0x00F0, + (unsigned int) 0x00F1, + (unsigned int) 0x00F2, + (unsigned int) 0x00F3, + (unsigned int) 0x00F4, + (unsigned int) 0x00F5, + (unsigned int) 0x00F6, + (unsigned int) 0x00F7, + (unsigned int) 0x00F8, + (unsigned int) 0x00F9, + (unsigned int) 0x00FA, + (unsigned int) 0x00FB, + (unsigned int) 0x00FC, + (unsigned int) 0x00FD, + (unsigned int) 0x00FE, + (unsigned int) 0x00FF +}; + +/* Exercise all 3 byte lengths: any ASCII character is 1 byte, 0xFC maps to + * U+00FC which is 2 bytes, and 0x80 maps to U+20AC which is 3 bytes. + */ +static const char *example_source = "print('Hello w\xfcrld - \x80');"; + +/* Example: compile and run test source encoded in Windows codepage 1252. */ +int main(int argc, char *argv[]) { + duk_context *ctx; + + (void) argc; (void) argv; + + ctx = duk_create_heap_default(); + if (!ctx) { + printf("Failed to create Duktape heap.\n"); + return 1; + } + + duk_decode_string_codepage(ctx, example_source, strlen(example_source), cp1252); + duk_eval_noresult(ctx); + + duk_destroy_heap(ctx); + return 0; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/README.rst b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/README.rst new file mode 100644 index 0000000..f147522 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/README.rst @@ -0,0 +1,10 @@ +===================== +Coffeescript examples +===================== + +A few tests to see how CoffeeScript works with Duktape. Just convert the +Coffeescript files to Javascript with the ``Makefile.coffee`` in the +distributable, or manually:: + + $ coffee -c hello.coffee + $ cat hello.js http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/globals.coffee ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/globals.coffee b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/globals.coffee new file mode 100644 index 0000000..25773cd --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/globals.coffee @@ -0,0 +1,7 @@ + +print '*** All globals' +print(name) for name in Object.getOwnPropertyNames(this) + +print '*** Globals with a short name (<= 8 chars)' +print(name) for name in Object.getOwnPropertyNames(this) when name.length <= 8 + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/hello.coffee ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/hello.coffee b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/hello.coffee new file mode 100644 index 0000000..088ed8d --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/hello.coffee @@ -0,0 +1,2 @@ +print 'Hello world!' +print 'version: ' + Duktape.version http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/mandel.coffee ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/mandel.coffee b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/mandel.coffee new file mode 100644 index 0000000..8e3e170 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/examples/coffee/mandel.coffee @@ -0,0 +1,28 @@ +mandel = (x0, y0, x1, y1, w, h, maxiter) -> + [dx, dy] = [(x1 - x0) / w, (y1 - y0) / h] + res = [] + + y = y0 + for yc in [0..h-1] + x = x0 + for xc in [0..w-1] + [xx, yy] = [x, y] + c = '*' + for i in [0..maxiter-1] + # (xx+i*yy)^2 + (x+i*y) = xx^2 + i*2*xx*yy - yy^2 + x + i*y + # = (xx^2 - yy^2 + x) + i*(2*xx*yy + y) + [xx2, yy2] = [xx*xx, yy*yy] + if xx2 + yy2 >= 4.0 + c = '.' + break + [xx, yy] = [xx2 - yy2 + x, 2*xx*yy + y] + res.push(c) + x += dx + res.push('\n') + y += dy + + print(res.join('')) + return + +mandel(-2, 2, 2, -2, 200, 100, 1000) +
