diff options
Diffstat (limited to '')
-rw-r--r-- | src/civetweb/src/third_party/duktape-1.8.0/examples/eventloop/main.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.8.0/examples/eventloop/main.c b/src/civetweb/src/third_party/duktape-1.8.0/examples/eventloop/main.c new file mode 100644 index 000000000..762792184 --- /dev/null +++ b/src/civetweb/src/third_party/duktape-1.8.0/examples/eventloop/main.c @@ -0,0 +1,256 @@ +/* + * Main for evloop command line tool. + * + * Runs a given script from file or stdin inside an eventloop. The + * script can then access setTimeout() etc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef NO_SIGNAL +#include <signal.h> +#endif + +#include "duktape.h" + +extern void poll_register(duk_context *ctx); +extern void ncurses_register(duk_context *ctx); +extern void socket_register(duk_context *ctx); +extern void fileio_register(duk_context *ctx); +extern void eventloop_register(duk_context *ctx); +extern int eventloop_run(duk_context *ctx); /* Duktape/C function, safe called */ + +static int c_evloop = 0; + +#ifndef NO_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); +} +#endif /* NO_SIGNAL */ + +/* Print error to stderr and pop error. */ +static void print_error(duk_context *ctx, FILE *f) { + if (duk_is_object(ctx, -1) && duk_has_prop_string(ctx, -1, "stack")) { + /* XXX: print error objects specially */ + /* XXX: pcall the string coercion */ + duk_get_prop_string(ctx, -1, "stack"); + if (duk_is_string(ctx, -1)) { + fprintf(f, "%s\n", duk_get_string(ctx, -1)); + fflush(f); + duk_pop_2(ctx); + return; + } else { + duk_pop(ctx); + } + } + duk_to_string(ctx, -1); + fprintf(f, "%s\n", duk_get_string(ctx, -1)); + fflush(f); + duk_pop(ctx); +} + +int wrapped_compile_execute(duk_context *ctx) { + int comp_flags = 0; + int rc; + + /* Compile input and place it into global _USERCODE */ + duk_compile(ctx, comp_flags); + duk_push_global_object(ctx); + duk_insert(ctx, -2); /* [ ... global func ] */ + duk_put_prop_string(ctx, -2, "_USERCODE"); + duk_pop(ctx); +#if 0 + printf("compiled usercode\n"); +#endif + + /* Start a zero timer which will call _USERCODE from within + * the event loop. + */ + fprintf(stderr, "set _USERCODE timer\n"); + fflush(stderr); + duk_eval_string(ctx, "setTimeout(function() { _USERCODE(); }, 0);"); + duk_pop(ctx); + + /* Finally, launch eventloop. This call only returns after the + * eventloop terminates. + */ + if (c_evloop) { + fprintf(stderr, "calling eventloop_run()\n"); + fflush(stderr); + rc = duk_safe_call(ctx, eventloop_run, 0 /*nargs*/, 1 /*nrets*/); + if (rc != 0) { + fprintf(stderr, "eventloop_run() failed: %s\n", duk_to_string(ctx, -1)); + fflush(stderr); + } + duk_pop(ctx); + } else { + fprintf(stderr, "calling EventLoop.run()\n"); + fflush(stderr); + duk_eval_string(ctx, "EventLoop.run();"); + duk_pop(ctx); + } + + return 0; +} + +int handle_fh(duk_context *ctx, FILE *f, const char *filename) { + char *buf = NULL; + int len; + int got; + int rc; + int retval = -1; + + if (fseek(f, 0, SEEK_END) < 0) { + goto error; + } + len = (int) ftell(f); + if (fseek(f, 0, SEEK_SET) < 0) { + goto error; + } + buf = (char *) malloc(len); + if (!buf) { + goto error; + } + + got = fread((void *) buf, (size_t) 1, (size_t) len, f); + + duk_push_lstring(ctx, buf, got); + duk_push_string(ctx, filename); + + free(buf); + buf = NULL; + + rc = duk_safe_call(ctx, wrapped_compile_execute, 2 /*nargs*/, 1 /*nret*/); + if (rc != DUK_EXEC_SUCCESS) { + print_error(ctx, stderr); + goto error; + } else { + duk_pop(ctx); + retval = 0; + } + /* fall thru */ + + error: + if (buf) { + free(buf); + } + return retval; +} + +int handle_file(duk_context *ctx, const char *filename) { + FILE *f = NULL; + int retval; + + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "failed to open source file: %s\n", filename); + fflush(stderr); + goto error; + } + + retval = handle_fh(ctx, f, filename); + + fclose(f); + return retval; + + error: + return -1; +} + +int handle_stdin(duk_context *ctx) { + int retval; + + retval = handle_fh(ctx, stdin, "stdin"); + + return retval; +} + +int main(int argc, char *argv[]) { + duk_context *ctx = NULL; + int retval = 0; + const char *filename = NULL; + int i; + +#ifndef NO_SIGNAL + set_sigint_handler(); + + /* This is useful at the global level; libraries should avoid SIGPIPE though */ + /*signal(SIGPIPE, SIG_IGN);*/ +#endif + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + if (!arg) { + goto usage; + } + if (strcmp(arg, "-c") == 0) { + c_evloop = 1; + } else if (strlen(arg) > 1 && arg[0] == '-') { + goto usage; + } else { + if (filename) { + goto usage; + } + filename = arg; + } + } + if (!filename) { + goto usage; + } + + ctx = duk_create_heap_default(); + + poll_register(ctx); + ncurses_register(ctx); + socket_register(ctx); + fileio_register(ctx); + + if (c_evloop) { + fprintf(stderr, "Using C based eventloop (omit -c to use Ecmascript based eventloop)\n"); + fflush(stderr); + + eventloop_register(ctx); + duk_eval_file(ctx, "c_eventloop.js"); + } else { + fprintf(stderr, "Using Ecmascript based eventloop (give -c to use C based eventloop)\n"); + fflush(stderr); + + duk_eval_file(ctx, "ecma_eventloop.js"); + } + + fprintf(stderr, "Executing code from: '%s'\n", filename); + fflush(stderr); + + if (strcmp(filename, "-") == 0) { + if (handle_stdin(ctx) != 0) { + retval = 1; + goto cleanup; + } + } else { + if (handle_file(ctx, filename) != 0) { + retval = 1; + goto cleanup; + } + } + + cleanup: + if (ctx) { + duk_destroy_heap(ctx); + } + + return retval; + + usage: + fprintf(stderr, "Usage: evloop [-c] <filename>\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Uses an Ecmascript based eventloop (ecma_eventloop.js) by default.\n"); + fprintf(stderr, "If -c option given, uses a C based eventloop (c_eventloop.{c,js}).\n"); + fprintf(stderr, "If <filename> is '-', the entire STDIN executed.\n"); + fflush(stderr); + exit(1); +} |