http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/README.rst b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/README.rst new file mode 100644 index 0000000..bbc26a0 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/README.rst @@ -0,0 +1,29 @@ +========================================= +C++ exceptions for long control transfers +========================================= + +Normally Duktape uses ``setjmp()`` / ``longjmp()`` or their variants for +internal long control transfers. One downside of these functions is that +C++ automatic destructors (scope-based resource management, SBRM, a special +case of RAII) in Duktape/C functions won't be executed which is awkward for +C++ programmers. + +When ``DUK_USE_CPP_EXCEPTIONS`` (``DUK_OPT_CPP_EXCEPTIONS``) is defined, and +both Duktape and application code is compiled using a C++ compiler, Duktape +uses C++ ``try-catch`` and ``throw`` for internal long control transfers. +This allows automatic destructors to run as expected. The config option is +not enabled by default because C++ exceptions are sometimes disabled even +when a C++ compiler is used (e.g. for performance reasons). + +The ``cpp_exceptions.cpp`` example illustrates how C++ exceptions can be +used in Duktape/C functions at the moment: + +* Duktape uses C++ try/catch/throw internally; this is not visible to user + code directly. + +* Automatic destructors (scope-based resource management) work as expected. + +* C++ exceptions can be used in Duktape/C functions normally, but user + exceptions must be caught before they reach Duktape. If this is not + done, such exceptions are caught by Duktape and converted to API errors + (in other words, they won't propagate "through" Duktape at the moment).
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/cpp_exceptions.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/cpp_exceptions.cpp b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/cpp_exceptions.cpp new file mode 100644 index 0000000..6fb3194 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/cpp-exceptions/cpp_exceptions.cpp @@ -0,0 +1,274 @@ +/* + * Example of how to use DUK_USE_CPP_EXCEPTIONS to support automatic + * variables (e.g. destructor calls) in Duktape/C functions. + * + * Compile with -DDUK_OPT_CPP_EXCEPTIONS: + * + * $ g++ -otest -DDUK_OPT_CPP_EXCEPTIONS -I<duktape_dist>/src/ \ + * <duktape_dist>/src/duktape.c cpp_exceptions.cpp -lm + * + * or ensure duk_config.h has DUK_USE_CPP_EXCEPTIONS enabled using + * genconfig. When executed you should see something like: + * + * $ ./test + * my_class instance created + * my_class instance destroyed <== destructor gets called + * --> rc=1 (SyntaxError: parse error (line 1)) + * [...] + * + * Duktape uses a custom exception class (duk_internal_exception) which + * doesn't inherit from any base class, so that catching any base classes + * in user code won't accidentally catch exceptions thrown by Duktape. + */ + +#if !defined(__cplusplus) +#error compile using a c++ compiler +#endif + +#include <stdio.h> +#include <exception> +#include "duktape.h" + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +#define NOEXCEPT noexcept +#else +#define NOEXCEPT throw() +#endif + +/* + * Example class with a destructor + */ + +class my_class { + public: + my_class(); + ~my_class(); +}; + +my_class::my_class() { + printf("my_class instance created\n"); +} + +my_class::~my_class() { + printf("my_class instance destroyed\n"); +} + +/* + * SyntaxError caused by eval exits Duktape/C function but destructors + * are executed. + */ + +duk_ret_t test1(duk_context *ctx) { + my_class myclass; + + duk_eval_string(ctx, "aiee="); + + return 0; +} + +/* + * You can use C++ exceptions inside Duktape/C functions for your own + * purposes but you should catch them before they propagate to Duktape. + */ + +duk_ret_t test2(duk_context *ctx) { + my_class myclass; + + try { + throw 123; + } catch (int myvalue) { + printf("Caught: %d\n", myvalue); + } + + return 0; +} + +/* + * If you let your own C++ exceptions propagate out of a Duktape/C function + * it will be caught by Duktape and considered a programming error. Duktape + * will catch the exception and convert it to a Duktape error. + * + * This may be allowed in a later version once all the implications have been + * worked out. + */ + +duk_ret_t test3(duk_context *ctx) { + my_class myclass; + + throw 123; /* ERROR: exception propagated to Duktape */ + + return 0; +} + +/* + * Same as above, but if the exception inherits from std::exception, it's + * "what()" will be included in the error message. + */ + +class my_exception : public std::exception { + virtual const char *what() const NOEXCEPT { + return "my_exception"; + } +}; + +duk_ret_t test4(duk_context *ctx) { + my_class myclass; + my_exception myexc; + + throw myexc; /* ERROR: exception propagated to Duktape */ + + return 0; +} + +/* + * Same as above, but if the exception inherits from std::exception with + * a NULL what(). Duktape will describe the error as 'unknown' if so. + */ + +class my_exception2 : public std::exception { + virtual const char *what() const NOEXCEPT { + return NULL; + } +}; + +duk_ret_t test5(duk_context *ctx) { + my_class myclass; + my_exception2 myexc; + + throw myexc; /* ERROR: exception propagated to Duktape */ + + return 0; +} + +int main(int argc, char *argv[]) { + duk_context *ctx = duk_create_heap_default(); + duk_int_t rc; + + (void) argc; (void) argv; /* suppress warning */ + + printf("*** test1 - duk_pcall()\n"); + duk_push_c_function(ctx, test1, 0); + rc = duk_pcall(ctx, 0); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test1 - duk_safe_call()\n"); + rc = duk_safe_call(ctx, test1, 0, 1); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test1 - ecmascript try-catch\n"); + duk_push_c_function(ctx, test1, 0); + duk_put_global_string(ctx, "test1"); + duk_eval_string_noresult(ctx, + "try {\n" + " test1();\n" + "} catch (e) {\n" + " print(e.stack || e);\n" + "}\n"); + printf("\n"); + + printf("*** test2 - duk_pcall()\n"); + duk_push_c_function(ctx, test2, 0); + rc = duk_pcall(ctx, 0); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test2 - duk_safe_call()\n"); + rc = duk_safe_call(ctx, test2, 0, 1); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test2 - ecmascript try-catch\n"); + duk_push_c_function(ctx, test2, 0); + duk_put_global_string(ctx, "test2"); + duk_eval_string_noresult(ctx, + "try {\n" + " test2();\n" + "} catch (e) {\n" + " print(e.stack || e);\n" + "}\n"); + printf("\n"); + + printf("*** test3 - duk_pcall()\n"); + duk_push_c_function(ctx, test3, 0); + rc = duk_pcall(ctx, 0); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test3 - duk_safe_call()\n"); + rc = duk_safe_call(ctx, test3, 0, 1); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test3 - ecmascript try-catch\n"); + duk_push_c_function(ctx, test3, 0); + duk_put_global_string(ctx, "test3"); + duk_eval_string_noresult(ctx, + "try {\n" + " test3();\n" + "} catch (e) {\n" + " print(e.stack || e);\n" + "}\n"); + printf("\n"); + + printf("*** test4 - duk_pcall()\n"); + duk_push_c_function(ctx, test4, 0); + rc = duk_pcall(ctx, 0); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test4 - duk_safe_call()\n"); + rc = duk_safe_call(ctx, test4, 0, 1); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test4 - ecmascript try-catch\n"); + duk_push_c_function(ctx, test4, 0); + duk_put_global_string(ctx, "test4"); + duk_eval_string_noresult(ctx, + "try {\n" + " test4();\n" + "} catch (e) {\n" + " print(e.stack || e);\n" + "}\n"); + printf("\n"); + + printf("*** test5 - duk_pcall()\n"); + duk_push_c_function(ctx, test5, 0); + rc = duk_pcall(ctx, 0); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test5 - duk_safe_call()\n"); + rc = duk_safe_call(ctx, test5, 0, 1); + printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); + duk_pop(ctx); + printf("\n"); + + printf("*** test5 - ecmascript try-catch\n"); + duk_push_c_function(ctx, test5, 0); + duk_put_global_string(ctx, "test5"); + duk_eval_string_noresult(ctx, + "try {\n" + " test5();\n" + "} catch (e) {\n" + " print(e.stack || e);\n" + "}\n"); + printf("\n"); + + printf("*** done\n"); + + duk_destroy_heap(ctx); + + return 0; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/README.rst b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/README.rst new file mode 100644 index 0000000..86b2bb5 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/README.rst @@ -0,0 +1,8 @@ +=========================================================== +Debug transport with local debug protocol encoding/decoding +=========================================================== + +This example implements a debug transport which decodes/encodes the Duktape +debug protocol locally into a more easy to use C interface, which is useful +for debug clients implemented locally on the target. The example also +demonstrates how to trial parse dvalues in C. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.c new file mode 100644 index 0000000..8470a5f --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.c @@ -0,0 +1,1239 @@ +/* + * Example debug transport with a local debug message encoder/decoder. + * + * Provides a "received dvalue" callback for a fully parsed dvalue (user + * code frees dvalue) and a "cooperate" callback for e.g. UI integration. + * There are a few other callbacks. See test.c for usage examples. + * + * This transport implementation is not multithreaded which means that: + * + * - Callbacks to "received dvalue" callback come from the Duktape thread, + * either during normal execution or from duk_debugger_cooperate(). + * + * - Calls into duk_trans_dvalue_send() must be made from the callbacks + * provided (e.g. "received dvalue" or "cooperate") which use the active + * Duktape thread. + * + * - The only exception to this is when Duktape is idle: you can then call + * duk_trans_dvalue_send() from any thread (only one thread at a time). + * When you next call into Duktape or call duk_debugger_cooperate(), the + * queued data will be read and processed by Duktape. + * + * There are functions for creating and freeing values; internally they use + * malloc() and free() for memory management. Duktape heap alloc functions + * are not used to minimize disturbances to the Duktape heap under debugging. + * + * Doesn't depend on C99 types; assumes "int" is at least 32 bits, and makes + * a few assumptions about format specifiers. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "duktape.h" +#include "duk_trans_dvalue.h" + +/* Define to enable debug prints to stderr. */ +#if 0 +#define DEBUG_PRINTS +#endif + +/* Define to enable error prints to stderr. */ +#if 1 +#define ERROR_PRINTS +#endif + +/* + * Dvalue handling + */ + +duk_dvalue *duk_dvalue_alloc(void) { + duk_dvalue *dv = (duk_dvalue *) malloc(sizeof(duk_dvalue)); + if (dv) { + memset((void *) dv, 0, sizeof(duk_dvalue)); + dv->buf = NULL; + } + return dv; +} + +void duk_dvalue_free(duk_dvalue *dv) { + if (dv) { + free(dv->buf); /* tolerates NULL */ + dv->buf = NULL; + free(dv); + } +} + +static void duk__dvalue_bufesc(duk_dvalue *dv, char *buf, size_t maxbytes, int stresc) { + size_t i, limit; + + *buf = (char) 0; + limit = dv->len > maxbytes ? maxbytes : dv->len; + for (i = 0; i < limit; i++) { + unsigned char c = dv->buf[i]; + if (stresc) { + if (c >= 0x20 && c <= 0x7e && c != (char) '"' && c != (char) '\'') { + sprintf(buf, "%c", c); + buf++; + } else { + sprintf(buf, "\\x%02x", (unsigned int) c); + buf += 4; + } + } else { + sprintf(buf, "%02x", (unsigned int) c); + buf += 2; + } + } + if (dv->len > maxbytes) { + sprintf(buf, "..."); + buf += 3; + } +} + +/* Caller must provide a buffer at least DUK_DVALUE_TOSTRING_BUFLEN in size. */ +void duk_dvalue_to_string(duk_dvalue *dv, char *buf) { + char hexbuf[32 * 4 + 4]; /* 32 hex encoded or \xXX escaped bytes, possible "...", NUL */ + + if (!dv) { + sprintf(buf, "NULL"); + return; + } + + switch (dv->tag) { + case DUK_DVALUE_EOM: + sprintf(buf, "EOM"); + break; + case DUK_DVALUE_REQ: + sprintf(buf, "REQ"); + break; + case DUK_DVALUE_REP: + sprintf(buf, "REP"); + break; + case DUK_DVALUE_ERR: + sprintf(buf, "ERR"); + break; + case DUK_DVALUE_NFY: + sprintf(buf, "NFY"); + break; + case DUK_DVALUE_INTEGER: + sprintf(buf, "%d", dv->i); + break; + case DUK_DVALUE_STRING: + duk__dvalue_bufesc(dv, hexbuf, 32, 1); + sprintf(buf, "str:%ld:\"%s\"", (long) dv->len, hexbuf); + break; + case DUK_DVALUE_BUFFER: + duk__dvalue_bufesc(dv, hexbuf, 32, 0); + sprintf(buf, "buf:%ld:%s", (long) dv->len, hexbuf); + break; + case DUK_DVALUE_UNUSED: + sprintf(buf, "undefined"); + break; + case DUK_DVALUE_UNDEFINED: + sprintf(buf, "undefined"); + break; + case DUK_DVALUE_NULL: + sprintf(buf, "null"); + break; + case DUK_DVALUE_TRUE: + sprintf(buf, "true"); + break; + case DUK_DVALUE_FALSE: + sprintf(buf, "false"); + break; + case DUK_DVALUE_NUMBER: + if (fpclassify(dv->d) == FP_ZERO) { + if (signbit(dv->d)) { + sprintf(buf, "-0"); + } else { + sprintf(buf, "0"); + } + } else { + sprintf(buf, "%lg", dv->d); + } + break; + case DUK_DVALUE_OBJECT: + duk__dvalue_bufesc(dv, hexbuf, 32, 0); + sprintf(buf, "obj:%d:%s", (int) dv->i, hexbuf); + break; + case DUK_DVALUE_POINTER: + duk__dvalue_bufesc(dv, hexbuf, 32, 0); + sprintf(buf, "ptr:%s", hexbuf); + break; + case DUK_DVALUE_LIGHTFUNC: + duk__dvalue_bufesc(dv, hexbuf, 32, 0); + sprintf(buf, "lfunc:%04x:%s", (unsigned int) dv->i, hexbuf); + break; + case DUK_DVALUE_HEAPPTR: + duk__dvalue_bufesc(dv, hexbuf, 32, 0); + sprintf(buf, "heapptr:%s", hexbuf); + break; + default: + sprintf(buf, "unknown:%d", (int) dv->tag); + } +} + +duk_dvalue *duk_dvalue_make_tag(int tag) { + duk_dvalue *dv = duk_dvalue_alloc(); + if (!dv) { return NULL; } + dv->tag = tag; + return dv; +} + +duk_dvalue *duk_dvalue_make_tag_int(int tag, int intval) { + duk_dvalue *dv = duk_dvalue_alloc(); + if (!dv) { return NULL; } + dv->tag = tag; + dv->i = intval; + return dv; +} + +duk_dvalue *duk_dvalue_make_tag_double(int tag, double dblval) { + duk_dvalue *dv = duk_dvalue_alloc(); + if (!dv) { return NULL; } + dv->tag = tag; + dv->d = dblval; + return dv; +} + +duk_dvalue *duk_dvalue_make_tag_data(int tag, const char *buf, size_t len) { + unsigned char *p; + duk_dvalue *dv = duk_dvalue_alloc(); + if (!dv) { return NULL; } + /* Alloc size is len + 1 so that a NUL terminator is always + * guaranteed which is convenient, e.g. you can printf() the + * value safely. + */ + p = (unsigned char *) malloc(len + 1); + if (!p) { + free(dv); + return NULL; + } + memcpy((void *) p, (const void *) buf, len); + p[len] = (unsigned char) 0; + dv->tag = tag; + dv->buf = p; + dv->len = len; + return dv; +} + +duk_dvalue *duk_dvalue_make_tag_int_data(int tag, int intval, const char *buf, size_t len) { + duk_dvalue *dv = duk_dvalue_make_tag_data(tag, buf, len); + if (!dv) { return NULL; } + dv->i = intval; + return dv; +} + +/* + * Dvalue transport handling + */ + +static void duk__trans_dvalue_double_byteswap(duk_trans_dvalue_ctx *ctx, volatile unsigned char *p) { + unsigned char t; + + /* Portable IEEE double byteswap. Relies on runtime detection of + * host endianness. + */ + + if (ctx->double_byteorder == 0) { + /* little endian */ + t = p[0]; p[0] = p[7]; p[7] = t; + t = p[1]; p[1] = p[6]; p[6] = t; + t = p[2]; p[2] = p[5]; p[5] = t; + t = p[3]; p[3] = p[4]; p[4] = t; + } else if (ctx->double_byteorder == 1) { + /* big endian: ok as is */ + ; + } else { + /* mixed endian */ + t = p[0]; p[0] = p[3]; p[3] = t; + t = p[1]; p[1] = p[2]; p[2] = t; + t = p[4]; p[4] = p[7]; p[7] = t; + t = p[5]; p[5] = p[6]; p[6] = t; + } +} + +static unsigned int duk__trans_dvalue_parse_u32(duk_trans_dvalue_ctx *ctx, unsigned char *p) { + /* Integers are network endian, read back into host format in + * a portable manner. + */ + (void) ctx; + return (((unsigned int) p[0]) << 24) + + (((unsigned int) p[1]) << 16) + + (((unsigned int) p[2]) << 8) + + (((unsigned int) p[3]) << 0); +} + +static int duk__trans_dvalue_parse_i32(duk_trans_dvalue_ctx *ctx, unsigned char *p) { + /* Portable sign handling, doesn't assume 'int' is exactly 32 bits + * like a direct cast would. + */ + unsigned int tmp = duk__trans_dvalue_parse_u32(ctx, p); + if (tmp & 0x80000000UL) { + return -((int) ((tmp ^ 0xffffffffUL) + 1UL)); + } else { + return tmp; + } +} + +static unsigned int duk__trans_dvalue_parse_u16(duk_trans_dvalue_ctx *ctx, unsigned char *p) { + /* Integers are network endian, read back into host format. */ + (void) ctx; + return (((unsigned int) p[0]) << 8) + + (((unsigned int) p[1]) << 0); +} + +static double duk__trans_dvalue_parse_double(duk_trans_dvalue_ctx *ctx, unsigned char *p) { + /* IEEE doubles are network endian, read back into host format. */ + volatile union { + double d; + unsigned char b[8]; + } u; + memcpy((void *) u.b, (const void *) p, 8); + duk__trans_dvalue_double_byteswap(ctx, u.b); + return u.d; +} + +static unsigned char *duk__trans_dvalue_encode_u32(duk_trans_dvalue_ctx *ctx, unsigned char *p, unsigned int val) { + /* Integers are written in network endian format. */ + (void) ctx; + *p++ = (unsigned char) ((val >> 24) & 0xff); + *p++ = (unsigned char) ((val >> 16) & 0xff); + *p++ = (unsigned char) ((val >> 8) & 0xff); + *p++ = (unsigned char) (val & 0xff); + return p; +} + +static unsigned char *duk__trans_dvalue_encode_i32(duk_trans_dvalue_ctx *ctx, unsigned char *p, int val) { + return duk__trans_dvalue_encode_u32(ctx, p, (unsigned int) val & 0xffffffffUL); +} + +static unsigned char *duk__trans_dvalue_encode_u16(duk_trans_dvalue_ctx *ctx, unsigned char *p, unsigned int val) { + /* Integers are written in network endian format. */ + (void) ctx; + *p++ = (unsigned char) ((val >> 8) & 0xff); + *p++ = (unsigned char) (val & 0xff); + return p; +} + +static unsigned char *duk__trans_dvalue_encode_double(duk_trans_dvalue_ctx *ctx, unsigned char *p, double val) { + /* IEEE doubles are written in network endian format. */ + volatile union { + double d; + unsigned char b[8]; + } u; + u.d = val; + duk__trans_dvalue_double_byteswap(ctx, u.b); + memcpy((void *) p, (const void *) u.b, 8); + p += 8; + return p; +} + +static unsigned char *duk__trans_buffer_ensure(duk_trans_buffer *dbuf, size_t space) { + size_t avail; + size_t used; + size_t new_size; + void *new_alloc; + + used = dbuf->write_offset; + avail = dbuf->alloc_size - dbuf->write_offset; + + if (avail >= space) { + if (avail - space > 256) { + /* Too big, resize so that we reclaim memory if we have just + * received a large string/buffer value. + */ + goto do_realloc; + } + } else { + /* Too small, resize. */ + goto do_realloc; + } + + return dbuf->base + dbuf->write_offset; + + do_realloc: + new_size = used + space + 256; /* some extra to reduce resizes */ + new_alloc = realloc(dbuf->base, new_size); + if (new_alloc) { + dbuf->base = (unsigned char *) new_alloc; + dbuf->alloc_size = new_size; +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: resized buffer %p to %ld bytes, read_offset=%ld, write_offset=%ld\n", + __func__, (void *) dbuf, (long) new_size, (long) dbuf->read_offset, (long) dbuf->write_offset); + fflush(stderr); +#endif + return dbuf->base + dbuf->write_offset; + } else { + return NULL; + } +} + +/* When read_offset is large enough, "rebase" buffer by deleting already + * read data and updating offsets. + */ +static void duk__trans_buffer_rebase(duk_trans_buffer *dbuf) { + if (dbuf->read_offset > 64) { +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: rebasing buffer %p, read_offset=%ld, write_offset=%ld\n", + __func__, (void *) dbuf, (long) dbuf->read_offset, (long) dbuf->write_offset); + fflush(stderr); +#endif + if (dbuf->write_offset > dbuf->read_offset) { + memmove((void *) dbuf->base, (const void *) (dbuf->base + dbuf->read_offset), dbuf->write_offset - dbuf->read_offset); + } + dbuf->write_offset -= dbuf->read_offset; + dbuf->read_offset = 0; + } +} + +duk_trans_dvalue_ctx *duk_trans_dvalue_init(void) { + volatile union { + double d; + unsigned char b[8]; + } u; + duk_trans_dvalue_ctx *ctx = NULL; + + ctx = (duk_trans_dvalue_ctx *) malloc(sizeof(duk_trans_dvalue_ctx)); + if (!ctx) { goto fail; } + memset((void *) ctx, 0, sizeof(duk_trans_dvalue_ctx)); + ctx->received = NULL; + ctx->cooperate = NULL; + ctx->handshake = NULL; + ctx->detached = NULL; + ctx->send_buf.base = NULL; + ctx->recv_buf.base = NULL; + + ctx->send_buf.base = malloc(256); + if (!ctx->send_buf.base) { goto fail; } + ctx->send_buf.alloc_size = 256; + + ctx->recv_buf.base = malloc(256); + if (!ctx->recv_buf.base) { goto fail; } + ctx->recv_buf.alloc_size = 256; + + /* IEEE double byte order, detect at run time (could also use + * preprocessor defines but that's verbose to make portable). + * + * >>> struct.unpack('>d', '1122334455667788'.decode('hex')) + * (3.841412024471731e-226,) + * >>> struct.unpack('>d', '8877665544332211'.decode('hex')) + * (-7.086876636573014e-268,) + * >>> struct.unpack('>d', '4433221188776655'.decode('hex')) + * (3.5294303071877444e+20,) + */ + u.b[0] = 0x11; u.b[1] = 0x22; u.b[2] = 0x33; u.b[3] = 0x44; + u.b[4] = 0x55; u.b[5] = 0x66; u.b[6] = 0x77; u.b[7] = 0x88; + if (u.d < 0.0) { + ctx->double_byteorder = 0; /* little endian */ + } else if (u.d < 1.0) { + ctx->double_byteorder = 1; /* big endian */ + } else { + ctx->double_byteorder = 2; /* mixed endian (arm) */ + } +#if defined(DEBUG_PRINTS) + fprintf(stderr, "double endianness test value is %lg -> byteorder %d\n", + u.d, ctx->double_byteorder); + fflush(stderr); +#endif + + return ctx; + + fail: + if (ctx) { + free(ctx->recv_buf.base); /* tolerates NULL */ + free(ctx->send_buf.base); /* tolerates NULL */ + free(ctx); + } + return NULL; +} + +void duk_trans_dvalue_free(duk_trans_dvalue_ctx *ctx) { + if (ctx) { + free(ctx->send_buf.base); /* tolerates NULL */ + free(ctx->recv_buf.base); /* tolerates NULL */ + free(ctx); + } +} + +void duk_trans_dvalue_send(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { + unsigned char *p; + + /* Convert argument dvalue into Duktape debug protocol format. + * Literal constants are used here for the debug protocol, + * e.g. initial byte 0x02 is REP, see doc/debugger.rst. + */ + +#if defined(DEBUG_PRINTS) + { + char buf[DUK_DVALUE_TOSTRING_BUFLEN]; + duk_dvalue_to_string(dv, buf); + fprintf(stderr, "%s: sending dvalue: %s\n", __func__, buf); + fflush(stderr); + } +#endif + + switch (dv->tag) { + case DUK_DVALUE_EOM: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x00; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_REQ: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x01; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_REP: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x02; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_ERR: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x03; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_NFY: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x04; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_INTEGER: { + int i = dv->i; + if (i >= 0 && i <= 63) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = (unsigned char) (0x80 + i); + ctx->send_buf.write_offset += 1; + } else if (i >= 0 && i <= 16383L) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 2); + if (!p) { goto alloc_error; } + *p++ = (unsigned char) (0xc0 + (i >> 8)); + *p++ = (unsigned char) (i & 0xff); + ctx->send_buf.write_offset += 2; + } else if (i >= -0x80000000L && i <= 0x7fffffffL) { /* Harmless warning on some platforms (re: range) */ + p = duk__trans_buffer_ensure(&ctx->send_buf, 5); + if (!p) { goto alloc_error; } + *p++ = 0x10; + p = duk__trans_dvalue_encode_i32(ctx, p, i); + ctx->send_buf.write_offset += 5; + } else { + goto dvalue_error; + } + break; + } + case DUK_DVALUE_STRING: { + size_t i = dv->len; + if (i <= 0x1fUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1 + i); + if (!p) { goto alloc_error; } + *p++ = (unsigned char) (0x60 + i); + memcpy((void *) p, (const void *) dv->buf, i); + p += i; + ctx->send_buf.write_offset += 1 + i; + } else if (i <= 0xffffUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 3 + i); + if (!p) { goto alloc_error; } + *p++ = 0x12; + p = duk__trans_dvalue_encode_u16(ctx, p, (unsigned int) i); + memcpy((void *) p, (const void *) dv->buf, i); + p += i; + ctx->send_buf.write_offset += 3 + i; + } else if (i <= 0xffffffffUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 5 + i); + if (!p) { goto alloc_error; } + *p++ = 0x11; + p = duk__trans_dvalue_encode_u32(ctx, p, (unsigned int) i); + memcpy((void *) p, (const void *) dv->buf, i); + p += i; + ctx->send_buf.write_offset += 5 + i; + } else { + goto dvalue_error; + } + break; + } + case DUK_DVALUE_BUFFER: { + size_t i = dv->len; + if (i <= 0xffffUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 3 + i); + if (!p) { goto alloc_error; } + *p++ = 0x14; + p = duk__trans_dvalue_encode_u16(ctx, p, (unsigned int) i); + memcpy((void *) p, (const void *) dv->buf, i); + p += i; + ctx->send_buf.write_offset += 3 + i; + } else if (i <= 0xffffffffUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 5 + i); + if (!p) { goto alloc_error; } + *p++ = 0x13; + p = duk__trans_dvalue_encode_u32(ctx, p, (unsigned int) i); + memcpy((void *) p, (const void *) dv->buf, i); + p += i; + ctx->send_buf.write_offset += 5 + i; + } else { + goto dvalue_error; + } + break; + } + case DUK_DVALUE_UNUSED: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x15; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_UNDEFINED: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x16; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_NULL: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x17; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_TRUE: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x18; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_FALSE: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 1); + if (!p) { goto alloc_error; } + *p++ = 0x19; + ctx->send_buf.write_offset += 1; + break; + } + case DUK_DVALUE_NUMBER: { + p = duk__trans_buffer_ensure(&ctx->send_buf, 9); + if (!p) { goto alloc_error; } + *p++ = 0x1a; + p = duk__trans_dvalue_encode_double(ctx, p, dv->d); + ctx->send_buf.write_offset += 9; + break; + } + case DUK_DVALUE_OBJECT: { + size_t i = dv->len; + if (i <= 0xffUL && dv->i >= 0 && dv->i <= 0xffL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 3 + i); + if (!p) { goto alloc_error; } + *p++ = 0x1b; + *p++ = (unsigned char) dv->i; + *p++ = (unsigned char) i; + memcpy((void *) p, (const void *) dv->buf, i); + ctx->send_buf.write_offset += 3 + i; + } else { + goto dvalue_error; + } + break; + } + case DUK_DVALUE_POINTER: { + size_t i = dv->len; + if (i <= 0xffUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 2 + i); + if (!p) { goto alloc_error; } + *p++ = 0x1c; + *p++ = (unsigned char) i; + memcpy((void *) p, (const void *) dv->buf, i); + ctx->send_buf.write_offset += 2 + i; + } else { + goto dvalue_error; + } + break; + } + case DUK_DVALUE_LIGHTFUNC: { + size_t i = dv->len; + if (i <= 0xffUL && dv->i >= 0 && dv->i <= 0xffffL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 4 + i); + if (!p) { goto alloc_error; } + *p++ = 0x1d; + p = duk__trans_dvalue_encode_u16(ctx, p, (unsigned int) dv->i); + *p++ = (unsigned char) i; + memcpy((void *) p, (const void *) dv->buf, i); + ctx->send_buf.write_offset += 4 + i; + } else { + goto dvalue_error; + } + break; + } + case DUK_DVALUE_HEAPPTR: { + size_t i = dv->len; + if (i <= 0xffUL) { + p = duk__trans_buffer_ensure(&ctx->send_buf, 2 + i); + if (!p) { goto alloc_error; } + *p++ = 0x1e; + *p++ = (unsigned char) i; + memcpy((void *) p, (const void *) dv->buf, i); + ctx->send_buf.write_offset += 2 + i; + } else { + goto dvalue_error; + } + break; + } + default: { + goto dvalue_error; + } + } /* end switch */ + + return; + + dvalue_error: +#if defined(ERROR_PRINTS) + fprintf(stderr, "%s: internal error, argument dvalue is invalid\n", __func__); + fflush(stdout); +#endif + return; + + alloc_error: +#if defined(ERROR_PRINTS) + fprintf(stderr, "%s: internal error, failed to allocate space for write\n", __func__); + fflush(stdout); +#endif + return; +} + +static void duk__trans_dvalue_send_and_free(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { + if (!dv) { return; } + duk_trans_dvalue_send(ctx, dv); + duk_dvalue_free(dv); +} + +void duk_trans_dvalue_send_eom(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_EOM)); +} + +void duk_trans_dvalue_send_req(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_REQ)); +} + +void duk_trans_dvalue_send_rep(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_REP)); +} + +void duk_trans_dvalue_send_err(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_ERR)); +} + +void duk_trans_dvalue_send_nfy(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_NFY)); +} + +void duk_trans_dvalue_send_integer(duk_trans_dvalue_ctx *ctx, int val) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, val)); +} + +void duk_trans_dvalue_send_string(duk_trans_dvalue_ctx *ctx, const char *str) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_STRING, str, strlen(str))); +} + +void duk_trans_dvalue_send_lstring(duk_trans_dvalue_ctx *ctx, const char *str, size_t len) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_STRING, str, len)); +} + +void duk_trans_dvalue_send_buffer(duk_trans_dvalue_ctx *ctx, const char *buf, size_t len) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_BUFFER, buf, len)); +} + +void duk_trans_dvalue_send_unused(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_UNUSED)); +} + +void duk_trans_dvalue_send_undefined(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_UNDEFINED)); +} + +void duk_trans_dvalue_send_null(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_NULL)); +} + +void duk_trans_dvalue_send_true(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_TRUE)); +} + +void duk_trans_dvalue_send_false(duk_trans_dvalue_ctx *ctx) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_FALSE)); +} + +void duk_trans_dvalue_send_number(duk_trans_dvalue_ctx *ctx, double val) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_double(DUK_DVALUE_NUMBER, val)); +} + +void duk_trans_dvalue_send_object(duk_trans_dvalue_ctx *ctx, int classnum, const char *ptr_data, size_t ptr_len) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_int_data(DUK_DVALUE_OBJECT, classnum, ptr_data, ptr_len)); +} + +void duk_trans_dvalue_send_pointer(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_POINTER, ptr_data, ptr_len)); +} + +void duk_trans_dvalue_send_lightfunc(duk_trans_dvalue_ctx *ctx, int lf_flags, const char *ptr_data, size_t ptr_len) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_int_data(DUK_DVALUE_LIGHTFUNC, lf_flags, ptr_data, ptr_len)); +} + +void duk_trans_dvalue_send_heapptr(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len) { + duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_HEAPPTR, ptr_data, ptr_len)); +} + +void duk_trans_dvalue_send_req_cmd(duk_trans_dvalue_ctx *ctx, int cmd) { + duk_trans_dvalue_send_req(ctx); + duk_trans_dvalue_send_integer(ctx, cmd); +} + +static duk_dvalue *duk__trans_trial_parse_dvalue(duk_trans_dvalue_ctx *ctx) { + unsigned char *p; + size_t len; + unsigned char ib; + duk_dvalue *dv; + size_t datalen; + + p = ctx->recv_buf.base + ctx->recv_buf.read_offset; + len = ctx->recv_buf.write_offset - ctx->recv_buf.read_offset; + + if (len == 0) { + return NULL; + } + ib = p[0]; + +#if defined(DEBUG_PRINTS) + { + size_t i; + fprintf(stderr, "%s: parsing dvalue, window:", __func__); + for (i = 0; i < 16; i++) { + if (i < len) { + fprintf(stderr, " %02x", (unsigned int) p[i]); + } else { + fprintf(stderr, " ??"); + } + } + fprintf(stderr, " (length %ld, read_offset %ld, write_offset %ld, alloc_size %ld)\n", + (long) len, (long) ctx->recv_buf.read_offset, (long) ctx->recv_buf.write_offset, + (long) ctx->recv_buf.alloc_size); + fflush(stderr); + } +#endif + + if (ib <= 0x1fU) { + /* 0x00 ... 0x1f */ + switch (ib) { + case 0x00: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_EOM); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x01: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_REQ); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x02: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_REP); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x03: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_ERR); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x04: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_NFY); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x10: { + int intval; + if (len < 5) { goto partial; } + intval = duk__trans_dvalue_parse_i32(ctx, p + 1); + ctx->recv_buf.read_offset += 5; + dv = duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, intval); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x11: { + if (len < 5) { goto partial; } + datalen = (size_t) duk__trans_dvalue_parse_u32(ctx, p + 1); + if (len < 5 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 5 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) (p + 5), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x12: { + if (len < 3) { goto partial; } + datalen = (size_t) duk__trans_dvalue_parse_u16(ctx, p + 1); + if (len < 3 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 3 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) (p + 3), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x13: { + if (len < 5) { goto partial; } + datalen = (size_t) duk__trans_dvalue_parse_u32(ctx, p + 1); + if (len < 5 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 5 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_BUFFER, (const char *) (p + 5), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x14: { + if (len < 3) { goto partial; } + datalen = (size_t) duk__trans_dvalue_parse_u16(ctx, p + 1); + if (len < 3 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 3 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_BUFFER, (const char *) (p + 3), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x15: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_UNUSED); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x16: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_UNDEFINED); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x17: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_NULL); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x18: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_TRUE); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x19: { + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag(DUK_DVALUE_FALSE); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x1a: { + double dblval; + if (len < 9) { goto partial; } + dblval = duk__trans_dvalue_parse_double(ctx, p + 1); + ctx->recv_buf.read_offset += 9; + dv = duk_dvalue_make_tag_double(DUK_DVALUE_NUMBER, dblval); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x1b: { + int classnum; + if (len < 3) { goto partial; } + datalen = (size_t) p[2]; + if (len < 3 + datalen) { goto partial; } + classnum = (int) p[1]; + ctx->recv_buf.read_offset += 3 + datalen; + dv = duk_dvalue_make_tag_int_data(DUK_DVALUE_OBJECT, classnum, (const char *) (p + 3), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x1c: { + if (len < 2) { goto partial; } + datalen = (size_t) p[1]; + if (len < 2 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 2 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_POINTER, (const char *) (p + 2), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x1d: { + int lf_flags; + if (len < 4) { goto partial; } + datalen = (size_t) p[3]; + if (len < 4 + datalen) { goto partial; } + lf_flags = (int) duk__trans_dvalue_parse_u16(ctx, p + 1); + ctx->recv_buf.read_offset += 4 + datalen; + dv = duk_dvalue_make_tag_int_data(DUK_DVALUE_LIGHTFUNC, lf_flags, (const char *) (p + 4), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + case 0x1e: { + if (len < 2) { goto partial; } + datalen = (size_t) p[1]; + if (len < 2 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 2 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_HEAPPTR, (const char *) (p + 2), datalen); + if (!dv) { goto alloc_error; } + return dv; + } + default: { + goto format_error; + } + } /* end switch */ + } else if (ib <= 0x5fU) { + /* 0x20 ... 0x5f */ + goto format_error; + } else if (ib <= 0x7fU) { + /* 0x60 ... 0x7f */ + datalen = (size_t) (ib - 0x60U); + if (len < 1 + datalen) { goto partial; } + ctx->recv_buf.read_offset += 1 + datalen; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) (p + 1), datalen); + if (!dv) { goto alloc_error; } + return dv; + } else if (ib <= 0xbfU) { + /* 0x80 ... 0xbf */ + int intval; + intval = (int) (ib - 0x80U); + ctx->recv_buf.read_offset += 1; + dv = duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, intval); + if (!dv) { goto alloc_error; } + return dv; + } else { + /* 0xc0 ... 0xff */ + int intval; + if (len < 2) { goto partial; } + intval = (((int) (ib - 0xc0U)) << 8) + (int) p[1]; + ctx->recv_buf.read_offset += 2; + dv = duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, intval); + if (!dv) { goto alloc_error; } + return dv; + } + + /* never here */ + + partial: + return NULL; + + alloc_error: +#if defined(ERROR_PRINTS) + fprintf(stderr, "%s: internal error, cannot allocate space for dvalue\n", __func__); + fflush(stdout); +#endif + return NULL; + + format_error: +#if defined(ERROR_PRINTS) + fprintf(stderr, "%s: internal error, dvalue format error\n", __func__); + fflush(stdout); +#endif + return NULL; +} + +static duk_dvalue *duk__trans_trial_parse_handshake(duk_trans_dvalue_ctx *ctx) { + unsigned char *p; + size_t len; + duk_dvalue *dv; + size_t i; + + p = ctx->recv_buf.base + ctx->recv_buf.read_offset; + len = ctx->recv_buf.write_offset - ctx->recv_buf.read_offset; + + for (i = 0; i < len; i++) { + if (p[i] == 0x0a) { + /* Handshake line is returned as a dvalue for convenience; it's + * not actually a part of the dvalue phase of the protocol. + */ + ctx->recv_buf.read_offset += i + 1; + dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) p, i); + if (!dv) { goto alloc_error; } + return dv; + } + } + + return NULL; + + alloc_error: +#if defined(ERROR_PRINTS) + fprintf(stderr, "%s: internal error, cannot allocate space for handshake line\n", __func__); + fflush(stdout); +#endif + return NULL; +} + +static void duk__trans_call_cooperate(duk_trans_dvalue_ctx *ctx, int block) { + if (ctx->cooperate) { + ctx->cooperate(ctx, block); + } +} + +static void duk__trans_call_received(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { + if (ctx->received) { + ctx->received(ctx, dv); + } +} + +static void duk__trans_call_handshake(duk_trans_dvalue_ctx *ctx, const char *line) { + if (ctx->handshake) { + ctx->handshake(ctx, line); + } +} + +static void duk__trans_call_detached(duk_trans_dvalue_ctx *ctx) { + if (ctx->detached) { + ctx->detached(ctx); + } +} + +/* + * Duktape callbacks + */ + +duk_size_t duk_trans_dvalue_read_cb(void *udata, char *buffer, duk_size_t length) { + duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: %p %p %ld\n", __func__, udata, (void *) buffer, (long) length); + fflush(stderr); +#endif + + duk__trans_call_cooperate(ctx, 0); + + for (;;) { + size_t avail, now; + + avail = (size_t) (ctx->send_buf.write_offset - ctx->send_buf.read_offset); + if (avail == 0) { + /* Must cooperate until user callback provides data. From + * Duktape's perspective we MUST block until data is received. + */ + duk__trans_call_cooperate(ctx, 1); + } else { + now = avail; + if (now > length) { + now = length; + } + memcpy((void *) buffer, (const void *) (ctx->send_buf.base + ctx->send_buf.read_offset), now); + duk__trans_buffer_rebase(&ctx->send_buf); + ctx->send_buf.read_offset += now; + return now; + } + } +} + +duk_size_t duk_trans_dvalue_write_cb(void *udata, const char *buffer, duk_size_t length) { + duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; + unsigned char *p; + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: %p %p %ld\n", __func__, udata, (void *) buffer, (long) length); + fflush(stderr); +#endif + + duk__trans_call_cooperate(ctx, 0); + + /* Append data. */ + duk__trans_buffer_rebase(&ctx->recv_buf); + p = duk__trans_buffer_ensure(&ctx->recv_buf, length); + memcpy((void *) p, (const void *) buffer, (size_t) length); + ctx->recv_buf.write_offset += length; + + /* Trial parse handshake line or dvalue(s). */ + if (!ctx->handshake_done) { + duk_dvalue *dv = duk__trans_trial_parse_handshake(ctx); + if (dv) { + /* Handshake line is available for caller for the + * duration of the callback, and must not be freed + * by the caller. + */ + duk__trans_call_handshake(ctx, (const char *) dv->buf); +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: handshake ok\n", __func__); + fflush(stderr); +#endif + duk_dvalue_free(dv); + ctx->handshake_done = 1; + } + } + if (ctx->handshake_done) { + for (;;) { + duk_dvalue *dv = duk__trans_trial_parse_dvalue(ctx); + if (dv) { +#if defined(DEBUG_PRINTS) + { + char buf[DUK_DVALUE_TOSTRING_BUFLEN]; + duk_dvalue_to_string(dv, buf); + fprintf(stderr, "%s: received dvalue: %s\n", __func__, buf); + fflush(stderr); + } +#endif + + duk__trans_call_received(ctx, dv); + } else { + break; + } + } + } + + duk__trans_call_cooperate(ctx, 0); /* just in case, if dvalues changed something */ + + return length; +} + +duk_size_t duk_trans_dvalue_peek_cb(void *udata) { + duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; + size_t avail; + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: %p\n", __func__, udata); + fflush(stderr); +#endif + + duk__trans_call_cooperate(ctx, 0); + avail = (size_t) (ctx->send_buf.write_offset - ctx->send_buf.read_offset); + return (duk_size_t) avail; +} + +void duk_trans_dvalue_read_flush_cb(void *udata) { + duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: %p\n", __func__, udata); + fflush(stderr); +#endif + + duk__trans_call_cooperate(ctx, 0); +} + +void duk_trans_dvalue_write_flush_cb(void *udata) { + duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: %p\n", __func__, udata); + fflush(stderr); +#endif + + duk__trans_call_cooperate(ctx, 0); +} + +void duk_trans_dvalue_detached_cb(void *udata) { + duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: %p\n", __func__, udata); + fflush(stderr); +#endif + + duk__trans_call_detached(ctx); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.h ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.h b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.h new file mode 100644 index 0000000..e0ba731 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.h @@ -0,0 +1,113 @@ +#ifndef DUK_TRANS_DVALUE_H_INCLUDED +#define DUK_TRANS_DVALUE_H_INCLUDED + +#include "duktape.h" + +typedef struct duk_dvalue duk_dvalue; +typedef struct duk_trans_buffer duk_trans_buffer; +typedef struct duk_trans_dvalue_ctx duk_trans_dvalue_ctx; + +typedef void (*duk_trans_dvalue_received_function)(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv); +typedef void (*duk_trans_dvalue_cooperate_function)(duk_trans_dvalue_ctx *ctx, int block); +typedef void (*duk_trans_dvalue_handshake_function)(duk_trans_dvalue_ctx *ctx, const char *handshake_line); +typedef void (*duk_trans_dvalue_detached_function)(duk_trans_dvalue_ctx *ctx); + +/* struct duk_dvalue 'tag' values, note that these have nothing to do with + * Duktape debug protocol inital byte. Struct fields used with the type + * are noted next to the define. + */ +#define DUK_DVALUE_EOM 1 /* no fields */ +#define DUK_DVALUE_REQ 2 /* no fields */ +#define DUK_DVALUE_REP 3 /* no fields */ +#define DUK_DVALUE_ERR 4 /* no fields */ +#define DUK_DVALUE_NFY 5 /* no fields */ +#define DUK_DVALUE_INTEGER 6 /* i: 32-bit signed integer */ +#define DUK_DVALUE_STRING 7 /* buf: string data, len: string length */ +#define DUK_DVALUE_BUFFER 8 /* buf: buffer data, len: buffer length */ +#define DUK_DVALUE_UNUSED 9 /* no fields */ +#define DUK_DVALUE_UNDEFINED 10 /* no fields */ +#define DUK_DVALUE_NULL 11 /* no fields */ +#define DUK_DVALUE_TRUE 12 /* no fields */ +#define DUK_DVALUE_FALSE 13 /* no fields */ +#define DUK_DVALUE_NUMBER 14 /* d: ieee double */ +#define DUK_DVALUE_OBJECT 15 /* i: class number, buf: pointer data, len: pointer length */ +#define DUK_DVALUE_POINTER 16 /* buf: pointer data, len: pointer length */ +#define DUK_DVALUE_LIGHTFUNC 17 /* i: lightfunc flags, buf: pointer data, len: pointer length */ +#define DUK_DVALUE_HEAPPTR 18 /* buf: pointer data, len: pointer length */ + +struct duk_dvalue { + /* Could use a union for the value but the gain would be relatively small. */ + int tag; + int i; + double d; + size_t len; + unsigned char *buf; +}; + +struct duk_trans_buffer { + unsigned char *base; + size_t write_offset; + size_t read_offset; + size_t alloc_size; +}; + +struct duk_trans_dvalue_ctx { + duk_trans_dvalue_received_function received; + duk_trans_dvalue_cooperate_function cooperate; + duk_trans_dvalue_handshake_function handshake; + duk_trans_dvalue_detached_function detached; + duk_trans_buffer send_buf; /* sending towards Duktape (duktape read callback) */ + duk_trans_buffer recv_buf; /* receiving from Duktape (duktape write callback) */ + int handshake_done; + int double_byteorder; /* 0=little endian, 1=big endian, 2=mixed endian */ +}; + +/* Buffer size needed by duk_dvalue_to_string(). */ +#define DUK_DVALUE_TOSTRING_BUFLEN 256 + +/* Dvalue handling. */ +duk_dvalue *duk_dvalue_alloc(void); +void duk_dvalue_free(duk_dvalue *dv); +void duk_dvalue_to_string(duk_dvalue *dv, char *buf); +duk_dvalue *duk_dvalue_make_tag(int tag); +duk_dvalue *duk_dvalue_make_tag_int(int tag, int intval); +duk_dvalue *duk_dvalue_make_tag_double(int tag, double dblval); +duk_dvalue *duk_dvalue_make_tag_data(int tag, const char *buf, size_t len); +duk_dvalue *duk_dvalue_make_tag_int_data(int tag, int intval, const char *buf, size_t len); + +/* Initializing and freeing the transport context. */ +duk_trans_dvalue_ctx *duk_trans_dvalue_init(void); +void duk_trans_dvalue_free(duk_trans_dvalue_ctx *ctx); + +/* Sending dvalues towards Duktape. */ +void duk_trans_dvalue_send(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv); +void duk_trans_dvalue_send_eom(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_req(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_rep(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_err(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_nfy(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_integer(duk_trans_dvalue_ctx *ctx, int val); +void duk_trans_dvalue_send_string(duk_trans_dvalue_ctx *ctx, const char *str); +void duk_trans_dvalue_send_lstring(duk_trans_dvalue_ctx *ctx, const char *str, size_t len); +void duk_trans_dvalue_send_buffer(duk_trans_dvalue_ctx *ctx, const char *buf, size_t len); +void duk_trans_dvalue_send_unused(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_undefined(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_null(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_true(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_false(duk_trans_dvalue_ctx *ctx); +void duk_trans_dvalue_send_number(duk_trans_dvalue_ctx *ctx, double val); +void duk_trans_dvalue_send_object(duk_trans_dvalue_ctx *ctx, int classnum, const char *ptr_data, size_t ptr_len); +void duk_trans_dvalue_send_pointer(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len); +void duk_trans_dvalue_send_lightfunc(duk_trans_dvalue_ctx *ctx, int lf_flags, const char *ptr_data, size_t ptr_len); +void duk_trans_dvalue_send_heapptr(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len); +void duk_trans_dvalue_send_req_cmd(duk_trans_dvalue_ctx *ctx, int cmd); + +/* Duktape debug callbacks provided by the transport. */ +duk_size_t duk_trans_dvalue_read_cb(void *udata, char *buffer, duk_size_t length); +duk_size_t duk_trans_dvalue_write_cb(void *udata, const char *buffer, duk_size_t length); +duk_size_t duk_trans_dvalue_peek_cb(void *udata); +void duk_trans_dvalue_read_flush_cb(void *udata); +void duk_trans_dvalue_write_flush_cb(void *udata); +void duk_trans_dvalue_detached_cb(void *udata); + +#endif /* DUK_TRANS_DVALUE_H_INCLUDED */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/test.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/test.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/test.c new file mode 100644 index 0000000..7830ec2 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/test.c @@ -0,0 +1,236 @@ +/* + * Example program using the dvalue debug transport. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "duktape.h" +#include "duk_trans_dvalue.h" + +void my_cooperate(duk_trans_dvalue_ctx *ctx, int block) { + static int first_blocked = 1; + + if (!block) { + /* Duktape is not blocked; you can cooperate with e.g. a user + * interface here and send dvalues to Duktape, but don't block. + */ + return; + } + + /* Duktape is blocked on a read and won't continue until debug + * command(s) are sent. + * + * Normally you'd enter your own event loop here, and process + * events until something needs to be sent to Duktape. For + * example, the user might press a "Step over" button in the + * UI which would cause dvalues to be sent. You can then + * return from this callback. + * + * The code below sends some example messages for testing the + * dvalue handling of the transport. + * + * If you create dvalues manually and send them using + * duk_trans_dvalue_send(), you must free the dvalues after + * the send call returns using duk_dvalue_free(). + */ + + if (first_blocked) { + char *tmp; + int i; + + /* First time Duktape becomes blocked, send DumpHeap which + * exercises a lot of parsing code. + * + * NOTE: Valgrind may complain about reading uninitialized + * bytes. This is caused by the DumpHeap command writing out + * verbatim duk_tval values which are intentionally not + * always fully initialized for performance reasons. + */ + first_blocked = 0; + + fprintf(stderr, "Duktape is blocked, send DumpHeap\n"); + fflush(stderr); + + duk_trans_dvalue_send_req(ctx); + duk_trans_dvalue_send_integer(ctx, 0x20); /* DumpHeap */ + duk_trans_dvalue_send_eom(ctx); + + /* Also send a dummy TriggerStatus request with trailing dvalues + * ignored by Duktape; Duktape will parse the dvalues to be able to + * skip them, so that the dvalue encoding is exercised. + */ + + tmp = malloc(100000); /* long buffer, >= 65536 chars */ + for (i = 0; i < 100000; i++) { + tmp[i] = (char) i; + } + duk_trans_dvalue_send_req(ctx); + duk_trans_dvalue_send_integer(ctx, 0x11); /* TriggerStatus */ + duk_trans_dvalue_send_string(ctx, "dummy"); /* short, <= 31 chars */ + duk_trans_dvalue_send_string(ctx, "123456789012345678901234567890foobar"); /* medium, >= 32 chars */ + duk_trans_dvalue_send_lstring(ctx, (const char *) tmp, 65535UL); + duk_trans_dvalue_send_lstring(ctx, (const char *) tmp, 65536UL); + duk_trans_dvalue_send_lstring(ctx, (const char *) tmp, 100000UL); + duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 255U); + duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 65535UL); + duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 65536UL); + duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 100000UL); + duk_trans_dvalue_send_unused(ctx); + duk_trans_dvalue_send_undefined(ctx); + duk_trans_dvalue_send_null(ctx); + duk_trans_dvalue_send_true(ctx); + duk_trans_dvalue_send_false(ctx); + duk_trans_dvalue_send_number(ctx, 123.456); + duk_trans_dvalue_send_object(ctx, 12 /*classnum*/, (const char *) tmp, 8); /* fake ptr len */ + duk_trans_dvalue_send_pointer(ctx, (const char *) tmp, 8); /* fake ptr len */ + duk_trans_dvalue_send_lightfunc(ctx, 0xdabc /*lf_flags*/, (const char *) tmp, 8); /* fake ptr len */ + duk_trans_dvalue_send_heapptr(ctx, (const char *) tmp, 8); /* fake ptr len */ + + duk_trans_dvalue_send_eom(ctx); + } + + fprintf(stderr, "Duktape is blocked, send Eval and StepInto to resume execution\n"); + fflush(stderr); + + /* duk_trans_dvalue_send_req_cmd() sends a REQ dvalue followed by + * an integer dvalue (command) for convenience. + */ + + duk_trans_dvalue_send_req_cmd(ctx, 0x1e); /* 0x1e = Eval */ + duk_trans_dvalue_send_string(ctx, "evalMe"); + duk_trans_dvalue_send_eom(ctx); + + duk_trans_dvalue_send_req_cmd(ctx, 0x14); /* 0x14 = StepOver */ + duk_trans_dvalue_send_eom(ctx); +} + +void my_received(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { + char buf[DUK_DVALUE_TOSTRING_BUFLEN]; + (void) ctx; + + duk_dvalue_to_string(dv, buf); + fprintf(stderr, "Received dvalue: %s\n", buf); + fflush(stderr); + + /* Here a normal debug client would wait for dvalues until an EOM + * dvalue was received (which completes a debug message). The + * debug message would then be handled, possibly causing UI changes + * and/or causing debug commands to be sent to Duktape. + * + * The callback is responsible for eventually freeing the dvalue. + * Here we free it immediately, but an actual client would probably + * gather dvalues into an array or linked list to handle when the + * debug message was complete. + */ + + duk_dvalue_free(dv); +} + +void my_handshake(duk_trans_dvalue_ctx *ctx, const char *line) { + (void) ctx; + + /* The Duktape handshake line is given in 'line' (without LF). + * The 'line' argument can be accessed for the duration of the + * callback (read only). Don't free 'line' here, the transport + * handles that. + */ + + fprintf(stderr, "Received handshake line: '%s'\n", line); + fflush(stderr); +} + +void my_detached(duk_trans_dvalue_ctx *ctx) { + (void) ctx; + + /* Detached call forwarded as is. */ + + fprintf(stderr, "Debug transport detached\n"); + fflush(stderr); +} + +int main(int argc, char *argv[]) { + duk_context *ctx; + duk_trans_dvalue_ctx *trans_ctx; + int exitval = 0; + + (void) argc; (void) argv; /* suppress warning */ + + ctx = duk_create_heap_default(); + if (!ctx) { + fprintf(stderr, "Failed to create Duktape heap\n"); + fflush(stderr); + exitval = 1; + goto cleanup; + } + + trans_ctx = duk_trans_dvalue_init(); + if (!trans_ctx) { + fprintf(stderr, "Failed to create debug transport context\n"); + fflush(stderr); + exitval = 1; + goto cleanup; + } + trans_ctx->cooperate = my_cooperate; + trans_ctx->received = my_received; + trans_ctx->handshake = my_handshake; + trans_ctx->detached = my_detached; + + /* Attach debugger; this will fail with a fatal error here unless + * debugger support is compiled in. To fail more gracefully, call + * this under a duk_safe_call() to catch the error. + */ + duk_debugger_attach(ctx, + duk_trans_dvalue_read_cb, + duk_trans_dvalue_write_cb, + duk_trans_dvalue_peek_cb, + duk_trans_dvalue_read_flush_cb, + duk_trans_dvalue_write_flush_cb, + duk_trans_dvalue_detached_cb, + (void *) trans_ctx); + + fprintf(stderr, "Debugger attached, running eval\n"); + fflush(stderr); + + /* Evaluate simple test code, callbacks will "step over" until end. + * + * The test code here is just for exercising the debug transport. + * The 'evalMe' variable is evaluated (using debugger command Eval) + * before every step to force different dvalues to be carried over + * the transport. + */ + + duk_eval_string(ctx, + "var evalMe;\n" + "\n" + "print('Hello world!');\n" + "[ undefined, null, true, false, 123, -123, 123.1, 0, -0, 1/0, 0/0, -1/0, \n" + " 'foo', Duktape.Buffer('bar'), Duktape.Pointer('dummy'), Math.cos, \n" + "].forEach(function (val) {\n" + " print(val);\n" + " evalMe = val;\n" + "});\n" + "\n" + "var str = 'xxx'\n" + "for (i = 0; i < 10; i++) {\n" + " print(i, str);\n" + " evalMe = str;\n" + " evalMe = Duktape.Buffer(str);\n" + " str = str + str;\n" + "}\n" + ); + duk_pop(ctx); + + duk_debugger_detach(ctx); + + cleanup: + if (trans_ctx) { + duk_trans_dvalue_free(trans_ctx); + trans_ctx = NULL; + } + if (ctx) { + duk_destroy_heap(ctx); + } + + return exitval; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/README.rst b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/README.rst new file mode 100644 index 0000000..78522cd --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/README.rst @@ -0,0 +1,17 @@ +================================================ +Debug transport using a simple socket connection +================================================ + +This example implements an example debug transport which uses a Linux or +Windows TCP server socket on the debug target. + +Files: + +* ``duk_trans_socket.h``: header file for the transport, used for both Linux + and Windows socket variants. + +* ``duk_trans_socket_unix.c``: implementation for Linux/Unix. + +* ``duk_trans_socket_windows.c``: implementation for Windows. + +Compile either Unix or Windows source file only. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket.h ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket.h b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket.h new file mode 100644 index 0000000..43f4a34 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket.h @@ -0,0 +1,15 @@ +#ifndef DUK_TRANS_SOCKET_H_INCLUDED +#define DUK_TRANS_SOCKET_H_INCLUDED + +#include "duktape.h" + +void duk_trans_socket_init(void); +void duk_trans_socket_finish(void); +void duk_trans_socket_waitconn(void); +duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length); +duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length); +duk_size_t duk_trans_socket_peek_cb(void *udata); +void duk_trans_socket_read_flush_cb(void *udata); +void duk_trans_socket_write_flush_cb(void *udata); + +#endif /* DUK_TRANS_SOCKET_H_INCLUDED */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_unix.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_unix.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_unix.c new file mode 100644 index 0000000..ac74de2 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_unix.c @@ -0,0 +1,340 @@ +/* + * Example debug transport using a Linux/Unix TCP socket + * + * Provides a TCP server socket which a debug client can connect to. + * After that data is just passed through. + */ + +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> +#include <poll.h> +#include <errno.h> +#include "duktape.h" + +#if !defined(DUK_DEBUG_PORT) +#define DUK_DEBUG_PORT 9091 +#endif + +#if 0 +#define DEBUG_PRINTS +#endif + +static int server_sock = -1; +static int client_sock = -1; + +/* + * Transport init and finish + */ + +void duk_trans_socket_init(void) { + struct sockaddr_in addr; + int on; + + server_sock = socket(AF_INET, SOCK_STREAM, 0); + if (server_sock < 0) { + fprintf(stderr, "%s: failed to create server socket: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; + } + + on = 1; + if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) { + fprintf(stderr, "%s: failed to set SO_REUSEADDR for server socket: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; + } + + memset((void *) &addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(DUK_DEBUG_PORT); + + if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + fprintf(stderr, "%s: failed to bind server socket: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; + } + + listen(server_sock, 1 /*backlog*/); + return; + + fail: + if (server_sock >= 0) { + (void) close(server_sock); + server_sock = -1; + } +} + +void duk_trans_socket_finish(void) { + if (client_sock >= 0) { + (void) close(client_sock); + client_sock = -1; + } + if (server_sock >= 0) { + (void) close(server_sock); + server_sock = -1; + } +} + +void duk_trans_socket_waitconn(void) { + struct sockaddr_in addr; + socklen_t sz; + + if (server_sock < 0) { + fprintf(stderr, "%s: no server socket, skip waiting for connection\n", + __FILE__); + fflush(stderr); + return; + } + if (client_sock >= 0) { + (void) close(client_sock); + client_sock = -1; + } + + fprintf(stderr, "Waiting for debug connection on port %d\n", (int) DUK_DEBUG_PORT); + fflush(stderr); + + sz = (socklen_t) sizeof(addr); + client_sock = accept(server_sock, (struct sockaddr *) &addr, &sz); + if (client_sock < 0) { + fprintf(stderr, "%s: accept() failed, skip waiting for connection: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; + } + + fprintf(stderr, "Debug connection established\n"); + fflush(stderr); + + /* XXX: For now, close the listen socket because we won't accept new + * connections anyway. A better implementation would allow multiple + * debug attaches. + */ + + if (server_sock >= 0) { + (void) close(server_sock); + server_sock = -1; + } + return; + + fail: + if (client_sock >= 0) { + (void) close(client_sock); + client_sock = -1; + } +} + +/* + * Duktape callbacks + */ + +/* Duktape debug transport callback: (possibly partial) read. */ +duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length) { + ssize_t ret; + + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n", + __func__, (void *) udata, (void *) buffer, (long) length); + fflush(stderr); +#endif + + if (client_sock < 0) { + return 0; + } + + if (length == 0) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: read request length == 0, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + if (buffer == NULL) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: read request buffer == NULL, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + /* In a production quality implementation there would be a sanity + * timeout here to recover from "black hole" disconnects. + */ + + ret = read(client_sock, (void *) buffer, (size_t) length); + if (ret < 0) { + fprintf(stderr, "%s: debug read failed, closing connection: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; + } else if (ret == 0) { + fprintf(stderr, "%s: debug read failed, ret == 0 (EOF), closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } else if (ret > (ssize_t) length) { + fprintf(stderr, "%s: debug read failed, ret too large (%ld > %ld), closing connection\n", + __FILE__, (long) ret, (long) length); + fflush(stderr); + goto fail; + } + + return (duk_size_t) ret; + + fail: + if (client_sock >= 0) { + (void) close(client_sock); + client_sock = -1; + } + return 0; +} + +/* Duktape debug transport callback: (possibly partial) write. */ +duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length) { + ssize_t ret; + + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n", + __func__, (void *) udata, (const void *) buffer, (long) length); + fflush(stderr); +#endif + + if (client_sock < 0) { + return 0; + } + + if (length == 0) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: write request length == 0, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + if (buffer == NULL) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: write request buffer == NULL, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + /* In a production quality implementation there would be a sanity + * timeout here to recover from "black hole" disconnects. + */ + + ret = write(client_sock, (const void *) buffer, (size_t) length); + if (ret <= 0 || ret > (ssize_t) length) { + fprintf(stderr, "%s: debug write failed, closing connection: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; + } + + return (duk_size_t) ret; + + fail: + if (client_sock >= 0) { + (void) close(client_sock); + client_sock = -1; + } + return 0; +} + +duk_size_t duk_trans_socket_peek_cb(void *udata) { + struct pollfd fds[1]; + int poll_rc; + + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata); + fflush(stderr); +#endif + + if (client_sock < 0) { + return 0; + } + + fds[0].fd = client_sock; + fds[0].events = POLLIN; + fds[0].revents = 0; + + poll_rc = poll(fds, 1, 0); + if (poll_rc < 0) { + fprintf(stderr, "%s: poll returned < 0, closing connection: %s\n", + __FILE__, strerror(errno)); + fflush(stderr); + goto fail; /* also returns 0, which is correct */ + } else if (poll_rc > 1) { + fprintf(stderr, "%s: poll returned > 1, treating like 1\n", + __FILE__); + fflush(stderr); + return 1; /* should never happen */ + } else if (poll_rc == 0) { + return 0; /* nothing to read */ + } else { + return 1; /* something to read */ + } + + fail: + if (client_sock >= 0) { + (void) close(client_sock); + client_sock = -1; + } + return 0; +} + +void duk_trans_socket_read_flush_cb(void *udata) { + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata); + fflush(stderr); +#endif + + /* Read flush: Duktape may not be making any more read calls at this + * time. If the transport maintains a receive window, it can use a + * read flush as a signal to update the window status to the remote + * peer. A read flush is guaranteed to occur before Duktape stops + * reading for a while; it may occur in other situations as well so + * it's not a 100% reliable indication. + */ + + /* This TCP transport requires no read flush handling so ignore. + * You can also pass a NULL to duk_debugger_attach() and not + * implement this callback at all. + */ +} + +void duk_trans_socket_write_flush_cb(void *udata) { + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata); + fflush(stderr); +#endif + + /* Write flush. If the transport combines multiple writes + * before actually sending, a write flush is an indication + * to write out any pending bytes: Duktape may not be doing + * any more writes on this occasion. + */ + + /* This TCP transport requires no write flush handling so ignore. + * You can also pass a NULL to duk_debugger_attach() and not + * implement this callback at all. + */ + return; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_windows.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_windows.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_windows.c new file mode 100644 index 0000000..e92ac26 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_windows.c @@ -0,0 +1,414 @@ +/* + * Example debug transport using a Windows TCP socket + * + * Provides a TCP server socket which a debug client can connect to. + * After that data is just passed through. + * + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx + * + * Compiling 'duk' with debugger support using MSVC (Visual Studio): + * + * > cl /W3 /O2 /Feduk.exe + * /DDUK_OPT_DEBUGGER_SUPPORT /DDUK_OPT_INTERRUPT_COUNTER + * /DDUK_CMDLINE_DEBUGGER_SUPPORT + * /Iexamples\debug-trans-socket /Isrc + * examples\cmdline\duk_cmdline.c + * examples\debug-trans-socket\duk_trans_socket_windows.c + * src\duktape.c + * + * With MinGW: + * + * $ gcc -oduk.exe -Wall -O2 \ + * -DDUK_OPT_DEBUGGER_SUPPORT -DDUK_OPT_INTERRUPT_COUNTER \ + * -DDUK_CMDLINE_DEBUGGER_SUPPORT \ + * -Iexamples/debug-trans-socket -Isrc \ + * examples/cmdline/duk_cmdline.c \ + * examples/debug-trans-socket/duk_trans_socket_windows.c \ + * src/duktape.c -lm -lws2_32 + */ + +#undef UNICODE +#if !defined(WIN32_LEAN_AND_MEAN) +#define WIN32_LEAN_AND_MEAN +#endif + +/* MinGW workaround for missing getaddrinfo() etc: + * http://programmingrants.blogspot.fi/2009/09/tips-on-undefined-reference-to.html + */ +#if defined(__MINGW32__) || defined(__MINGW64__) +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0501 +#endif +#endif + +#include <windows.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#include <stdio.h> +#include <string.h> +#include "duktape.h" + +#if defined(_MSC_VER) +#pragma comment (lib, "Ws2_32.lib") +#endif + +#if !defined(DUK_DEBUG_PORT) +#define DUK_DEBUG_PORT 9091 +#endif +#if !defined(DUK_DEBUG_ADDRESS) +#define DUK_DEBUG_ADDRESS "0.0.0.0" +#endif +#define DUK__STRINGIFY_HELPER(x) #x +#define DUK__STRINGIFY(x) DUK__STRINGIFY_HELPER(x) + +#if 0 +#define DEBUG_PRINTS +#endif + +static SOCKET server_sock = INVALID_SOCKET; +static SOCKET client_sock = INVALID_SOCKET; +static int wsa_inited = 0; + +/* + * Transport init and finish + */ + +void duk_trans_socket_init(void) { + WSADATA wsa_data; + struct addrinfo hints; + struct addrinfo *result = NULL; + int rc; + + memset((void *) &wsa_data, 0, sizeof(wsa_data)); + memset((void *) &hints, 0, sizeof(hints)); + + rc = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (rc != 0) { + fprintf(stderr, "%s: WSAStartup() failed: %d\n", __FILE__, rc); + fflush(stderr); + goto fail; + } + wsa_inited = 1; + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + + rc = getaddrinfo(DUK_DEBUG_ADDRESS, DUK__STRINGIFY(DUK_DEBUG_PORT), &hints, &result); + if (rc != 0) { + fprintf(stderr, "%s: getaddrinfo() failed: %d\n", __FILE__, rc); + fflush(stderr); + goto fail; + } + + server_sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + if (server_sock == INVALID_SOCKET) { + fprintf(stderr, "%s: socket() failed with error: %ld\n", + __FILE__, (long) WSAGetLastError()); + fflush(stderr); + goto fail; + } + + rc = bind(server_sock, result->ai_addr, (int) result->ai_addrlen); + if (rc == SOCKET_ERROR) { + fprintf(stderr, "%s: bind() failed with error: %ld\n", + __FILE__, (long) WSAGetLastError()); + fflush(stderr); + goto fail; + } + + rc = listen(server_sock, SOMAXCONN); + if (rc == SOCKET_ERROR) { + fprintf(stderr, "%s: listen() failed with error: %ld\n", + __FILE__, (long) WSAGetLastError()); + fflush(stderr); + goto fail; + } + + if (result != NULL) { + freeaddrinfo(result); + result = NULL; + } + return; + + fail: + if (result != NULL) { + freeaddrinfo(result); + result = NULL; + } + if (server_sock != INVALID_SOCKET) { + (void) closesocket(server_sock); + server_sock = INVALID_SOCKET; + } + if (wsa_inited) { + WSACleanup(); + wsa_inited = 0; + } +} + +void duk_trans_socket_finish(void) { + if (client_sock != INVALID_SOCKET) { + (void) closesocket(client_sock); + client_sock = INVALID_SOCKET; + } + if (server_sock != INVALID_SOCKET) { + (void) closesocket(server_sock); + server_sock = INVALID_SOCKET; + } + if (wsa_inited) { + WSACleanup(); + wsa_inited = 0; + } +} + +void duk_trans_socket_waitconn(void) { + if (server_sock == INVALID_SOCKET) { + fprintf(stderr, "%s: no server socket, skip waiting for connection\n", + __FILE__); + fflush(stderr); + return; + } + if (client_sock != INVALID_SOCKET) { + (void) closesocket(client_sock); + client_sock = INVALID_SOCKET; + } + + fprintf(stderr, "Waiting for debug connection on port %d\n", (int) DUK_DEBUG_PORT); + fflush(stderr); + + client_sock = accept(server_sock, NULL, NULL); + if (client_sock == INVALID_SOCKET) { + fprintf(stderr, "%s: accept() failed with error %ld, skip waiting for connection\n", + __FILE__, (long) WSAGetLastError()); + fflush(stderr); + goto fail; + } + + fprintf(stderr, "Debug connection established\n"); + fflush(stderr); + + /* XXX: For now, close the listen socket because we won't accept new + * connections anyway. A better implementation would allow multiple + * debug attaches. + */ + + if (server_sock != INVALID_SOCKET) { + (void) closesocket(server_sock); + server_sock = INVALID_SOCKET; + } + return; + + fail: + if (client_sock != INVALID_SOCKET) { + (void) closesocket(client_sock); + client_sock = INVALID_SOCKET; + } +} + +/* + * Duktape callbacks + */ + +/* Duktape debug transport callback: (possibly partial) read. */ +duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length) { + int ret; + + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n", + __FUNCTION__, (void *) udata, (void *) buffer, (long) length); + fflush(stderr); +#endif + + if (client_sock == INVALID_SOCKET) { + return 0; + } + + if (length == 0) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: read request length == 0, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + if (buffer == NULL) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: read request buffer == NULL, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + /* In a production quality implementation there would be a sanity + * timeout here to recover from "black hole" disconnects. + */ + + ret = recv(client_sock, (void *) buffer, (int) length, 0); + if (ret < 0) { + fprintf(stderr, "%s: debug read failed, error %d, closing connection\n", + __FILE__, ret); + fflush(stderr); + goto fail; + } else if (ret == 0) { + fprintf(stderr, "%s: debug read failed, ret == 0 (EOF), closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } else if (ret > (int) length) { + fprintf(stderr, "%s: debug read failed, ret too large (%ld > %ld), closing connection\n", + __FILE__, (long) ret, (long) length); + fflush(stderr); + goto fail; + } + + return (duk_size_t) ret; + + fail: + if (client_sock != INVALID_SOCKET) { + (void) closesocket(client_sock); + client_sock = INVALID_SOCKET; + } + return 0; +} + +/* Duktape debug transport callback: (possibly partial) write. */ +duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length) { + int ret; + + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n", + __FUNCTION__, (void *) udata, (const void *) buffer, (long) length); + fflush(stderr); +#endif + + if (client_sock == INVALID_SOCKET) { + return 0; + } + + if (length == 0) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: write request length == 0, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + if (buffer == NULL) { + /* This shouldn't happen. */ + fprintf(stderr, "%s: write request buffer == NULL, closing connection\n", + __FILE__); + fflush(stderr); + goto fail; + } + + /* In a production quality implementation there would be a sanity + * timeout here to recover from "black hole" disconnects. + */ + + ret = send(client_sock, (const void *) buffer, (int) length, 0); + if (ret <= 0 || ret > (int) length) { + fprintf(stderr, "%s: debug write failed, ret %d, closing connection\n", + __FILE__, ret); + fflush(stderr); + goto fail; + } + + return (duk_size_t) ret; + + fail: + if (client_sock != INVALID_SOCKET) { + (void) closesocket(INVALID_SOCKET); + client_sock = INVALID_SOCKET; + } + return 0; +} + +duk_size_t duk_trans_socket_peek_cb(void *udata) { + u_long avail; + int rc; + + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p\n", __FUNCTION__, (void *) udata); + fflush(stderr); +#endif + + if (client_sock == INVALID_SOCKET) { + return 0; + } + + avail = 0; + rc = ioctlsocket(client_sock, FIONREAD, &avail); + if (rc != 0) { + fprintf(stderr, "%s: ioctlsocket() returned %d, closing connection\n", + __FILE__, rc); + fflush(stderr); + goto fail; /* also returns 0, which is correct */ + } else { + if (avail == 0) { + return 0; /* nothing to read */ + } else { + return 1; /* something to read */ + } + } + /* never here */ + + fail: + if (client_sock != INVALID_SOCKET) { + (void) closesocket(client_sock); + client_sock = INVALID_SOCKET; + } + return 0; +} + +void duk_trans_socket_read_flush_cb(void *udata) { + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p\n", __FUNCTION__, (void *) udata); + fflush(stderr); +#endif + + /* Read flush: Duktape may not be making any more read calls at this + * time. If the transport maintains a receive window, it can use a + * read flush as a signal to update the window status to the remote + * peer. A read flush is guaranteed to occur before Duktape stops + * reading for a while; it may occur in other situations as well so + * it's not a 100% reliable indication. + */ + + /* This TCP transport requires no read flush handling so ignore. + * You can also pass a NULL to duk_debugger_attach() and not + * implement this callback at all. + */ +} + +void duk_trans_socket_write_flush_cb(void *udata) { + (void) udata; /* not needed by the example */ + +#if defined(DEBUG_PRINTS) + fprintf(stderr, "%s: udata=%p\n", __FUNCTION__, (void *) udata); + fflush(stderr); +#endif + + /* Write flush. If the transport combines multiple writes + * before actually sending, a write flush is an indication + * to write out any pending bytes: Duktape may not be doing + * any more writes on this occasion. + */ + + /* This TCP transport requires no write flush handling so ignore. + * You can also pass a NULL to duk_debugger_attach() and not + * implement this callback at all. + */ + return; +} + +#undef DUK__STRINGIFY_HELPER +#undef DUK__STRINGIFY http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/README.rst b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/README.rst new file mode 100644 index 0000000..bc62779 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/README.rst @@ -0,0 +1,5 @@ +==================================== +Dummy external Date provider example +==================================== + +This example implements a dummy, minimal external Date provider. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/dummy_date_provider.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/dummy_date_provider.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/dummy_date_provider.c new file mode 100644 index 0000000..9c9e716 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/dummy-date-provider/dummy_date_provider.c @@ -0,0 +1,27 @@ +/* + * Dummy Date provider + * + * There are two minimally required macros which you must provide in + * duk_config.h: + * + * extern duk_double_t dummy_get_now(void); + * + * #define DUK_USE_DATE_GET_NOW(ctx) dummy_get_now() + * #define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) 0 + * + * Note that since the providers are macros, you don't need to use + * all arguments. Similarly, you can "return" fixed values as + * constants. Above, local timezone offset is always zero i.e. + * we're always in UTC. + * + * You can also provide optional macros to parse and format timestamps + * in a platform specific format. If not provided, Duktape will use + * ISO 8601 only (which is often good enough). + */ + +#include "duktape.h" + +duk_double_t dummy_get_now(void) { + /* Return a fixed time here as a dummy example. */ + return -11504520000.0; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/README.rst ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/README.rst b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/README.rst new file mode 100644 index 0000000..eed1806 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/README.rst @@ -0,0 +1,5 @@ +============ +Eval example +============ + +Evaluate expressions from command line. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/eval.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/eval.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/eval.c new file mode 100644 index 0000000..4409926 --- /dev/null +++ b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eval/eval.c @@ -0,0 +1,48 @@ +/* + * Very simple example program for evaluating expressions from + * command line + */ + +#include "duktape.h" +#include <stdio.h> + +static int eval_raw(duk_context *ctx) { + duk_eval(ctx); + return 1; +} + +static int tostring_raw(duk_context *ctx) { + duk_to_string(ctx, -1); + return 1; +} + +static void usage_exit(void) { + fprintf(stderr, "Usage: eval <expression> [<expression>] ...\n"); + fflush(stderr); + exit(1); +} + +int main(int argc, char *argv[]) { + duk_context *ctx; + int i; + const char *res; + + if (argc < 2) { + usage_exit(); + } + + ctx = duk_create_heap_default(); + for (i = 1; i < argc; i++) { + printf("=== eval: '%s' ===\n", argv[i]); + duk_push_string(ctx, argv[i]); + duk_safe_call(ctx, eval_raw, 1 /*nargs*/, 1 /*nrets*/); + duk_safe_call(ctx, tostring_raw, 1 /*nargs*/, 1 /*nrets*/); + res = duk_get_string(ctx, -1); + printf("%s\n", res ? res : "null"); + duk_pop(ctx); + } + + duk_destroy_heap(ctx); + + return 0; +}