Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duk_cmdline.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "duktape.h"

Go to the source code of this file.

Macros

#define GREET_CODE(variant)
 
#define MEM_LIMIT_NORMAL   (128*1024*1024) /* 128 MB */
 
#define MEM_LIMIT_HIGH   (2047*1024*1024) /* ~2 GB */
 
#define LINEBUF_SIZE   65536
 
#define ALLOC_DEFAULT   0
 
#define ALLOC_LOGGING   1
 
#define ALLOC_TORTURE   2
 
#define ALLOC_HYBRID   3
 
#define ALLOC_AJSHEAP   4
 

Functions

static int get_stack_raw (duk_context *ctx)
 
static void print_pop_error (duk_context *ctx, FILE *f)
 
static int wrapped_compile_execute (duk_context *ctx)
 
static int handle_fh (duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename)
 
static int handle_file (duk_context *ctx, const char *filename, const char *bytecode_filename)
 
static int handle_eval (duk_context *ctx, char *code)
 
static int handle_interactive (duk_context *ctx)
 
static duk_contextcreate_duktape_heap (int alloc_provider, int debugger, int ajsheap_log)
 
static void destroy_duktape_heap (duk_context *ctx, int alloc_provider)
 
int main (int argc, char *argv[])
 

Variables

static int main_argc = 0
 
static char ** main_argv = NULL
 
static int interactive_mode = 0
 

Macro Definition Documentation

◆ ALLOC_AJSHEAP

#define ALLOC_AJSHEAP   4

◆ ALLOC_DEFAULT

#define ALLOC_DEFAULT   0

Definition at line 994 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by create_duktape_heap(), and main().

◆ ALLOC_HYBRID

#define ALLOC_HYBRID   3

Definition at line 997 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by create_duktape_heap(), and main().

◆ ALLOC_LOGGING

#define ALLOC_LOGGING   1

Definition at line 995 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by create_duktape_heap(), and main().

◆ ALLOC_TORTURE

#define ALLOC_TORTURE   2

Definition at line 996 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by create_duktape_heap(), and main().

◆ GREET_CODE

#define GREET_CODE ( variant)
Value:
"print('((o) Duktape" variant " ' + " \
"Math.floor(Duktape.version / 10000) + '.' + " \
"Math.floor(Duktape.version / 100) % 100 + '.' + " \
"Duktape.version % 100" \
", '(" DUK_GIT_DESCRIBE ")');"

Definition at line 31 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

31#define GREET_CODE(variant) \
32 "print('((o) Duktape" variant " ' + " \
33 "Math.floor(Duktape.version / 10000) + '.' + " \
34 "Math.floor(Duktape.version / 100) % 100 + '.' + " \
35 "Duktape.version % 100" \
36 ", '(" DUK_GIT_DESCRIBE ")');"

Referenced by handle_interactive().

◆ LINEBUF_SIZE

#define LINEBUF_SIZE   65536

Definition at line 89 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by handle_interactive().

◆ MEM_LIMIT_HIGH

#define MEM_LIMIT_HIGH   (2047*1024*1024) /* ~2 GB */

Definition at line 88 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by main().

◆ MEM_LIMIT_NORMAL

#define MEM_LIMIT_NORMAL   (128*1024*1024) /* 128 MB */

Definition at line 87 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by main().

Function Documentation

◆ create_duktape_heap()

static duk_context * create_duktape_heap ( int alloc_provider,
int debugger,
int ajsheap_log )
static

Definition at line 1000 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

1000 {
1001 duk_context *ctx;
1002
1003 (void) ajsheap_log; /* suppress warning */
1004
1005 ctx = NULL;
1006 if (!ctx && alloc_provider == ALLOC_LOGGING) {
1007#if defined(DUK_CMDLINE_ALLOC_LOGGING)
1011 (void *) 0xdeadbeef,
1012 NULL);
1013#else
1014 fprintf(stderr, "Warning: option --alloc-logging ignored, no logging allocator support\n");
1015 fflush(stderr);
1016#endif
1017 }
1018 if (!ctx && alloc_provider == ALLOC_TORTURE) {
1019#if defined(DUK_CMDLINE_ALLOC_TORTURE)
1023 (void *) 0xdeadbeef,
1024 NULL);
1025#else
1026 fprintf(stderr, "Warning: option --alloc-torture ignored, no torture allocator support\n");
1027 fflush(stderr);
1028#endif
1029 }
1030 if (!ctx && alloc_provider == ALLOC_HYBRID) {
1031#if defined(DUK_CMDLINE_ALLOC_HYBRID)
1032 void *udata = duk_alloc_hybrid_init();
1033 if (!udata) {
1034 fprintf(stderr, "Failed to init hybrid allocator\n");
1035 fflush(stderr);
1036 } else {
1040 udata,
1041 NULL);
1042 }
1043#else
1044 fprintf(stderr, "Warning: option --alloc-hybrid ignored, no hybrid allocator support\n");
1045 fflush(stderr);
1046#endif
1047 }
1048 if (!ctx && alloc_provider == ALLOC_AJSHEAP) {
1049#if defined(DUK_CMDLINE_AJSHEAP)
1050 ajsheap_init();
1051
1052 ctx = duk_create_heap(
1053 ajsheap_log ? ajsheap_alloc_wrapped : AJS_Alloc,
1054 ajsheap_log ? ajsheap_realloc_wrapped : AJS_Realloc,
1055 ajsheap_log ? ajsheap_free_wrapped : AJS_Free,
1056 (void *) 0xdeadbeef, /* heap_udata: ignored by AjsHeap, use as marker */
1057 NULL
1058 ); /* fatal_handler */
1059#else
1060 fprintf(stderr, "Warning: option --alloc-ajsheap ignored, no ajsheap allocator support\n");
1061 fflush(stderr);
1062#endif
1063 }
1064 if (!ctx && alloc_provider == ALLOC_DEFAULT) {
1066 }
1067
1068 if (!ctx) {
1069 fprintf(stderr, "Failed to create Duktape heap\n");
1070 fflush(stderr);
1071 exit(-1);
1072 }
1073
1074#if defined(DUK_CMDLINE_AJSHEAP)
1075 if (alloc_provider == ALLOC_AJSHEAP) {
1076 fprintf(stdout, "Pool dump after heap creation\n");
1077 ajsheap_dump();
1078 }
1079#endif
1080
1081#if defined(DUK_CMDLINE_AJSHEAP)
1082 if (alloc_provider == ALLOC_AJSHEAP) {
1083 ajsheap_register(ctx);
1084 }
1085#endif
1086
1087#if defined(DUK_CMDLINE_FILEIO)
1088 duk_push_c_function(ctx, fileio_read_file, 1 /*nargs*/);
1089 duk_put_global_string(ctx, "readFile");
1090 duk_push_c_function(ctx, fileio_write_file, 2 /*nargs*/);
1091 duk_put_global_string(ctx, "writeFile");
1092#endif
1093
1094 if (debugger) {
1095#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
1096 fprintf(stderr, "Debugger enabled, create socket and wait for connection\n");
1097 fflush(stderr);
1100 fprintf(stderr, "Debugger connected, call duk_debugger_attach() and then execute requested file(s)/eval\n");
1101 fflush(stderr);
1108 debugger_request,
1109 debugger_detached,
1110 (void *) ctx);
1111#else
1112 fprintf(stderr, "Warning: option --debugger ignored, no debugger support\n");
1113 fflush(stderr);
1114#endif
1115 }
1116
1117#if 0
1118 /* Manual test for duk_debugger_cooperate() */
1119 {
1120 for (i = 0; i < 60; i++) {
1121 printf("cooperate: %d\n", i);
1122 usleep(1000000);
1124 }
1125 }
1126#endif
1127
1128 return ctx;
1129}
void * duk_realloc_hybrid(void *udata, void *ptr, duk_size_t size)
void * duk_alloc_hybrid(void *udata, duk_size_t size)
void duk_free_hybrid(void *udata, void *ptr)
void * duk_alloc_logging(void *udata, duk_size_t size)
void * duk_realloc_logging(void *udata, void *ptr, duk_size_t size)
void duk_free_logging(void *udata, void *ptr)
void * duk_realloc_torture(void *udata, void *ptr, duk_size_t size)
void duk_free_torture(void *udata, void *ptr)
void * duk_alloc_torture(void *udata, duk_size_t size)
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_EXTERNAL void duk_debugger_cooperate(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key)
DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs)
DUK_EXTERNAL void duk_debugger_attach_custom(duk_context *ctx, duk_debug_read_function read_cb, duk_debug_write_function write_cb, duk_debug_peek_function peek_cb, duk_debug_read_flush_function read_flush_cb, duk_debug_write_flush_function write_flush_cb, duk_debug_request_function request_cb, duk_debug_detached_function detached_cb, void *udata)
DUK_EXTERNAL duk_context * duk_create_heap(duk_alloc_function alloc_func, duk_realloc_function realloc_func, duk_free_function free_func, void *heap_udata, duk_fatal_function fatal_handler)
#define duk_create_heap_default()
#define NULL
Definition gmacros.h:924
#define printf

References ALLOC_AJSHEAP, ALLOC_DEFAULT, ALLOC_HYBRID, ALLOC_LOGGING, ALLOC_TORTURE, duk_alloc_hybrid(), duk_alloc_hybrid_init(), duk_alloc_logging(), duk_alloc_torture(), duk_create_heap(), duk_create_heap_default, duk_debugger_attach_custom(), duk_debugger_cooperate(), duk_free_hybrid(), duk_free_logging(), duk_free_torture(), duk_push_c_function(), duk_put_global_string(), duk_realloc_hybrid(), duk_realloc_logging(), duk_realloc_torture(), duk_trans_socket_init(), duk_trans_socket_peek_cb(), duk_trans_socket_read_cb(), duk_trans_socket_read_flush_cb(), duk_trans_socket_waitconn(), duk_trans_socket_write_cb(), duk_trans_socket_write_flush_cb(), NULL, and printf.

Referenced by main().

◆ destroy_duktape_heap()

static void destroy_duktape_heap ( duk_context * ctx,
int alloc_provider )
static

Definition at line 1131 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

1131 {
1132 (void) alloc_provider;
1133
1134#if defined(DUK_CMDLINE_AJSHEAP)
1135 if (alloc_provider == ALLOC_AJSHEAP) {
1136 fprintf(stdout, "Pool dump before duk_destroy_heap(), before forced gc\n");
1137 ajsheap_dump();
1138
1139 duk_gc(ctx, 0);
1140
1141 fprintf(stdout, "Pool dump before duk_destroy_heap(), after forced gc\n");
1142 ajsheap_dump();
1143 }
1144#endif
1145
1146 if (ctx) {
1147 duk_destroy_heap(ctx);
1148 }
1149
1150#if defined(DUK_CMDLINE_AJSHEAP)
1151 if (alloc_provider == ALLOC_AJSHEAP) {
1152 fprintf(stdout, "Pool dump after duk_destroy_heap() (should have zero allocs)\n");
1153 ajsheap_dump();
1154 }
1155 ajsheap_free();
1156#endif
1157}
DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags)
DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx)

References ALLOC_AJSHEAP, duk_destroy_heap(), and duk_gc().

Referenced by main().

◆ get_stack_raw()

static int get_stack_raw ( duk_context * ctx)
static

Definition at line 144 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

144 {
145 if (!duk_is_object(ctx, -1)) {
146 return 1;
147 }
148 if (!duk_has_prop_string(ctx, -1, "stack")) {
149 return 1;
150 }
151 if (!duk_is_error(ctx, -1)) {
152 /* Not an Error instance, don't read "stack". */
153 return 1;
154 }
155
156 duk_get_prop_string(ctx, -1, "stack"); /* caller coerces */
157 duk_remove(ctx, -2);
158 return 1;
159}
DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key)
DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key)
#define duk_is_error(ctx, index)

References duk_get_prop_string(), duk_has_prop_string(), duk_is_error, duk_is_object(), and duk_remove().

Referenced by print_pop_error().

◆ handle_eval()

static int handle_eval ( duk_context * ctx,
char * code )
static

Definition at line 657 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

657 {
658 int rc;
659 int retval = -1;
660
661 duk_push_pointer(ctx, (void *) code);
662 duk_push_uint(ctx, (duk_uint_t) strlen(code));
663 duk_push_string(ctx, "eval");
664
665 interactive_mode = 0; /* global */
666
667 rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/);
668
669#if defined(DUK_CMDLINE_AJSHEAP)
670 ajsheap_clear_exec_timeout();
671#endif
672
673 if (rc != DUK_EXEC_SUCCESS) {
674 print_pop_error(ctx, stderr);
675 } else {
676 duk_pop(ctx);
677 retval = 0;
678 }
679
680 return retval;
681}
static void print_pop_error(duk_context *ctx, FILE *f)
static int wrapped_compile_execute(duk_context *ctx)
duk_uint_fast32_t duk_uint_t
DUK_EXTERNAL const char * duk_push_string(duk_context *ctx, const char *str)
DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val)
DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets)
DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val)
DUK_EXTERNAL void duk_pop(duk_context *ctx)

References DUK_EXEC_SUCCESS, duk_pop(), duk_push_pointer(), duk_push_string(), duk_push_uint(), duk_safe_call(), interactive_mode, print_pop_error(), and wrapped_compile_execute().

Referenced by main().

◆ handle_fh()

static int handle_fh ( duk_context * ctx,
FILE * f,
const char * filename,
const char * bytecode_filename )
static

Definition at line 493 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

