2 Copyright (C) 2007-2010, Parrot Foundation.
7 src/main.c - the Entry Point to Parrot Programs
23 #include "parrot/parrot.h"
24 #include "parrot/embed.h"
25 #include "parrot/imcc.h"
26 #include "parrot/longopt.h"
27 #include "parrot/runcore_api.h"
28 #include "pmc/pmc_callcontext.h"
30 /* For gc_sys_type_enum */
31 #include "gc/gc_private.h"
33 /* HEADERIZER HFILE: none */
35 /* HEADERIZER BEGIN: static */
36 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
38 static void help(void);
39 static void help_debug(void);
40 PARROT_WARN_UNUSED_RESULT
42 static int is_all_hex_digits(ARGIN(const char *s
))
43 __attribute__nonnull__(1);
45 static void Parrot_version(void);
46 PARROT_CAN_RETURN_NULL
47 static const char * parseflags(PARROT_INTERP
,
49 ARGIN(const char *argv
[]),
50 ARGOUT(int *pgm_argc
),
51 ARGOUT(const char ***pgm_argv
),
52 ARGMOD(Parrot_Run_core_t
*core
),
53 ARGMOD(Parrot_trace_flags
*trace
))
54 __attribute__nonnull__(1)
55 __attribute__nonnull__(3)
56 __attribute__nonnull__(4)
57 __attribute__nonnull__(5)
58 __attribute__nonnull__(6)
59 __attribute__nonnull__(7)
60 FUNC_MODIFIES(*pgm_argc
)
61 FUNC_MODIFIES(*pgm_argv
)
63 FUNC_MODIFIES(*trace
);
65 static void parseflags_minimal(PARROT_INTERP
,
67 ARGIN(const char *argv
[]))
68 __attribute__nonnull__(1)
69 __attribute__nonnull__(3);
71 static void usage(ARGMOD(FILE *fp
))
72 __attribute__nonnull__(1)
75 #define ASSERT_ARGS_help __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
76 #define ASSERT_ARGS_help_debug __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
77 #define ASSERT_ARGS_is_all_hex_digits __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
79 #define ASSERT_ARGS_Parrot_version __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
80 #define ASSERT_ARGS_parseflags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
81 PARROT_ASSERT_ARG(interp) \
82 , PARROT_ASSERT_ARG(argv) \
83 , PARROT_ASSERT_ARG(pgm_argc) \
84 , PARROT_ASSERT_ARG(pgm_argv) \
85 , PARROT_ASSERT_ARG(core) \
86 , PARROT_ASSERT_ARG(trace))
87 #define ASSERT_ARGS_parseflags_minimal __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
88 PARROT_ASSERT_ARG(interp) \
89 , PARROT_ASSERT_ARG(argv))
90 #define ASSERT_ARGS_usage __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
91 PARROT_ASSERT_ARG(fp))
92 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
93 /* HEADERIZER END: static */
97 =item C<int main(int argc, const char *argv[])>
99 The entry point from the command line into Parrot.
106 main(int argc
, const char *argv
[])
109 const char *sourcefile
;
110 const char *execname
;
114 const char **pir_argv
;
116 Parrot_Run_core_t core
= PARROT_SLOW_CORE
;
117 Parrot_trace_flags trace
= PARROT_NO_TRACE
;
119 /* internationalization setup */
120 /* setlocale(LC_ALL, ""); */
121 PARROT_BINDTEXTDOMAIN(PACKAGE
, LOCALEDIR
);
122 PARROT_TEXTDOMAIN(PACKAGE
);
124 Parrot_set_config_hash();
126 interp
= allocate_interpreter(NULL
, PARROT_NO_FLAGS
);
128 /* We parse the arguments, but first store away the name of the Parrot
129 executable, since parsing destroys that and we want to make it
133 /* Parse minimal subset of flags */
134 parseflags_minimal(interp
, argc
, argv
);
136 /* Now initialize interpreter */
137 initialize_interpreter(interp
, (void*)&stacktop
);
140 sourcefile
= parseflags(interp
, argc
, argv
, &pir_argc
, &pir_argv
, &core
, &trace
);
142 Parrot_set_trace(interp
, trace
);
143 Parrot_set_run_core(interp
, (Parrot_Run_core_t
) core
);
144 Parrot_set_executable_name(interp
, Parrot_str_new(interp
, execname
, 0));
146 status
= imcc_run(interp
, sourcefile
, argc
, argv
);
149 imcc_run_pbc(interp
, interp
->output_file
, pir_argc
, pir_argv
);
151 /* Clean-up after ourselves */
152 Parrot_destroy(interp
);
153 Parrot_exit(interp
, 0);
156 #define SET_FLAG(flag) Parrot_set_flag(interp, (flag))
157 #define SET_DEBUG(flag) Parrot_set_debug(interp, (flag))
158 #define SET_TRACE(flag) Parrot_set_trace(interp, (flag))
162 =item C<static int is_all_hex_digits(const char *s)>
164 Tests all characters in a string are hexadecimal digits.
165 Returns 1 if true, 0 as soon as a non-hex found
171 PARROT_WARN_UNUSED_RESULT
174 is_all_hex_digits(ARGIN(const char *s
))
176 ASSERT_ARGS(is_all_hex_digits
)
185 =item C<static void usage(FILE *fp)>
187 Outputs usage error message.
194 usage(ARGMOD(FILE *fp
))
198 "parrot -[acEGhprtvVwy.] [-d [FLAGS]] [-D [FLAGS]]"
199 "[-O [level]] [-R runcore] [-o FILE] <file>\n");
204 =item C<static void help_debug(void)>
206 Print out list of debugging flag values.
215 ASSERT_ARGS(help_debug
)
216 /* split printf for C89 compliance on string length */
218 "--imcc-debug -d [Flags] ...\n"
223 " 0020 optimization 1\n"
224 " 0040 optimization 2\n"
227 " 2000 PBC constants\n"
231 "--parrot-debug -D [Flags] ...\n"
232 " 0001 memory statistics\n"
233 " 0002 print backtrace on exception\n"
234 " 0004 JIT debugging\n"
235 " 0008 interpreter startup\n"
236 " 0010 thread debugging\n"
237 " 0020 eval/compile\n"
238 " 0040 fill I, N registers with garbage\n"
239 " 0080 show when a context is destroyed\n"
241 "--trace -t [Flags] ...\n"
243 " 0002 find_method\n"
244 " 0004 function calls\n");
249 =item C<static void help(void)>
251 Print out "help" list of options.
261 /* split printf for C89 compliance on string length */
263 "parrot [Options] <file>\n"
267 " -I --include add path to include search\n"
268 " -L --library add path to library search\n"
269 " --hash-seed F00F specify hex value to use as hash seed\n"
270 " -X --dynext add path to dynamic extension search\n"
271 " <Run core options>\n"
272 " -R --runcore slow|bounds|fast\n"
273 " -R --runcore trace|profiling|gcdebug\n"
274 " -t --trace [flags]\n"
276 " -D --parrot-debug[=HEXFLAGS]\n"
282 " --leak-test|--destroy-at-end\n"
283 " -g --gc ms|inf set GC type\n"
284 " -. --wait Read a keystroke before starting\n"
285 " --runtime-prefix\n"
286 " <Compiler options>\n"
287 " -d --imcc-debug[=HEXFLAGS]\n"
289 " -E --pre-process-only\n"
290 " -o --output=FILE\n"
292 " -O --optimize[=LEVEL]\n"
297 " <Language options>\n"
298 "see docs/running.pod for more\n");
304 =item C<static void Parrot_version(void)>
306 Print out parrot version number.
315 ASSERT_ARGS(Parrot_version
)
316 printf("This is Parrot version " PARROT_VERSION
);
317 printf(" built for " PARROT_ARCHNAME
".\n");
318 printf("Copyright (C) 2001-2010, Parrot Foundation.\n\
320 This code is distributed under the terms of the Artistic License 2.0.\
322 For more details, see the full text of the license in the LICENSE file\
324 included in the Parrot source tree.\n\n");
331 =item C<static void parseflags_minimal(PARROT_INTERP, int argc, const char
334 Parse minimal subset of args required for initializing interpreter.
340 parseflags_minimal(PARROT_INTERP
, int argc
, ARGIN(const char *argv
[]))
342 ASSERT_ARGS(parseflags_minimal
)
347 const char *arg
= argv
[pos
];
349 if (STREQ(arg
, "--gc")) {
353 "main: No GC specified."
354 "\n\nhelp: parrot -h\n");
358 if (STREQ(arg
, "ms"))
359 interp
->gc_sys
->sys_type
= MS
;
360 else if (STREQ(arg
, "inf"))
361 interp
->gc_sys
->sys_type
= INF
;
364 "main: Unrecognized GC '%s' specified."
365 "\n\nhelp: parrot -h\n", arg
);
370 else if (!strncmp(arg
, "--hash-seed", 11)) {
372 if ((arg
= strrchr(arg
, '=')))
377 if (is_all_hex_digits(arg
)) {
378 interp
->hash_seed
= strtoul(arg
, NULL
, 16);
381 fprintf(stderr
, "error: invalid hash seed specified:"
394 =item C<static const char * parseflags(PARROT_INTERP, int argc, const char
395 *argv[], int *pgm_argc, const char ***pgm_argv, Parrot_Run_core_t *core,
396 Parrot_trace_flags *trace)>
398 Parse Parrot's command line for options and set appropriate flags.
404 PARROT_CAN_RETURN_NULL
406 parseflags(PARROT_INTERP
,
407 int argc
, ARGIN(const char *argv
[]),
408 ARGOUT(int *pgm_argc
), ARGOUT(const char ***pgm_argv
),
409 ARGMOD(Parrot_Run_core_t
*core
), ARGMOD(Parrot_trace_flags
*trace
))
411 ASSERT_ARGS(parseflags
)
412 struct longopt_opt_info opt
= LONGOPT_OPT_INFO_INIT
;
420 while ((status
= longopt_get(interp
, argc
, argv
, Parrot_cmd_options(), &opt
)) > 0) {
421 switch (opt
.opt_id
) {
423 if (STREQ(opt
.opt_arg
, "slow") || STREQ(opt
.opt_arg
, "bounds"))
424 *core
= PARROT_SLOW_CORE
;
425 else if (STREQ(opt
.opt_arg
, "fast") || STREQ(opt
.opt_arg
, "function"))
426 *core
= PARROT_FAST_CORE
;
427 else if (STREQ(opt
.opt_arg
, "jit"))
428 *core
= PARROT_FAST_CORE
;
429 else if (STREQ(opt
.opt_arg
, "exec"))
430 *core
= PARROT_EXEC_CORE
;
431 else if (STREQ(opt
.opt_arg
, "trace"))
432 *core
= PARROT_SLOW_CORE
;
433 else if (STREQ(opt
.opt_arg
, "profiling"))
434 *core
= PARROT_PROFILING_CORE
;
435 else if (STREQ(opt
.opt_arg
, "gcdebug"))
436 *core
= PARROT_GC_DEBUG_CORE
;
439 "main: Unrecognized runcore '%s' specified."
440 "\n\nhelp: parrot -h\n", opt
.opt_arg
);
445 /* Handled in parseflags_minimal */
448 if (opt
.opt_arg
&& is_all_hex_digits(opt
.opt_arg
)) {
449 const unsigned long _temp
= strtoul(opt
.opt_arg
, NULL
, 16);
450 const Parrot_trace_flags _temp_flag
= (Parrot_trace_flags
)_temp
;
454 *trace
= PARROT_TRACE_OPS_FLAG
;
457 if (opt
.opt_arg
&& is_all_hex_digits(opt
.opt_arg
)) {
458 SET_DEBUG(strtoul(opt
.opt_arg
, NULL
, 16));
461 SET_DEBUG(PARROT_MEM_STAT_DEBUG_FLAG
);
464 case '.': /* Give Windows Parrot hackers an opportunity to
465 * attach a debuggger. */
473 /* handled in parseflags_minimal */
479 case OPT_RUNTIME_PREFIX
:
480 Parrot_io_printf(interp
, "%Ss\n",
481 Parrot_get_runtime_path(interp
));
489 Parrot_warn(interp
, PARROT_WARNINGS_ALL_FLAG
,
490 "PARROT_GC_DEBUG is set but the binary was compiled "
491 "with DISABLE_GC_DEBUG.");
493 SET_FLAG(PARROT_GC_DEBUG_FLAG
);
495 case OPT_DESTROY_FLAG
:
496 SET_FLAG(PARROT_DESTROY_FLAG
);
499 Parrot_lib_add_path_from_cstring(interp
, opt
.opt_arg
,
500 PARROT_LIB_PATH_INCLUDE
);
503 Parrot_lib_add_path_from_cstring(interp
, opt
.opt_arg
,
504 PARROT_LIB_PATH_LIBRARY
);
507 Parrot_lib_add_path_from_cstring(interp
, opt
.opt_arg
,
508 PARROT_LIB_PATH_DYNEXT
);
511 /* FIXME It's not best way to set warnings... */
512 Parrot_setwarnings(interp
, PARROT_WARNINGS_ALL_FLAG
);
515 interp
->output_file
= opt
.opt_arg
;
518 if (!interp
->output_file
)
519 interp
->output_file
= "-";
521 /* languages handle their arguments later (after being initialized) */
527 fprintf(stderr
, "%s\n", opt
.opt_error
);
532 /* reached the end of the option list and consumed all of argv */
533 if (argc
== opt
.opt_index
) {
534 if (interp
->output_file
) {
535 fprintf(stderr
, "Missing program name or argument for -o\n");
538 /* We are not looking at an option, so it must be a program name */
539 fprintf(stderr
, "Missing program name\n");
545 *pgm_argc
= argc
- opt
.opt_index
;
546 *pgm_argv
= argv
+ opt
.opt_index
;
548 return (*pgm_argv
)[0];
556 F<compilers/imcc/main.c>, unfortunately.
564 * c-file-style: "parrot"
566 * vim: expandtab shiftwidth=4: