2 Copyright (C) 2001-2009, Parrot Foundation.
7 src/debug.c - Parrot debugging
11 This file implements Parrot debugging and is used by C<parrot_debugger>,
12 the Parrot debugger, and the C<debug> ops.
24 #include "parrot/parrot.h"
25 #include "parrot/extend.h"
26 #include "parrot/embed.h"
27 #include "parrot/oplib.h"
28 #include "parrot/debugger.h"
29 #include "parrot/oplib/ops.h"
30 #include "pmc/pmc_key.h"
31 #include "parrot/runcore_api.h"
32 #include "parrot/runcore_trace.h"
34 #include "pmc/pmc_continuation.h"
35 #include "pmc/pmc_context.h"
37 /* Hand switched debugger tracing
38 * Set to 1 to enable tracing to stderr
41 #define TRACE_DEBUGGER 0
44 # define TRACEDEB_MSG(msg) fprintf(stderr, "%s\n", (msg))
46 # define TRACEDEB_MSG(msg)
49 /* Length of command line buffers */
50 #define DEBUG_CMD_BUFFER_LENGTH 255
52 /* Easier register access */
53 #define IREG(i) REG_INT(interp, (i))
54 #define NREG(i) REG_NUM(interp, (i))
55 #define SREG(i) REG_STR(interp, (i))
56 #define PREG(i) REG_PMC(interp, (i))
58 typedef struct DebuggerCmd DebuggerCmd
;
59 typedef struct DebuggerCmdList DebuggerCmdList
;
62 /* HEADERIZER HFILE: include/parrot/debugger.h */
64 /* HEADERIZER BEGIN: static */
65 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
67 static void chop_newline(ARGMOD(char * buf
))
68 __attribute__nonnull__(1)
71 static void close_script_file(PARROT_INTERP
)
72 __attribute__nonnull__(1);
74 static unsigned short condition_regtype(ARGIN(const char *cmd
))
75 __attribute__nonnull__(1);
77 PARROT_CAN_RETURN_NULL
78 static PDB_breakpoint_t
* current_breakpoint(ARGIN(PDB_t
* pdb
))
79 __attribute__nonnull__(1);
81 static void debugger_cmdline(PARROT_INTERP
)
82 __attribute__nonnull__(1);
84 PARROT_WARN_UNUSED_RESULT
85 PARROT_CANNOT_RETURN_NULL
87 static STRING
* GDB_P(PARROT_INTERP
, ARGIN(const char *s
))
88 __attribute__nonnull__(1)
89 __attribute__nonnull__(2);
91 PARROT_WARN_UNUSED_RESULT
92 PARROT_CANNOT_RETURN_NULL
94 static STRING
* GDB_print_reg(PARROT_INTERP
, int t
, int n
)
95 __attribute__nonnull__(1);
97 PARROT_WARN_UNUSED_RESULT
98 PARROT_CAN_RETURN_NULL
99 static const DebuggerCmd
* get_cmd(ARGIN_NULLOK(const char **cmd
));
101 PARROT_WARN_UNUSED_RESULT
102 static unsigned long get_uint(ARGMOD(const char **cmd
), unsigned int def
)
103 __attribute__nonnull__(1)
106 PARROT_WARN_UNUSED_RESULT
107 static unsigned long get_ulong(ARGMOD(const char **cmd
), unsigned long def
)
108 __attribute__nonnull__(1)
111 static void list_breakpoints(ARGIN(PDB_t
*pdb
))
112 __attribute__nonnull__(1);
114 PARROT_CAN_RETURN_NULL
115 PARROT_WARN_UNUSED_RESULT
116 static const char * nextarg(ARGIN_NULLOK(const char *command
));
118 static void no_such_register(PARROT_INTERP
,
120 UINTVAL register_num
)
121 __attribute__nonnull__(1);
123 PARROT_CANNOT_RETURN_NULL
124 PARROT_WARN_UNUSED_RESULT
125 static const char * parse_int(ARGIN(const char *str
), ARGOUT(int *intP
))
126 __attribute__nonnull__(1)
127 __attribute__nonnull__(2)
128 FUNC_MODIFIES(*intP
);
130 PARROT_CAN_RETURN_NULL
131 PARROT_WARN_UNUSED_RESULT
132 static const char* parse_key(PARROT_INTERP
,
133 ARGIN(const char *str
),
135 __attribute__nonnull__(1)
136 __attribute__nonnull__(2)
137 __attribute__nonnull__(3)
138 FUNC_MODIFIES(*keyP
);
140 PARROT_CAN_RETURN_NULL
141 PARROT_WARN_UNUSED_RESULT
142 static const char * parse_string(PARROT_INTERP
,
143 ARGIN(const char *str
),
144 ARGOUT(STRING
**strP
))
145 __attribute__nonnull__(1)
146 __attribute__nonnull__(2)
147 __attribute__nonnull__(3)
148 FUNC_MODIFIES(*strP
);
150 PARROT_CANNOT_RETURN_NULL
151 static const char * skip_command(ARGIN(const char *str
))
152 __attribute__nonnull__(1);
154 PARROT_WARN_UNUSED_RESULT
155 PARROT_CANNOT_RETURN_NULL
156 static const char * skip_whitespace(ARGIN(const char *cmd
))
157 __attribute__nonnull__(1);
159 #define ASSERT_ARGS_chop_newline __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
160 PARROT_ASSERT_ARG(buf))
161 #define ASSERT_ARGS_close_script_file __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
162 PARROT_ASSERT_ARG(interp))
163 #define ASSERT_ARGS_condition_regtype __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
164 PARROT_ASSERT_ARG(cmd))
165 #define ASSERT_ARGS_current_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
166 PARROT_ASSERT_ARG(pdb))
167 #define ASSERT_ARGS_debugger_cmdline __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
168 PARROT_ASSERT_ARG(interp))
169 #define ASSERT_ARGS_GDB_P __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
170 PARROT_ASSERT_ARG(interp) \
171 , PARROT_ASSERT_ARG(s))
172 #define ASSERT_ARGS_GDB_print_reg __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
173 PARROT_ASSERT_ARG(interp))
174 #define ASSERT_ARGS_get_cmd __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
175 #define ASSERT_ARGS_get_uint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
176 PARROT_ASSERT_ARG(cmd))
177 #define ASSERT_ARGS_get_ulong __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
178 PARROT_ASSERT_ARG(cmd))
179 #define ASSERT_ARGS_list_breakpoints __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
180 PARROT_ASSERT_ARG(pdb))
181 #define ASSERT_ARGS_nextarg __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
182 #define ASSERT_ARGS_no_such_register __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
183 PARROT_ASSERT_ARG(interp))
184 #define ASSERT_ARGS_parse_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
185 PARROT_ASSERT_ARG(str) \
186 , PARROT_ASSERT_ARG(intP))
187 #define ASSERT_ARGS_parse_key __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
188 PARROT_ASSERT_ARG(interp) \
189 , PARROT_ASSERT_ARG(str) \
190 , PARROT_ASSERT_ARG(keyP))
191 #define ASSERT_ARGS_parse_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
192 PARROT_ASSERT_ARG(interp) \
193 , PARROT_ASSERT_ARG(str) \
194 , PARROT_ASSERT_ARG(strP))
195 #define ASSERT_ARGS_skip_command __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
196 PARROT_ASSERT_ARG(str))
197 #define ASSERT_ARGS_skip_whitespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
198 PARROT_ASSERT_ARG(cmd))
199 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
200 /* HEADERIZER END: static */
203 * Command functions and help dispatch
206 typedef void (* debugger_func_t
)(PDB_t
* pdb
, const char * cmd
);
208 static int nomoreargs(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
210 if (*skip_whitespace(cmd
) == '\0')
213 Parrot_io_eprintf(pdb
->debugger
, "Spurious arg\n");
218 static void dbg_assign(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
220 TRACEDEB_MSG("dbg_assign");
222 PDB_assign(pdb
->debugee
, cmd
);
225 static void dbg_break(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
227 TRACEDEB_MSG("dbg_break");
229 PDB_set_break(pdb
->debugee
, cmd
);
232 static void dbg_continue(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
234 TRACEDEB_MSG("dbg_continue");
236 PDB_continue(pdb
->debugee
, cmd
);
239 static void dbg_delete(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
241 TRACEDEB_MSG("dbg_delete");
243 PDB_delete_breakpoint(pdb
->debugee
, cmd
);
246 static void dbg_disable(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
248 TRACEDEB_MSG("dbg_disable");
250 PDB_disable_breakpoint(pdb
->debugee
, cmd
);
253 static void dbg_disassemble(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
255 TRACEDEB_MSG("dbg_disassemble");
257 PDB_disassemble(pdb
->debugee
, cmd
);
260 static void dbg_echo(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
262 TRACEDEB_MSG("dbg_echo");
264 if (! nomoreargs(pdb
, cmd
))
267 if (pdb
->state
& PDB_ECHO
) {
268 TRACEDEB_MSG("Disabling echo");
269 pdb
->state
&= ~PDB_ECHO
;
272 TRACEDEB_MSG("Enabling echo");
273 pdb
->state
|= PDB_ECHO
;
277 static void dbg_enable(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
279 PDB_enable_breakpoint(pdb
->debugee
, cmd
);
282 static void dbg_eval(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
284 PDB_eval(pdb
->debugee
, cmd
);
287 static void dbg_gcdebug(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
289 TRACEDEB_MSG("dbg_gcdebug");
291 if (! nomoreargs(pdb
, cmd
))
294 if (pdb
->state
& PDB_GCDEBUG
) {
295 TRACEDEB_MSG("Disabling gcdebug mode");
296 pdb
->state
&= ~PDB_GCDEBUG
;
299 TRACEDEB_MSG("Enabling gcdebug mode");
300 pdb
->state
|= PDB_GCDEBUG
;
304 static void dbg_help(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
306 TRACEDEB_MSG("dbg_help");
308 PDB_help(pdb
->debugee
, cmd
);
311 static void dbg_info(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
313 TRACEDEB_MSG("dbg_info");
315 if (! nomoreargs(pdb
, cmd
))
318 PDB_info(pdb
->debugger
);
321 static void dbg_list(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
323 TRACEDEB_MSG("dbg_list");
325 PDB_list(pdb
->debugee
, cmd
);
328 static void dbg_listbreakpoints(PDB_t
* pdb
, SHIM(const char * cmd
)) /* HEADERIZER SKIP */
330 TRACEDEB_MSG("dbg_list");
332 list_breakpoints(pdb
);
335 static void dbg_load(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
337 TRACEDEB_MSG("dbg_load");
339 PDB_load_source(pdb
->debugee
, cmd
);
342 static void dbg_next(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
344 TRACEDEB_MSG("dbg_next");
346 PDB_next(pdb
->debugee
, cmd
);
349 static void dbg_print(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
351 TRACEDEB_MSG("dbg_print");
353 PDB_print(pdb
->debugee
, cmd
);
356 static void dbg_quit(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
358 TRACEDEB_MSG("dbg_quit");
360 if (! nomoreargs(pdb
, cmd
))
363 pdb
->state
|= PDB_EXIT
;
364 pdb
->state
&= ~PDB_STOPPED
;
367 static void dbg_run(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
369 TRACEDEB_MSG("dbg_run");
371 PDB_init(pdb
->debugee
, cmd
);
372 PDB_continue(pdb
->debugee
, NULL
);
375 static void dbg_script(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
377 TRACEDEB_MSG("dbg_script");
379 PDB_script_file(pdb
->debugee
, cmd
);
382 static void dbg_stack(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
384 TRACEDEB_MSG("dbg_stack");
386 if (! nomoreargs(pdb
, cmd
))
389 PDB_backtrace(pdb
->debugee
);
392 static void dbg_trace(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
394 TRACEDEB_MSG("dbg_trace");
396 PDB_trace(pdb
->debugee
, cmd
);
399 static void dbg_watch(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
401 TRACEDEB_MSG("dbg_watch");
403 PDB_watchpoint(pdb
->debugee
, cmd
);
407 debugger_func_t func
;
408 PARROT_OBSERVER
const char * const shorthelp
;
409 PARROT_OBSERVER
const char * const help
;
412 static const DebuggerCmd
415 "assign to a register",
416 "Assign a value to a register. For example:\n\
419 The first command sets I0 to 42 and the second sets N1 to 3.14."
424 "Set a breakpoint at a given line number (which must be specified).\n\n\
425 Optionally, specify a condition, in which case the breakpoint will only\n\
426 activate if the condition is met. Conditions take the form:\n\n\
427 if [REGISTER] [COMPARISON] [REGISTER or CONSTANT]\n\n\
430 break 10 if I4 > I3\n\n\
431 break 45 if S1 == \"foo\"\n\n\
432 The command returns a number which is the breakpoint identifier."
436 "continue the program execution",
437 "Continue the program execution.\n\n\
438 Without arguments, the program runs until a breakpoint is found\n\
439 (or until the program terminates for some other reason).\n\n\
440 If a number is specified, then skip that many breakpoints.\n\n\
441 If the program has terminated, then \"continue\" will do nothing;\n\
442 use \"run\" to re-run the program."
446 "delete a breakpoint",
447 "Delete a breakpoint.\n\n\
448 The breakpoint to delete must be specified by its breakpoint number.\n\
449 Deleted breakpoints are gone completely. If instead you want to\n\
450 temporarily disable a breakpoint, use \"disable\"."
454 "disable a breakpoint",
455 "Disable a breakpoint.\n\n\
456 The breakpoint to disable must be specified by its breakpoint number.\n\
457 Disabled breakpoints are not forgotten, but have no effect until re-enabled\n\
458 with the \"enable\" command."
462 "disassemble the bytecode",
467 "toggle echo of script commands",
468 "Toggle echo mode.\n\n\
469 In echo mode the script commands are written to stderr before executing."
473 "reenable a disabled breakpoint",
474 "Re-enable a disabled breakpoint."
478 "run an instruction",
479 "No documentation yet"
483 "toggle gcdebug mode",
484 "Toggle gcdebug mode.\n\n\
485 In gcdebug mode a garbage collection cycle is run before each opcocde,\n\
486 same as using the gcdebug core."
491 "Print a list of available commands."
495 "print interpreter information",
496 "Print information about the current interpreter"
500 "list the source code file",
501 "List the source code.\n\n\
502 Optionally specify the line number to begin the listing from and the number\n\
503 of lines to display."
505 cmd_listbreakpoints
= {
506 & dbg_listbreakpoints
,
512 "load a source code file",
513 "Load a source code file."
517 "run the next instruction",
518 "Execute a specified number of instructions.\n\n\
519 If a number is specified with the command (e.g. \"next 5\"), then\n\
520 execute that number of instructions, unless the program reaches a\n\
521 breakpoint, or stops for some other reason.\n\n\
522 If no number is specified, it defaults to 1."
526 "print the interpreter registers",
527 "Print register: e.g. \"p i2\"\n\
528 Note that the register type is case-insensitive. If no digits appear\n\
529 after the register type, all registers of that type are printed."
539 "Run (or restart) the program being debugged.\n\n\
540 Arguments specified after \"run\" are passed as command line arguments to\n\
545 "interprets a file as user commands",
546 "Interprets a file s user commands.\n\
548 (pdb) script file.script"
553 "Print a stack trace of the parrot VM"
557 "trace the next instruction",
558 "Similar to \"next\", but prints additional trace information.\n\
559 This is the same as the information you get when running Parrot with\n\
568 struct DebuggerCmdList
{
569 PARROT_OBSERVER
const char * const name
;
571 PARROT_OBSERVER
const DebuggerCmd
* const cmd
;
574 DebuggerCmdList DebCmdList
[] = {
575 { "assign", 'a', &cmd_assign
},
576 { "break", '\0', &cmd_break
},
577 { "continue", '\0', &cmd_continue
},
578 { "delete", 'd', &cmd_delete
},
579 { "disable", '\0', &cmd_disable
},
580 { "disassemble", '\0', &cmd_disassemble
},
581 { "e", '\0', &cmd_eval
},
582 { "echo", '\0', &cmd_echo
},
583 { "enable", '\0', &cmd_enable
},
584 { "eval", '\0', &cmd_eval
},
585 { "f", '\0', &cmd_script
},
586 { "gcdebug", '\0', &cmd_gcdebug
},
587 { "help", '\0', &cmd_help
},
588 { "info", '\0', &cmd_info
},
589 { "L", '\0', &cmd_listbreakpoints
},
590 { "list", 'l', &cmd_list
},
591 { "load", '\0', &cmd_load
},
592 { "next", '\0', &cmd_next
},
593 { "print", '\0', &cmd_print
},
594 { "quit", '\0', &cmd_quit
},
595 { "run", '\0', &cmd_run
},
596 { "script", '\0', &cmd_script
},
597 { "stack", 's', &cmd_stack
},
598 { "trace", '\0', &cmd_trace
},
599 { "watch", '\0', &cmd_watch
}
604 =item C<static const DebuggerCmd * get_cmd(const char **cmd)>
610 PARROT_WARN_UNUSED_RESULT
611 PARROT_CAN_RETURN_NULL
612 static const DebuggerCmd
*
613 get_cmd(ARGIN_NULLOK(const char **cmd
))
617 const char * const start
= skip_whitespace(*cmd
);
618 const char *next
= start
;
625 for (; (c
= *next
) != '\0' && !isspace((unsigned char)c
); ++next
)
630 for (i
= 0; i
< sizeof (DebCmdList
) / sizeof (DebuggerCmdList
); ++i
) {
631 const DebuggerCmdList
* const cmdlist
= DebCmdList
+ i
;
632 if (l
== 1 && cmdlist
->shortname
== (*cmd
)[0]) {
637 if (strncmp(*cmd
, cmdlist
->name
, l
) == 0) {
638 if (strlen(cmdlist
->name
) == l
) {
650 *cmd
= skip_whitespace(next
);
651 return DebCmdList
[found
].cmd
;
659 =item C<static const char * skip_whitespace(const char *cmd)>
665 PARROT_WARN_UNUSED_RESULT
666 PARROT_CANNOT_RETURN_NULL
668 skip_whitespace(ARGIN(const char *cmd
))
670 ASSERT_ARGS(skip_whitespace
)
671 while (*cmd
&& isspace((unsigned char)*cmd
))
678 =item C<static unsigned long get_uint(const char **cmd, unsigned int def)>
685 PARROT_WARN_UNUSED_RESULT
687 get_uint(ARGMOD(const char **cmd
), unsigned int def
)
689 ASSERT_ARGS(get_uint
)
691 unsigned int result
= strtoul(skip_whitespace(* cmd
), & cmdnext
, 0);
701 =item C<static unsigned long get_ulong(const char **cmd, unsigned long def)>
708 PARROT_WARN_UNUSED_RESULT
710 get_ulong(ARGMOD(const char **cmd
), unsigned long def
)
712 ASSERT_ARGS(get_ulong
)
714 unsigned long result
= strtoul(skip_whitespace(* cmd
), & cmdnext
, 0);
715 if (cmdnext
!= * cmd
)
724 =item C<static void chop_newline(char * buf)>
726 If the C string argument end with a newline, delete it.
733 chop_newline(ARGMOD(char * buf
))
735 ASSERT_ARGS(chop_newline
)
736 const size_t l
= strlen(buf
);
738 if (l
> 0 && buf
[l
- 1] == '\n')
744 =item C<static const char * nextarg(const char *command)>
746 Returns the position just past the current argument in the PASM instruction
747 C<command>. This is not the same as C<skip_command()>, which is intended for
748 debugger commands. This function is used for C<eval>.
754 PARROT_CAN_RETURN_NULL
755 PARROT_WARN_UNUSED_RESULT
757 nextarg(ARGIN_NULLOK(const char *command
))
760 /* as long as the character pointed to by command is not NULL,
761 * and it is either alphanumeric, a comma or a closing bracket,
762 * continue looking for the next argument.
765 while (isalnum((unsigned char) *command
) || *command
== ',' || *command
== ']')
768 /* eat as much space as possible */
769 command
= skip_whitespace(command
);
777 =item C<static const char * skip_command(const char *str)>
779 Returns the pointer past the current debugger command. (This is an
780 alternative to the C<skip_command()> macro above.)
786 PARROT_CANNOT_RETURN_NULL
788 skip_command(ARGIN(const char *str
))
790 ASSERT_ARGS(skip_command
)
791 /* while str is not null and it contains a command (no spaces),
794 while (*str
&& !isspace((unsigned char) *str
))
797 /* eat all space after that */
798 return skip_whitespace(str
);
803 =item C<static const char * parse_int(const char *str, int *intP)>
805 Parse an C<int> out of a string and return a pointer to just after the C<int>.
806 The output parameter C<intP> contains the parsed value.
812 PARROT_CANNOT_RETURN_NULL
813 PARROT_WARN_UNUSED_RESULT
815 parse_int(ARGIN(const char *str
), ARGOUT(int *intP
))
817 ASSERT_ARGS(parse_int
)
820 *intP
= strtol(str
, &end
, 0);
827 =item C<static const char * parse_string(PARROT_INTERP, const char *str, STRING
830 Parse a double-quoted string out of a C string and return a pointer to
831 just after the string. The parsed string is converted to a Parrot
832 C<STRING> and placed in the output parameter C<strP>.
838 PARROT_CAN_RETURN_NULL
839 PARROT_WARN_UNUSED_RESULT
841 parse_string(PARROT_INTERP
, ARGIN(const char *str
), ARGOUT(STRING
**strP
))
843 ASSERT_ARGS(parse_string
)
844 const char *string_start
;
846 /* if this is not a quoted string, there's nothing to parse */
855 /* parse while there's no closing quote */
856 while (*str
&& *str
!= '"') {
857 /* skip any potentially escaped quotes */
858 if (*str
== '\\' && str
[1])
864 /* create the output STRING */
865 *strP
= string_make(interp
, string_start
, (UINTVAL
)(str
- string_start
),
868 /* skip the closing quote */
877 =item C<static const char* parse_key(PARROT_INTERP, const char *str, PMC
880 Parse an aggregate key out of a string and return a pointer to just
881 after the key. Currently only string and integer keys are allowed.
887 PARROT_CAN_RETURN_NULL
888 PARROT_WARN_UNUSED_RESULT
890 parse_key(PARROT_INTERP
, ARGIN(const char *str
), ARGOUT(PMC
**keyP
))
892 ASSERT_ARGS(parse_key
)
893 /* clear output parameter */
896 /* make sure it's a key */
903 /* if this is a string key, create a Parrot STRING */
905 STRING
*parrot_string
;
906 str
= parse_string(interp
, str
, &parrot_string
);
907 *keyP
= key_new_string(interp
, parrot_string
);
909 /* if this is a numeric key */
910 else if (isdigit((unsigned char) *str
)) {
912 str
= parse_int(str
, &value
);
913 *keyP
= key_new_integer(interp
, (INTVAL
) value
);
915 /* unsupported case; neither a string nor a numeric key */
920 /* hm, but if this doesn't match, it's probably an error */
921 /* XXX str can be NULL from parse_string() */
925 /* skip the closing brace on the key */
931 =item C<static void debugger_cmdline(PARROT_INTERP)>
933 Debugger command line.
935 Gets and executes commands, looping until the debugger state
936 is changed, either to exit or to start executing code.
943 debugger_cmdline(PARROT_INTERP
)
945 ASSERT_ARGS(debugger_cmdline
)
946 TRACEDEB_MSG("debugger_cmdline");
948 /*while (!(interp->pdb->state & PDB_EXIT)) {*/
949 while (interp
->pdb
->state
& PDB_STOPPED
) {
950 const char * command
;
951 interp
->pdb
->state
&= ~PDB_TRACING
;
952 PDB_get_command(interp
);
953 command
= interp
->pdb
->cur_command
;
954 if (command
[0] == '\0')
955 command
= interp
->pdb
->last_command
;
957 PDB_run_command(interp
, command
);
959 TRACEDEB_MSG("debugger_cmdline finished");
964 =item C<static void close_script_file(PARROT_INTERP)>
966 Close the script file, returning to command prompt mode.
973 close_script_file(PARROT_INTERP
)
975 ASSERT_ARGS(close_script_file
)
976 TRACEDEB_MSG("Closing debugger script file");
977 if (interp
->pdb
->script_file
) {
978 fclose(interp
->pdb
->script_file
);
979 interp
->pdb
->script_file
= NULL
;
980 interp
->pdb
->state
|= PDB_STOPPED
;
981 interp
->pdb
->last_command
[0] = '\0';
982 interp
->pdb
->cur_command
[0] = '\0';
988 =item C<void Parrot_debugger_init(PARROT_INTERP)>
990 Initializes the Parrot debugger, if it's not already initialized.
998 Parrot_debugger_init(PARROT_INTERP
)
1000 ASSERT_ARGS(Parrot_debugger_init
)
1001 TRACEDEB_MSG("Parrot_debugger_init");
1003 if (! interp
->pdb
) {
1004 PDB_t
*pdb
= mem_allocate_zeroed_typed(PDB_t
);
1005 Parrot_Interp debugger
= Parrot_new(interp
);
1007 debugger
->pdb
= pdb
;
1008 pdb
->debugee
= interp
;
1009 pdb
->debugger
= debugger
;
1011 /* Allocate space for command line buffers, NUL terminated c strings */
1012 pdb
->cur_command
= (char *)mem_sys_allocate_zeroed(DEBUG_CMD_BUFFER_LENGTH
+ 1);
1013 pdb
->last_command
= (char *)mem_sys_allocate_zeroed(DEBUG_CMD_BUFFER_LENGTH
+ 1);
1014 pdb
->file
= mem_allocate_zeroed_typed(PDB_file_t
);
1017 /* PDB_disassemble(interp, NULL); */
1019 interp
->pdb
->state
|= PDB_RUNNING
;
1024 =item C<void Parrot_debugger_destroy(PARROT_INTERP)>
1026 Destroy the current Parrot debugger instance.
1034 Parrot_debugger_destroy(PARROT_INTERP
)
1036 ASSERT_ARGS(Parrot_debugger_destroy
)
1038 Free all debugger allocated resources.
1040 PDB_t
*pdb
= interp
->pdb
;
1042 TRACEDEB_MSG("Parrot_debugger_destroy");
1045 PARROT_ASSERT(pdb
->debugee
== interp
);
1047 mem_sys_free(pdb
->last_command
);
1048 mem_sys_free(pdb
->cur_command
);
1056 =item C<void Parrot_debugger_load(PARROT_INTERP, STRING *filename)>
1058 Loads a Parrot source file for the current program.
1066 Parrot_debugger_load(PARROT_INTERP
, ARGIN_NULLOK(STRING
*filename
))
1068 ASSERT_ARGS(Parrot_debugger_load
)
1071 TRACEDEB_MSG("Parrot_debugger_load");
1074 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No debugger");
1076 file
= Parrot_str_to_cstring(interp
, filename
);
1077 PDB_load_source(interp
, file
);
1078 Parrot_str_free_cstring(file
);
1083 =item C<void Parrot_debugger_start(PARROT_INTERP, opcode_t * cur_opcode)>
1093 Parrot_debugger_start(PARROT_INTERP
, ARGIN(opcode_t
* cur_opcode
))
1095 ASSERT_ARGS(Parrot_debugger_start
)
1096 TRACEDEB_MSG("Parrot_debugger_start");
1099 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No debugger");
1101 interp
->pdb
->cur_opcode
= interp
->code
->base
.data
;
1103 if (interp
->pdb
->state
& PDB_ENTER
) {
1104 if (!interp
->pdb
->file
) {
1105 /* PDB_disassemble(interp, NULL); */
1107 interp
->pdb
->state
&= ~PDB_ENTER
;
1110 interp
->pdb
->cur_opcode
= cur_opcode
;
1112 interp
->pdb
->state
|= PDB_STOPPED
;
1114 debugger_cmdline(interp
);
1116 if (interp
->pdb
->state
& PDB_EXIT
) {
1117 TRACEDEB_MSG("Parrot_debugger_start Parrot_exit");
1118 Parrot_exit(interp
, 0);
1120 TRACEDEB_MSG("Parrot_debugger_start ends");
1125 =item C<void Parrot_debugger_break(PARROT_INTERP, opcode_t * cur_opcode)>
1127 Breaks execution and drops into the debugger. If we are already into the
1128 debugger and it is the first call, set a breakpoint.
1130 When you re run/continue the program being debugged it will pay no attention to
1139 Parrot_debugger_break(PARROT_INTERP
, ARGIN(opcode_t
* cur_opcode
))
1141 ASSERT_ARGS(Parrot_debugger_break
)
1142 TRACEDEB_MSG("Parrot_debugger_break");
1145 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No debugger");
1147 if (!interp
->pdb
->file
)
1148 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No file loaded to debug");
1150 if (!(interp
->pdb
->state
& PDB_BREAK
)) {
1151 TRACEDEB_MSG("Parrot_debugger_break - in BREAK state");
1152 new_runloop_jump_point(interp
);
1153 if (setjmp(interp
->current_runloop
->resume
)) {
1154 fprintf(stderr
, "Unhandled exception in debugger\n");
1158 interp
->pdb
->state
|= PDB_BREAK
;
1159 interp
->pdb
->state
|= PDB_STOPPED
;
1160 interp
->pdb
->cur_opcode
= (opcode_t
*)cur_opcode
+ 1;
1162 /*PDB_set_break(interp, NULL);*/
1164 debugger_cmdline(interp
);
1167 interp
->pdb
->cur_opcode
= (opcode_t
*)cur_opcode
+ 1;
1168 /*PDB_set_break(interp, NULL);*/
1170 TRACEDEB_MSG("Parrot_debugger_break done");
1175 =item C<void PDB_get_command(PARROT_INTERP)>
1177 Get a command from the user input to execute.
1179 It saves the last command executed (in C<< pdb->last_command >>), so it
1180 first frees the old one and updates it with the current one.
1182 Also prints the next line to run if the program is still active.
1184 The user input can't be longer than DEBUG_CMD_BUFFER_LENGTH characters.
1186 The input is saved in C<< pdb->cur_command >>.
1193 PDB_get_command(PARROT_INTERP
)
1195 ASSERT_ARGS(PDB_get_command
)
1199 PDB_t
* const pdb
= interp
->pdb
;
1201 /***********************************
1206 ***********************************/
1208 /* flush the buffered data */
1211 TRACEDEB_MSG("PDB_get_command");
1213 PARROT_ASSERT(pdb
->last_command
);
1214 PARROT_ASSERT(pdb
->cur_command
);
1216 if (interp
->pdb
->script_file
) {
1217 FILE *fd
= interp
->pdb
->script_file
;
1218 char buf
[DEBUG_CMD_BUFFER_LENGTH
+1];
1222 if (fgets(buf
, DEBUG_CMD_BUFFER_LENGTH
, fd
) == NULL
) {
1223 close_script_file(interp
);
1229 fprintf(stderr
, "script (%lu): '%s'\n", pdb
->script_line
, buf
);
1233 ptr
= skip_whitespace(buf
);
1235 /* skip blank and commented lines */
1236 } while (*ptr
== '\0' || *ptr
== '#');
1238 if (pdb
->state
& PDB_ECHO
)
1239 Parrot_io_eprintf(pdb
->debugger
, "[%lu %s]\n", pdb
->script_line
, buf
);
1242 fprintf(stderr
, "(script) %s\n", buf
);
1245 strcpy(pdb
->cur_command
, buf
);
1249 /* update the last command */
1250 if (pdb
->cur_command
[0] != '\0')
1251 strcpy(pdb
->last_command
, pdb
->cur_command
);
1255 c
= pdb
->cur_command
;
1257 /*Parrot_io_eprintf(pdb->debugger, "\n(pdb) ");*/
1258 Parrot_io_eprintf(pdb
->debugger
, "\n");
1260 /* skip leading whitespace */
1264 } while (isspace((unsigned char)ch) && ch != '\n');
1267 Interp
* interpdeb
= interp
->pdb
->debugger
;
1268 STRING
* readline
= CONST_STRING(interpdeb
, "readline_interactive");
1269 STRING
* prompt
= CONST_STRING(interpdeb
, "(pdb) ");
1270 STRING
*s
= Parrot_str_new(interpdeb
, NULL
, 0);
1271 PMC
*tmp_stdin
= Parrot_io_stdhandle(interpdeb
, 0, NULL
);
1273 Parrot_pcc_invoke_method_from_c_args(interpdeb
,
1274 tmp_stdin
, readline
,
1275 "S->S", prompt
, & s
);
1277 char * aux
= Parrot_str_to_cstring(interpdeb
, s
);
1279 Parrot_str_free_cstring(aux
);
1284 /* generate string (no more than buffer length) */
1286 while (ch != EOF && ch != '\n' && (i < DEBUG_CMD_BUFFER_LENGTH)) {
1288 ch = fgetc(tmp_stdin);
1300 =item C<void PDB_script_file(PARROT_INTERP, const char *command)>
1302 Interprets the contents of a file as user input commands
1310 PDB_script_file(PARROT_INTERP
, ARGIN(const char *command
))
1312 ASSERT_ARGS(PDB_script_file
)
1315 TRACEDEB_MSG("PDB_script_file");
1317 /* If already executing a script, close it */
1318 close_script_file(interp
);
1320 TRACEDEB_MSG("Opening debugger script file");
1322 fd
= fopen(command
, "r");
1324 Parrot_io_eprintf(interp
->pdb
->debugger
,
1325 "Error reading script file %s.\n",
1329 interp
->pdb
->script_file
= fd
;
1330 interp
->pdb
->script_line
= 0;
1331 TRACEDEB_MSG("PDB_script_file finished");
1336 =item C<int PDB_run_command(PARROT_INTERP, const char *command)>
1340 Hash the command to make a simple switch calling the correct handler.
1346 PARROT_IGNORABLE_RESULT
1348 PDB_run_command(PARROT_INTERP
, ARGIN(const char *command
))
1350 ASSERT_ARGS(PDB_run_command
)
1351 PDB_t
* const pdb
= interp
->pdb
;
1352 const DebuggerCmd
*cmd
;
1354 /* keep a pointer to the command, in case we need to report an error */
1356 const char * cmdline
= command
;
1358 TRACEDEB_MSG("PDB_run_command");
1359 cmd
= get_cmd(& cmdline
);
1362 (* cmd
->func
)(pdb
, cmdline
);
1366 if (*cmdline
== '\0') {
1370 Parrot_io_eprintf(pdb
->debugger
,
1371 "Undefined command: \"%s\"", command
);
1372 if (pdb
->script_file
)
1373 Parrot_io_eprintf(pdb
->debugger
, " in line %lu", pdb
->script_line
);
1374 Parrot_io_eprintf(pdb
->debugger
, ". Try \"help\".");
1375 close_script_file(interp
);
1383 =item C<void PDB_next(PARROT_INTERP, const char *command)>
1385 Execute the next N operation(s).
1387 Inits the program if needed, runs the next N >= 1 operations and stops.
1394 PDB_next(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1396 ASSERT_ARGS(PDB_next
)
1397 PDB_t
* const pdb
= interp
->pdb
;
1400 TRACEDEB_MSG("PDB_next");
1402 /* Init the program if it's not running */
1403 if (!(pdb
->state
& PDB_RUNNING
))
1404 PDB_init(interp
, command
);
1406 /* Get the number of operations to execute if any */
1407 pdb
->tracing
= get_ulong(& command
, 1);
1409 /* Erase the stopped flag */
1410 pdb
->state
&= ~PDB_STOPPED
;
1412 /* Testing use of the debugger runloop */
1416 for (; n
&& pdb
->cur_opcode
; n
--)
1417 DO_OP(pdb
->cur_opcode
, pdb
->debugee
);
1419 /* Set the stopped flag */
1420 pdb
->state
|= PDB_STOPPED
;
1422 /* If program ended */
1424 if (!pdb
->cur_opcode
)
1425 (void)PDB_program_end(interp
);
1428 debugee
= pdb
->debugee
;
1430 new_runloop_jump_point(debugee
);
1431 if (setjmp(debugee
->current_runloop
->resume
)) {
1432 Parrot_io_eprintf(pdb
->debugger
, "Unhandled exception while tracing\n");
1433 pdb
->state
|= PDB_STOPPED
;
1437 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1439 TRACEDEB_MSG("PDB_next finished");
1444 =item C<void PDB_trace(PARROT_INTERP, const char *command)>
1446 Execute the next N operations; if no number is specified, it defaults to 1.
1453 PDB_trace(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1455 ASSERT_ARGS(PDB_trace
)
1456 PDB_t
* const pdb
= interp
->pdb
;
1459 TRACEDEB_MSG("PDB_trace");
1461 /* if debugger is not running yet, initialize */
1463 if (!(pdb->state & PDB_RUNNING))
1464 PDB_init(interp, command);
1467 /* get the number of ops to run, if specified */
1468 pdb
->tracing
= get_ulong(& command
, 1);
1470 /* clear the PDB_STOPPED flag, we'll be running n ops now */
1471 pdb
->state
&= ~PDB_STOPPED
;
1472 debugee
= pdb
->debugee
;
1475 new_runloop_jump_point(debugee
);
1476 if (setjmp(debugee
->current_runloop
->resume
)) {
1477 Parrot_io_eprintf(pdb
->debugger
, "Unhandled exception while tracing\n");
1478 pdb
->state
|= PDB_STOPPED
;
1482 pdb
->state
|= PDB_TRACING
;
1483 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1485 /* Clear the following when done some testing */
1487 /* we just stopped */
1488 pdb
->state
|= PDB_STOPPED
;
1490 /* If program ended */
1491 if (!pdb
->cur_opcode
)
1492 (void)PDB_program_end(interp
);
1493 pdb
->state
|= PDB_RUNNING
;
1494 pdb
->state
&= ~PDB_STOPPED
;
1496 TRACEDEB_MSG("PDB_trace finished");
1501 =item C<static unsigned short condition_regtype(const char *cmd)>
1507 static unsigned short
1508 condition_regtype(ARGIN(const char *cmd
))
1510 ASSERT_ARGS(condition_regtype
)
1514 return PDB_cond_int
;
1517 return PDB_cond_num
;
1520 return PDB_cond_str
;
1523 return PDB_cond_pmc
;
1531 =item C<PDB_condition_t * PDB_cond(PARROT_INTERP, const char *command)>
1533 Analyzes a condition from the user input.
1539 PARROT_CAN_RETURN_NULL
1541 PDB_cond(PARROT_INTERP
, ARGIN(const char *command
))
1543 ASSERT_ARGS(PDB_cond
)
1544 PDB_condition_t
*condition
;
1546 char str
[DEBUG_CMD_BUFFER_LENGTH
+ 1];
1547 unsigned short cond_argleft
;
1548 unsigned short cond_type
;
1549 unsigned char regleft
;
1552 TRACEDEB_MSG("PDB_cond");
1554 /* Return if no more arguments */
1555 if (!(command
&& *command
)) {
1556 Parrot_io_eprintf(interp
->pdb
->debugger
, "No condition specified\n");
1560 command
= skip_whitespace(command
);
1562 fprintf(stderr
, "PDB_trace: '%s'\n", command
);
1565 cond_argleft
= condition_regtype(command
);
1567 /* get the register number */
1569 regleft
= (unsigned char)get_uint(&command
, 0);
1570 if (auxcmd
== command
) {
1571 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid register\n");
1575 /* Now the condition */
1576 command
= skip_whitespace(command
);
1579 if (*(command
+ 1) == '=')
1580 cond_type
= PDB_cond_ge
;
1582 cond_type
= PDB_cond_gt
;
1585 if (*(command
+ 1) == '=')
1586 cond_type
= PDB_cond_le
;
1588 cond_type
= PDB_cond_lt
;
1591 if (*(command
+ 1) == '=')
1592 cond_type
= PDB_cond_eq
;
1597 if (*(command
+ 1) == '=')
1598 cond_type
= PDB_cond_ne
;
1603 if (cond_argleft
!= PDB_cond_str
&& cond_argleft
!= PDB_cond_pmc
) {
1604 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid null condition\n");
1607 cond_type
= PDB_cond_notnull
;
1610 INV_COND
: Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid condition\n");
1614 /* if there's an '=', skip it */
1615 if (*(command
+ 1) == '=')
1620 command
= skip_whitespace(command
);
1622 /* return if no notnull condition and no more arguments */
1623 if (!(command
&& *command
) && (cond_type
!= PDB_cond_notnull
)) {
1624 Parrot_io_eprintf(interp
->pdb
->debugger
, "Can't compare a register with nothing\n");
1628 /* Allocate new condition */
1629 condition
= mem_allocate_zeroed_typed(PDB_condition_t
);
1631 condition
->type
= cond_argleft
| cond_type
;
1633 if (cond_type
!= PDB_cond_notnull
) {
1635 if (isalpha((unsigned char)*command
)) {
1636 /* It's a register - we first check that it's the correct type */
1638 unsigned short cond_argright
= condition_regtype(command
);
1640 if (cond_argright
!= cond_argleft
) {
1641 Parrot_io_eprintf(interp
->pdb
->debugger
, "Register types don't agree\n");
1642 mem_sys_free(condition
);
1646 /* Now we check and store the register number */
1648 reg_number
= (int)get_uint(&command
, 0);
1649 if (auxcmd
== command
) {
1650 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid register\n");
1651 mem_sys_free(condition
);
1655 if (reg_number
< 0) {
1656 Parrot_io_eprintf(interp
->pdb
->debugger
, "Out-of-bounds register\n");
1657 mem_sys_free(condition
);
1661 condition
->value
= mem_allocate_typed(int);
1662 *(int *)condition
->value
= reg_number
;
1664 /* If the first argument was an integer */
1665 else if (condition
->type
& PDB_cond_int
) {
1666 /* This must be either an integer constant or register */
1667 condition
->value
= mem_allocate_typed(INTVAL
);
1668 *(INTVAL
*)condition
->value
= (INTVAL
)atoi(command
);
1669 condition
->type
|= PDB_cond_const
;
1671 else if (condition
->type
& PDB_cond_num
) {
1672 condition
->value
= mem_allocate_typed(FLOATVAL
);
1673 *(FLOATVAL
*)condition
->value
= (FLOATVAL
)atof(command
);
1674 condition
->type
|= PDB_cond_const
;
1676 else if (condition
->type
& PDB_cond_str
) {
1677 for (i
= 1; ((command
[i
] != '"') && (i
< DEBUG_CMD_BUFFER_LENGTH
)); i
++)
1678 str
[i
- 1] = command
[i
];
1681 fprintf(stderr
, "PDB_break: '%s'\n", str
);
1683 condition
->value
= string_make(interp
, str
, (UINTVAL
)(i
- 1),
1686 condition
->type
|= PDB_cond_const
;
1688 else if (condition
->type
& PDB_cond_pmc
) {
1689 /* TT #1259: Need to figure out what to do in this case.
1690 * For the time being, we just bail. */
1691 Parrot_io_eprintf(interp
->pdb
->debugger
, "Can't compare PMC with constant\n");
1692 mem_sys_free(condition
);
1703 =item C<void PDB_watchpoint(PARROT_INTERP, const char *command)>
1712 PDB_watchpoint(PARROT_INTERP
, ARGIN(const char *command
))
1714 ASSERT_ARGS(PDB_watchpoint
)
1715 PDB_t
* const pdb
= interp
->pdb
;
1716 PDB_condition_t
* const condition
= PDB_cond(interp
, command
);
1721 /* Add it to the head of the list */
1722 if (pdb
->watchpoint
)
1723 condition
->next
= pdb
->watchpoint
;
1724 pdb
->watchpoint
= condition
;
1725 fprintf(stderr
, "Adding watchpoint\n");
1730 =item C<void PDB_set_break(PARROT_INTERP, const char *command)>
1732 Set a break point, the source code file must be loaded.
1739 PDB_set_break(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1741 ASSERT_ARGS(PDB_set_break
)
1742 PDB_t
* const pdb
= interp
->pdb
;
1743 PDB_breakpoint_t
*newbreak
;
1744 PDB_breakpoint_t
**lbreak
;
1745 PDB_line_t
*line
= NULL
;
1747 opcode_t
*breakpos
= NULL
;
1749 unsigned long ln
= get_ulong(& command
, 0);
1751 TRACEDEB_MSG("PDB_set_break");
1753 /* If there is a source file use line number, else opcode position */
1757 TRACEDEB_MSG("PDB_set_break file");
1759 if (!pdb
->file
->size
) {
1760 Parrot_io_eprintf(pdb
->debugger
,
1761 "Can't set a breakpoint in empty file\n");
1765 /* If no line number was specified, set it at the current line */
1769 /* Move to the line where we will set the break point */
1770 line
= pdb
->file
->line
;
1772 for (i
= 1; ((i
< ln
) && (line
->next
)); i
++)
1775 /* Abort if the line number provided doesn't exist */
1776 if (line
== NULL
|| !line
->next
) {
1777 Parrot_io_eprintf(pdb
->debugger
,
1778 "Can't set a breakpoint at line number %li\n", ln
);
1783 /* Get the line to set it */
1784 line
= pdb
->file
->line
;
1786 TRACEDEB_MSG("PDB_set_break reading ops");
1787 while (line
->opcode
!= pdb
->cur_opcode
) {
1790 Parrot_io_eprintf(pdb
->debugger
,
1791 "No current line found and no line number specified\n");
1796 /* Skip lines that are not related to an opcode */
1797 while (line
&& !line
->opcode
)
1799 /* Abort if the line number provided doesn't exist */
1801 Parrot_io_eprintf(pdb
->debugger
,
1802 "Can't set a breakpoint at line number %li\n", ln
);
1806 breakpos
= line
->opcode
;
1809 TRACEDEB_MSG("PDB_set_break no file");
1810 breakpos
= interp
->code
->base
.data
+ ln
;
1813 TRACEDEB_MSG("PDB_set_break allocate breakpoint");
1814 /* Allocate the new break point */
1815 newbreak
= mem_allocate_zeroed_typed(PDB_breakpoint_t
);
1818 /*command = skip_command(command);*/
1821 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
1822 "NULL command passed to PDB_set_break");
1825 /* if there is another argument to break, besides the line number,
1826 * it should be an 'if', so we call another handler. */
1827 if (command
&& *command
) {
1828 command
= skip_whitespace(command
);
1829 while (! isspace((unsigned char)*command
))
1831 command
= skip_whitespace(command
);
1832 newbreak
->condition
= PDB_cond(interp
, command
);
1835 /* Set the address where to stop */
1836 newbreak
->pc
= breakpos
;
1838 /* No next breakpoint */
1839 newbreak
->next
= NULL
;
1841 /* Don't skip (at least initially) */
1844 /* Add the breakpoint to the end of the list */
1846 lbreak
= & pdb
->breakpoint
;
1848 bp_id
= (*lbreak
)->id
+ 1;
1849 lbreak
= & (*lbreak
)->next
;
1851 newbreak
->prev
= *lbreak
;
1853 newbreak
->id
= bp_id
;
1855 /* Show breakpoint position */
1857 Parrot_io_eprintf(pdb
->debugger
, "Breakpoint %li at", newbreak
->id
);
1859 Parrot_io_eprintf(pdb
->debugger
, " line %li", line
->number
);
1860 Parrot_io_eprintf(pdb
->debugger
, " pos %li\n", newbreak
->pc
- interp
->code
->base
.data
);
1865 =item C<static void list_breakpoints(PDB_t *pdb)>
1872 list_breakpoints(ARGIN(PDB_t
*pdb
))
1874 ASSERT_ARGS(list_breakpoints
)
1876 PDB_breakpoint_t
**lbreak
;
1877 for (lbreak
= & pdb
->breakpoint
; *lbreak
; lbreak
= & (*lbreak
)->next
) {
1878 PDB_breakpoint_t
*br
= *lbreak
;
1879 Parrot_io_eprintf(pdb
->debugger
, "Breakpoint %li at", br
->id
);
1880 Parrot_io_eprintf(pdb
->debugger
, " pos %li", br
->pc
- pdb
->debugee
->code
->base
.data
);
1882 Parrot_io_eprintf(pdb
->debugger
, " (disabled)");
1883 Parrot_io_eprintf(pdb
->debugger
, "\n");
1889 =item C<void PDB_init(PARROT_INTERP, const char *command)>
1898 PDB_init(PARROT_INTERP
, SHIM(const char *command
))
1900 ASSERT_ARGS(PDB_init
)
1901 PDB_t
* const pdb
= interp
->pdb
;
1903 /* Restart if we are already running */
1904 if (pdb
->state
& PDB_RUNNING
)
1905 Parrot_io_eprintf(pdb
->debugger
, "Restarting\n");
1907 /* Add the RUNNING state */
1908 pdb
->state
|= PDB_RUNNING
;
1913 =item C<void PDB_continue(PARROT_INTERP, const char *command)>
1915 Continue running the program. If a number is specified, skip that many
1923 PDB_continue(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1925 ASSERT_ARGS(PDB_continue
)
1926 PDB_t
* const pdb
= interp
->pdb
;
1927 unsigned long ln
= 0;
1929 TRACEDEB_MSG("PDB_continue");
1931 /* Skip any breakpoint? */
1933 ln
= get_ulong(& command
, 0);
1936 if (!pdb
->breakpoint
) {
1937 Parrot_io_eprintf(pdb
->debugger
, "No breakpoints to skip\n");
1941 PDB_skip_breakpoint(interp
, ln
);
1944 /* Run while no break point is reached */
1946 while (!PDB_break(interp))
1947 DO_OP(pdb->cur_opcode, pdb->debugee);
1952 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1954 new_internal_exception(pdb
->debugee
);
1955 if (setjmp(pdb
->debugee
->exceptions
->destination
)) {
1956 Parrot_io_eprintf(pdb
->debugee
, "Unhandled exception while debugging: %Ss\n",
1957 pdb
->debugee
->exceptions
->msg
);
1958 pdb
->state
|= PDB_STOPPED
;
1961 runops_int(pdb
->debugee
, pdb
->debugee
->code
->base
.data
- pdb
->cur_opcode
);
1962 if (!pdb
->cur_opcode
)
1963 (void)PDB_program_end(interp
);
1965 pdb
->state
|= PDB_RUNNING
;
1966 pdb
->state
&= ~PDB_BREAK
;
1967 pdb
->state
&= ~PDB_STOPPED
;
1972 =item C<PDB_breakpoint_t * PDB_find_breakpoint(PARROT_INTERP, const char
1975 Find breakpoint number N; returns C<NULL> if the breakpoint doesn't
1976 exist or if no breakpoint was specified.
1982 PARROT_CAN_RETURN_NULL
1983 PARROT_WARN_UNUSED_RESULT
1985 PDB_find_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
1987 ASSERT_ARGS(PDB_find_breakpoint
)
1988 const char *oldcmd
= command
;
1989 const unsigned long n
= get_ulong(&command
, 0);
1990 if (command
!= oldcmd
) {
1991 PDB_breakpoint_t
*breakpoint
= interp
->pdb
->breakpoint
;
1993 while (breakpoint
&& breakpoint
->id
!= n
)
1994 breakpoint
= breakpoint
->next
;
1997 Parrot_io_eprintf(interp
->pdb
->debugger
, "No breakpoint number %ld", n
);
2004 /* Report an appropriate error */
2006 Parrot_io_eprintf(interp
->pdb
->debugger
, "Not a valid breakpoint");
2008 Parrot_io_eprintf(interp
->pdb
->debugger
, "No breakpoint specified");
2016 =item C<void PDB_disable_breakpoint(PARROT_INTERP, const char *command)>
2018 Disable a breakpoint; it can be reenabled with the enable command.
2025 PDB_disable_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2027 ASSERT_ARGS(PDB_disable_breakpoint
)
2028 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2030 /* if the breakpoint exists, disable it. */
2032 breakpoint
->skip
= -1;
2037 =item C<void PDB_enable_breakpoint(PARROT_INTERP, const char *command)>
2039 Reenable a disabled breakpoint; if the breakpoint was not disabled, has
2047 PDB_enable_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2049 ASSERT_ARGS(PDB_enable_breakpoint
)
2050 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2052 /* if the breakpoint exists, and it was disabled, enable it. */
2053 if (breakpoint
&& breakpoint
->skip
== -1)
2054 breakpoint
->skip
= 0;
2059 =item C<void PDB_delete_breakpoint(PARROT_INTERP, const char *command)>
2061 Delete a breakpoint.
2068 PDB_delete_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2070 ASSERT_ARGS(PDB_delete_breakpoint
)
2071 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2072 const PDB_line_t
*line
;
2076 if (!interp
->pdb
->file
)
2077 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No file loaded");
2079 line
= interp
->pdb
->file
->line
;
2080 while (line
->opcode
!= breakpoint
->pc
)
2083 /* Delete the condition structure, if there is one */
2084 if (breakpoint
->condition
) {
2085 PDB_delete_condition(interp
, breakpoint
);
2086 breakpoint
->condition
= NULL
;
2089 /* Remove the breakpoint from the list */
2090 if (breakpoint
->prev
&& breakpoint
->next
) {
2091 breakpoint
->prev
->next
= breakpoint
->next
;
2092 breakpoint
->next
->prev
= breakpoint
->prev
;
2094 else if (breakpoint
->prev
&& !breakpoint
->next
) {
2095 breakpoint
->prev
->next
= NULL
;
2097 else if (!breakpoint
->prev
&& breakpoint
->next
) {
2098 breakpoint
->next
->prev
= NULL
;
2099 interp
->pdb
->breakpoint
= breakpoint
->next
;
2102 interp
->pdb
->breakpoint
= NULL
;
2104 bp_id
= breakpoint
->id
;
2105 /* Kill the breakpoint */
2106 mem_sys_free(breakpoint
);
2108 Parrot_io_eprintf(interp
->pdb
->debugger
, "Breakpoint %li deleted\n", bp_id
);
2114 =item C<void PDB_delete_condition(PARROT_INTERP, PDB_breakpoint_t *breakpoint)>
2116 Delete a condition associated with a breakpoint.
2123 PDB_delete_condition(SHIM_INTERP
, ARGMOD(PDB_breakpoint_t
*breakpoint
))
2125 ASSERT_ARGS(PDB_delete_condition
)
2126 if (breakpoint
->condition
->value
) {
2127 if (breakpoint
->condition
->type
& PDB_cond_str
) {
2128 /* 'value' is a string, so we need to be careful */
2129 PObj_external_CLEAR((STRING
*)breakpoint
->condition
->value
);
2130 PObj_on_free_list_SET((STRING
*)breakpoint
->condition
->value
);
2131 /* it should now be properly garbage collected after
2132 we destroy the condition */
2135 /* 'value' is a float or an int, so we can just free it */
2136 mem_sys_free(breakpoint
->condition
->value
);
2137 breakpoint
->condition
->value
= NULL
;
2141 mem_sys_free(breakpoint
->condition
);
2142 breakpoint
->condition
= NULL
;
2147 =item C<void PDB_skip_breakpoint(PARROT_INTERP, unsigned long i)>
2149 Skip C<i> times all breakpoints.
2156 PDB_skip_breakpoint(PARROT_INTERP
, unsigned long i
)
2158 ASSERT_ARGS(PDB_skip_breakpoint
)
2160 fprintf(stderr
, "PDB_skip_breakpoint: %li\n", i
);
2163 interp
->pdb
->breakpoint_skip
= i
;
2168 =item C<char PDB_program_end(PARROT_INTERP)>
2177 PDB_program_end(PARROT_INTERP
)
2179 ASSERT_ARGS(PDB_program_end
)
2180 PDB_t
* const pdb
= interp
->pdb
;
2182 TRACEDEB_MSG("PDB_program_end");
2184 /* Remove the RUNNING state */
2185 pdb
->state
&= ~PDB_RUNNING
;
2187 Parrot_io_eprintf(pdb
->debugger
, "Program exited.\n");
2193 =item C<char PDB_check_condition(PARROT_INTERP, const PDB_condition_t
2196 Returns true if the condition was met.
2202 PARROT_WARN_UNUSED_RESULT
2204 PDB_check_condition(PARROT_INTERP
, ARGIN(const PDB_condition_t
*condition
))
2206 ASSERT_ARGS(PDB_check_condition
)
2207 PMC
*ctx
= CURRENT_CONTEXT(interp
);
2209 TRACEDEB_MSG("PDB_check_condition");
2213 if (condition
->type
& PDB_cond_int
) {
2215 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_INT
))
2217 i
= CTX_REG_INT(ctx
, condition
->reg
);
2219 if (condition
->type
& PDB_cond_const
)
2220 j
= *(INTVAL
*)condition
->value
;
2222 j
= REG_INT(interp
, *(int *)condition
->value
);
2224 if (((condition
->type
& PDB_cond_gt
) && (i
> j
)) ||
2225 ((condition
->type
& PDB_cond_ge
) && (i
>= j
)) ||
2226 ((condition
->type
& PDB_cond_eq
) && (i
== j
)) ||
2227 ((condition
->type
& PDB_cond_ne
) && (i
!= j
)) ||
2228 ((condition
->type
& PDB_cond_le
) && (i
<= j
)) ||
2229 ((condition
->type
& PDB_cond_lt
) && (i
< j
)))
2234 else if (condition
->type
& PDB_cond_num
) {
2237 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_NUM
))
2239 k
= CTX_REG_NUM(ctx
, condition
->reg
);
2241 if (condition
->type
& PDB_cond_const
)
2242 l
= *(FLOATVAL
*)condition
->value
;
2244 l
= REG_NUM(interp
, *(int *)condition
->value
);
2246 if (((condition
->type
& PDB_cond_gt
) && (k
> l
)) ||
2247 ((condition
->type
& PDB_cond_ge
) && (k
>= l
)) ||
2248 ((condition
->type
& PDB_cond_eq
) && (k
== l
)) ||
2249 ((condition
->type
& PDB_cond_ne
) && (k
!= l
)) ||
2250 ((condition
->type
& PDB_cond_le
) && (k
<= l
)) ||
2251 ((condition
->type
& PDB_cond_lt
) && (k
< l
)))
2256 else if (condition
->type
& PDB_cond_str
) {
2259 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_STR
))
2261 m
= CTX_REG_STR(ctx
, condition
->reg
);
2263 if (condition
->type
& PDB_cond_notnull
)
2264 return ! STRING_IS_NULL(m
);
2266 if (condition
->type
& PDB_cond_const
)
2267 n
= (STRING
*)condition
->value
;
2269 n
= REG_STR(interp
, *(int *)condition
->value
);
2271 if (((condition
->type
& PDB_cond_gt
) &&
2272 (Parrot_str_compare(interp
, m
, n
) > 0)) ||
2273 ((condition
->type
& PDB_cond_ge
) &&
2274 (Parrot_str_compare(interp
, m
, n
) >= 0)) ||
2275 ((condition
->type
& PDB_cond_eq
) &&
2276 (Parrot_str_compare(interp
, m
, n
) == 0)) ||
2277 ((condition
->type
& PDB_cond_ne
) &&
2278 (Parrot_str_compare(interp
, m
, n
) != 0)) ||
2279 ((condition
->type
& PDB_cond_le
) &&
2280 (Parrot_str_compare(interp
, m
, n
) <= 0)) ||
2281 ((condition
->type
& PDB_cond_lt
) &&
2282 (Parrot_str_compare(interp
, m
, n
) < 0)))
2287 else if (condition
->type
& PDB_cond_pmc
) {
2290 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_PMC
))
2292 m
= CTX_REG_PMC(ctx
, condition
->reg
);
2294 if (condition
->type
& PDB_cond_notnull
)
2295 return ! PMC_IS_NULL(m
);
2304 =item C<static PDB_breakpoint_t * current_breakpoint(PDB_t * pdb)>
2306 Returns a pointer to the breakpoint at the current position,
2307 or NULL if there is none.
2313 PARROT_CAN_RETURN_NULL
2314 static PDB_breakpoint_t
*
2315 current_breakpoint(ARGIN(PDB_t
* pdb
))
2317 ASSERT_ARGS(current_breakpoint
)
2318 PDB_breakpoint_t
*breakpoint
= pdb
->breakpoint
;
2319 while (breakpoint
) {
2320 if (pdb
->cur_opcode
== breakpoint
->pc
)
2322 breakpoint
= breakpoint
->next
;
2329 =item C<char PDB_break(PARROT_INTERP)>
2331 Returns true if we have to stop running.
2337 PARROT_WARN_UNUSED_RESULT
2339 PDB_break(PARROT_INTERP
)
2341 ASSERT_ARGS(PDB_break
)
2342 PDB_t
* const pdb
= interp
->pdb
;
2343 PDB_condition_t
*watchpoint
= pdb
->watchpoint
;
2344 PDB_breakpoint_t
*breakpoint
;
2347 TRACEDEB_MSG("PDB_break");
2350 /* Check the watchpoints first. */
2351 while (watchpoint
) {
2352 if (PDB_check_condition(interp
, watchpoint
)) {
2353 pdb
->state
|= PDB_STOPPED
;
2357 watchpoint
= watchpoint
->next
;
2360 /* If program ended */
2361 if (!pdb
->cur_opcode
)
2362 return PDB_program_end(interp
);
2364 /* If the program is STOPPED allow it to continue */
2365 if (pdb
->state
& PDB_STOPPED
) {
2366 pdb
->state
&= ~PDB_STOPPED
;
2370 breakpoint
= current_breakpoint(pdb
);
2372 /* If we have to skip breakpoints, do so. */
2373 if (pdb
->breakpoint_skip
) {
2374 TRACEDEB_MSG("PDB_break skipping");
2375 pdb
->breakpoint_skip
--;
2379 if (breakpoint
->skip
< 0)
2382 /* Check if there is a condition for this breakpoint */
2383 if ((breakpoint
->condition
) &&
2384 (!PDB_check_condition(interp
, breakpoint
->condition
)))
2387 TRACEDEB_MSG("PDB_break stopping");
2389 /* Add the STOPPED state and stop */
2390 pdb
->state
|= PDB_STOPPED
;
2399 =item C<char * PDB_escape(const char *string, UINTVAL length)>
2401 Escapes C<">, C<\r>, C<\n>, C<\t>, C<\a> and C<\\>.
2403 The returned string must be freed.
2409 PARROT_WARN_UNUSED_RESULT
2410 PARROT_CAN_RETURN_NULL
2413 PDB_escape(ARGIN(const char *string
), UINTVAL length
)
2415 ASSERT_ARGS(PDB_escape
)
2419 length
= length
> 20 ? 20 : length
;
2420 end
= string
+ length
;
2422 /* Return if there is no string to escape*/
2426 fill
= _new
= (char *)mem_sys_allocate(length
* 2 + 1);
2428 for (; string
< end
; string
++) {
2459 *(fill
++) = *string
;
2471 =item C<int PDB_unescape(char *string)>
2473 Do inplace unescape of C<\r>, C<\n>, C<\t>, C<\a> and C<\\>.
2480 PDB_unescape(ARGMOD(char *string
))
2482 ASSERT_ARGS(PDB_unescape
)
2485 for (; *string
; string
++) {
2488 if (*string
== '\\') {
2492 switch (string
[1]) {
2514 for (i
= 1; fill
[i
+ 1]; i
++)
2515 fill
[i
] = fill
[i
+ 1];
2526 =item C<size_t PDB_disassemble_op(PARROT_INTERP, char *dest, size_t space, const
2527 op_info_t *info, const opcode_t *op, PDB_file_t *file, const opcode_t
2528 *code_start, int full_name)>
2537 PDB_disassemble_op(PARROT_INTERP
, ARGOUT(char *dest
), size_t space
,
2538 ARGIN(const op_info_t
*info
), ARGIN(const opcode_t
*op
),
2539 ARGMOD_NULLOK(PDB_file_t
*file
), ARGIN_NULLOK(const opcode_t
*code_start
),
2542 ASSERT_ARGS(PDB_disassemble_op
)
2547 /* Write the opcode name */
2548 const char * p
= full_name
? info
->full_name
: info
->name
;
2550 TRACEDEB_MSG("PDB_disassemble_op");
2559 /* Concat the arguments */
2560 for (j
= 1; j
< info
->op_count
; j
++) {
2564 PARROT_ASSERT(size
+ 2 < space
);
2566 switch (info
->types
[j
- 1]) {
2580 /* If the opcode jumps and this is the last argument,
2581 that means this is a label */
2582 if ((j
== info
->op_count
- 1) &&
2583 (info
->jump
& PARROT_JUMP_RELATIVE
)) {
2586 i
= PDB_add_label(file
, op
, op
[j
]);
2588 else if (code_start
) {
2591 i
= op
[j
] + (op
- code_start
);
2600 /* Convert the integer to a string */
2605 PARROT_ASSERT(size
+ 20 < space
);
2607 size
+= sprintf(&dest
[size
], INTVAL_FMT
, i
);
2612 /* Convert the float to a string */
2613 const FLOATVAL f
= interp
->code
->const_table
->constants
[op
[j
]]->u
.number
;
2614 Parrot_snprintf(interp
, buf
, sizeof (buf
), FLOATVAL_FMT
, f
);
2615 strcpy(&dest
[size
], buf
);
2616 size
+= strlen(buf
);
2621 if (interp
->code
->const_table
->constants
[op
[j
]]-> u
.string
->strlen
) {
2622 char * const unescaped
=
2623 Parrot_str_to_cstring(interp
, interp
->code
->
2624 const_table
->constants
[op
[j
]]->u
.string
);
2625 char * const escaped
=
2626 PDB_escape(unescaped
, interp
->code
->const_table
->
2627 constants
[op
[j
]]->u
.string
->strlen
);
2629 strcpy(&dest
[size
], escaped
);
2630 size
+= strlen(escaped
);
2631 mem_sys_free(escaped
);
2633 Parrot_str_free_cstring(unescaped
);
2638 Parrot_snprintf(interp
, buf
, sizeof (buf
), "PMC_CONST(%d)", op
[j
]);
2639 strcpy(&dest
[size
], buf
);
2640 size
+= strlen(buf
);
2643 dest
[size
- 1] = '[';
2644 Parrot_snprintf(interp
, buf
, sizeof (buf
), "P" INTVAL_FMT
, op
[j
]);
2645 strcpy(&dest
[size
], buf
);
2646 size
+= strlen(buf
);
2651 PMC
* k
= interp
->code
->const_table
->constants
[op
[j
]]->u
.key
;
2652 dest
[size
- 1] = '[';
2654 switch (PObj_get_FLAGS(k
)) {
2657 case KEY_integer_FLAG
:
2658 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2659 INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2660 strcpy(&dest
[size
], buf
);
2661 size
+= strlen(buf
);
2663 case KEY_number_FLAG
:
2664 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2665 FLOATVAL_FMT
, VTABLE_get_number(interp
, k
));
2666 strcpy(&dest
[size
], buf
);
2667 size
+= strlen(buf
);
2669 case KEY_string_FLAG
:
2672 char * const temp
= Parrot_str_to_cstring(interp
,
2673 VTABLE_get_string(interp
, k
));
2674 strcpy(&dest
[size
], temp
);
2675 Parrot_str_free_cstring(temp
);
2677 size
+= Parrot_str_byte_length(interp
,
2678 VTABLE_get_string(interp
, (k
)));
2681 case KEY_integer_FLAG
|KEY_register_FLAG
:
2682 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2683 "I" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2684 strcpy(&dest
[size
], buf
);
2685 size
+= strlen(buf
);
2687 case KEY_number_FLAG
|KEY_register_FLAG
:
2688 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2689 "N" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2690 strcpy(&dest
[size
], buf
);
2691 size
+= strlen(buf
);
2693 case KEY_string_FLAG
|KEY_register_FLAG
:
2694 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2695 "S" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2696 strcpy(&dest
[size
], buf
);
2697 size
+= strlen(buf
);
2699 case KEY_pmc_FLAG
|KEY_register_FLAG
:
2700 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2701 "P" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2702 strcpy(&dest
[size
], buf
);
2703 size
+= strlen(buf
);
2709 GETATTR_Key_next_key(interp
, k
, k
);
2717 dest
[size
- 1] = '[';
2718 Parrot_snprintf(interp
, buf
, sizeof (buf
), "I" INTVAL_FMT
, op
[j
]);
2719 strcpy(&dest
[size
], buf
);
2720 size
+= strlen(buf
);
2723 case PARROT_ARG_KIC
:
2724 dest
[size
- 1] = '[';
2725 Parrot_snprintf(interp
, buf
, sizeof (buf
), INTVAL_FMT
, op
[j
]);
2726 strcpy(&dest
[size
], buf
);
2727 size
+= strlen(buf
);
2731 Parrot_ex_throw_from_c_args(interp
, NULL
, 1, "Unknown opcode type");
2734 if (j
!= info
->op_count
- 1)
2738 /* Special decoding for the signature used in args/returns. Such ops have
2739 one fixed parameter (the signature vector), plus a varying number of
2740 registers/constants. For each arg/return, we show the register and its
2741 flags using PIR syntax. */
2742 if (*(op
) == PARROT_OP_set_args_pc
|| *(op
) == PARROT_OP_set_returns_pc
)
2745 /* if it's a retrieving op, specialop = 2, so that later a :flat flag
2746 * can be changed into a :slurpy flag. See flag handling below.
2748 if (*(op
) == PARROT_OP_get_results_pc
|| *(op
) == PARROT_OP_get_params_pc
)
2751 if (specialop
> 0) {
2753 PMC
* const sig
= interp
->code
->const_table
->constants
[op
[1]]->u
.key
;
2754 const int n_values
= VTABLE_elements(interp
, sig
);
2755 /* The flag_names strings come from Call_bits_enum_t (with which it
2756 should probably be colocated); they name the bits from LSB to MSB.
2757 The two least significant bits are not flags; they are the register
2758 type, which is decoded elsewhere. We also want to show unused bits,
2759 which could indicate problems.
2761 PARROT_OBSERVER
const char * const flag_names
[] = {
2767 " :flat", /* should be :slurpy for args */
2776 /* Register decoding. It would be good to abstract this, too. */
2777 PARROT_OBSERVER
static const char regs
[] = "ISPN";
2779 for (j
= 0; j
< n_values
; j
++) {
2781 const int sig_value
= VTABLE_get_integer_keyed_int(interp
, sig
, j
);
2783 /* Print the register name, e.g. P37. */
2786 buf
[idx
++] = regs
[sig_value
& PARROT_ARG_TYPE_MASK
];
2787 Parrot_snprintf(interp
, &buf
[idx
], sizeof (buf
)-idx
,
2788 INTVAL_FMT
, op
[j
+2]);
2791 /* Add flags, if we have any. */
2794 int flags
= sig_value
;
2796 /* End when we run out of flags, off the end of flag_names, or
2797 * get too close to the end of buf.
2798 * 100 is just an estimate of all buf lengths added together.
2800 while (flags
&& idx
< sizeof (buf
) - 100) {
2801 const char * const flag_string
2802 = (specialop
== 2 && STREQ(flag_names
[flag_idx
], " :flat"))
2804 : flag_names
[flag_idx
];
2808 if (flags
& 1 && *flag_string
) {
2809 const size_t n
= strlen(flag_string
);
2810 strcpy(&buf
[idx
], flag_string
);
2818 /* Add it to dest. */
2820 strcpy(&dest
[size
], buf
);
2821 size
+= strlen(buf
);
2831 =item C<void PDB_disassemble(PARROT_INTERP, const char *command)>
2833 Disassemble the bytecode.
2840 PDB_disassemble(PARROT_INTERP
, SHIM(const char *command
))
2842 ASSERT_ARGS(PDB_disassemble
)
2843 PDB_t
* const pdb
= interp
->pdb
;
2844 opcode_t
* pc
= interp
->code
->base
.data
;
2847 PDB_line_t
*pline
, *newline
;
2851 const unsigned int default_size
= 32768;
2852 size_t space
; /* How much space do we have? */
2853 size_t size
, alloced
, n
;
2855 TRACEDEB_MSG("PDB_disassemble");
2857 pfile
= mem_allocate_zeroed_typed(PDB_file_t
);
2858 pline
= mem_allocate_zeroed_typed(PDB_line_t
);
2860 /* If we already got a source, free it */
2862 PDB_free_file(interp
, pdb
->file
);
2866 pfile
->line
= pline
;
2868 pfile
->source
= (char *)mem_sys_allocate(default_size
);
2870 alloced
= space
= default_size
;
2871 code_end
= pc
+ interp
->code
->base
.size
;
2873 while (pc
!= code_end
) {
2875 if (space
< default_size
) {
2876 alloced
+= default_size
;
2877 space
+= default_size
;
2878 pfile
->source
= (char *)mem_sys_realloc(pfile
->source
, alloced
);
2881 size
= PDB_disassemble_op(interp
, pfile
->source
+ pfile
->size
,
2882 space
, &interp
->op_info_table
[*pc
], pc
, pfile
, NULL
, 1);
2884 pfile
->size
+= size
;
2885 pfile
->source
[pfile
->size
- 1] = '\n';
2887 /* Store the opcode of this line */
2889 n
= interp
->op_info_table
[*pc
].op_count
;
2891 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
2894 /* Prepare for next line */
2895 newline
= mem_allocate_typed(PDB_line_t
);
2896 newline
->label
= NULL
;
2897 newline
->next
= NULL
;
2898 newline
->number
= pline
->number
+ 1;
2899 pline
->next
= newline
;
2901 pline
->source_offset
= pfile
->size
;
2904 /* Add labels to the lines they belong to */
2905 label
= pfile
->label
;
2908 /* Get the line to apply the label */
2909 pline
= pfile
->line
;
2911 while (pline
&& pline
->opcode
!= label
->opcode
)
2912 pline
= pline
->next
;
2915 Parrot_io_eprintf(pdb
->debugger
,
2916 "Label number %li out of bounds.\n", label
->number
);
2918 PDB_free_file(interp
, pfile
);
2922 pline
->label
= label
;
2924 label
= label
->next
;
2927 pdb
->state
|= PDB_SRC_LOADED
;
2933 =item C<long PDB_add_label(PDB_file_t *file, const opcode_t *cur_opcode,
2936 Add a label to the label list.
2943 PDB_add_label(ARGMOD(PDB_file_t
*file
), ARGIN(const opcode_t
*cur_opcode
),
2946 ASSERT_ARGS(PDB_add_label
)
2948 PDB_label_t
*label
= file
->label
;
2950 /* See if there is already a label at this line */
2952 if (label
->opcode
== cur_opcode
+ offset
)
2953 return label
->number
;
2954 label
= label
->next
;
2957 /* Allocate a new label */
2958 label
= file
->label
;
2959 _new
= mem_allocate_typed(PDB_label_t
);
2960 _new
->opcode
= cur_opcode
+ offset
;
2965 label
= label
->next
;
2967 _new
->number
= label
->number
+ 1;
2975 return _new
->number
;
2980 =item C<void PDB_free_file(PARROT_INTERP, PDB_file_t *file)>
2982 Frees any allocated source files.
2989 PDB_free_file(SHIM_INTERP
, ARGIN_NULLOK(PDB_file_t
*file
))
2991 ASSERT_ARGS(PDB_free_file
)
2993 /* Free all of the allocated line structures */
2994 PDB_line_t
*line
= file
->line
;
2999 PDB_line_t
* const nline
= line
->next
;
3004 /* Free all of the allocated label structures */
3005 label
= file
->label
;
3008 PDB_label_t
* const nlabel
= label
->next
;
3010 mem_sys_free(label
);
3014 /* Free the remaining allocated portions of the file structure */
3015 if (file
->sourcefilename
)
3016 mem_sys_free(file
->sourcefilename
);
3019 mem_sys_free(file
->source
);
3029 =item C<void PDB_load_source(PARROT_INTERP, const char *command)>
3031 Load a source code file.
3039 PDB_load_source(PARROT_INTERP
, ARGIN(const char *command
))
3041 ASSERT_ARGS(PDB_load_source
)
3043 char f
[DEBUG_CMD_BUFFER_LENGTH
+ 1];
3047 PDB_t
* const pdb
= interp
->pdb
;
3048 opcode_t
*pc
= interp
->code
->base
.data
;
3050 unsigned long size
= 0;
3052 TRACEDEB_MSG("PDB_load_source");
3054 /* If there was a file already loaded or the bytecode was
3055 disassembled, free it */
3057 PDB_free_file(interp
->pdb
->debugee
, interp
->pdb
->debugee
->pdb
->file
);
3058 interp
->pdb
->debugee
->pdb
->file
= NULL
;
3061 /* Get the name of the file */
3062 for (j
= 0; command
[j
] == ' '; ++j
)
3064 for (i
= 0; command
[j
]; i
++, j
++)
3070 file
= fopen(f
, "r");
3072 /* abort if fopen failed */
3074 Parrot_io_eprintf(pdb
->debugger
, "Unable to load '%s'\n", f
);
3078 pfile
= mem_allocate_zeroed_typed(PDB_file_t
);
3079 pline
= mem_allocate_zeroed_typed(PDB_line_t
);
3081 pfile
->source
= (char *)mem_sys_allocate(1024);
3082 pfile
->line
= pline
;
3085 PARROT_ASSERT(interp
->op_info_table
);
3088 while ((c
= fgetc(file
)) != EOF
) {
3090 if (++size
== 1024) {
3091 pfile
->source
= (char *)mem_sys_realloc(pfile
->source
,
3092 (size_t)pfile
->size
+ 1024);
3095 pfile
->source
[pfile
->size
] = (char)c
;
3100 /* If the line has an opcode move to the next one,
3101 otherwise leave it with NULL to skip it. */
3102 PDB_line_t
*newline
= mem_allocate_zeroed_typed(PDB_line_t
);
3104 if (PDB_hasinstruction(pfile
->source
+ pline
->source_offset
)) {
3105 size_t n
= interp
->op_info_table
[*pc
].op_count
;
3107 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
3110 /* don't walk off the end of the program into neverland */
3111 if (pc
>= interp
->code
->base
.data
+ interp
->code
->base
.size
)
3115 newline
->number
= pline
->number
+ 1;
3116 pline
->next
= newline
;
3118 pline
->source_offset
= pfile
->size
;
3119 pline
->opcode
= NULL
;
3120 pline
->label
= NULL
;
3126 pdb
->state
|= PDB_SRC_LOADED
;
3129 TRACEDEB_MSG("PDB_load_source finished");
3134 =item C<char PDB_hasinstruction(const char *c)>
3136 Return true if the line has an instruction.
3142 PARROT_WARN_UNUSED_RESULT
3143 PARROT_PURE_FUNCTION
3145 PDB_hasinstruction(ARGIN(const char *c
))
3147 ASSERT_ARGS(PDB_hasinstruction
)
3150 /* as long as c is not NULL, we're not looking at a comment (#...) or a '\n'... */
3151 while (*c
&& *c
!= '#' && *c
!= '\n') {
3152 /* ... and c is alphanumeric or a quoted string then the line contains
3153 * an instruction. */
3154 if (isalnum((unsigned char) *c
) || *c
== '"') {
3157 else if (*c
== ':') {
3158 /* probably a label */
3170 =item C<static void no_such_register(PARROT_INTERP, char register_type, UINTVAL
3173 Auxiliar error message function.
3180 no_such_register(PARROT_INTERP
, char register_type
, UINTVAL register_num
)
3182 ASSERT_ARGS(no_such_register
)
3184 Parrot_io_eprintf(interp
, "%c%u = no such register\n",
3185 register_type
, register_num
);
3190 =item C<void PDB_assign(PARROT_INTERP, const char *command)>
3192 Assign to registers.
3199 PDB_assign(PARROT_INTERP
, ARGIN(const char *command
))
3201 ASSERT_ARGS(PDB_assign
)
3202 UINTVAL register_num
;
3205 PDB_t
*pdb
= interp
->pdb
;
3206 Interp
*debugger
= pdb
? pdb
->debugger
: interp
;
3207 Interp
*debugee
= pdb
? pdb
->debugee
: interp
;
3209 /* smallest valid commad length is 4, i.e. "I0 1" */
3210 if (strlen(command
) < 4) {
3211 Parrot_io_eprintf(debugger
, "Must give a register number and value to assign\n");
3214 reg_type_id
= (unsigned char) toupper((unsigned char) command
[0]);
3216 register_num
= get_ulong(&command
, 0);
3218 switch (reg_type_id
) {
3220 reg_type
= REGNO_INT
;
3223 reg_type
= REGNO_NUM
;
3226 reg_type
= REGNO_STR
;
3229 reg_type
= REGNO_PMC
;
3230 Parrot_io_eprintf(debugger
, "Assigning to PMCs is not currently supported\n");
3233 Parrot_io_eprintf(debugger
, "Invalid register type %c\n", reg_type_id
);
3236 if (register_num
>= Parrot_pcc_get_regs_used(debugee
,
3237 CURRENT_CONTEXT(debugee
), reg_type
)) {
3238 no_such_register(debugger
, reg_type_id
, register_num
);
3243 IREG(register_num
) = get_ulong(&command
, 0);
3246 NREG(register_num
) = atof(command
);
3249 SREG(register_num
) = Parrot_str_new(debugee
, command
, strlen(command
));
3251 default: ; /* Must never come here */
3253 Parrot_io_eprintf(debugger
, "\n %c%u = ", reg_type_id
, register_num
);
3254 Parrot_io_eprintf(debugger
, "%Ss\n", GDB_print_reg(debugee
, reg_type
, register_num
));
3259 =item C<void PDB_list(PARROT_INTERP, const char *command)>
3261 Show lines from the source code file.
3268 PDB_list(PARROT_INTERP
, ARGIN(const char *command
))
3270 ASSERT_ARGS(PDB_list
)
3272 unsigned long line_number
;
3275 PDB_t
*pdb
= interp
->pdb
;
3276 unsigned long n
= 10;
3278 TRACEDEB_MSG("PDB_list");
3279 if (!pdb
->file
|| !pdb
->file
->line
) {
3280 Parrot_io_eprintf(pdb
->debugger
, "No source file loaded\n");
3284 /* set the list line if provided */
3285 line_number
= get_ulong(&command
, 0);
3286 pdb
->file
->list_line
= (unsigned long) line_number
;
3288 /* set the number of lines to print */
3289 n
= get_ulong(&command
, 10);
3291 /* if n is zero, we simply return, as we don't have to print anything */
3295 line
= pdb
->file
->line
;
3297 for (i
= 0; i
< pdb
->file
->list_line
&& line
->next
; i
++)
3301 while (line
->next
) {
3302 Parrot_io_eprintf(pdb
->debugger
, "%li ", pdb
->file
->list_line
+ i
);
3303 /* If it has a label print it */
3305 Parrot_io_eprintf(pdb
->debugger
, "L%li:\t", line
->label
->number
);
3307 c
= pdb
->file
->source
+ line
->source_offset
;
3310 Parrot_io_eprintf(pdb
->debugger
, "%c", *(c
++));
3312 Parrot_io_eprintf(pdb
->debugger
, "\n");
3321 pdb
->file
->list_line
= 0;
3323 pdb
->file
->list_line
+= n
;
3328 =item C<void PDB_eval(PARROT_INTERP, const char *command)>
3330 C<eval>s an instruction.
3337 PDB_eval(PARROT_INTERP
, ARGIN(const char *command
))
3339 ASSERT_ARGS(PDB_eval
)
3341 PDB_t
*pdb
= interp
->pdb
;
3342 Interp
*warninterp
= (interp
->pdb
&& interp
->pdb
->debugger
) ?
3343 interp
->pdb
->debugger
: interp
;
3344 TRACEDEB_MSG("PDB_eval");
3346 Parrot_io_eprintf(warninterp
, "The eval command is currently unimplemeneted\n");
3351 =item C<opcode_t * PDB_compile(PARROT_INTERP, const char *command)>
3353 Compiles instructions with the PASM compiler.
3355 Appends an C<end> op.
3357 This may be called from C<PDB_eval> above or from the compile opcode
3358 which generates a malloced string.
3364 PARROT_CAN_RETURN_NULL
3366 PDB_compile(PARROT_INTERP
, ARGIN(const char *command
))
3368 ASSERT_ARGS(PDB_compile
)
3371 Parrot_ex_throw_from_c_args(interp
, NULL
,
3372 EXCEPTION_UNIMPLEMENTED
,
3373 "PDB_compile ('PASM1' compiler) has been deprecated");
3378 =item C<void PDB_print(PARROT_INTERP, const char *command)>
3380 Print interp registers.
3387 PDB_print(PARROT_INTERP
, ARGIN(const char *command
))
3389 ASSERT_ARGS(PDB_print
)
3390 const STRING
*s
= GDB_P(interp
->pdb
->debugee
, command
);
3392 TRACEDEB_MSG("PDB_print");
3393 Parrot_io_eprintf(interp
, "%Ss\n", s
);
3399 =item C<void PDB_info(PARROT_INTERP)>
3401 Print the interpreter info.
3408 PDB_info(PARROT_INTERP
)
3410 ASSERT_ARGS(PDB_info
)
3412 /* If a debugger is created, use it for printing and use the
3413 * data in his debugee. Otherwise, use current interpreter
3415 Parrot_Interp itdeb
= interp
->pdb
? interp
->pdb
->debugger
: interp
;
3416 Parrot_Interp itp
= interp
->pdb
? interp
->pdb
->debugee
: interp
;
3418 Parrot_io_eprintf(itdeb
, "Total memory allocated = %ld\n",
3419 interpinfo(itp
, TOTAL_MEM_ALLOC
));
3420 Parrot_io_eprintf(itdeb
, "GC mark runs = %ld\n",
3421 interpinfo(itp
, GC_MARK_RUNS
));
3422 Parrot_io_eprintf(itdeb
, "Lazy gc mark runs = %ld\n",
3423 interpinfo(itp
, GC_LAZY_MARK_RUNS
));
3424 Parrot_io_eprintf(itdeb
, "GC collect runs = %ld\n",
3425 interpinfo(itp
, GC_COLLECT_RUNS
));
3426 Parrot_io_eprintf(itdeb
, "Collect memory = %ld\n",
3427 interpinfo(itp
, TOTAL_COPIED
));
3428 Parrot_io_eprintf(itdeb
, "Active PMCs = %ld\n",
3429 interpinfo(itp
, ACTIVE_PMCS
));
3430 Parrot_io_eprintf(itdeb
, "Extended PMCs = %ld\n",
3431 interpinfo(itp
, EXTENDED_PMCS
));
3432 Parrot_io_eprintf(itdeb
, "Timely GC PMCs = %ld\n",
3433 interpinfo(itp
, IMPATIENT_PMCS
));
3434 Parrot_io_eprintf(itdeb
, "Total PMCs = %ld\n",
3435 interpinfo(itp
, TOTAL_PMCS
));
3436 Parrot_io_eprintf(itdeb
, "Active buffers = %ld\n",
3437 interpinfo(itp
, ACTIVE_BUFFERS
));
3438 Parrot_io_eprintf(itdeb
, "Total buffers = %ld\n",
3439 interpinfo(itp
, TOTAL_BUFFERS
));
3440 Parrot_io_eprintf(itdeb
, "Header allocations since last collect = %ld\n",
3441 interpinfo(itp
, HEADER_ALLOCS_SINCE_COLLECT
));
3442 Parrot_io_eprintf(itdeb
, "Memory allocations since last collect = %ld\n",
3443 interpinfo(itp
, MEM_ALLOCS_SINCE_COLLECT
));
3448 =item C<void PDB_help(PARROT_INTERP, const char *command)>
3450 Print the help text. "Help" with no arguments prints a list of commands.
3451 "Help xxx" prints information on command xxx.
3458 PDB_help(PARROT_INTERP
, ARGIN(const char *command
))
3460 ASSERT_ARGS(PDB_help
)
3461 const DebuggerCmd
*cmd
;
3463 const char * cmdline
= command
;
3464 cmd
= get_cmd(& cmdline
);
3467 Parrot_io_eprintf(interp
->pdb
->debugger
, "%s\n", cmd
->help
);
3470 if (*cmdline
== '\0') {
3472 Parrot_io_eprintf(interp
->pdb
->debugger
, "List of commands:\n");
3473 for (i
= 0; i
< sizeof (DebCmdList
) / sizeof (DebuggerCmdList
); ++i
) {
3474 const DebuggerCmdList
*cmdlist
= DebCmdList
+ i
;
3475 Parrot_io_eprintf(interp
->pdb
->debugger
,
3476 " %-12s-- %s\n", cmdlist
->name
, cmdlist
->cmd
->shorthelp
);
3478 Parrot_io_eprintf(interp
->pdb
->debugger
, "\n"
3479 "Type \"help\" followed by a command name for full documentation.\n\n");
3483 Parrot_io_eprintf(interp
->pdb
->debugger
, "Unknown command: %s\n", command
);
3490 =item C<void PDB_backtrace(PARROT_INTERP)>
3492 Prints a backtrace of the interp's call chain.
3499 PDB_backtrace(PARROT_INTERP
)
3501 ASSERT_ARGS(PDB_backtrace
)
3505 int limit_count
= 0;
3507 /* information about the current sub */
3508 PMC
*sub
= interpinfo_p(interp
, CURRENT_SUB
);
3509 PMC
*ctx
= CURRENT_CONTEXT(interp
);
3511 if (!PMC_IS_NULL(sub
)) {
3512 str
= Parrot_Context_infostr(interp
, ctx
);
3514 Parrot_io_eprintf(interp
, "%Ss", str
);
3515 if (interp
->code
->annotations
) {
3516 PMC
*annot
= PackFile_Annotations_lookup(interp
, interp
->code
->annotations
,
3517 Parrot_pcc_get_pc(interp
, ctx
) - interp
->code
->base
.data
+ 1, NULL
);
3518 if (!PMC_IS_NULL(annot
)) {
3519 PMC
*pfile
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3520 Parrot_str_new_constant(interp
, "file"));
3521 PMC
*pline
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3522 Parrot_str_new_constant(interp
, "line"));
3523 if ((!PMC_IS_NULL(pfile
)) && (!PMC_IS_NULL(pline
))) {
3524 STRING
*file
= VTABLE_get_string(interp
, pfile
);
3525 INTVAL line
= VTABLE_get_integer(interp
, pline
);
3526 Parrot_io_eprintf(interp
, " (%Ss:%li)", file
, (long)line
);
3530 Parrot_io_eprintf(interp
, "\n");
3534 /* backtrace: follow the continuation chain */
3536 Parrot_Continuation_attributes
*sub_cont
;
3538 /* Limit the levels dumped, no segfault on infinite recursion */
3539 if (++limit_count
> RECURSION_LIMIT
)
3542 sub
= Parrot_pcc_get_continuation(interp
, ctx
);
3544 if (PMC_IS_NULL(sub
))
3548 sub_cont
= PARROT_CONTINUATION(sub
);
3554 str
= Parrot_Context_infostr(interp
, Parrot_pcc_get_caller_ctx(interp
, ctx
));
3561 /* recursion detection */
3562 if (ctx
== sub_cont
->to_ctx
) {
3565 else if (!PMC_IS_NULL(old
) && PMC_cont(old
) &&
3566 Parrot_pcc_get_pc(interp
, PMC_cont(old
)->to_ctx
) ==
3567 Parrot_pcc_get_pc(interp
, PMC_cont(sub
)->to_ctx
) &&
3568 Parrot_pcc_get_sub(interp
, PMC_cont(old
)->to_ctx
) ==
3569 Parrot_pcc_get_sub(interp
, PMC_cont(sub
)->to_ctx
)) {
3572 else if (rec_level
!= 0) {
3573 Parrot_io_eprintf(interp
, "... call repeated %d times\n", rec_level
);
3577 /* print the context description */
3578 if (rec_level
== 0) {
3579 PackFile_ByteCode
*seg
= sub_cont
->seg
;
3580 Parrot_io_eprintf(interp
, "%Ss", str
);
3581 if (seg
->annotations
) {
3582 PMC
*annot
= PackFile_Annotations_lookup(interp
, seg
->annotations
,
3583 Parrot_pcc_get_pc(interp
, sub_cont
->to_ctx
) - seg
->base
.data
,
3586 if (!PMC_IS_NULL(annot
)) {
3587 PMC
*pfile
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3588 Parrot_str_new_constant(interp
, "file"));
3589 PMC
*pline
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3590 Parrot_str_new_constant(interp
, "line"));
3591 if ((!PMC_IS_NULL(pfile
)) && (!PMC_IS_NULL(pline
))) {
3592 STRING
*file
= VTABLE_get_string(interp
, pfile
);
3593 INTVAL line
= VTABLE_get_integer(interp
, pline
);
3594 Parrot_io_eprintf(interp
, " (%Ss:%li)", file
, (long)line
);
3598 Parrot_io_eprintf(interp
, "\n");
3601 /* get the next Continuation */
3602 ctx
= Parrot_pcc_get_caller_ctx(interp
, ctx
);
3610 Parrot_io_eprintf(interp
, "... call repeated %d times\n", rec_level
);
3616 * GDB_P gdb> pp $I0 print register I0 value
3618 * RT46139 more, more
3623 =item C<static STRING * GDB_print_reg(PARROT_INTERP, int t, int n)>
3625 Used by GDB_P to convert register values for display. Takes register
3626 type and number as arguments.
3628 Returns a pointer to the start of the string, (except for PMCs, which
3629 print directly and return "").
3635 PARROT_WARN_UNUSED_RESULT
3636 PARROT_CANNOT_RETURN_NULL
3639 GDB_print_reg(PARROT_INTERP
, int t
, int n
)
3641 ASSERT_ARGS(GDB_print_reg
)
3644 if (n
>= 0 && (UINTVAL
)n
< Parrot_pcc_get_regs_used(interp
, CURRENT_CONTEXT(interp
), t
)) {
3647 return Parrot_str_from_int(interp
, IREG(n
));
3649 return Parrot_str_from_num(interp
, NREG(n
));
3651 /* This hack is needed because we occasionally are told
3652 that we have string registers when we actually don't */
3653 string
= (char *) SREG(n
);
3656 return Parrot_str_new(interp
, "", 0);
3660 /* prints directly */
3661 trace_pmc_dump(interp
, PREG(n
));
3662 return Parrot_str_new(interp
, "", 0);
3667 return Parrot_str_new(interp
, "no such register", 0);
3672 =item C<static STRING * GDB_P(PARROT_INTERP, const char *s)>
3674 Used by PDB_print to print register values. Takes a pointer to the
3677 Returns "" or error message.
3683 PARROT_WARN_UNUSED_RESULT
3684 PARROT_CANNOT_RETURN_NULL
3687 GDB_P(PARROT_INTERP
, ARGIN(const char *s
))
3693 TRACEDEB_MSG("GDB_P");
3694 /* Skip leading whitespace. */
3695 while (isspace((unsigned char)*s
))
3698 reg_type
= (unsigned char) toupper((unsigned char)*s
);
3701 case 'I': t
= REGNO_INT
; break;
3702 case 'N': t
= REGNO_NUM
; break;
3703 case 'S': t
= REGNO_STR
; break;
3704 case 'P': t
= REGNO_PMC
; break;
3705 default: return Parrot_str_new(interp
, "Need a register.", 0);
3708 /* Print all registers of this type. */
3709 const int max_reg
= Parrot_pcc_get_regs_used(interp
, CURRENT_CONTEXT(interp
), t
);
3712 for (n
= 0; n
< max_reg
; n
++) {
3713 /* this must be done in two chunks because PMC's print directly. */
3714 Parrot_io_eprintf(interp
, "\n %c%d = ", reg_type
, n
);
3715 Parrot_io_eprintf(interp
, "%Ss", GDB_print_reg(interp
, t
, n
));
3717 return Parrot_str_new(interp
, "", 0);
3719 else if (s
[1] && isdigit((unsigned char)s
[1])) {
3720 const int n
= atoi(s
+ 1);
3721 return GDB_print_reg(interp
, t
, n
);
3724 return Parrot_str_new(interp
, "no such register", 0);
3734 F<include/parrot/debugger.h>, F<src/parrot_debugger.c> and F<ops/debug.ops>.
3740 =item Initial version by Daniel Grunblatt on 2002.5.19.
3742 =item Start of rewrite - leo 2005.02.16
3744 The debugger now uses its own interpreter. User code is run in
3745 Interp *debugee. We have:
3747 debug_interp->pdb->debugee->debugger
3750 +------------- := -----------+
3752 Debug commands are mostly run inside the C<debugger>. User code
3753 runs of course in the C<debugee>.
3764 * c-file-style: "parrot"
3766 * vim: expandtab shiftwidth=4: