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(PARROT_INTERP
)
46 __attribute__nonnull__(1);
48 PARROT_CAN_RETURN_NULL
49 static const char * parseflags(PARROT_INTERP
,
52 ARGIN(Parrot_Run_core_t
*core
),
53 ARGIN(Parrot_trace_flags
*trace
))
54 __attribute__nonnull__(1)
55 __attribute__nonnull__(2)
56 __attribute__nonnull__(3)
57 __attribute__nonnull__(4)
58 __attribute__nonnull__(5);
60 static void parseflags_minimal(PARROT_INTERP
, int argc
, ARGIN(char *argv
[]))
61 __attribute__nonnull__(1)
62 __attribute__nonnull__(3);
64 static void usage(ARGMOD(FILE *fp
))
65 __attribute__nonnull__(1)
68 #define ASSERT_ARGS_help __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
69 #define ASSERT_ARGS_help_debug __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
70 #define ASSERT_ARGS_is_all_hex_digits __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
72 #define ASSERT_ARGS_Parrot_version __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
73 PARROT_ASSERT_ARG(interp))
74 #define ASSERT_ARGS_parseflags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
75 PARROT_ASSERT_ARG(interp) \
76 , PARROT_ASSERT_ARG(argc) \
77 , PARROT_ASSERT_ARG(argv) \
78 , PARROT_ASSERT_ARG(core) \
79 , PARROT_ASSERT_ARG(trace))
80 #define ASSERT_ARGS_parseflags_minimal __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
81 PARROT_ASSERT_ARG(interp) \
82 , PARROT_ASSERT_ARG(argv))
83 #define ASSERT_ARGS_usage __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
84 PARROT_ASSERT_ARG(fp))
85 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
86 /* HEADERIZER END: static */
90 =item C<int main(int argc, char * argv[])>
92 The entry point from the command line into Parrot.
99 main(int argc
, char * argv
[])
102 const char *sourcefile
;
103 const char *execname
;
107 Parrot_Run_core_t core
= PARROT_SLOW_CORE
;
108 Parrot_trace_flags trace
= PARROT_NO_TRACE
;
110 /* internationalization setup */
111 /* setlocale(LC_ALL, ""); */
112 PARROT_BINDTEXTDOMAIN(PACKAGE
, LOCALEDIR
);
113 PARROT_TEXTDOMAIN(PACKAGE
);
115 Parrot_set_config_hash();
117 interp
= allocate_interpreter(NULL
, PARROT_NO_FLAGS
);
119 /* We parse the arguments, but first store away the name of the Parrot
120 executable, since parsing destroys that and we want to make it
124 /* Parse minimal subset of flags */
125 parseflags_minimal(interp
, argc
, argv
);
127 /* Now initialize interpreter */
128 initialize_interpreter(interp
, (void*)&stacktop
);
129 imcc_initialize(interp
);
131 { /* EXPERIMENTAL: add library and include paths from environment */
132 PMC
*env
= Parrot_pmc_new(interp
, enum_class_Env
);
133 STRING
*path
= VTABLE_get_string_keyed_str(interp
, env
,
134 Parrot_str_new_constant(interp
, "PARROT_LIBRARY"));
135 if (!Parrot_str_is_null(interp
, path
) && Parrot_str_length(interp
, path
) > 0)
136 Parrot_lib_add_path(interp
, path
, PARROT_LIB_PATH_LIBRARY
);
137 path
= VTABLE_get_string_keyed_str(interp
, env
,
138 Parrot_str_new_constant(interp
, "PARROT_INCLUDE"));
139 if (!Parrot_str_is_null(interp
, path
) && Parrot_str_length(interp
, path
) > 0)
140 Parrot_lib_add_path(interp
, path
, PARROT_LIB_PATH_INCLUDE
);
144 sourcefile
= parseflags(interp
, &argc
, &argv
, &core
, &trace
);
146 Parrot_set_trace(interp
, trace
);
147 Parrot_set_run_core(interp
, (Parrot_Run_core_t
) core
);
148 Parrot_set_executable_name(interp
, Parrot_str_new(interp
, execname
, 0));
150 status
= imcc_run(interp
, sourcefile
, argc
, argv
);
153 /* Clean-up after ourselves */
154 Parrot_destroy(interp
);
155 Parrot_exit(interp
, 0);
158 #define OPT_GC_DEBUG 128
159 #define OPT_DESTROY_FLAG 129
160 #define OPT_HELP_DEBUG 130
161 #define OPT_PBC_OUTPUT 131
162 #define OPT_RUNTIME_PREFIX 132
164 #define SET_FLAG(flag) Parrot_set_flag(interp, (flag))
165 #define SET_DEBUG(flag) Parrot_set_debug(interp, (flag))
166 #define SET_TRACE(flag) Parrot_set_trace(interp, (flag))
168 static struct longopt_opt_decl options
[] = {
169 { '.', '.', (OPTION_flags
)0, { "--wait" } },
170 { 'D', 'D', OPTION_optional_FLAG
, { "--parrot-debug" } },
171 { 'E', 'E', (OPTION_flags
)0, { "--pre-process-only" } },
172 { 'G', 'G', (OPTION_flags
)0, { "--no-gc" } },
173 { 'H', 'H', OPTION_required_FLAG
, { "--hash-seed" } },
174 { 'I', 'I', OPTION_required_FLAG
, { "--include" } },
175 { 'L', 'L', OPTION_required_FLAG
, { "--library" } },
176 { 'O', 'O', OPTION_optional_FLAG
, { "--optimize" } },
177 { 'R', 'R', OPTION_required_FLAG
, { "--runcore" } },
178 { 'g', 'g', OPTION_required_FLAG
, { "--gc" } },
179 { 'V', 'V', (OPTION_flags
)0, { "--version" } },
180 { 'X', 'X', OPTION_required_FLAG
, { "--dynext" } },
181 { '\0', OPT_DESTROY_FLAG
, (OPTION_flags
)0,
182 { "--leak-test", "--destroy-at-end" } },
183 { '\0', OPT_GC_DEBUG
, (OPTION_flags
)0, { "--gc-debug" } },
184 { 'a', 'a', (OPTION_flags
)0, { "--pasm" } },
185 { 'c', 'c', (OPTION_flags
)0, { "--pbc" } },
186 { 'd', 'd', OPTION_optional_FLAG
, { "--imcc-debug" } },
187 { '\0', OPT_HELP_DEBUG
, (OPTION_flags
)0, { "--help-debug" } },
188 { 'h', 'h', (OPTION_flags
)0, { "--help" } },
189 { 'o', 'o', OPTION_required_FLAG
, { "--output" } },
190 { '\0', OPT_PBC_OUTPUT
, (OPTION_flags
)0, { "--output-pbc" } },
191 { 'r', 'r', (OPTION_flags
)0, { "--run-pbc" } },
192 { '\0', OPT_RUNTIME_PREFIX
, (OPTION_flags
)0, { "--runtime-prefix" } },
193 { 't', 't', OPTION_optional_FLAG
, { "--trace" } },
194 { 'v', 'v', (OPTION_flags
)0, { "--verbose" } },
195 { 'w', 'w', (OPTION_flags
)0, { "--warnings" } },
196 { 'y', 'y', (OPTION_flags
)0, { "--yydebug" } },
197 { 0, 0, (OPTION_flags
)0, { NULL
} }
202 =item C<static int is_all_hex_digits(const char *s)>
204 Tests all characters in a string are hexadecimal digits.
205 Returns 1 if true, 0 as soon as a non-hex found
211 PARROT_WARN_UNUSED_RESULT
214 is_all_hex_digits(ARGIN(const char *s
))
216 ASSERT_ARGS(is_all_hex_digits
)
225 =item C<static void usage(FILE *fp)>
227 Outputs usage error message.
234 usage(ARGMOD(FILE *fp
))
238 "parrot -[acEGhprtvVwy.] [-d [FLAGS]] [-D [FLAGS]]"
239 "[-O [level]] [-R runcore] [-o FILE] <file>\n");
244 =item C<static void help_debug(void)>
246 Print out list of debugging flag values.
255 ASSERT_ARGS(help_debug
)
256 /* split printf for C89 compliance on string length */
258 "--imcc-debug -d [Flags] ...\n"
263 " 0020 optimization 1\n"
264 " 0040 optimization 2\n"
267 " 2000 PBC constants\n"
271 "--parrot-debug -D [Flags] ...\n"
272 " 0001 memory statistics\n"
273 " 0002 print backtrace on exception\n"
274 " 0004 JIT debugging\n"
275 " 0008 interpreter startup\n"
276 " 0010 thread debugging\n"
277 " 0020 eval/compile\n"
278 " 0040 fill I, N registers with garbage\n"
279 " 0080 show when a context is destroyed\n"
281 "--trace -t [Flags] ...\n"
283 " 0002 find_method\n"
284 " 0004 function calls\n");
289 =item C<static void help(void)>
291 Print out "help" list of options.
301 /* split printf for C89 compliance on string length */
303 "parrot [Options] <file>\n"
307 " -I --include add path to include search\n"
308 " -L --library add path to library search\n"
309 " -H --hash-seed F00F specify hex value to use as hash seed\n"
310 " -X --dynext add path to dynamic extension search\n"
311 " <Run core options>\n"
312 " -R --runcore slow|bounds|fast|cgoto|cgp\n"
313 " -R --runcore switch|trace|profiling|gcdebug\n"
314 " -t --trace [flags]\n"
316 " -D --parrot-debug[=HEXFLAGS]\n"
322 " --leak-test|--destroy-at-end\n"
323 " -g --gc ms|inf set GC type\n"
324 " -. --wait Read a keystroke before starting\n"
325 " --runtime-prefix\n"
326 " <Compiler options>\n"
327 " -d --imcc-debug[=HEXFLAGS]\n"
329 " -E --pre-process-only\n"
330 " -o --output=FILE\n"
332 " -O --optimize[=LEVEL]\n"
337 " <Language options>\n"
338 "see docs/running.pod for more\n");
344 =item C<static void Parrot_version(PARROT_INTERP)>
346 Print out parrot version number.
353 Parrot_version(PARROT_INTERP
)
355 ASSERT_ARGS(Parrot_version
)
356 printf("This is Parrot version " PARROT_VERSION
);
357 printf(" built for " PARROT_ARCHNAME
".\n");
358 printf("Copyright (C) 2001-2010, Parrot Foundation.\n\
360 This code is distributed under the terms of the Artistic License 2.0.\
362 For more details, see the full text of the license in the LICENSE file\
364 included in the Parrot source tree.\n\n");
371 =item C<static void parseflags_minimal(PARROT_INTERP, int argc, char *argv[])>
373 Parse minimal subset of args required for initializing interpreter.
379 parseflags_minimal(PARROT_INTERP
, int argc
, ARGIN(char *argv
[]))
381 ASSERT_ARGS(parseflags_minimal
)
387 if (STREQ(arg
, "--gc")) {
391 "main: No GC specified."
392 "\n\nhelp: parrot -h\n");
396 if (STREQ(arg
, "ms"))
397 interp
->gc_sys
->sys_type
= MS
;
398 else if (STREQ(arg
, "inf"))
399 interp
->gc_sys
->sys_type
= INF
;
402 "main: Unrecognized GC '%s' specified."
403 "\n\nhelp: parrot -h\n", arg
);
408 else if (STREQ(arg
, "--hash-seed")) {
411 if (is_all_hex_digits(arg
)) {
412 interp
->hash_seed
= strtoul(arg
, NULL
, 16);
421 =item C<static const char * parseflags(PARROT_INTERP, int *argc, char **argv[],
422 Parrot_Run_core_t *core, Parrot_trace_flags *trace)>
424 Parse Parrot's command line for options and set appropriate flags.
430 PARROT_CAN_RETURN_NULL
432 parseflags(PARROT_INTERP
,
433 ARGIN(int *argc
), ARGIN(char **argv
[]),
434 ARGIN(Parrot_Run_core_t
*core
), ARGIN(Parrot_trace_flags
*trace
))
436 ASSERT_ARGS(parseflags
)
437 struct longopt_opt_info opt
= LONGOPT_OPT_INFO_INIT
;
439 /* g++ complains if we cast char** to const char** directly. However, nobody
440 ever complains if you const to void* first. Sure we lose a certain
441 amount of compiler-enforced type safety, but this is a rare occasion
442 with a very long explanatory comment. */
443 const char ** const _tempargv
= (const char **)((void *)*argv
);
450 imcc_start_handling_flags(interp
);
452 while ((status
= longopt_get(interp
, *argc
, _tempargv
, options
,
454 switch (opt
.opt_id
) {
456 if (STREQ(opt
.opt_arg
, "slow") || STREQ(opt
.opt_arg
, "bounds"))
457 *core
= PARROT_SLOW_CORE
;
458 else if (STREQ(opt
.opt_arg
, "fast") || STREQ(opt
.opt_arg
, "function"))
459 *core
= PARROT_FAST_CORE
;
460 else if (STREQ(opt
.opt_arg
, "switch"))
461 *core
= PARROT_SWITCH_CORE
;
462 else if (STREQ(opt
.opt_arg
, "cgp"))
463 *core
= PARROT_CGP_CORE
;
464 else if (STREQ(opt
.opt_arg
, "cgoto"))
465 *core
= PARROT_CGOTO_CORE
;
466 else if (STREQ(opt
.opt_arg
, "jit"))
467 *core
= PARROT_FAST_CORE
;
468 else if (STREQ(opt
.opt_arg
, "cgp-jit"))
469 *core
= PARROT_CGP_CORE
;
470 else if (STREQ(opt
.opt_arg
, "switch-jit"))
471 *core
= PARROT_SWITCH_CORE
;
472 else if (STREQ(opt
.opt_arg
, "exec"))
473 *core
= PARROT_EXEC_CORE
;
474 else if (STREQ(opt
.opt_arg
, "trace"))
475 *core
= PARROT_SLOW_CORE
;
476 else if (STREQ(opt
.opt_arg
, "profiling"))
477 *core
= PARROT_PROFILING_CORE
;
478 else if (STREQ(opt
.opt_arg
, "gcdebug"))
479 *core
= PARROT_GC_DEBUG_CORE
;
482 "main: Unrecognized runcore '%s' specified."
483 "\n\nhelp: parrot -h\n", opt
.opt_arg
);
488 /* Handled in parseflags_minimal */
491 if (opt
.opt_arg
&& is_all_hex_digits(opt
.opt_arg
)) {
492 const unsigned long _temp
= strtoul(opt
.opt_arg
, NULL
, 16);
493 const Parrot_trace_flags _temp_flag
= (Parrot_trace_flags
)_temp
;
497 *trace
= PARROT_TRACE_OPS_FLAG
;
500 if (opt
.opt_arg
&& is_all_hex_digits(opt
.opt_arg
)) {
501 SET_DEBUG(strtoul(opt
.opt_arg
, NULL
, 16));
504 SET_DEBUG(PARROT_MEM_STAT_DEBUG_FLAG
);
507 case '.': /* Give Windows Parrot hackers an opportunity to
508 * attach a debuggger. */
516 /* handled in parseflags_minimal */
522 case OPT_RUNTIME_PREFIX
:
523 Parrot_io_printf(interp
, "%Ss\n",
524 Parrot_get_runtime_path(interp
));
527 Parrot_version(interp
);
532 Parrot_warn(interp
, PARROT_WARNINGS_ALL_FLAG
,
533 "PARROT_GC_DEBUG is set but the binary was compiled "
534 "with DISABLE_GC_DEBUG.");
536 SET_FLAG(PARROT_GC_DEBUG_FLAG
);
538 case OPT_DESTROY_FLAG
:
539 SET_FLAG(PARROT_DESTROY_FLAG
);
542 Parrot_lib_add_path_from_cstring(interp
, opt
.opt_arg
,
543 PARROT_LIB_PATH_INCLUDE
);
546 Parrot_lib_add_path_from_cstring(interp
, opt
.opt_arg
,
547 PARROT_LIB_PATH_LIBRARY
);
550 Parrot_lib_add_path_from_cstring(interp
, opt
.opt_arg
,
551 PARROT_LIB_PATH_DYNEXT
);
554 /* Delegate handling of IMCC flags to IMCC */
555 if (imcc_handle_flag(interp
, &opt
, core
))
558 /* PIRC flags handling goes here */
560 "main: Invalid flag '%s' used.\n\nhelp: parrot -h\n",
567 fprintf(stderr
, "%s\n", opt
.opt_error
);
572 /* reached the end of the option list and consumed all of argv */
573 if (*argc
== opt
.opt_index
) {
574 if (interp
->output_file
) {
575 fprintf(stderr
, "Missing program name or argument for -o\n");
578 /* We are not looking at an option, so it must be a program name */
579 fprintf(stderr
, "Missing program name\n");
585 *argc
-= opt
.opt_index
;
586 *argv
+= opt
.opt_index
;
596 F<compilers/imcc/main.c>, unfortunately.
604 * c-file-style: "parrot"
606 * vim: expandtab shiftwidth=4: