2
Copyright (C) 2007-2010, Parrot Foundation.
6
src/main.c - the Entry Point to Parrot Programs
22
#include "parrot/parrot.h"
23
#include "parrot/embed.h"
24
#include "parrot/imcc.h"
25
#include "parrot/longopt.h"
26
#include "parrot/runcore_api.h"
27
#include "pmc/pmc_callcontext.h"
29
/* For gc_sys_type_enum */
30
#include "gc/gc_private.h"
32
/* HEADERIZER HFILE: none */
34
/* HEADERIZER BEGIN: static */
35
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
37
static void help(void);
38
static void help_debug(void);
39
PARROT_WARN_UNUSED_RESULT
41
static int is_all_digits(ARGIN(const char *s))
42
__attribute__nonnull__(1);
44
PARROT_WARN_UNUSED_RESULT
46
static int is_all_hex_digits(ARGIN(const char *s))
47
__attribute__nonnull__(1);
49
static void Parrot_version(void);
50
PARROT_CAN_RETURN_NULL
51
static const char * parseflags(PARROT_INTERP,
53
ARGIN(const char *argv[]),
54
ARGOUT(int *pgm_argc),
55
ARGOUT(const char ***pgm_argv),
56
ARGMOD(Parrot_Run_core_t *core),
57
ARGMOD(Parrot_trace_flags *trace))
58
__attribute__nonnull__(1)
59
__attribute__nonnull__(3)
60
__attribute__nonnull__(4)
61
__attribute__nonnull__(5)
62
__attribute__nonnull__(6)
63
__attribute__nonnull__(7)
64
FUNC_MODIFIES(*pgm_argc)
65
FUNC_MODIFIES(*pgm_argv)
67
FUNC_MODIFIES(*trace);
69
static void parseflags_minimal(PARROT_INTERP,
71
ARGIN(const char *argv[]))
72
__attribute__nonnull__(1)
73
__attribute__nonnull__(3);
75
static void usage(ARGMOD(FILE *fp))
76
__attribute__nonnull__(1)
79
#define ASSERT_ARGS_help __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
80
#define ASSERT_ARGS_help_debug __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
81
#define ASSERT_ARGS_is_all_digits __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
83
#define ASSERT_ARGS_is_all_hex_digits __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
85
#define ASSERT_ARGS_Parrot_version __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
86
#define ASSERT_ARGS_parseflags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
87
PARROT_ASSERT_ARG(interp) \
88
, PARROT_ASSERT_ARG(argv) \
89
, PARROT_ASSERT_ARG(pgm_argc) \
90
, PARROT_ASSERT_ARG(pgm_argv) \
91
, PARROT_ASSERT_ARG(core) \
92
, PARROT_ASSERT_ARG(trace))
93
#define ASSERT_ARGS_parseflags_minimal __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
94
PARROT_ASSERT_ARG(interp) \
95
, PARROT_ASSERT_ARG(argv))
96
#define ASSERT_ARGS_usage __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
97
PARROT_ASSERT_ARG(fp))
98
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
99
/* HEADERIZER END: static */
103
=item C<int main(int argc, const char *argv[])>
105
The entry point from the command line into Parrot.
112
main(int argc, const char *argv[])
115
const char *sourcefile;
116
const char *execname;
120
const char **pir_argv;
122
Parrot_Run_core_t core = PARROT_SLOW_CORE;
123
Parrot_trace_flags trace = PARROT_NO_TRACE;
125
/* internationalization setup */
126
/* setlocale(LC_ALL, ""); */
127
PARROT_BINDTEXTDOMAIN(PACKAGE, LOCALEDIR);
128
PARROT_TEXTDOMAIN(PACKAGE);
130
Parrot_set_config_hash();
132
interp = allocate_interpreter(NULL, PARROT_NO_FLAGS);
134
/* We parse the arguments, but first store away the name of the Parrot
135
executable, since parsing destroys that and we want to make it
139
/* Parse minimal subset of flags */
140
parseflags_minimal(interp, argc, argv);
142
/* Now initialize interpreter */
143
initialize_interpreter(interp, (void*)&stacktop);
146
sourcefile = parseflags(interp, argc, argv, &pir_argc, &pir_argv, &core, &trace);
148
Parrot_set_trace(interp, trace);
149
Parrot_set_run_core(interp, (Parrot_Run_core_t) core);
150
Parrot_set_executable_name(interp, Parrot_str_new(interp, execname, 0));
152
status = imcc_run(interp, sourcefile, argc, argv);
155
imcc_run_pbc(interp, interp->output_file, pir_argc, pir_argv);
157
/* Clean-up after ourselves */
158
Parrot_destroy(interp);
159
Parrot_x_exit(interp, 0);
162
#define SET_FLAG(flag) Parrot_set_flag(interp, (flag))
163
#define SET_DEBUG(flag) Parrot_set_debug(interp, (flag))
164
#define SET_TRACE(flag) Parrot_set_trace(interp, (flag))
168
=item C<static int is_all_digits(const char *s)>
170
Tests all characters in a string are decimal digits.
171
Returns 1 if true, 0 as soon as a non-decimal found
177
PARROT_WARN_UNUSED_RESULT
180
is_all_digits(ARGIN(const char *s))
182
ASSERT_ARGS(is_all_digits)
184
if (!isdigit((unsigned char)*s))
191
=item C<static int is_all_hex_digits(const char *s)>
193
Tests all characters in a string are hexadecimal digits.
194
Returns 1 if true, 0 as soon as a non-hex found
200
PARROT_WARN_UNUSED_RESULT
203
is_all_hex_digits(ARGIN(const char *s))
205
ASSERT_ARGS(is_all_hex_digits)
214
=item C<static void usage(FILE *fp)>
216
Outputs usage error message.
223
usage(ARGMOD(FILE *fp))
227
"parrot -[acEGhprtvVwy.] [-d [FLAGS]] [-D [FLAGS]]"
228
"[-O [level]] [-R runcore] [-o FILE] <file>\n");
233
=item C<static void help_debug(void)>
235
Print out list of debugging flag values.
244
ASSERT_ARGS(help_debug)
245
/* split printf for C89 compliance on string length */
247
"--imcc-debug -d [Flags] ...\n"
252
" 0020 optimization 1\n"
253
" 0040 optimization 2\n"
256
" 2000 PBC constants\n"
260
"--parrot-debug -D [Flags] ...\n"
261
" 0001 memory statistics\n"
262
" 0002 print backtrace on exception\n"
263
" 0004 JIT debugging\n"
264
" 0008 interpreter startup\n"
265
" 0010 thread debugging\n"
266
" 0020 eval/compile\n"
267
" 0040 fill I, N registers with garbage\n"
268
" 0080 show when a context is destroyed\n"
270
"--trace -t [Flags] ...\n"
272
" 0002 find_method\n"
273
" 0004 function calls\n");
278
=item C<static void help(void)>
280
Print out "help" list of options.
290
/* split printf for C89 compliance on string length */
292
"parrot [Options] <file>\n"
296
" -I --include add path to include search\n"
297
" -L --library add path to library search\n"
298
" --hash-seed F00F specify hex value to use as hash seed\n"
299
" -X --dynext add path to dynamic extension search\n"
300
" <Run core options>\n"
301
" -R --runcore slow|bounds|fast\n"
302
" -R --runcore trace|profiling|gcdebug\n"
303
" -t --trace [flags]\n"
305
" -D --parrot-debug[=HEXFLAGS]\n"
310
" --gc-threshold=percentage maximum memory wasted by GC\n"
312
" --leak-test|--destroy-at-end\n"
313
" -g --gc ms|inf set GC type\n"
314
" -. --wait Read a keystroke before starting\n"
315
" --runtime-prefix\n"
316
" <Compiler options>\n"
317
" -d --imcc-debug[=HEXFLAGS]\n"
319
" -E --pre-process-only\n"
320
" -o --output=FILE\n"
322
" -O --optimize[=LEVEL]\n"
327
" <Language options>\n"
328
"see docs/running.pod for more\n");
334
=item C<static void Parrot_version(void)>
336
Print out parrot version number.
345
ASSERT_ARGS(Parrot_version)
346
printf("This is Parrot version " PARROT_VERSION);
347
printf(" built for " PARROT_ARCHNAME ".\n");
348
printf("Copyright (C) 2001-2010, Parrot Foundation.\n\
350
This code is distributed under the terms of the Artistic License 2.0.\
352
For more details, see the full text of the license in the LICENSE file\
354
included in the Parrot source tree.\n\n");
361
=item C<static void parseflags_minimal(PARROT_INTERP, int argc, const char
364
Parse minimal subset of args required for initializing interpreter.
370
parseflags_minimal(PARROT_INTERP, int argc, ARGIN(const char *argv[]))
372
ASSERT_ARGS(parseflags_minimal)
377
const char *arg = argv[pos];
379
if (STREQ(arg, "--gc")) {
383
"main: No GC specified."
384
"\n\nhelp: parrot -h\n");
388
if (STREQ(arg, "ms"))
389
interp->gc_sys->sys_type = MS;
390
else if (STREQ(arg, "inf"))
391
interp->gc_sys->sys_type = INF;
392
else if (STREQ(arg, "ms2"))
393
interp->gc_sys->sys_type = MS2;
396
"main: Unrecognized GC '%s' specified."
397
"\n\nhelp: parrot -h\n", arg);
403
/* arg should start with --gc-threshold *and* contain more chars */
404
else if (strncmp(arg, "--gc-threshold", 14) == 0) {
406
/* the next character could be '=' */
407
if (arg[14] == '=') {
411
/* or the end of the string... */
412
else if (arg[14] == '\0'
414
/* and there's another argument */
419
/* ANYTHING ELSE IS WRONG */
421
fprintf(stderr, "--gc-threshold needs an argument");
425
if (is_all_digits(arg)) {
426
interp->gc_threshold = strtoul(arg, NULL, 10);
428
if (interp->gc_threshold > 1000) {
429
fprintf(stderr, "error: maximum GC threshold is 1000\n");
434
fprintf(stderr, "error: invalid GC threshold specified:"
441
else if (!strncmp(arg, "--hash-seed", 11)) {
443
if ((arg = strrchr(arg, '=')))
448
if (is_all_hex_digits(arg)) {
449
interp->hash_seed = strtoul(arg, NULL, 16);
452
fprintf(stderr, "error: invalid hash seed specified:"
465
=item C<static const char * parseflags(PARROT_INTERP, int argc, const char
466
*argv[], int *pgm_argc, const char ***pgm_argv, Parrot_Run_core_t *core,
467
Parrot_trace_flags *trace)>
469
Parse Parrot's command line for options and set appropriate flags.
475
PARROT_CAN_RETURN_NULL
477
parseflags(PARROT_INTERP,
478
int argc, ARGIN(const char *argv[]),
479
ARGOUT(int *pgm_argc), ARGOUT(const char ***pgm_argv),
480
ARGMOD(Parrot_Run_core_t *core), ARGMOD(Parrot_trace_flags *trace))
482
ASSERT_ARGS(parseflags)
483
struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT;
491
while ((status = longopt_get(interp, argc, argv, Parrot_cmd_options(), &opt)) > 0) {
492
switch (opt.opt_id) {
494
if (STREQ(opt.opt_arg, "slow") || STREQ(opt.opt_arg, "bounds"))
495
*core = PARROT_SLOW_CORE;
496
else if (STREQ(opt.opt_arg, "fast") || STREQ(opt.opt_arg, "function"))
497
*core = PARROT_FAST_CORE;
498
else if (STREQ(opt.opt_arg, "jit"))
499
*core = PARROT_FAST_CORE;
500
else if (STREQ(opt.opt_arg, "exec"))
501
*core = PARROT_EXEC_CORE;
502
else if (STREQ(opt.opt_arg, "trace"))
503
*core = PARROT_SLOW_CORE;
504
else if (STREQ(opt.opt_arg, "profiling"))
505
*core = PARROT_PROFILING_CORE;
506
else if (STREQ(opt.opt_arg, "gcdebug"))
507
*core = PARROT_GC_DEBUG_CORE;
510
"main: Unrecognized runcore '%s' specified."
511
"\n\nhelp: parrot -h\n", opt.opt_arg);
516
/* Handled in parseflags_minimal */
518
case OPT_GC_THRESHOLD:
519
/* handled in parseflags_minimal */
522
if (opt.opt_arg && is_all_hex_digits(opt.opt_arg)) {
523
const unsigned long _temp = strtoul(opt.opt_arg, NULL, 16);
524
const Parrot_trace_flags _temp_flag = (Parrot_trace_flags)_temp;
528
*trace = PARROT_TRACE_OPS_FLAG;
531
if (opt.opt_arg && is_all_hex_digits(opt.opt_arg)) {
532
SET_DEBUG(strtoul(opt.opt_arg, NULL, 16));
535
SET_DEBUG(PARROT_MEM_STAT_DEBUG_FLAG);
538
case '.': /* Give Windows Parrot hackers an opportunity to
539
* attach a debuggger. */
547
/* handled in parseflags_minimal */
553
case OPT_RUNTIME_PREFIX:
554
Parrot_io_printf(interp, "%Ss\n",
555
Parrot_get_runtime_path(interp));
563
Parrot_warn(interp, PARROT_WARNINGS_ALL_FLAG,
564
"PARROT_GC_DEBUG is set but the binary was compiled "
565
"with DISABLE_GC_DEBUG.");
567
SET_FLAG(PARROT_GC_DEBUG_FLAG);
569
case OPT_DESTROY_FLAG:
570
SET_FLAG(PARROT_DESTROY_FLAG);
573
Parrot_lib_add_path_from_cstring(interp, opt.opt_arg,
574
PARROT_LIB_PATH_INCLUDE);
577
Parrot_lib_add_path_from_cstring(interp, opt.opt_arg,
578
PARROT_LIB_PATH_LIBRARY);
581
Parrot_lib_add_path_from_cstring(interp, opt.opt_arg,
582
PARROT_LIB_PATH_DYNEXT);
585
/* FIXME It's not best way to set warnings... */
586
Parrot_setwarnings(interp, PARROT_WARNINGS_ALL_FLAG);
589
interp->output_file = opt.opt_arg;
592
if (!interp->output_file)
593
interp->output_file = "-";
595
/* languages handle their arguments later (after being initialized) */
601
fprintf(stderr, "%s\n", opt.opt_error);
606
/* reached the end of the option list and consumed all of argv */
607
if (argc == opt.opt_index) {
608
if (interp->output_file) {
609
fprintf(stderr, "Missing program name or argument for -o\n");
612
/* We are not looking at an option, so it must be a program name */
613
fprintf(stderr, "Missing program name\n");
619
*pgm_argc = argc - opt.opt_index;
620
*pgm_argv = argv + opt.opt_index;
622
return (*pgm_argv)[0];
630
F<compilers/imcc/main.c>, unfortunately.
638
* c-file-style: "parrot"
640
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :