3 * Copyright (c) 1998 New Generation Software (NGS) Oy
5 * Author: Markku Rossi <mtr@ngs.fi>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/ksrc/main.c,v $
42 #else /* not HAVE_STDC_HEADERS */
56 #endif /* not HAVE_STDC_HEADERS */
70 * -a, --annotate-assembler
72 * Annotate generated assembler listing with the original source code.
75 int annotate_assembler
= 0;
80 * Compile all given JavaScript files to byte-code and save the result
87 * -d METHOD, --dispatch=METHOD
89 * Use byte-code instruction dispatch method METHOD. Possible values are
90 * `switch', `switch-basic' and `jumps'.
93 JSVMDispatchMethod dispatch_method
= JS_VM_DISPATCH_JUMPS
;
96 * -e CODE, --eval=CODE
98 * Evaluate JavaScript code CODE.
104 * Print virtual machine events to the standard error.
111 * Use the next argument as the main source file and pass all
112 * remaining arguments to it through the ARGS array.
118 * Generate debugging information to the generated byte-code file.
120 int generate_debug_info
= 0;
125 * Print short help and exit successfully.
131 * Treat all following arguments, up to option -f / --file, as
132 * byte-code or JavaScript files and execute them. When option -f, --file
133 * is encountered, the next argument is the actual main source file that
134 * is executed with the remaining arguments.
140 * Do not define compiler in the interpreter. Options makes the
141 * interpreter a pure virtual machine that can't compile any JavaScript
148 * -O [LEVEL], --optimize[=LEVEL]
150 * Optimize at level LEVEL. The default level for batch-compile is 1.
151 * Value 0 disable optimization.
157 * -r OPTION, --secure=OPTIONS
159 * Turn on security option OPTION.
162 int secure_builtin_file
= 0;
163 int secure_builtin_system
= 0;
166 * -s SIZE, --stack-size=SIZE
168 * Set the virtual machine stack size to SIZE.
170 unsigned int stack_size
= 2048;
175 * Compile al given JavaScript files to JavaScript assembler and save the
184 * Print stack trace on error.
187 int stacktrace_on_error
= 0;
192 * Tell more about what we do.
195 unsigned int verbose
= 0;
200 * Print version information and exit successfully.
204 * -W OPTION, --compiler-option=OPTION
206 * Set compiler option OPTION.
209 int warn_deprecated
= 0;
210 int warn_unused_argument
= 0;
211 int warn_unused_variable
= 1;
214 int warn_with_clobber
= 1;
215 int warn_missing_semicolon
= 0;
216 int warn_strict_ecma
= 0;
221 * Generate executable byte-code files.
223 int generate_executable_bc_files
= 0;
230 static struct option long_options
[] =
232 {"annotate-assembler", no_argument
, 0, 'a'},
233 {"compile", no_argument
, 0, 'c'},
234 {"dispatch", required_argument
, 0, 'd'},
235 {"eval", required_argument
, 0, 'e'},
236 {"events", no_argument
, 0, 'E'},
237 {"file", no_argument
, 0, 'f'},
238 {"debug", no_argument
, 0, 'g'},
239 {"help", no_argument
, 0, 'h'},
240 {"load", no_argument
, 0, 'l'},
241 {"no-compiler", no_argument
, 0, 'N'},
242 {"optimize", optional_argument
, 0, 'O'},
243 {"secure", required_argument
, 0, 'r'},
244 {"stack-size", required_argument
, 0, 's'},
245 {"no-assemble", no_argument
, 0, 'S'},
246 {"stacktrace", no_argument
, 0, 't'},
247 {"verbose", no_argument
, 0, 'v'},
248 {"version", no_argument
, 0, 'V'},
249 {"compiler-option", required_argument
, 0, 'W'},
250 {"executable", no_argument
, 0, 'x'},
255 /* Compiler options. */
257 /* Flags for options. */
258 #define JSC_RUNTIME 0x01
259 #define JSC_WALL 0x02
260 #define JSC_PEDANTIC 0x04
261 #define JSC_LINT 0x08
268 } compiler_options
[] =
270 {"deprecated", &warn_deprecated
, JSC_WALL
},
271 {"unused-argument", &warn_unused_argument
, JSC_WALL
},
272 {"unused-variable", &warn_unused_variable
, JSC_WALL
},
273 {"undefined", &warn_undef
, JSC_RUNTIME
},
274 {"shadow", &warn_shadow
, JSC_WALL
},
275 {"with-clobber", &warn_with_clobber
, JSC_WALL
},
276 {"missing-semicolon", &warn_missing_semicolon
, JSC_PEDANTIC
},
277 {"strict-ecma", &warn_strict_ecma
, JSC_LINT
},
284 * Prototypes for static functions.
287 static void handle_compiler_option (char *name
);
289 static JSInterpPtr
create_interp (void);
291 static void usage (void);
292 static void version (void);
299 main (int argc
, char *argv
[])
301 JSInterpPtr interp
= NULL
;
305 /* Get program's name. */
306 program
= strrchr (argv
[0], '/');
312 /* Make getopt_long() to use our modified program name. */
315 /* Parse arguments. */
319 int option_index
= 0;
321 c
= getopt_long (argc
, argv
, "acd:e:EfghlNO::r:s:StvVW:x",
322 long_options
, &option_index
);
328 case 'a': /* --annotate-assembler */
329 annotate_assembler
= 1;
332 case 'c': /* --compile */
336 case 'd': /* --dispatch */
337 if (strcmp (optarg
, "switch-basic") == 0)
338 dispatch_method
= JS_VM_DISPATCH_SWITCH_BASIC
;
339 else if (strcmp (optarg
, "switch") == 0)
340 dispatch_method
= JS_VM_DISPATCH_SWITCH
;
341 else if (strcmp (optarg
, "jumps") == 0)
342 dispatch_method
= JS_VM_DISPATCH_JUMPS
;
345 fprintf (stderr
, "%s: illegal dispatch method `%s'\n",
351 case 'e': /* --eval */
353 interp
= create_interp ();
355 if (!js_eval (interp
, optarg
))
357 fprintf (stderr
, "%s: eval failed: %s\n", program
,
358 js_error_message (interp
));
363 case 'E': /* --events */
367 case 'f': /* --file */
370 no_argument_for_file
:
371 fprintf (stderr
, "%s: no arguments after option --file\n",
378 case 'g': /* --debug */
379 generate_debug_info
= 1;
382 case 'h': /* --help */
387 case 'l': /* --load */
392 case 'N': /* --no-compiler */
396 case 'O': /* --optimize */
398 optimize
= atoi (optarg
);
401 case 'r': /* --secure */
402 if (strcmp (optarg
, "file") == 0)
403 secure_builtin_file
= 1;
404 else if (strcmp (optarg
, "system") == 0)
405 secure_builtin_system
= 1;
408 fprintf (stderr
, "%s: unknown security option `%s'\n",
414 case 's': /* --stack-size */
415 stack_size
= atoi (optarg
);
418 case 'S': /* --no-assemble */
422 case 't': /* --stacktrace */
423 stacktrace_on_error
= 1;
426 case 'v': /* --verbose */
430 case 'V': /* --version */
435 case 'W': /* --compiler-option */
436 handle_compiler_option (optarg
);
439 case 'x': /* --executable */
440 generate_executable_bc_files
= 1;
444 fprintf (stderr
, "Try `%s --help' for more information.\n",
450 printf ("Hey! main() didn't handle option \"%c\" (%d)", c
, c
);
452 printf (" with arg %s", optarg
);
461 interp
= create_interp ();
463 /* Let's see what we have to do. */
469 * Treat all remaining arguments as JavaScript files and compile them.
472 for (; optind
< argc
; optind
++)
474 /* Create name for the byte-code file. */
476 jscname
= malloc (strlen (argv
[optind
]) + 5);
477 assert (jscname
!= NULL
);
478 strcpy (jscname
, argv
[optind
]);
480 cp
= strrchr (jscname
, '.');
482 strcpy (++cp
, "jsc");
484 strcat (jscname
, ".jsc");
487 printf ("%s: compiling `%s' to `%s'\n", program
,
488 argv
[optind
], jscname
);
490 if (!js_compile (interp
, argv
[optind
], NULL
, jscname
))
492 fprintf (stderr
, "%s\n", js_error_message (interp
));
499 else if (no_assemble
)
503 /* Compile argument files to assembler. */
504 for (; optind
< argc
; optind
++)
506 /* Create name for the assembler file. */
508 jasname
= malloc (strlen (argv
[optind
]) + 5);
509 assert (jasname
!= NULL
);
510 strcpy (jasname
, argv
[optind
]);
512 cp
= strrchr (jasname
, '.');
514 strcpy (++cp
, "jas");
516 strcat (jasname
, ".jas");
519 printf ("%s: compiling `%s' to `%s'\n", program
,
520 argv
[optind
], jasname
);
522 if (!js_compile (interp
, argv
[optind
], jasname
, NULL
))
524 fprintf (stderr
, "%s\n", js_error_message (interp
));
531 else if (optind
< argc
)
533 char *main_file
= argv
[optind
];
538 * Assume that <main_file> contains JavaScript (or byte-code) and
539 * execute it. All the remaining arguments are passed to the
540 * interpreter through the ARGS array.
543 /* Save all remaining arguments to ARGS */
544 js_type_make_array (interp
, &args
, argc
- optind
);
546 for (i
= 0; optind
+ i
< argc
; i
++)
547 js_type_make_string (interp
, &args
.u
.array
->data
[i
],
548 argv
[optind
+ i
], strlen (argv
[optind
+ i
]));
550 js_set_var (interp
, "ARGS", &args
);
552 if (!js_eval_file (interp
, main_file
))
554 fprintf (stderr
, "%s: evaluation of file `%s' failed:\n%s\n",
555 program
, main_file
, js_error_message (interp
));
560 js_destroy_interp (interp
);
571 is_prefix (char *prefix
, char *str
)
575 for (i
= 0; prefix
[i
] && str
[i
] && prefix
[i
] == str
[i
]; i
++)
585 handle_compiler_option (char *name
)
592 if (name
[0] == 'n' && name
[1] == 'o' && name
[2] == '-')
598 for (i
= 0; compiler_options
[i
].name
; i
++)
602 if ((was_prefix
= is_prefix (name
, compiler_options
[i
].name
))
603 || (strcmp (name
, "runtime") == 0
604 && (compiler_options
[i
].flags
& JSC_RUNTIME
))
605 || (strcmp (name
, "all") == 0
606 && (compiler_options
[i
].flags
& JSC_WALL
))
607 || (strcmp (name
, "pedantic") == 0
608 && (compiler_options
[i
].flags
& (JSC_WALL
| JSC_PEDANTIC
))))
610 *compiler_options
[i
].option
= value
;
621 fprintf (stderr
, "%s: unknown compiler option `-W%s%s'\n", program
,
622 value
? "" : "no-", name
);
627 fprintf (stderr
, "%s: ambiguous compiler option `-W%s%s'\n",
628 program
, value
? "" : "no-", name
);
635 show_events_hook (int event
, void *context
)
641 case JS_EVENT_OPERAND_COUNT
:
642 event_name
= "operand count";
645 case JS_EVENT_GARBAGE_COLLECT
:
646 event_name
= "garbage collect";
650 event_name
= "unknown";
654 fprintf (stderr
, "[%s: %s]\n", program
, event_name
);
663 JSInterpOptions options
;
666 js_init_default_options (&options
);
668 options
.stack_size
= stack_size
;
669 options
.dispatch_method
= dispatch_method
;
670 options
.verbose
= verbose
;
672 options
.no_compiler
= no_compiler
;
673 options
.stacktrace_on_error
= stacktrace_on_error
;
675 options
.secure_builtin_file
= secure_builtin_file
;
676 options
.secure_builtin_system
= secure_builtin_system
;
678 options
.annotate_assembler
= annotate_assembler
;
679 options
.debug_info
= generate_debug_info
;
680 options
.executable_bc_files
= generate_executable_bc_files
;
682 options
.warn_unused_argument
= warn_unused_argument
;
683 options
.warn_unused_variable
= warn_unused_variable
;
684 options
.warn_undef
= warn_undef
;
685 options
.warn_shadow
= warn_shadow
;
686 options
.warn_with_clobber
= warn_with_clobber
;
687 options
.warn_missing_semicolon
= warn_missing_semicolon
;
688 options
.warn_strict_ecma
= warn_strict_ecma
;
689 options
.warn_deprecated
= warn_deprecated
;
691 /* As a default, no optimization */
692 options
.optimize_peephole
= 0;
693 options
.optimize_jumps_to_jumps
= 0;
694 options
.optimize_bc_size
= 0;
695 options
.optimize_heavy
= 0;
699 options
.optimize_peephole
= 1;
700 options
.optimize_jumps_to_jumps
= 1;
701 options
.optimize_bc_size
= 1;
706 options
.optimize_heavy
= 1;
712 options
.hook
= show_events_hook
;
713 options
.hook_operand_count_trigger
= 1000000;
716 interp
= js_create_interp (&options
);
719 fprintf (stderr
, "%s: couldn't create interpreter\n", program
);
723 /* And finally, define the requested modules. */
726 if (!js_define_module (interp
, js_ext_JS
))
727 fprintf (stderr
, "%s: warning: couldn't create the JS extension\n",
732 if (!js_define_module (interp
, js_ext_curses
))
733 fprintf (stderr
, "%s: warning: couldn't create the curses extension\n",
738 if (!js_define_module (interp
, js_ext_MD5
))
739 fprintf (stderr
, "%s: warning: couldn't create the MD5 extension\n",
751 Usage: %s [OPTION]... FILE [ARGUMENT]...\n\
752 Mandatory arguments to long options are mandatory for short options too.\n\
753 -a, --annotate-assembler annotate generated assembler listing with\n\
754 the original source code\n\
755 -c, --compile compile JavaScript input file to byte-code\n\
756 and save the result to the file `FILE.jsc'\n\
757 -d, --dispatch=METHOD use method METHOD for byte-code instruction\n\
759 -e, --eval=CODE evaluate JavaScript code CODE\n\
760 -E, --events print interpreter events\n\
761 -f, --file evaluate the next argument file and pass\n\
762 all remaining arguments to the interpreter\n\
763 through the ARGS array\n\
764 -g, --debug generate debugging information\n\
765 -h, --help print this help and exit\n\
766 -l, --load evaluate argument files until option `-f',\n\
767 `--file' is encountered\n\
768 -N, --no-compiler do not define compiler to the JavaScript\n\
770 -O, --optimize[=LEVEL] optimize at level LEVEL\n\
771 -r, --secure=OPTION turn on security option OPTION\n\
772 -s, --stack-size=SIZE set the interpreter stack size to SIZE nodes\n\
773 -S, --assembler compile JavaScript intput file to assembler\n\
774 and save the result to the file `FILE.jas'\n\
775 -t, --stacktrace print stacktrace on error\n\
776 -v, --verbose tell what the interpreter is doing\n\
777 -V, --version print version number\n\
778 -W, --compiler-option=OPTION\n\
779 set compilation option OPTION\n\
780 -x, --executable generate executable byte-code files\n",
783 printf ("\nReport bugs to mtr@ngs.fi.\n");
790 printf ("NGS JavaScript Interpter %s\n\
791 Copyright (C) 1998 New Generation Software (NGS) Oy.\n\
792 NGS JavaScript Interpreter comes with NO WARRANTY, to the extent\n\
793 permitted by law. You may redistribute copies of NGS JavaScript\n\
794 Interpreter under the terms of the GNU Library General Public License.\n\
795 For more information about these matters, see the files named COPYING.\n\