qjsc.c (22271B)
1 /* 2 * QuickJS command line compiler 3 * 4 * Copyright (c) 2018-2021 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include <stdlib.h> 25 #include <stdio.h> 26 #include <stdarg.h> 27 #include <inttypes.h> 28 #include <string.h> 29 #include <assert.h> 30 #include <unistd.h> 31 #include <errno.h> 32 #if !defined(_WIN32) 33 #include <sys/wait.h> 34 #endif 35 36 #include "cutils.h" 37 #include "quickjs-libc.h" 38 39 typedef struct { 40 char *name; 41 char *short_name; 42 int flags; 43 } namelist_entry_t; 44 45 typedef struct namelist_t { 46 namelist_entry_t *array; 47 int count; 48 int size; 49 } namelist_t; 50 51 typedef struct { 52 const char *option_name; 53 const char *init_name; 54 } FeatureEntry; 55 56 static namelist_t cname_list; 57 static namelist_t cmodule_list; 58 static namelist_t init_module_list; 59 static uint64_t feature_bitmap; 60 static FILE *outfile; 61 static BOOL byte_swap; 62 static BOOL dynamic_export; 63 static const char *c_ident_prefix = "qjsc_"; 64 65 #define FE_ALL (-1) 66 67 static const FeatureEntry feature_list[] = { 68 { "date", "Date" }, 69 { "eval", "Eval" }, 70 { "string-normalize", "StringNormalize" }, 71 { "regexp", "RegExp" }, 72 { "json", "JSON" }, 73 { "proxy", "Proxy" }, 74 { "map", "MapSet" }, 75 { "typedarray", "TypedArrays" }, 76 { "promise", "Promise" }, 77 #define FE_MODULE_LOADER 9 78 { "module-loader", NULL }, 79 { "bigint", "BigInt" }, 80 }; 81 82 void namelist_add(namelist_t *lp, const char *name, const char *short_name, 83 int flags) 84 { 85 namelist_entry_t *e; 86 if (lp->count == lp->size) { 87 size_t newsize = lp->size + (lp->size >> 1) + 4; 88 namelist_entry_t *a = 89 realloc(lp->array, sizeof(lp->array[0]) * newsize); 90 /* XXX: check for realloc failure */ 91 lp->array = a; 92 lp->size = newsize; 93 } 94 e = &lp->array[lp->count++]; 95 e->name = strdup(name); 96 if (short_name) 97 e->short_name = strdup(short_name); 98 else 99 e->short_name = NULL; 100 e->flags = flags; 101 } 102 103 void namelist_free(namelist_t *lp) 104 { 105 while (lp->count > 0) { 106 namelist_entry_t *e = &lp->array[--lp->count]; 107 free(e->name); 108 free(e->short_name); 109 } 110 free(lp->array); 111 lp->array = NULL; 112 lp->size = 0; 113 } 114 115 namelist_entry_t *namelist_find(namelist_t *lp, const char *name) 116 { 117 int i; 118 for(i = 0; i < lp->count; i++) { 119 namelist_entry_t *e = &lp->array[i]; 120 if (!strcmp(e->name, name)) 121 return e; 122 } 123 return NULL; 124 } 125 126 static void get_c_name(char *buf, size_t buf_size, const char *file) 127 { 128 const char *p, *r; 129 size_t len, i; 130 int c; 131 char *q; 132 133 p = strrchr(file, '/'); 134 if (!p) 135 p = file; 136 else 137 p++; 138 r = strrchr(p, '.'); 139 if (!r) 140 len = strlen(p); 141 else 142 len = r - p; 143 pstrcpy(buf, buf_size, c_ident_prefix); 144 q = buf + strlen(buf); 145 for(i = 0; i < len; i++) { 146 c = p[i]; 147 if (!((c >= '0' && c <= '9') || 148 (c >= 'A' && c <= 'Z') || 149 (c >= 'a' && c <= 'z'))) { 150 c = '_'; 151 } 152 if ((q - buf) < buf_size - 1) 153 *q++ = c; 154 } 155 *q = '\0'; 156 } 157 158 static void dump_hex(FILE *f, const uint8_t *buf, size_t len) 159 { 160 size_t i, col; 161 col = 0; 162 for(i = 0; i < len; i++) { 163 fprintf(f, " 0x%02x,", buf[i]); 164 if (++col == 8) { 165 fprintf(f, "\n"); 166 col = 0; 167 } 168 } 169 if (col != 0) 170 fprintf(f, "\n"); 171 } 172 173 static void output_object_code(JSContext *ctx, 174 FILE *fo, JSValueConst obj, const char *c_name, 175 BOOL load_only) 176 { 177 uint8_t *out_buf; 178 size_t out_buf_len; 179 int flags; 180 flags = JS_WRITE_OBJ_BYTECODE; 181 if (byte_swap) 182 flags |= JS_WRITE_OBJ_BSWAP; 183 out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags); 184 if (!out_buf) { 185 js_std_dump_error(ctx); 186 exit(1); 187 } 188 189 namelist_add(&cname_list, c_name, NULL, load_only); 190 191 fprintf(fo, "const uint32_t %s_size = %u;\n\n", 192 c_name, (unsigned int)out_buf_len); 193 fprintf(fo, "const uint8_t %s[%u] = {\n", 194 c_name, (unsigned int)out_buf_len); 195 dump_hex(fo, out_buf, out_buf_len); 196 fprintf(fo, "};\n\n"); 197 198 js_free(ctx, out_buf); 199 } 200 201 static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m) 202 { 203 /* should never be called when compiling JS code */ 204 abort(); 205 } 206 207 static void find_unique_cname(char *cname, size_t cname_size) 208 { 209 char cname1[1024]; 210 int suffix_num; 211 size_t len, max_len; 212 assert(cname_size >= 32); 213 /* find a C name not matching an existing module C name by 214 adding a numeric suffix */ 215 len = strlen(cname); 216 max_len = cname_size - 16; 217 if (len > max_len) 218 cname[max_len] = '\0'; 219 suffix_num = 1; 220 for(;;) { 221 snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num); 222 if (!namelist_find(&cname_list, cname1)) 223 break; 224 suffix_num++; 225 } 226 pstrcpy(cname, cname_size, cname1); 227 } 228 229 JSModuleDef *jsc_module_loader(JSContext *ctx, 230 const char *module_name, void *opaque) 231 { 232 JSModuleDef *m; 233 namelist_entry_t *e; 234 235 /* check if it is a declared C or system module */ 236 e = namelist_find(&cmodule_list, module_name); 237 if (e) { 238 /* add in the static init module list */ 239 namelist_add(&init_module_list, e->name, e->short_name, 0); 240 /* create a dummy module */ 241 m = JS_NewCModule(ctx, module_name, js_module_dummy_init); 242 } else if (has_suffix(module_name, ".so")) { 243 fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name); 244 /* create a dummy module */ 245 m = JS_NewCModule(ctx, module_name, js_module_dummy_init); 246 /* the resulting executable will export its symbols for the 247 dynamic library */ 248 dynamic_export = TRUE; 249 } else { 250 size_t buf_len; 251 uint8_t *buf; 252 JSValue func_val; 253 char cname[1024]; 254 255 buf = js_load_file(ctx, &buf_len, module_name); 256 if (!buf) { 257 JS_ThrowReferenceError(ctx, "could not load module filename '%s'", 258 module_name); 259 return NULL; 260 } 261 262 /* compile the module */ 263 func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, 264 JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); 265 js_free(ctx, buf); 266 if (JS_IsException(func_val)) 267 return NULL; 268 get_c_name(cname, sizeof(cname), module_name); 269 if (namelist_find(&cname_list, cname)) { 270 find_unique_cname(cname, sizeof(cname)); 271 } 272 output_object_code(ctx, outfile, func_val, cname, TRUE); 273 274 /* the module is already referenced, so we must free it */ 275 m = JS_VALUE_GET_PTR(func_val); 276 JS_FreeValue(ctx, func_val); 277 } 278 return m; 279 } 280 281 static void compile_file(JSContext *ctx, FILE *fo, 282 const char *filename, 283 const char *c_name1, 284 int module) 285 { 286 uint8_t *buf; 287 char c_name[1024]; 288 int eval_flags; 289 JSValue obj; 290 size_t buf_len; 291 292 buf = js_load_file(ctx, &buf_len, filename); 293 if (!buf) { 294 fprintf(stderr, "Could not load '%s'\n", filename); 295 exit(1); 296 } 297 eval_flags = JS_EVAL_FLAG_COMPILE_ONLY; 298 if (module < 0) { 299 module = (has_suffix(filename, ".mjs") || 300 JS_DetectModule((const char *)buf, buf_len)); 301 } 302 if (module) 303 eval_flags |= JS_EVAL_TYPE_MODULE; 304 else 305 eval_flags |= JS_EVAL_TYPE_GLOBAL; 306 // obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags); // filename contains full path 307 obj = JS_Eval(ctx, (const char *)buf, buf_len, "<compiled_js>", eval_flags); // which we don't want to expose 308 // TODO: In the future we should to make this behavior configurable with a flag to qjsc 309 if (JS_IsException(obj)) { 310 js_std_dump_error(ctx); 311 exit(1); 312 } 313 js_free(ctx, buf); 314 if (c_name1) { 315 pstrcpy(c_name, sizeof(c_name), c_name1); 316 } else { 317 get_c_name(c_name, sizeof(c_name), filename); 318 } 319 output_object_code(ctx, fo, obj, c_name, FALSE); 320 JS_FreeValue(ctx, obj); 321 } 322 323 static const char main_c_template1[] = 324 "int main(int argc, char **argv)\n" 325 "{\n" 326 " JSRuntime *rt;\n" 327 " JSContext *ctx;\n" 328 " rt = JS_NewRuntime();\n" 329 " js_std_set_worker_new_context_func(JS_NewCustomContext);\n" 330 " js_std_init_handlers(rt);\n" 331 ; 332 333 static const char main_c_template2[] = 334 " js_std_loop(ctx);\n" 335 " js_std_free_handlers(rt);\n" 336 " JS_FreeContext(ctx);\n" 337 " JS_FreeRuntime(rt);\n" 338 " return 0;\n" 339 "}\n"; 340 341 #define PROG_NAME "qjsc" 342 343 void help(void) 344 { 345 printf("QuickJS Compiler version " CONFIG_VERSION "\n" 346 "usage: " PROG_NAME " [options] [files]\n" 347 "\n" 348 "options are:\n" 349 "-c only output bytecode to a C file\n" 350 "-e output main() and bytecode to a C file (default = executable output)\n" 351 "-o output set the output filename\n" 352 "-N cname set the C name of the generated data\n" 353 "-m compile as Javascript module (default=autodetect)\n" 354 "-D module_name compile a dynamically loaded module or worker\n" 355 "-M module_name[,cname] add initialization code for an external C module\n" 356 "-x byte swapped output\n" 357 "-p prefix set the prefix of the generated C names\n" 358 "-S n set the maximum stack size to 'n' bytes (default=%d)\n", 359 JS_DEFAULT_STACK_SIZE); 360 #ifdef CONFIG_LTO 361 { 362 int i; 363 printf("-flto use link time optimization\n"); 364 printf("-fbignum enable bignum extensions\n"); 365 printf("-fno-["); 366 for(i = 0; i < countof(feature_list); i++) { 367 if (i != 0) 368 printf("|"); 369 printf("%s", feature_list[i].option_name); 370 } 371 printf("]\n" 372 " disable selected language features (smaller code size)\n"); 373 } 374 #endif 375 exit(1); 376 } 377 378 #if defined(CONFIG_CC) && !defined(_WIN32) 379 380 int exec_cmd(char **argv) 381 { 382 int pid, status, ret; 383 384 pid = fork(); 385 if (pid == 0) { 386 execvp(argv[0], argv); 387 exit(1); 388 } 389 390 for(;;) { 391 ret = waitpid(pid, &status, 0); 392 if (ret == pid && WIFEXITED(status)) 393 break; 394 } 395 return WEXITSTATUS(status); 396 } 397 398 static int output_executable(const char *out_filename, const char *cfilename, 399 BOOL use_lto, BOOL verbose, const char *exename) 400 { 401 const char *argv[64]; 402 const char **arg, *bn_suffix, *lto_suffix; 403 char libjsname[1024]; 404 char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p; 405 int ret; 406 407 /* get the directory of the executable */ 408 pstrcpy(exe_dir, sizeof(exe_dir), exename); 409 p = strrchr(exe_dir, '/'); 410 if (p) { 411 *p = '\0'; 412 } else { 413 pstrcpy(exe_dir, sizeof(exe_dir), "."); 414 } 415 416 /* if 'quickjs.h' is present at the same path as the executable, we 417 use it as include and lib directory */ 418 snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir); 419 if (access(buf, R_OK) == 0) { 420 pstrcpy(inc_dir, sizeof(inc_dir), exe_dir); 421 pstrcpy(lib_dir, sizeof(lib_dir), exe_dir); 422 } else { 423 snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX); 424 snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX); 425 } 426 427 lto_suffix = ""; 428 bn_suffix = ""; 429 430 arg = argv; 431 *arg++ = CONFIG_CC; 432 *arg++ = "-O2"; 433 #ifdef CONFIG_LTO 434 if (use_lto) { 435 *arg++ = "-flto"; 436 lto_suffix = ".lto"; 437 } 438 #endif 439 /* XXX: use the executable path to find the includes files and 440 libraries */ 441 *arg++ = "-D"; 442 *arg++ = "_GNU_SOURCE"; 443 *arg++ = "-I"; 444 *arg++ = inc_dir; 445 *arg++ = "-o"; 446 *arg++ = out_filename; 447 if (dynamic_export) 448 *arg++ = "-rdynamic"; 449 *arg++ = cfilename; 450 snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a", 451 lib_dir, bn_suffix, lto_suffix); 452 *arg++ = libjsname; 453 *arg++ = "-lm"; 454 *arg++ = "-ldl"; 455 *arg++ = "-lpthread"; 456 // FIXME: Make conditional 457 *arg++ = "-lcurl"; 458 *arg++ = "-lsodium"; 459 *arg++ = "-lmbedcrypto"; 460 *arg = NULL; 461 462 if (verbose) { 463 for(arg = argv; *arg != NULL; arg++) 464 printf("%s ", *arg); 465 printf("\n"); 466 } 467 468 ret = exec_cmd((char **)argv); 469 unlink(cfilename); 470 return ret; 471 } 472 #else 473 static int output_executable(const char *out_filename, const char *cfilename, 474 BOOL use_lto, BOOL verbose, const char *exename) 475 { 476 fprintf(stderr, "Executable output is not supported for this target\n"); 477 exit(1); 478 return 0; 479 } 480 #endif 481 482 483 typedef enum { 484 OUTPUT_C, 485 OUTPUT_C_MAIN, 486 OUTPUT_EXECUTABLE, 487 } OutputTypeEnum; 488 489 int main(int argc, char **argv) 490 { 491 int c, i, verbose; 492 const char *out_filename, *cname; 493 char cfilename[1024]; 494 FILE *fo; 495 JSRuntime *rt; 496 JSContext *ctx; 497 BOOL use_lto; 498 int module; 499 OutputTypeEnum output_type; 500 size_t stack_size; 501 #ifdef CONFIG_BIGNUM 502 BOOL bignum_ext = FALSE; 503 #endif 504 namelist_t dynamic_module_list; 505 506 out_filename = NULL; 507 output_type = OUTPUT_EXECUTABLE; 508 cname = NULL; 509 feature_bitmap = FE_ALL; 510 module = -1; 511 byte_swap = FALSE; 512 verbose = 0; 513 use_lto = FALSE; 514 stack_size = 0; 515 memset(&dynamic_module_list, 0, sizeof(dynamic_module_list)); 516 517 /* add system modules */ 518 namelist_add(&cmodule_list, "std", "std", 0); 519 namelist_add(&cmodule_list, "os", "os", 0); 520 521 for(;;) { 522 c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:"); 523 if (c == -1) 524 break; 525 switch(c) { 526 case 'h': 527 help(); 528 case 'o': 529 out_filename = optarg; 530 break; 531 case 'c': 532 output_type = OUTPUT_C; 533 break; 534 case 'e': 535 output_type = OUTPUT_C_MAIN; 536 break; 537 case 'N': 538 cname = optarg; 539 break; 540 case 'f': 541 { 542 const char *p; 543 p = optarg; 544 if (!strcmp(optarg, "lto")) { 545 use_lto = TRUE; 546 } else if (strstart(p, "no-", &p)) { 547 use_lto = TRUE; 548 for(i = 0; i < countof(feature_list); i++) { 549 if (!strcmp(p, feature_list[i].option_name)) { 550 feature_bitmap &= ~((uint64_t)1 << i); 551 break; 552 } 553 } 554 if (i == countof(feature_list)) 555 goto bad_feature; 556 } else 557 #ifdef CONFIG_BIGNUM 558 if (!strcmp(optarg, "bignum")) { 559 bignum_ext = TRUE; 560 } else 561 #endif 562 { 563 bad_feature: 564 fprintf(stderr, "unsupported feature: %s\n", optarg); 565 exit(1); 566 } 567 } 568 break; 569 case 'm': 570 module = 1; 571 break; 572 case 'M': 573 { 574 char *p; 575 char path[1024]; 576 char cname[1024]; 577 pstrcpy(path, sizeof(path), optarg); 578 p = strchr(path, ','); 579 if (p) { 580 *p = '\0'; 581 pstrcpy(cname, sizeof(cname), p + 1); 582 } else { 583 get_c_name(cname, sizeof(cname), path); 584 } 585 namelist_add(&cmodule_list, path, cname, 0); 586 } 587 break; 588 case 'D': 589 namelist_add(&dynamic_module_list, optarg, NULL, 0); 590 break; 591 case 'x': 592 byte_swap = TRUE; 593 break; 594 case 'v': 595 verbose++; 596 break; 597 case 'p': 598 c_ident_prefix = optarg; 599 break; 600 case 'S': 601 stack_size = (size_t)strtod(optarg, NULL); 602 break; 603 default: 604 break; 605 } 606 } 607 608 if (optind >= argc) 609 help(); 610 611 if (!out_filename) { 612 if (output_type == OUTPUT_EXECUTABLE) { 613 out_filename = "a.out"; 614 } else { 615 out_filename = "out.c"; 616 } 617 } 618 619 if (output_type == OUTPUT_EXECUTABLE) { 620 #if defined(_WIN32) || defined(__ANDROID__) 621 /* XXX: find a /tmp directory ? */ 622 snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid()); 623 #else 624 snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid()); 625 #endif 626 } else { 627 pstrcpy(cfilename, sizeof(cfilename), out_filename); 628 } 629 630 fo = fopen(cfilename, "w"); 631 if (!fo) { 632 perror(cfilename); 633 exit(1); 634 } 635 outfile = fo; 636 637 rt = JS_NewRuntime(); 638 ctx = JS_NewContext(rt); 639 #ifdef CONFIG_BIGNUM 640 if (bignum_ext) { 641 JS_AddIntrinsicBigFloat(ctx); 642 JS_AddIntrinsicBigDecimal(ctx); 643 JS_AddIntrinsicOperators(ctx); 644 JS_EnableBignumExt(ctx, TRUE); 645 } 646 #endif 647 648 /* loader for ES6 modules */ 649 JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL); 650 651 fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n" 652 "\n" 653 ); 654 655 if (output_type != OUTPUT_C) { 656 fprintf(fo, "#include \"quickjs-libc.h\"\n" 657 "\n" 658 ); 659 } else { 660 fprintf(fo, "#include <inttypes.h>\n" 661 "\n" 662 ); 663 } 664 665 for(i = optind; i < argc; i++) { 666 const char *filename = argv[i]; 667 compile_file(ctx, fo, filename, cname, module); 668 cname = NULL; 669 } 670 671 for(i = 0; i < dynamic_module_list.count; i++) { 672 if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) { 673 fprintf(stderr, "Could not load dynamic module '%s'\n", 674 dynamic_module_list.array[i].name); 675 exit(1); 676 } 677 } 678 679 if (output_type != OUTPUT_C) { 680 fprintf(fo, 681 "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n" 682 "{\n" 683 " JSContext *ctx = JS_NewContextRaw(rt);\n" 684 " if (!ctx)\n" 685 " return NULL;\n"); 686 /* add the basic objects */ 687 fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n"); 688 for(i = 0; i < countof(feature_list); i++) { 689 if ((feature_bitmap & ((uint64_t)1 << i)) && 690 feature_list[i].init_name) { 691 fprintf(fo, " JS_AddIntrinsic%s(ctx);\n", 692 feature_list[i].init_name); 693 } 694 } 695 #ifdef CONFIG_BIGNUM 696 if (bignum_ext) { 697 fprintf(fo, 698 " JS_AddIntrinsicBigFloat(ctx);\n" 699 " JS_AddIntrinsicBigDecimal(ctx);\n" 700 " JS_AddIntrinsicOperators(ctx);\n" 701 " JS_EnableBignumExt(ctx, 1);\n"); 702 } 703 #endif 704 /* add the precompiled modules (XXX: could modify the module 705 loader instead) */ 706 for(i = 0; i < init_module_list.count; i++) { 707 namelist_entry_t *e = &init_module_list.array[i]; 708 /* initialize the static C modules */ 709 710 fprintf(fo, 711 " {\n" 712 " extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n" 713 " js_init_module_%s(ctx, \"%s\");\n" 714 " }\n", 715 e->short_name, e->short_name, e->name); 716 } 717 for(i = 0; i < cname_list.count; i++) { 718 namelist_entry_t *e = &cname_list.array[i]; 719 if (e->flags) { 720 fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n", 721 e->name, e->name); 722 } 723 } 724 fprintf(fo, 725 " return ctx;\n" 726 "}\n\n"); 727 728 fputs(main_c_template1, fo); 729 730 if (stack_size != 0) { 731 fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n", 732 (unsigned int)stack_size); 733 } 734 735 /* add the module loader if necessary */ 736 if (feature_bitmap & (1 << FE_MODULE_LOADER)) { 737 fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n"); 738 } 739 740 fprintf(fo, 741 " ctx = JS_NewCustomContext(rt);\n" 742 " js_std_add_helpers(ctx, argc, argv);\n"); 743 744 for(i = 0; i < cname_list.count; i++) { 745 namelist_entry_t *e = &cname_list.array[i]; 746 if (!e->flags) { 747 fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n", 748 e->name, e->name); 749 } 750 } 751 fputs(main_c_template2, fo); 752 } 753 754 JS_FreeContext(ctx); 755 JS_FreeRuntime(rt); 756 757 fclose(fo); 758 759 if (output_type == OUTPUT_EXECUTABLE) { 760 return output_executable(out_filename, cfilename, use_lto, verbose, 761 argv[0]); 762 } 763 namelist_free(&cname_list); 764 namelist_free(&cmodule_list); 765 namelist_free(&init_module_list); 766 return 0; 767 }