493 {
494 char *buf = NULL;
495 size_t bufsz;
496 size_t bufoff;
497 size_t got;
498 int rc;
499 int retval = -1;
500
501 buf = (char *) malloc(1024);
502 if (!buf) {
503 goto error;
504 }
505 bufsz = 1024;
506 bufoff = 0;
507
508 /* Read until EOF, avoid fseek/stat because it won't work with stdin. */
509 for (;;) {
510 size_t avail;
511
512 avail = bufsz - bufoff;
513 if (avail < 1024) {
514 size_t newsz;
515 char *buf_new;
516#if 0
517 fprintf(stderr, "resizing read buffer: %ld -> %ld\n", (long) bufsz, (long) (bufsz * 2));
518#endif
519 newsz = bufsz + (bufsz >> 2) + 1024; /* +25% and some extra */
520 buf_new = (char *) realloc(buf, newsz);
521 if (!buf_new) {
522 goto error;
523 }
524 buf = buf_new;
525 bufsz = newsz;
526 }
527
528 avail = bufsz - bufoff;
529#if 0
530 fprintf(stderr, "reading input: buf=%p bufsz=%ld bufoff=%ld avail=%ld\n",
531 (void *) buf, (long) bufsz, (long) bufoff, (long) avail);
532#endif
533
534 got = fread((void *) (buf + bufoff), (size_t) 1, avail, f);
535#if 0
536 fprintf(stderr, "got=%ld\n", (long) got);
537#endif
538 if (got == 0) {
539 break;
540 }
541 bufoff += got;
542
543 /* Emscripten specific: stdin EOF doesn't work as expected.
544 * Instead, when 'emduk' is executed using Node.js, a file
545 * piped to stdin repeats (!). Detect that repeat and cut off
546 * the stdin read. Ensure the loop repeats enough times to
547 * avoid detecting spurious loops.
548 *
549 * This only seems to work for inputs up to 256 bytes long.
550 */
551#if defined(EMSCRIPTEN)
552 if (bufoff >= 16384) {
553 size_t i, j, nloops;
554 int looped = 0;
555
556 for (i = 16; i < bufoff / 8; i++) {
557 int ok;
558
559 nloops = bufoff / i;
560 ok = 1;
561 for (j = 1; j < nloops; j++) {
562 if (memcmp((void *) buf, (void *) (buf + i * j), i) != 0) {
563 ok = 0;
564 break;
565 }
566 }
567 if (ok) {
568 fprintf(stderr, "emscripten workaround: detect looping at index %ld, verified with %ld loops\n", (long) i, (long) (nloops - 1));
569 bufoff = i;
570 looped = 1;
571 break;
572 }
573 }
574
575 if (looped) {
576 break;
577 }
578 }
579#endif
580 }
581
582 duk_push_string(ctx, bytecode_filename);
583 duk_push_pointer(ctx, (void *) buf);
584 duk_push_uint(ctx, (duk_uint_t) bufoff);
585 duk_push_string(ctx, filename);
586
587 interactive_mode = 0; /* global */
588
589 rc = duk_safe_call(ctx, wrapped_compile_execute, 4 /*nargs*/, 1 /*nret*/);
590
591#if defined(DUK_CMDLINE_AJSHEAP)
592 ajsheap_clear_exec_timeout();
593#endif
594
595 free(buf);
596 buf = NULL;
597
598 if (rc != DUK_EXEC_SUCCESS) {
599 print_pop_error(ctx, stderr);
600 goto error;
601 } else {
602 duk_pop(ctx);
603 retval = 0;
604 }
605 /* fall thru */
606
607 cleanup:
608 if (buf) {
609 free(buf);
610 buf = NULL;
611 }
612 return retval;
613
614 error:
615 fprintf(stderr, "error in executing file %s\n", filename);
616 fflush(stderr);
617 goto cleanup;
618}
#define realloc
Definition civetweb.c:1541
#define free
Definition civetweb.c:1542
#define malloc
Definition civetweb.c:1539
static void error(LoadState *S, const char *why)
size_t fread(void *, size_t, size_t, FILE *)

References DUK_EXEC_SUCCESS, duk_pop(), duk_push_pointer(), duk_push_string(), duk_push_uint(), duk_safe_call(), error(), fread(), free, interactive_mode, malloc, NULL, print_pop_error(), realloc, and wrapped_compile_execute().

Referenced by handle_file(), and main().

◆ handle_file()

static int handle_file ( duk_context * ctx,
const char * filename,
const char * bytecode_filename )
static

Definition at line 620 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

620 {
621 FILE *f = NULL;
622 int retval;
623 char fnbuf[256];
624
625 /* Example of sending an application specific debugger notification. */
626 duk_push_string(ctx, "DebuggerHandleFile");
627 duk_push_string(ctx, filename);
628 duk_debugger_notify(ctx, 2);
629
630#if defined(EMSCRIPTEN)
631 if (filename[0] == '/') {
632 snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
633 } else {
634 snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename);
635 }
636#else
637 snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
638#endif
639 fnbuf[sizeof(fnbuf) - 1] = (char) 0;
640
641 f = fopen(fnbuf, "rb");
642 if (!f) {
643 fprintf(stderr, "failed to open source file: %s\n", filename);
644 fflush(stderr);
645 goto error;
646 }
647
648 retval = handle_fh(ctx, f, filename, bytecode_filename);
649
650 fclose(f);
651 return retval;
652
653 error:
654 return -1;
655}
#define snprintf
Definition civetweb.c:1543
static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename)
DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues)

References duk_debugger_notify(), duk_push_string(), error(), handle_fh(), NULL, and snprintf.

Referenced by main().

◆ handle_interactive()

static int handle_interactive ( duk_context * ctx)
static

Definition at line 755 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

755 {
756 const char *prompt = "duk> ";
757 char *buffer = NULL;
758 int retval = 0;
759 int rc;
760 int got_eof = 0;
761
762 duk_eval_string(ctx, GREET_CODE(""));
763 duk_pop(ctx);
764
765 buffer = (char *) malloc(LINEBUF_SIZE);
766 if (!buffer) {
767 fprintf(stderr, "failed to allocated a line buffer\n");
768 fflush(stderr);
769 retval = -1;
770 goto done;
771 }
772
773 while (!got_eof) {
774 size_t idx = 0;
775
776 fwrite(prompt, 1, strlen(prompt), stdout);
777 fflush(stdout);
778
779 for (;;) {
780 int c = fgetc(stdin);
781 if (c == EOF) {
782 got_eof = 1;
783 break;
784 } else if (c == '\n') {
785 break;
786 } else if (idx >= LINEBUF_SIZE) {
787 fprintf(stderr, "line too long\n");
788 fflush(stderr);
789 retval = -1;
790 goto done;
791 } else {
792 buffer[idx++] = (char) c;
793 }
794 }
795
796 duk_push_pointer(ctx, (void *) buffer);
797 duk_push_uint(ctx, (duk_uint_t) idx);
798 duk_push_string(ctx, "input");
799
800 interactive_mode = 1; /* global */
801
802 rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/);
803
804#if defined(DUK_CMDLINE_AJSHEAP)
805 ajsheap_clear_exec_timeout();
806#endif
807
808 if (rc != DUK_EXEC_SUCCESS) {
809 /* in interactive mode, write to stdout */
810 print_pop_error(ctx, stdout);
811 retval = -1; /* an error 'taints' the execution */
812 } else {
813 duk_pop(ctx);
814 }
815 }
816
817 done:
818 if (buffer) {
819 free(buffer);
820 buffer = NULL;
821 }
822
823 return retval;
824}
#define GREET_CODE(variant)
#define duk_eval_string(ctx, src)
size_t fwrite(const void *, size_t, size_t, FILE *)

References duk_eval_string, DUK_EXEC_SUCCESS, duk_pop(), duk_push_pointer(), duk_push_string(), duk_push_uint(), duk_safe_call(), free, fwrite(), GREET_CODE, interactive_mode, LINEBUF_SIZE, malloc, NULL, print_pop_error(), and wrapped_compile_execute().

Referenced by main().

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 1163 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

1163 {
1164 duk_context *ctx = NULL;
1165 int retval = 0;
1166 int have_files = 0;
1167 int have_eval = 0;
1168 int interactive = 0;
1169 int memlimit_high = 1;
1170 int alloc_provider = ALLOC_DEFAULT;
1171 int ajsheap_log = 0;
1172 int debugger = 0;
1173 int recreate_heap = 0;
1174 int no_heap_destroy = 0;
1175 int verbose = 0;
1176 int run_stdin = 0;
1177 const char *compile_filename = NULL;
1178 int i;
1179
1180 main_argc = argc;
1181 main_argv = (char **) argv;
1182
1183#if defined(EMSCRIPTEN)
1184 /* Try to use NODEFS to provide access to local files. Mount the
1185 * CWD as /working, and then prepend "/working/" to relative native
1186 * paths in file calls to get something that works reasonably for
1187 * relative paths. Emscripten doesn't support replacing virtual
1188 * "/" with host "/" (the default MEMFS at "/" can't be unmounted)
1189 * but we can mount "/tmp" as host "/tmp" to allow testcase runs.
1190 *
1191 * https://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.html#filesystem-api-nodefs
1192 * https://github.com/kripken/emscripten/blob/master/tests/fs/test_nodefs_rw.c
1193 */
1194 EM_ASM(
1195 /* At the moment it's not possible to replace the default MEMFS mounted at '/':
1196 * https://github.com/kripken/emscripten/issues/2040
1197 * https://github.com/kripken/emscripten/blob/incoming/src/library_fs.js#L1341-L1358
1198 */
1199 /*
1200 try {
1201 FS.unmount("/");
1202 } catch (e) {
1203 console.log("Failed to unmount default '/' MEMFS mount: " + e);
1204 }
1205 */
1206 try {
1207 FS.mkdir("/working");
1208 FS.mount(NODEFS, { root: "." }, "/working");
1209 } catch (e) {
1210 console.log("Failed to mount NODEFS /working: " + e);
1211 }
1212 /* A virtual '/tmp' exists by default:
1213 * https://gist.github.com/evanw/e6be28094f34451bd5bd#file-temp-js-L3806-L3809
1214 */
1215 /*
1216 try {
1217 FS.mkdir("/tmp");
1218 } catch (e) {
1219 console.log("Failed to create virtual /tmp: " + e);
1220 }
1221 */
1222 try {
1223 FS.mount(NODEFS, { root: "/tmp" }, "/tmp");
1224 } catch (e) {
1225 console.log("Failed to mount NODEFS /tmp: " + e);
1226 }
1227 );
1228#endif /* EMSCRIPTEN */
1229
1230#if defined(DUK_CMDLINE_AJSHEAP)
1231 alloc_provider = ALLOC_AJSHEAP;
1232#endif
1233 (void) ajsheap_log;
1234
1235 /*
1236 * Signal handling setup
1237 */
1238
1239#if defined(DUK_CMDLINE_SIGNAL)
1241
1242 /* This is useful at the global level; libraries should avoid SIGPIPE though */
1243 /*signal(SIGPIPE, SIG_IGN);*/
1244#endif
1245
1246 /*
1247 * Parse options
1248 */
1249
1250 for (i = 1; i < argc; i++) {
1251 char *arg = argv[i];
1252 if (!arg) {
1253 goto usage;
1254 }
1255 if (strcmp(arg, "--restrict-memory") == 0) {
1256 memlimit_high = 0;
1257 } else if (strcmp(arg, "-i") == 0) {
1258 interactive = 1;
1259 } else if (strcmp(arg, "-c") == 0) {
1260 if (i == argc - 1) {
1261 goto usage;
1262 }
1263 i++;
1264 compile_filename = argv[i];
1265 } else if (strcmp(arg, "-e") == 0) {
1266 have_eval = 1;
1267 if (i == argc - 1) {
1268 goto usage;
1269 }
1270 i++; /* skip code */
1271 } else if (strcmp(arg, "--alloc-default") == 0) {
1272 alloc_provider = ALLOC_DEFAULT;
1273 } else if (strcmp(arg, "--alloc-logging") == 0) {
1274 alloc_provider = ALLOC_LOGGING;
1275 } else if (strcmp(arg, "--alloc-torture") == 0) {
1276 alloc_provider = ALLOC_TORTURE;
1277 } else if (strcmp(arg, "--alloc-hybrid") == 0) {
1278 alloc_provider = ALLOC_HYBRID;
1279 } else if (strcmp(arg, "--alloc-ajsheap") == 0) {
1280 alloc_provider = ALLOC_AJSHEAP;
1281 } else if (strcmp(arg, "--ajsheap-log") == 0) {
1282 ajsheap_log = 1;
1283 } else if (strcmp(arg, "--debugger") == 0) {
1284 debugger = 1;
1285#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
1286 } else if (strcmp(arg, "--reattach") == 0) {
1287 debugger_reattach = 1;
1288#endif
1289 } else if (strcmp(arg, "--recreate-heap") == 0) {
1290 recreate_heap = 1;
1291 } else if (strcmp(arg, "--no-heap-destroy") == 0) {
1292 no_heap_destroy = 1;
1293 } else if (strcmp(arg, "--verbose") == 0) {
1294 verbose = 1;
1295 } else if (strcmp(arg, "--run-stdin") == 0) {
1296 run_stdin = 1;
1297 } else if (strlen(arg) >= 1 && arg[0] == '-') {
1298 goto usage;
1299 } else {
1300 have_files = 1;
1301 }
1302 }
1303 if (!have_files && !have_eval && !run_stdin) {
1304 interactive = 1;
1305 }
1306
1307 /*
1308 * Memory limit
1309 */
1310
1311#if defined(DUK_CMDLINE_RLIMIT)
1312 set_resource_limits(memlimit_high ? MEM_LIMIT_HIGH : MEM_LIMIT_NORMAL);
1313#else
1314 if (memlimit_high == 0) {
1315 fprintf(stderr, "Warning: option --restrict-memory ignored, no rlimit support\n");
1316 fflush(stderr);
1317 }
1318#endif
1319
1320 /*
1321 * Create heap
1322 */
1323
1324 ctx = create_duktape_heap(alloc_provider, debugger, ajsheap_log);
1325
1326 /*
1327 * Execute any argument file(s)
1328 */
1329
1330 for (i = 1; i < argc; i++) {
1331 char *arg = argv[i];
1332 if (!arg) {
1333 continue;
1334 } else if (strlen(arg) == 2 && strcmp(arg, "-e") == 0) {
1335 /* Here we know the eval arg exists but check anyway */
1336 if (i == argc - 1) {
1337 retval = 1;
1338 goto cleanup;
1339 }
1340 if (handle_eval(ctx, argv[i + 1]) != 0) {
1341 retval = 1;
1342 goto cleanup;
1343 }
1344 i++; /* skip code */
1345 continue;
1346 } else if (strlen(arg) == 2 && strcmp(arg, "-c") == 0) {
1347 i++; /* skip filename */
1348 continue;
1349 } else if (strlen(arg) >= 1 && arg[0] == '-') {
1350 continue;
1351 }
1352
1353 if (verbose) {
1354 fprintf(stderr, "*** Executing file: %s\n", arg);
1355 fflush(stderr);
1356 }
1357
1358 if (handle_file(ctx, arg, compile_filename) != 0) {
1359 retval = 1;
1360 goto cleanup;
1361 }
1362
1363 if (recreate_heap) {
1364 if (verbose) {
1365 fprintf(stderr, "*** Recreating heap...\n");
1366 fflush(stderr);
1367 }
1368
1369 destroy_duktape_heap(ctx, alloc_provider);
1370 ctx = create_duktape_heap(alloc_provider, debugger, ajsheap_log);
1371 }
1372 }
1373
1374 if (run_stdin) {
1375 /* Running stdin like a full file (reading all lines before
1376 * compiling) is useful with emduk:
1377 * cat test.js | ./emduk --run-stdin
1378 */
1379 if (handle_fh(ctx, stdin, "stdin", compile_filename) != 0) {
1380 retval = 1;
1381 goto cleanup;
1382 }
1383
1384 if (recreate_heap) {
1385 if (verbose) {
1386 fprintf(stderr, "*** Recreating heap...\n");
1387 fflush(stderr);
1388 }
1389
1390 destroy_duktape_heap(ctx, alloc_provider);
1391 ctx = create_duktape_heap(alloc_provider, debugger, ajsheap_log);
1392 }
1393 }
1394
1395 /*
1396 * Enter interactive mode if options indicate it
1397 */
1398
1399 if (interactive) {
1400 if (handle_interactive(ctx) != 0) {
1401 retval = 1;
1402 goto cleanup;
1403 }
1404 }
1405
1406 /*
1407 * Cleanup and exit
1408 */
1409
1410 cleanup:
1411 if (interactive) {
1412 fprintf(stderr, "Cleaning up...\n");
1413 fflush(stderr);
1414 }
1415
1416 if (ctx && no_heap_destroy) {
1417 duk_gc(ctx, 0);
1418 }
1419 if (ctx && !no_heap_destroy) {
1420 destroy_duktape_heap(ctx, alloc_provider);
1421 }
1422 ctx = NULL;
1423
1424 return retval;
1425
1426 /*
1427 * Usage
1428 */
1429
1430 usage:
1431 fprintf(stderr, "Usage: duk [options] [<filenames>]\n"
1432 "\n"
1433 " -i enter interactive mode after executing argument file(s) / eval code\n"
1434 " -e CODE evaluate code\n"
1435 " -c FILE compile into bytecode (use with only one file argument)\n"
1436 " --run-stdin treat stdin like a file, i.e. compile full input (not line by line)\n"
1437 " --verbose verbose messages to stderr\n"
1438 " --restrict-memory use lower memory limit (used by test runner)\n"
1439 " --alloc-default use Duktape default allocator\n"
1440#if defined(DUK_CMDLINE_ALLOC_LOGGING)
1441 " --alloc-logging use logging allocator (writes to /tmp)\n"
1442#endif
1443#if defined(DUK_CMDLINE_ALLOC_TORTURE)
1444 " --alloc-torture use torture allocator\n"
1445#endif
1446#if defined(DUK_CMDLINE_ALLOC_HYBRID)
1447 " --alloc-hybrid use hybrid allocator\n"
1448#endif
1449#if defined(DUK_CMDLINE_AJSHEAP)
1450 " --alloc-ajsheap use ajsheap allocator (enabled by default with 'ajduk')\n"
1451 " --ajsheap-log write alloc log to /tmp/ajduk-alloc-log.txt\n"
1452#endif
1453#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
1454 " --debugger start example debugger\n"
1455 " --reattach automatically reattach debugger on detach\n"
1456#endif
1457 " --recreate-heap recreate heap after every file\n"
1458 " --no-heap-destroy force GC, but don't destroy heap at end (leak testing)\n"
1459 "\n"
1460 "If <filename> is omitted, interactive mode is started automatically.\n");
1461 fflush(stderr);
1462 exit(1);
1463}
CURL_EXTERN int void * arg
Definition curl.h:2622
static int handle_file(duk_context *ctx, const char *filename, const char *bytecode_filename)
static int handle_eval(duk_context *ctx, char *code)
static duk_context * create_duktape_heap(int alloc_provider, int debugger, int ajsheap_log)
static void destroy_duktape_heap(duk_context *ctx, int alloc_provider)
static int handle_interactive(duk_context *ctx)
static void usage(const char *message)

References ALLOC_AJSHEAP, ALLOC_DEFAULT, ALLOC_HYBRID, ALLOC_LOGGING, ALLOC_TORTURE, arg, create_duktape_heap(), destroy_duktape_heap(), duk_gc(), handle_eval(), handle_fh(), handle_file(), handle_interactive(), main_argc, main_argv, MEM_LIMIT_HIGH, MEM_LIMIT_NORMAL, NULL, set_sigint_handler(), and usage().

◆ print_pop_error()

static void print_pop_error ( duk_context * ctx,
FILE * f )
static

Definition at line 162 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

162 {
163 /* Print error objects with a stack trace specially.
164 * Note that getting the stack trace may throw an error
165 * so this also needs to be safe call wrapped.
166 */
167 (void) duk_safe_call(ctx, get_stack_raw, 1 /*nargs*/, 1 /*nrets*/);
168 fprintf(f, "%s\n", duk_safe_to_string(ctx, -1));
169 fflush(f);
170 duk_pop(ctx);
171}
static int get_stack_raw(duk_context *ctx)
#define duk_safe_to_string(ctx, index)

References duk_pop(), duk_safe_call(), duk_safe_to_string, and get_stack_raw().

Referenced by handle_eval(), handle_fh(), and handle_interactive().

◆ wrapped_compile_execute()

static int wrapped_compile_execute ( duk_context * ctx)
static

Definition at line 173 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

173 {
174 const char *src_data;
175 duk_size_t src_len;
176 int comp_flags;
177
178 /* XXX: Here it'd be nice to get some stats for the compilation result
179 * when a suitable command line is given (e.g. code size, constant
180 * count, function count. These are available internally but not through
181 * the public API.
182 */
183
184 /* Use duk_compile_lstring_filename() variant which avoids interning
185 * the source code. This only really matters for low memory environments.
186 */
187
188 /* [ ... bytecode_filename src_data src_len filename ] */
189
190 src_data = (const char *) duk_require_pointer(ctx, -3);
191 src_len = (duk_size_t) duk_require_uint(ctx, -2);
192
193 if (src_data != NULL && src_len >= 2 && src_data[0] == (char) 0xff) {
194 /* Bytecode. */
195 duk_push_lstring(ctx, src_data, src_len);
196 duk_to_buffer(ctx, -1, NULL);
198 } else {
199 /* Source code. */
200 comp_flags = 0;
201 duk_compile_lstring_filename(ctx, comp_flags, src_data, src_len);
202 }
203
204 /* [ ... bytecode_filename src_data src_len function ] */
205
206 /* Optional bytecode dump. */
207 if (duk_is_string(ctx, -4)) {
208 FILE *f;
209 void *bc_ptr;
210 duk_size_t bc_len;
211 size_t wrote;
212 char fnbuf[256];
213 const char *filename;
214
215 duk_dup_top(ctx);
217 bc_ptr = duk_require_buffer(ctx, -1, &bc_len);
218 filename = duk_require_string(ctx, -5);
219#if defined(EMSCRIPTEN)
220 if (filename[0] == '/') {
221 snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
222 } else {
223 snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename);
224 }
225#else
226 snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
227#endif
228 fnbuf[sizeof(fnbuf) - 1] = (char) 0;
229
230 f = fopen(fnbuf, "wb");
231 if (!f) {
232 duk_error(ctx, DUK_ERR_ERROR, "failed to open bytecode output file");
233 }
234 wrote = fwrite(bc_ptr, 1, (size_t) bc_len, f); /* XXX: handle partial writes */
235 (void) fclose(f);
236 if (wrote != bc_len) {
237 duk_error(ctx, DUK_ERR_ERROR, "failed to write all bytecode");
238 }
239
240 return 0; /* duk_safe_call() cleans up */
241 }
242
243#if 0
244 /* Manual test for bytecode dump/load cycle: dump and load before
245 * execution. Enable manually, then run "make qecmatest" for a
246 * reasonably good coverage of different functions and programs.
247 */
250#endif
251
252#if defined(DUK_CMDLINE_AJSHEAP)
253 ajsheap_start_exec_timeout();
254#endif
255
256 duk_push_global_object(ctx); /* 'this' binding */
257 duk_call_method(ctx, 0);
258
259#if defined(DUK_CMDLINE_AJSHEAP)
260 ajsheap_clear_exec_timeout();
261#endif
262
263 if (interactive_mode) {
264 /*
265 * In interactive mode, write to stdout so output won't
266 * interleave as easily.
267 *
268 * NOTE: the ToString() coercion may fail in some cases;
269 * for instance, if you evaluate:
270 *
271 * ( {valueOf: function() {return {}},
272 * toString: function() {return {}}});
273 *
274 * The error is:
275 *
276 * TypeError: failed to coerce with [[DefaultValue]]
277 * duk_api.c:1420
278 *
279 * These are handled now by the caller which also has stack
280 * trace printing support. User code can print out errors
281 * safely using duk_safe_to_string().
282 */
283
284 fprintf(stdout, "= %s\n", duk_to_string(ctx, -1));
285 fflush(stdout);
286 } else {
287 /* In non-interactive mode, success results are not written at all.
288 * It is important that the result value is not string coerced,
289 * as the string coercion may cause an error in some cases.
290 */
291 }
292
293 return 0; /* duk_safe_call() cleans up */
294}
DUK_EXTERNAL const char * duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len)
DUK_EXTERNAL void duk_dup_top(duk_context *ctx)
DUK_EXTERNAL void * duk_require_pointer(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL void * duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_EXTERNAL void duk_load_function(duk_context *ctx)
DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs)
DUK_EXTERNAL void duk_push_global_object(duk_context *ctx)
DUK_EXTERNAL const char * duk_to_string(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL void duk_dump_function(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL const char * duk_require_string(duk_context *ctx, duk_idx_t index)
#define duk_to_buffer(ctx, index, out_size)
#define duk_compile_lstring_filename(ctx, flags, buf, len)

References duk_call_method(), duk_compile_lstring_filename, duk_dump_function(), duk_dup_top(), DUK_ERR_ERROR, duk_error, duk_is_string(), duk_load_function(), duk_push_global_object(), duk_push_lstring(), duk_require_buffer(), duk_require_pointer(), duk_require_string(), duk_require_uint(), duk_to_buffer, duk_to_string(), fwrite(), interactive_mode, NULL, and snprintf.

Referenced by handle_eval(), handle_fh(), and handle_interactive().

Variable Documentation

◆ interactive_mode

int interactive_mode = 0
static

◆ main_argc

int main_argc = 0
static

Definition at line 91 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by main().

◆ main_argv

char** main_argv = NULL
static

Definition at line 92 of file duktape-1.5.2/examples/cmdline/duk_cmdline.c.

Referenced by main().