You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2017/02/22 20:52:22 UTC

[27/51] [partial] nifi-minifi-cpp git commit: MINIFI-183 Added civet 1.9.1 sources Added onScheduled hook Added initial two-way TLS-enabled ListenHTTP implementation

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)
+