[t][TT#1509] Prevent core dumps by preventing negative length array creation. Tests...
[parrot.git] / src / embed.c
blob8ebc4d61400267f7813a92853e28e2e81e68cbeb
1 /*
2 Copyright (C) 2001-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/embed.c - The Parrot embedding interface
9 =head1 DESCRIPTION
11 This file implements the Parrot embedding interface.
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/embed.h"
23 #include "parrot/oplib/ops.h"
24 #include "pmc/pmc_sub.h"
25 #include "pmc/pmc_callcontext.h"
26 #include "parrot/runcore_api.h"
28 #include "../compilers/imcc/imc.h"
30 /* HEADERIZER HFILE: none */ /* The visible types are different than what we use in here */
32 /* HEADERIZER BEGIN: static */
33 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
35 static void print_constant_table(PARROT_INTERP, ARGIN(PMC *output))
36 __attribute__nonnull__(1)
37 __attribute__nonnull__(2);
39 static void print_debug(PARROT_INTERP, SHIM(int status), SHIM(void *p))
40 __attribute__nonnull__(1);
42 PARROT_CANNOT_RETURN_NULL
43 static PMC* set_current_sub(PARROT_INTERP)
44 __attribute__nonnull__(1);
46 PARROT_CANNOT_RETURN_NULL
47 static PMC* setup_argv(PARROT_INTERP, int argc, ARGIN(char **argv))
48 __attribute__nonnull__(1)
49 __attribute__nonnull__(3);
51 #define ASSERT_ARGS_print_constant_table __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
52 PARROT_ASSERT_ARG(interp) \
53 , PARROT_ASSERT_ARG(output))
54 #define ASSERT_ARGS_print_debug __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
55 PARROT_ASSERT_ARG(interp))
56 #define ASSERT_ARGS_set_current_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
57 PARROT_ASSERT_ARG(interp))
58 #define ASSERT_ARGS_setup_argv __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
59 PARROT_ASSERT_ARG(interp) \
60 , PARROT_ASSERT_ARG(argv))
61 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
62 /* HEADERIZER END: static */
64 extern int Parrot_exec_run;
68 =item C<Parrot_Interp Parrot_new(Parrot_Interp parent)>
70 Returns a new Parrot interpreter.
72 The first created interpreter (C<parent> is C<NULL>) is the last one
73 to get destroyed.
75 =cut
79 PARROT_EXPORT
80 PARROT_CANNOT_RETURN_NULL
81 Parrot_Interp
82 Parrot_new(ARGIN_NULLOK(Parrot_Interp parent))
84 /* inter_create.c:make_interpreter builds a new Parrot_Interp. */
85 return make_interpreter(parent, PARROT_NO_FLAGS);
91 =item C<void Parrot_init_stacktop(PARROT_INTERP, void *stack_top)>
93 Initializes the new interpreter when it hasn't been initialized before.
95 Additionally sets the stack top, so that Parrot objects created
96 in inner stack frames will be visible during GC stack walking code.
97 B<stack_top> should be the address of an automatic variable in the caller's
98 stack frame. All unanchored Parrot objects (PMCs) must live in inner stack
99 frames so that they are not destroyed during GC runs.
101 Use this function when you call into Parrot before entering a run loop.
103 =cut
107 PARROT_EXPORT
108 void
109 Parrot_init_stacktop(PARROT_INTERP, void *stack_top)
111 interp->lo_var_ptr = stack_top;
112 init_world_once(interp);
118 =item C<void Parrot_set_flag(PARROT_INTERP, INTVAL flag)>
120 Sets on any of the following flags, specified by C<flag>, in the interpreter:
122 Flag Effect
123 C<PARROT_BOUNDS_FLAG> enable bounds checking
124 C<PARROT_PROFILE_FLAG> enable profiling,
125 C<PARROT_THR_TYPE_1> disable variable sharing and thread communication
126 C<PARROT_THR_TYPE_2> disable variable sharing but enable thread communication
127 C<PARROT_THR_TYPE_3> enable variable sharing.
129 =cut
133 PARROT_EXPORT
134 void
135 Parrot_set_flag(PARROT_INTERP, INTVAL flag)
137 /* These two macros (from interpreter.h) do exactly what they look like. */
139 Interp_flags_SET(interp, flag);
140 switch (flag) {
141 case PARROT_BOUNDS_FLAG:
142 case PARROT_PROFILE_FLAG:
143 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "slow"));
144 break;
145 default:
146 break;
153 =item C<void Parrot_set_debug(PARROT_INTERP, UINTVAL flag)>
155 Set a debug flag: C<PARROT_DEBUG_FLAG>.
157 =cut
161 PARROT_EXPORT
162 void
163 Parrot_set_debug(PARROT_INTERP, UINTVAL flag)
165 interp->debug_flags |= flag;
171 =item C<void Parrot_set_executable_name(PARROT_INTERP, Parrot_String name)>
173 Sets the name of the executable launching Parrot (see C<pbc_to_exe> and the
174 C<parrot> binary).
176 =cut
180 PARROT_EXPORT
181 void
182 Parrot_set_executable_name(PARROT_INTERP, Parrot_String name)
184 PMC * const name_pmc = Parrot_pmc_new(interp, enum_class_String);
185 VTABLE_set_string_native(interp, name_pmc, name);
186 VTABLE_set_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_EXECUTABLE,
187 name_pmc);
193 =item C<void Parrot_set_trace(PARROT_INTERP, UINTVAL flag)>
195 Set a trace flag: C<PARROT_TRACE_FLAG>
197 =cut
201 PARROT_EXPORT
202 void
203 Parrot_set_trace(PARROT_INTERP, UINTVAL flag)
205 Parrot_pcc_trace_flags_on(interp, interp->ctx, flag);
206 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "slow"));
212 =item C<void Parrot_clear_flag(PARROT_INTERP, INTVAL flag)>
214 Clears a flag in the interpreter.
216 =cut
220 PARROT_EXPORT
221 void
222 Parrot_clear_flag(PARROT_INTERP, INTVAL flag)
224 Interp_flags_CLEAR(interp, flag);
230 =item C<void Parrot_clear_debug(PARROT_INTERP, UINTVAL flag)>
232 Clears a flag in the interpreter.
234 =cut
238 PARROT_EXPORT
239 void
240 Parrot_clear_debug(PARROT_INTERP, UINTVAL flag)
242 interp->debug_flags &= ~flag;
248 =item C<void Parrot_clear_trace(PARROT_INTERP, UINTVAL flag)>
250 Clears a flag in the interpreter.
252 =cut
256 PARROT_EXPORT
257 void
258 Parrot_clear_trace(PARROT_INTERP, UINTVAL flag)
260 Parrot_pcc_trace_flags_off(interp, interp->ctx, flag);
266 =item C<Parrot_Int Parrot_test_flag(PARROT_INTERP, INTVAL flag)>
268 Test the interpreter flags specified in C<flag>.
270 =cut
274 PARROT_EXPORT
275 Parrot_Int
276 Parrot_test_flag(PARROT_INTERP, INTVAL flag)
278 return Interp_flags_TEST(interp, flag);
284 =item C<UINTVAL Parrot_test_debug(PARROT_INTERP, UINTVAL flag)>
286 Test the interpreter flags specified in C<flag>.
288 =cut
292 PARROT_EXPORT
293 UINTVAL
294 Parrot_test_debug(PARROT_INTERP, UINTVAL flag)
296 return interp->debug_flags & flag;
302 =item C<UINTVAL Parrot_test_trace(PARROT_INTERP, UINTVAL flag)>
304 Test the interpreter flags specified in C<flag>.
306 =cut
310 PARROT_EXPORT
311 UINTVAL
312 Parrot_test_trace(PARROT_INTERP, UINTVAL flag)
314 return Parrot_pcc_trace_flags_test(interp, interp->ctx, flag);
320 =item C<void Parrot_set_run_core(PARROT_INTERP, Parrot_Run_core_t core)>
322 Sets the specified run core.
324 =cut
328 PARROT_EXPORT
329 void
330 Parrot_set_run_core(PARROT_INTERP, Parrot_Run_core_t core)
332 switch (core) {
333 case PARROT_SLOW_CORE:
334 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "slow"));
335 break;
336 case PARROT_FAST_CORE:
337 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "fast"));
338 break;
339 case PARROT_SWITCH_CORE:
340 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "switch"));
341 break;
342 case PARROT_CGP_CORE:
343 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "cgp"));
344 break;
345 case PARROT_CGOTO_CORE:
346 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "cgoto"));
347 break;
348 case PARROT_EXEC_CORE:
349 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "exec"));
350 break;
351 case PARROT_GC_DEBUG_CORE:
352 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "gc_debug"));
353 break;
354 case PARROT_DEBUGGER_CORE:
355 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "debugger"));
356 break;
357 case PARROT_PROFILING_CORE:
358 Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "profiling"));
359 break;
360 default:
361 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
362 "Invalid runcore requested\n");
369 =item C<void Parrot_setwarnings(PARROT_INTERP, Parrot_warnclass wc)>
371 Activates the given warnings.
373 =cut
377 PARROT_EXPORT
378 void
379 Parrot_setwarnings(PARROT_INTERP, Parrot_warnclass wc)
381 /* Activates the given warnings. (Macro from warnings.h.) */
382 PARROT_WARNINGS_on(interp, wc);
388 =item C<PackFile * Parrot_pbc_read(PARROT_INTERP, const char *fullname, const
389 int debug)>
391 Read in a bytecode, unpack it into a C<PackFile> structure, and do fixups.
393 =cut
397 PARROT_EXPORT
398 PARROT_CAN_RETURN_NULL
399 PackFile *
400 Parrot_pbc_read(PARROT_INTERP, ARGIN_NULLOK(const char *fullname), const int debug)
402 PackFile *pf;
403 char *program_code;
404 FILE *io = NULL;
405 INTVAL is_mapped = 0;
406 INTVAL program_size;
408 #ifdef PARROT_HAS_HEADER_SYSMMAN
409 int fd = -1;
410 #endif
412 if (!fullname || STREQ(fullname, "-")) {
413 /* read from STDIN */
414 io = stdin;
416 /* read 1k at a time */
417 program_size = 0;
419 else {
420 STRING * const fs = string_make(interp, fullname, strlen(fullname),
421 NULL, 0);
423 /* can't read a file that doesn't exist */
424 if (!Parrot_stat_info_intval(interp, fs, STAT_EXISTS)) {
425 Parrot_io_eprintf(interp, "Parrot VM: Can't stat %s, code %i.\n",
426 fullname, errno);
427 return NULL;
430 /* we may need to relax this if we want to read bytecode from pipes */
431 if (!Parrot_stat_info_intval(interp, fs, STAT_ISREG)) {
432 Parrot_io_eprintf(interp,
433 "Parrot VM: '%s', is not a regular file %i.\n",
434 fullname, errno);
435 return NULL;
438 program_size = Parrot_stat_info_intval(interp, fs, STAT_FILESIZE);
440 #ifndef PARROT_HAS_HEADER_SYSMMAN
441 io = fopen(fullname, "rb");
443 if (!io) {
444 Parrot_io_eprintf(interp, "Parrot VM: Can't open %s, code %i.\n",
445 fullname, errno);
446 return NULL;
448 #endif /* PARROT_HAS_HEADER_SYSMMAN */
451 #ifdef PARROT_HAS_HEADER_SYSMMAN
452 again:
453 #endif
454 /* if we've opened a file (or stdin) with PIO, read it in */
455 if (io) {
456 char *cursor;
457 size_t chunk_size = program_size > 0 ? program_size : 1024;
458 INTVAL wanted = program_size;
459 size_t read_result;
461 program_code = mem_gc_allocate_n_typed(interp, chunk_size, char);
462 cursor = program_code;
463 program_size = 0;
465 while ((read_result = fread(cursor, 1, chunk_size, io)) > 0) {
466 program_size += read_result;
468 if (program_size == wanted)
469 break;
471 chunk_size = 1024;
472 program_code = mem_gc_realloc_n_typed(interp, program_code,
473 program_size + chunk_size, char);
475 if (!program_code) {
476 Parrot_io_eprintf(interp,
477 "Parrot VM: Could not reallocate buffer "
478 "while reading packfile from PIO.\n");
479 fclose(io);
480 return NULL;
483 cursor = (char *)(program_code + program_size);
486 if (ferror(io)) {
487 Parrot_io_eprintf(interp,
488 "Parrot VM: Problem reading packfile from PIO: code %d.\n",
489 ferror(io));
490 fclose(io);
491 mem_gc_free(interp, program_code);
492 return NULL;
495 fclose(io);
497 else {
498 /* if we've gotten here, we opted not to use PIO to read the file.
499 * use mmap */
501 #ifdef PARROT_HAS_HEADER_SYSMMAN
503 /* check that fullname isn't NULL, just in case */
504 if (!fullname)
505 Parrot_ex_throw_from_c_args(interp, NULL, 1,
506 "Trying to open a NULL filename");
508 fd = open(fullname, O_RDONLY | O_BINARY);
510 if (!fd) {
511 Parrot_io_eprintf(interp, "Parrot VM: Can't open %s, code %i.\n",
512 fullname, errno);
513 return NULL;
516 program_code = (char *)mmap(0, (size_t)program_size,
517 PROT_READ, MAP_SHARED, fd, (off_t)0);
519 if (program_code == (void *)MAP_FAILED) {
520 Parrot_warn(interp, PARROT_WARNINGS_IO_FLAG,
521 "Parrot VM: Can't mmap file %s, code %i.\n",
522 fullname, errno);
524 /* try again, now with IO reading the file */
525 io = fopen(fullname, "rb");
526 if (!io) {
527 Parrot_io_eprintf(interp,
528 "Parrot VM: Can't open %s, code %i.\n", fullname, errno);
529 return NULL;
531 goto again;
534 is_mapped = 1;
536 #else /* PARROT_HAS_HEADER_SYSMMAN */
538 Parrot_io_eprintf(interp, "Parrot VM: uncaught error occurred reading "
539 "file or mmap not available.\n");
540 return NULL;
542 #endif /* PARROT_HAS_HEADER_SYSMMAN */
546 /* Now that we have the bytecode, let's unpack it. */
548 pf = PackFile_new(interp, is_mapped);
550 /* Make the cmdline option available to the unpackers */
551 pf->options = debug;
553 if (!PackFile_unpack(interp, pf, (opcode_t *)program_code,
554 (size_t)program_size)) {
555 Parrot_io_eprintf(interp, "Parrot VM: Can't unpack packfile %s.\n",
556 fullname);
557 return NULL;
560 /* Set :main routine */
561 if (!(pf->options & PFOPT_HEADERONLY))
562 do_sub_pragmas(interp, pf->cur_cs, PBC_PBC, NULL);
564 /* Prederefing the sub/the bytecode is done in switch_to_cs before
565 * actual usage of the segment */
567 #ifdef PARROT_HAS_HEADER_SYSMMAN
568 /* the man page states that it's ok to close a mmaped file */
569 if (fd >= 0)
570 close(fd);
571 #endif
573 return pf;
579 =item C<void Parrot_pbc_load(PARROT_INTERP, PackFile *pf)>
581 Loads the C<PackFile> returned by C<Parrot_pbc_read()>.
583 =cut
587 PARROT_EXPORT
588 void
589 Parrot_pbc_load(PARROT_INTERP, NOTNULL(PackFile *pf))
591 if (!pf) {
592 Parrot_io_eprintf(interp, "Invalid packfile\n");
593 return;
596 interp->initial_pf = pf;
597 interp->code = pf->cur_cs;
603 =item C<void Parrot_pbc_fixup_loaded(PARROT_INTERP)>
605 Fixups after pbc loading
607 =cut
611 PARROT_EXPORT
612 void
613 Parrot_pbc_fixup_loaded(PARROT_INTERP)
615 PackFile_fixup_subs(interp, PBC_LOADED, NULL);
621 =item C<static PMC* setup_argv(PARROT_INTERP, int argc, char **argv)>
623 Creates and returns C<ARGS> array PMC.
625 =cut
629 PARROT_CANNOT_RETURN_NULL
630 static PMC*
631 setup_argv(PARROT_INTERP, int argc, ARGIN(char **argv))
633 ASSERT_ARGS(setup_argv)
634 PMC *userargv = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
635 INTVAL i;
637 if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG)) {
638 Parrot_io_eprintf(interp,
639 "*** Parrot VM: Setting up ARGV array. Current argc: %d ***\n",
640 argc);
643 /* immediately anchor pmc to root set */
644 VTABLE_set_pmc_keyed_int(interp, interp->iglobals,
645 (INTVAL)IGLOBALS_ARGV_LIST, userargv);
647 for (i = 0; i < argc; i++) {
648 /* Run through argv, adding everything to @ARGS. */
649 STRING * const arg =
650 string_make(interp, argv[i], strlen(argv[i]), "unicode",
651 PObj_external_FLAG);
653 if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG))
654 Parrot_io_eprintf(interp, "\t%vd: %s\n", i, argv[i]);
656 VTABLE_push_string(interp, userargv, arg);
659 return userargv;
665 =item C<static void print_debug(PARROT_INTERP, int status, void *p)>
667 Prints GC info.
669 =cut
673 static void
674 print_debug(PARROT_INTERP, SHIM(int status), SHIM(void *p))
676 ASSERT_ARGS(print_debug)
677 if (Interp_debug_TEST(interp, PARROT_MEM_STAT_DEBUG_FLAG)) {
678 /* Give souls brave enough to activate debugging an earful about GC. */
680 Parrot_io_eprintf(interp, "*** Parrot VM: Dumping GC info ***\n");
681 PDB_info(interp);
688 =item C<static PMC* set_current_sub(PARROT_INTERP)>
690 Search the fixup table for a PMC matching the argument. On a match,
691 set up the appropriate context.
693 If no match, set up a dummy PMC entry. In either case, return a
694 pointer to the PMC.
696 =cut
700 PARROT_CANNOT_RETURN_NULL
701 static PMC*
702 set_current_sub(PARROT_INTERP)
704 ASSERT_ARGS(set_current_sub)
705 PMC *sub_pmc;
707 PackFile_ByteCode * const cur_cs = interp->code;
708 PackFile_FixupTable * const ft = cur_cs->fixups;
709 PackFile_ConstTable * const ct = cur_cs->const_table;
711 opcode_t i;
714 * Walk the fixup table. The first Sub-like entry should be our
715 * entry point with the address at our resume_offset.
718 for (i = 0; i < ft->fixup_count; i++) {
719 if (ft->fixups[i]->type == enum_fixup_sub) {
720 const opcode_t ci = ft->fixups[i]->offset;
721 PMC *sub_pmc = ct->constants[ci]->u.key;
722 Parrot_Sub_attributes *sub;
724 PMC_get_sub(interp, sub_pmc, sub);
725 if (sub->seg == cur_cs) {
726 const size_t offs = sub->start_offs;
728 if (offs == interp->resume_offset) {
729 Parrot_pcc_set_sub(interp, CURRENT_CONTEXT(interp), sub_pmc);
730 Parrot_pcc_set_HLL(interp, CURRENT_CONTEXT(interp), sub->HLL_id);
731 return sub_pmc;
734 break;
739 /* If we didn't find anything, put a dummy PMC into current_sub.
740 The default values set by SUb.init are appropiate for the
741 dummy, don't need additional settings. */
742 sub_pmc = Parrot_pmc_new(interp, enum_class_Sub);
743 Parrot_pcc_set_sub(interp, CURRENT_CONTEXT(interp), sub_pmc);
745 return sub_pmc;
751 =item C<void Parrot_runcode(PARROT_INTERP, int argc, char **argv)>
753 Sets up C<ARGV> and runs the ops.
755 =cut
759 PARROT_EXPORT
760 void
761 Parrot_runcode(PARROT_INTERP, int argc, ARGIN(char **argv))
763 PMC *userargv, *main_sub;
765 /* Debugging mode nonsense. */
766 if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG)) {
767 if (Interp_flags_TEST(interp, PARROT_BOUNDS_FLAG)) {
768 Parrot_io_eprintf(interp,
769 "*** Parrot VM: Bounds checking enabled. ***\n");
772 if (Interp_trace_TEST(interp, PARROT_TRACE_OPS_FLAG))
773 Parrot_io_eprintf(interp, "*** Parrot VM: Tracing enabled. ***\n");
775 Parrot_io_eprintf(interp, "*** Parrot VM: %Ss core ***\n",
776 interp->run_core->name);
779 /* Set up @ARGS (or whatever this language calls it) in userargv. */
780 userargv = setup_argv(interp, argc, argv);
783 * If any profile information was gathered, print it out
784 * before exiting, then print debug infos if turned on.
786 Parrot_on_exit(interp, print_debug, NULL);
788 /* Let's kick the tires and light the fires--call interpreter.c:runops. */
789 main_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
791 /* if no sub was marked being :main, we create a dummy sub with offset 0 */
793 if (!main_sub)
794 main_sub = set_current_sub(interp);
796 Parrot_pcc_set_sub(interp, CURRENT_CONTEXT(interp), NULL);
797 Parrot_pcc_set_constants(interp, interp->ctx, interp->code->const_table->constants);
799 Parrot_pcc_invoke_sub_from_c_args(interp, main_sub, "P->", userargv);
805 =item C<opcode_t * Parrot_debug(PARROT_INTERP, Parrot_Interp debugger, opcode_t
806 * pc)>
808 Runs the interpreter's bytecode in debugging mode.
810 =cut
814 PARROT_EXPORT
815 PARROT_CAN_RETURN_NULL
816 opcode_t *
817 Parrot_debug(PARROT_INTERP, NOTNULL(Parrot_Interp debugger), opcode_t * pc)
819 const char *command;
820 PDB_t * const pdb = debugger->pdb;
822 pdb->cur_opcode = pc;
824 PDB_init(debugger, NULL);
826 /* disassemble needs this for now */
828 interp = pdb->debugee;
829 interp->pdb = pdb;
831 debugger->lo_var_ptr = interp->lo_var_ptr;
833 PDB_disassemble(interp, NULL);
835 while (!(pdb->state & PDB_EXIT)) {
836 PDB_get_command(debugger);
837 command = pdb->cur_command;
838 PDB_run_command(debugger, command);
841 return NULL;
847 =item C<static void print_constant_table(PARROT_INTERP, PMC *output)>
849 Prints the contents of the constants table.
851 =cut
854 static void
855 print_constant_table(PARROT_INTERP, ARGIN(PMC *output))
857 ASSERT_ARGS(print_constant_table)
858 const INTVAL numconstants = interp->code->const_table->const_count;
859 INTVAL i;
861 /* TODO: would be nice to print the name of the file as well */
862 Parrot_io_fprintf(interp, output, "=head1 Constant-table\n\n");
864 for (i = 0; i < numconstants; ++i) {
865 const PackFile_Constant * const c = interp->code->const_table->constants[i];
867 switch (c->type) {
868 case PFC_NUMBER:
869 Parrot_io_fprintf(interp, output, "PMC_CONST(%d): %f\n", i, c->u.number);
870 break;
871 case PFC_STRING:
872 Parrot_io_fprintf(interp, output, "PMC_CONST(%d): %S\n", i, c->u.string);
873 break;
874 case PFC_KEY:
875 Parrot_io_fprintf(interp, output, "PMC_CONST(%d): ", i);
876 /* XXX */
877 /* Parrot_print_p(interp, c->u.key); */
878 Parrot_io_fprintf(interp, output, "(PMC constant)");
879 Parrot_io_fprintf(interp, output, "\n");
880 break;
881 case PFC_PMC:
883 Parrot_io_fprintf(interp, output, "PMC_CONST(%d): ", i);
885 switch (c->u.key->vtable->base_type) {
886 /* each PBC file has a ParrotInterpreter, but it can't
887 * stringify by itself */
888 case enum_class_ParrotInterpreter:
889 Parrot_io_fprintf(interp, output, "'ParrotInterpreter'");
890 break;
892 /* FixedIntegerArrays used for signatures, handy to print */
893 case enum_class_FixedIntegerArray:
895 INTVAL n = VTABLE_elements(interp, c->u.key);
896 INTVAL i;
897 Parrot_io_fprintf(interp, output, "[");
899 for (i = 0; i < n; ++i) {
900 INTVAL val = VTABLE_get_integer_keyed_int(interp, c->u.key, i);
901 Parrot_io_fprintf(interp, output, "%d", val);
902 if (i < n - 1)
903 Parrot_io_fprintf(interp, output, ",");
905 Parrot_io_fprintf(interp, output, "]");
906 break;
908 case enum_class_NameSpace:
909 case enum_class_String:
910 case enum_class_Key:
911 case enum_class_ResizableStringArray:
913 /*Parrot_print_p(interp, c->u.key);*/
914 STRING * const s = VTABLE_get_string(interp, c->u.key);
915 if (s)
916 Parrot_io_fprintf(interp, output, "%Ss", s);
917 break;
919 case enum_class_Sub:
920 Parrot_io_fprintf(interp, output, "%S", VTABLE_get_string(interp, c->u.key));
921 break;
922 default:
923 Parrot_io_fprintf(interp, output, "(PMC constant)");
924 break;
927 Parrot_io_fprintf(interp, output, "\n");
928 break;
930 default:
931 Parrot_io_fprintf(interp, output, "wrong constant type in constant table!\n");
932 /* XXX throw an exception? Is it worth the trouble? */
933 break;
937 Parrot_io_fprintf(interp, output, "\n=cut\n\n");
943 =item C<void Parrot_disassemble(PARROT_INTERP, const char *outfile,
944 Parrot_disassemble_options options)>
946 Disassembles and prints out the interpreter's bytecode.
948 This is used by the Parrot disassembler.
950 =cut
954 PARROT_EXPORT
955 void
956 Parrot_disassemble(PARROT_INTERP, ARGIN(const char *outfile), Parrot_disassemble_options options)
958 PDB_line_t *line;
959 PDB_t * const pdb = mem_gc_allocate_typed(interp, PDB_t);
960 int num_mappings = 0;
961 int curr_mapping = 0;
962 int op_code_seq_num = 0;
963 int debugs;
964 PMC *output;
966 if (outfile != NULL) {
967 output = Parrot_io_open(interp, PMCNULL,
968 Parrot_str_new(interp, outfile, 0),
969 Parrot_str_new_constant(interp, "tw"));
971 else
972 output = Parrot_io_stdhandle(interp, PIO_STDOUT_FILENO, PMCNULL);
974 interp->pdb = pdb;
975 pdb->cur_opcode = interp->code->base.data;
977 PDB_disassemble(interp, NULL);
979 line = pdb->file->line;
980 debugs = (interp->code->debugs != NULL);
982 print_constant_table(interp, output);
983 if (options & enum_DIS_HEADER)
984 return;
986 if (!(options & enum_DIS_BARE))
987 Parrot_io_fprintf(interp, output, "# %12s-%12s", "Seq_Op_Num", "Relative-PC");
989 if (debugs) {
990 if (!(options & enum_DIS_BARE))
991 Parrot_io_fprintf(interp, output, " %6s:\n", "SrcLn#");
992 num_mappings = interp->code->debugs->num_mappings;
994 else {
995 Parrot_io_fprintf(interp, output, "\n");
998 while (line->next) {
999 const char *c;
1001 /* Parrot_io_fprintf(interp, output, "%i < %i %i == %i \n", curr_mapping,
1002 * num_mappings, op_code_seq_num,
1003 * interp->code->debugs->mappings[curr_mapping]->offset); */
1005 if (debugs && curr_mapping < num_mappings) {
1006 if (op_code_seq_num == interp->code->debugs->mappings[curr_mapping]->offset) {
1007 const int filename_const_offset =
1008 interp->code->debugs->mappings[curr_mapping]->filename;
1009 Parrot_io_fprintf(interp, output, "# Current Source Filename '%Ss'\n",
1010 interp->code->const_table->constants[filename_const_offset]->u.string);
1011 curr_mapping++;
1015 if (!(options & enum_DIS_BARE))
1016 Parrot_io_fprintf(interp, output, "%012i-%012i",
1017 op_code_seq_num, line->opcode - interp->code->base.data);
1019 if (debugs && !(options & enum_DIS_BARE))
1020 Parrot_io_fprintf(interp, output, " %06i: ",
1021 interp->code->debugs->base.data[op_code_seq_num]);
1023 /* If it has a label print it */
1024 if (line->label)
1025 Parrot_io_fprintf(interp, output, "L%li:\t", line->label->number);
1026 else
1027 Parrot_io_fprintf(interp, output, "\t");
1029 c = pdb->file->source + line->source_offset;
1031 while (c && *c != '\n')
1032 Parrot_io_fprintf(interp, output, "%c", *(c++));
1034 Parrot_io_fprintf(interp, output, "\n");
1035 line = line->next;
1036 op_code_seq_num++;
1038 if (outfile != NULL)
1039 Parrot_io_close(interp, output);
1041 return;
1047 =item C<void Parrot_run_native(PARROT_INTERP, native_func_t func)>
1049 Runs the C function C<func> through the program C<[enternative, end]>. This
1050 ensures that the function runs with the same setup as in other run loops.
1052 This function is used in some of the source tests in F<t/src> which use
1053 the interpreter outside a runloop.
1055 =cut
1059 PARROT_EXPORT
1060 void
1061 Parrot_run_native(PARROT_INTERP, native_func_t func)
1063 PackFile * const pf = PackFile_new(interp, 0);
1064 static opcode_t program_code[2];
1066 program_code[0] = interp->op_lib->op_code(interp, "enternative", 0);
1067 program_code[1] = 0; /* end */
1069 pf->cur_cs = (PackFile_ByteCode *)
1070 (pf->PackFuncs[PF_BYTEC_SEG].new_seg)(interp, pf,
1071 Parrot_str_new_constant(interp, "code"), 1);
1072 pf->cur_cs->base.data = program_code;
1073 pf->cur_cs->base.size = 2;
1075 Parrot_pbc_load(interp, pf);
1077 run_native = func;
1079 if (interp->code && interp->code->const_table)
1080 Parrot_pcc_set_constants(interp, interp->ctx, interp->code->const_table->constants);
1082 runops(interp, interp->resume_offset);
1088 =item C<Parrot_PMC Parrot_compile_string(PARROT_INTERP, Parrot_String type,
1089 const char *code, Parrot_String *error)>
1091 Compiles a code string.
1093 =cut
1097 PARROT_EXPORT
1098 Parrot_PMC
1099 Parrot_compile_string(PARROT_INTERP, Parrot_String type,
1100 const char *code, Parrot_String *error)
1102 /* For the benefit of embedders that do not load any pbc
1103 * before compiling a string */
1105 if (!interp->initial_pf) {
1106 PackFile * const pf = PackFile_new_dummy(interp,
1107 Parrot_str_new_constant(interp, "compile_string"));
1108 /* Assumption: there is no valid reason to fail to create it.
1109 * If the assumption changes, replace the assertion with a
1110 * runtime check */
1111 PARROT_ASSERT(interp->initial_pf);
1114 if (Parrot_str_compare(interp, Parrot_str_new(interp, "PIR", 3), type) == 0)
1115 return IMCC_compile_pir_s(interp, code, error);
1117 if (Parrot_str_compare(interp, Parrot_str_new(interp, "PASM", 4), type) == 0)
1118 return IMCC_compile_pasm_s(interp, code, error);
1120 *error = Parrot_str_new(interp, "Invalid interpreter type", 0);
1121 return NULL;
1127 =back
1129 =head1 SEE ALSO
1131 F<include/parrot/embed.h> and F<docs/embed.pod>.
1133 =head1 HISTORY
1135 Initial version by Brent Dax on 2002.1.28.
1137 =cut
1142 * Local variables:
1143 * c-file-style: "parrot"
1144 * End:
1145 * vim: expandtab shiftwidth=4: