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