fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / main.c
blobbb086978453db267a096312a4ced6825a0dde8e1
1 /*
2 Copyright (C) 2007-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/main.c - the Entry Point to Parrot Programs
9 =head1 DESCRIPTION
11 Start Parrot
13 =head2 Functions
15 =over 4
17 =cut
21 #include <stdio.h>
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
41 PARROT_PURE_FUNCTION
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,
48 int argc,
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)
62 FUNC_MODIFIES(*core)
63 FUNC_MODIFIES(*trace);
65 static void parseflags_minimal(PARROT_INTERP,
66 int argc,
67 ARGIN(const char *argv[]))
68 __attribute__nonnull__(1)
69 __attribute__nonnull__(3);
71 static void usage(ARGMOD(FILE *fp))
72 __attribute__nonnull__(1)
73 FUNC_MODIFIES(*fp);
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 = (\
78 PARROT_ASSERT_ARG(s))
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.
101 =cut
106 main(int argc, const char *argv[])
108 int stacktop;
109 const char *sourcefile;
110 const char *execname;
111 Interp *interp;
112 int status;
113 int pir_argc;
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
130 available. */
131 execname = argv[0];
133 /* Parse minimal subset of flags */
134 parseflags_minimal(interp, argc, argv);
136 /* Now initialize interpreter */
137 initialize_interpreter(interp, (void*)&stacktop);
139 /* Parse flags */
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);
148 if (status)
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
167 =cut
171 PARROT_WARN_UNUSED_RESULT
172 PARROT_PURE_FUNCTION
173 static int
174 is_all_hex_digits(ARGIN(const char *s))
176 ASSERT_ARGS(is_all_hex_digits)
177 for (; *s; ++s)
178 if (!isxdigit(*s))
179 return 0;
180 return 1;
185 =item C<static void usage(FILE *fp)>
187 Outputs usage error message.
189 =cut
193 static void
194 usage(ARGMOD(FILE *fp))
196 ASSERT_ARGS(usage)
197 fprintf(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.
208 =cut
212 static void
213 help_debug(void)
215 ASSERT_ARGS(help_debug)
216 /* split printf for C89 compliance on string length */
217 printf(
218 "--imcc-debug -d [Flags] ...\n"
219 " 0002 lexer\n"
220 " 0004 parser\n"
221 " 0008 imc\n"
222 " 0010 CFG\n"
223 " 0020 optimization 1\n"
224 " 0040 optimization 2\n"
225 " 0100 AST\n"
226 " 1000 PBC\n"
227 " 2000 PBC constants\n"
228 " 4000 PBC fixups\n"
229 "\n");
230 printf(
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"
240 "\n"
241 "--trace -t [Flags] ...\n"
242 " 0001 opcodes\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.
253 =cut
257 static void
258 help(void)
260 ASSERT_ARGS(help)
261 /* split printf for C89 compliance on string length */
262 printf(
263 "parrot [Options] <file>\n"
264 " Options:\n"
265 " -h --help\n"
266 " -V --version\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"
275 " <VM options>\n"
276 " -D --parrot-debug[=HEXFLAGS]\n"
277 " --help-debug\n");
278 printf(
279 " -w --warnings\n"
280 " -G --no-gc\n"
281 " --gc-debug\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"
288 " -v --verbose\n"
289 " -E --pre-process-only\n"
290 " -o --output=FILE\n"
291 " --output-pbc\n"
292 " -O --optimize[=LEVEL]\n"
293 " -a --pasm\n"
294 " -c --pbc\n"
295 " -r --run-pbc\n"
296 " -y --yydebug\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.
308 =cut
312 static void
313 Parrot_version(void)
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");
326 exit(EXIT_SUCCESS);
331 =item C<static void parseflags_minimal(PARROT_INTERP, int argc, const char
332 *argv[])>
334 Parse minimal subset of args required for initializing interpreter.
336 =cut
339 static void
340 parseflags_minimal(PARROT_INTERP, int argc, ARGIN(const char *argv[]))
342 ASSERT_ARGS(parseflags_minimal)
344 int pos = 0;
346 while (pos < argc) {
347 const char *arg = argv[pos];
349 if (STREQ(arg, "--gc")) {
350 ++pos;
351 if (pos == argc) {
352 fprintf(stderr,
353 "main: No GC specified."
354 "\n\nhelp: parrot -h\n");
355 exit(EXIT_FAILURE);
357 arg = argv[pos];
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;
362 else {
363 fprintf(stderr,
364 "main: Unrecognized GC '%s' specified."
365 "\n\nhelp: parrot -h\n", arg);
366 exit(EXIT_FAILURE);
368 break;
370 else if (!strncmp(arg, "--hash-seed", 11)) {
372 if ((arg = strrchr(arg, '=')))
373 ++arg;
374 else
375 arg = argv[++pos];
377 if (is_all_hex_digits(arg)) {
378 interp->hash_seed = strtoul(arg, NULL, 16);
380 else {
381 fprintf(stderr, "error: invalid hash seed specified:"
382 "'%s'\n", arg);
383 exit(EXIT_FAILURE);
385 ++pos;
386 arg = argv[pos];
388 ++pos;
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.
400 =cut
404 PARROT_CAN_RETURN_NULL
405 static const char *
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;
413 int status;
415 if (argc == 1) {
416 usage(stderr);
417 exit(EXIT_SUCCESS);
420 while ((status = longopt_get(interp, argc, argv, Parrot_cmd_options(), &opt)) > 0) {
421 switch (opt.opt_id) {
422 case 'R':
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;
437 else {
438 fprintf(stderr,
439 "main: Unrecognized runcore '%s' specified."
440 "\n\nhelp: parrot -h\n", opt.opt_arg);
441 exit(EXIT_FAILURE);
443 break;
444 case 'g':
445 /* Handled in parseflags_minimal */
446 break;
447 case 't':
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;
451 *trace = _temp_flag;
453 else
454 *trace = PARROT_TRACE_OPS_FLAG;
455 break;
456 case 'D':
457 if (opt.opt_arg && is_all_hex_digits(opt.opt_arg)) {
458 SET_DEBUG(strtoul(opt.opt_arg, NULL, 16));
460 else
461 SET_DEBUG(PARROT_MEM_STAT_DEBUG_FLAG);
462 break;
464 case '.': /* Give Windows Parrot hackers an opportunity to
465 * attach a debuggger. */
466 fgetc(stdin);
467 break;
468 case 'h':
469 help();
470 exit(EXIT_FAILURE);
471 break;
472 case OPT_HASH_SEED:
473 /* handled in parseflags_minimal */
474 break;
475 case OPT_HELP_DEBUG:
476 help_debug();
477 exit(EXIT_FAILURE);
478 break;
479 case OPT_RUNTIME_PREFIX:
480 Parrot_io_printf(interp, "%Ss\n",
481 Parrot_get_runtime_path(interp));
482 exit(EXIT_SUCCESS);
483 case 'V':
484 Parrot_version();
485 break;
487 case OPT_GC_DEBUG:
488 #if DISABLE_GC_DEBUG
489 Parrot_warn(interp, PARROT_WARNINGS_ALL_FLAG,
490 "PARROT_GC_DEBUG is set but the binary was compiled "
491 "with DISABLE_GC_DEBUG.");
492 #endif
493 SET_FLAG(PARROT_GC_DEBUG_FLAG);
494 break;
495 case OPT_DESTROY_FLAG:
496 SET_FLAG(PARROT_DESTROY_FLAG);
497 break;
498 case 'I':
499 Parrot_lib_add_path_from_cstring(interp, opt.opt_arg,
500 PARROT_LIB_PATH_INCLUDE);
501 break;
502 case 'L':
503 Parrot_lib_add_path_from_cstring(interp, opt.opt_arg,
504 PARROT_LIB_PATH_LIBRARY);
505 break;
506 case 'X':
507 Parrot_lib_add_path_from_cstring(interp, opt.opt_arg,
508 PARROT_LIB_PATH_DYNEXT);
509 break;
510 case 'w':
511 /* FIXME It's not best way to set warnings... */
512 Parrot_setwarnings(interp, PARROT_WARNINGS_ALL_FLAG);
513 break;
514 case 'o':
515 interp->output_file = opt.opt_arg;
516 break;
517 case OPT_PBC_OUTPUT:
518 if (!interp->output_file)
519 interp->output_file = "-";
520 default:
521 /* languages handle their arguments later (after being initialized) */
522 break;
526 if (status == -1) {
527 fprintf(stderr, "%s\n", opt.opt_error);
528 usage(stderr);
529 exit(EXIT_FAILURE);
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");
537 else {
538 /* We are not looking at an option, so it must be a program name */
539 fprintf(stderr, "Missing program name\n");
541 usage(stderr);
542 exit(EXIT_FAILURE);
545 *pgm_argc = argc - opt.opt_index;
546 *pgm_argv = argv + opt.opt_index;
548 return (*pgm_argv)[0];
552 =back
554 =head1 SEE ALSO
556 F<compilers/imcc/main.c>, unfortunately.
558 =cut
563 * Local variables:
564 * c-file-style: "parrot"
565 * End:
566 * vim: expandtab shiftwidth=4: