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
);
1166 /* RT #42378 this is not ok */
1167 /* exit(EXIT_SUCCESS); */
1170 interp
->pdb
->cur_opcode
= (opcode_t
*)cur_opcode
+ 1;
1171 /*PDB_set_break(interp, NULL);*/
1173 TRACEDEB_MSG("Parrot_debugger_break done");
1178 =item C<void PDB_get_command(PARROT_INTERP)>
1180 Get a command from the user input to execute.
1182 It saves the last command executed (in C<< pdb->last_command >>), so it
1183 first frees the old one and updates it with the current one.
1185 Also prints the next line to run if the program is still active.
1187 The user input can't be longer than DEBUG_CMD_BUFFER_LENGTH characters.
1189 The input is saved in C<< pdb->cur_command >>.
1196 PDB_get_command(PARROT_INTERP
)
1198 ASSERT_ARGS(PDB_get_command
)
1202 PDB_t
* const pdb
= interp
->pdb
;
1204 /***********************************
1209 ***********************************/
1211 /* flush the buffered data */
1214 TRACEDEB_MSG("PDB_get_command");
1216 PARROT_ASSERT(pdb
->last_command
);
1217 PARROT_ASSERT(pdb
->cur_command
);
1219 if (interp
->pdb
->script_file
) {
1220 FILE *fd
= interp
->pdb
->script_file
;
1221 char buf
[DEBUG_CMD_BUFFER_LENGTH
+1];
1225 if (fgets(buf
, DEBUG_CMD_BUFFER_LENGTH
, fd
) == NULL
) {
1226 close_script_file(interp
);
1232 fprintf(stderr
, "script (%lu): '%s'\n", pdb
->script_line
, buf
);
1236 ptr
= skip_whitespace(buf
);
1238 /* skip blank and commented lines */
1239 } while (*ptr
== '\0' || *ptr
== '#');
1241 if (pdb
->state
& PDB_ECHO
)
1242 Parrot_io_eprintf(pdb
->debugger
, "[%lu %s]\n", pdb
->script_line
, buf
);
1245 fprintf(stderr
, "(script) %s\n", buf
);
1248 strcpy(pdb
->cur_command
, buf
);
1252 /* update the last command */
1253 if (pdb
->cur_command
[0] != '\0')
1254 strcpy(pdb
->last_command
, pdb
->cur_command
);
1258 c
= pdb
->cur_command
;
1260 /*Parrot_io_eprintf(pdb->debugger, "\n(pdb) ");*/
1261 Parrot_io_eprintf(pdb
->debugger
, "\n");
1263 /* skip leading whitespace */
1267 } while (isspace((unsigned char)ch) && ch != '\n');
1270 Interp
* interpdeb
= interp
->pdb
->debugger
;
1271 STRING
* readline
= CONST_STRING(interpdeb
, "readline_interactive");
1272 STRING
* prompt
= CONST_STRING(interpdeb
, "(pdb) ");
1273 STRING
*s
= Parrot_str_new(interpdeb
, NULL
, 0);
1274 PMC
*tmp_stdin
= Parrot_io_stdhandle(interpdeb
, 0, NULL
);
1276 Parrot_pcc_invoke_method_from_c_args(interpdeb
,
1277 tmp_stdin
, readline
,
1278 "S->S", prompt
, & s
);
1280 char * aux
= Parrot_str_to_cstring(interpdeb
, s
);
1282 Parrot_str_free_cstring(aux
);
1287 /* generate string (no more than buffer length) */
1289 while (ch != EOF && ch != '\n' && (i < DEBUG_CMD_BUFFER_LENGTH)) {
1291 ch = fgetc(tmp_stdin);
1303 =item C<void PDB_script_file(PARROT_INTERP, const char *command)>
1305 Interprets the contents of a file as user input commands
1313 PDB_script_file(PARROT_INTERP
, ARGIN(const char *command
))
1315 ASSERT_ARGS(PDB_script_file
)
1318 TRACEDEB_MSG("PDB_script_file");
1320 /* If already executing a script, close it */
1321 close_script_file(interp
);
1323 TRACEDEB_MSG("Opening debugger script file");
1325 fd
= fopen(command
, "r");
1327 Parrot_io_eprintf(interp
->pdb
->debugger
,
1328 "Error reading script file %s.\n",
1332 interp
->pdb
->script_file
= fd
;
1333 interp
->pdb
->script_line
= 0;
1334 TRACEDEB_MSG("PDB_script_file finished");
1339 =item C<int PDB_run_command(PARROT_INTERP, const char *command)>
1343 Hash the command to make a simple switch calling the correct handler.
1349 PARROT_IGNORABLE_RESULT
1351 PDB_run_command(PARROT_INTERP
, ARGIN(const char *command
))
1353 ASSERT_ARGS(PDB_run_command
)
1354 PDB_t
* const pdb
= interp
->pdb
;
1355 const DebuggerCmd
*cmd
;
1357 /* keep a pointer to the command, in case we need to report an error */
1359 const char * cmdline
= command
;
1361 TRACEDEB_MSG("PDB_run_command");
1362 cmd
= get_cmd(& cmdline
);
1365 (* cmd
->func
)(pdb
, cmdline
);
1369 if (*cmdline
== '\0') {
1373 Parrot_io_eprintf(pdb
->debugger
,
1374 "Undefined command: \"%s\"", command
);
1375 if (pdb
->script_file
)
1376 Parrot_io_eprintf(pdb
->debugger
, " in line %lu", pdb
->script_line
);
1377 Parrot_io_eprintf(pdb
->debugger
, ". Try \"help\".");
1378 close_script_file(interp
);
1386 =item C<void PDB_next(PARROT_INTERP, const char *command)>
1388 Execute the next N operation(s).
1390 Inits the program if needed, runs the next N >= 1 operations and stops.
1397 PDB_next(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1399 ASSERT_ARGS(PDB_next
)
1400 PDB_t
* const pdb
= interp
->pdb
;
1403 TRACEDEB_MSG("PDB_next");
1405 /* Init the program if it's not running */
1406 if (!(pdb
->state
& PDB_RUNNING
))
1407 PDB_init(interp
, command
);
1409 /* Get the number of operations to execute if any */
1410 pdb
->tracing
= get_ulong(& command
, 1);
1412 /* Erase the stopped flag */
1413 pdb
->state
&= ~PDB_STOPPED
;
1415 /* Testing use of the debugger runloop */
1419 for (; n
&& pdb
->cur_opcode
; n
--)
1420 DO_OP(pdb
->cur_opcode
, pdb
->debugee
);
1422 /* Set the stopped flag */
1423 pdb
->state
|= PDB_STOPPED
;
1425 /* If program ended */
1428 * RT #46119 this doesn't handle resume opcodes
1430 if (!pdb
->cur_opcode
)
1431 (void)PDB_program_end(interp
);
1434 debugee
= pdb
->debugee
;
1436 new_runloop_jump_point(debugee
);
1437 if (setjmp(debugee
->current_runloop
->resume
)) {
1438 Parrot_io_eprintf(pdb
->debugger
, "Unhandled exception while tracing\n");
1439 pdb
->state
|= PDB_STOPPED
;
1443 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1445 TRACEDEB_MSG("PDB_next finished");
1450 =item C<void PDB_trace(PARROT_INTERP, const char *command)>
1452 Execute the next N operations; if no number is specified, it defaults to 1.
1459 PDB_trace(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1461 ASSERT_ARGS(PDB_trace
)
1462 PDB_t
* const pdb
= interp
->pdb
;
1465 TRACEDEB_MSG("PDB_trace");
1467 /* if debugger is not running yet, initialize */
1469 if (!(pdb->state & PDB_RUNNING))
1470 PDB_init(interp, command);
1473 /* get the number of ops to run, if specified */
1474 pdb
->tracing
= get_ulong(& command
, 1);
1476 /* clear the PDB_STOPPED flag, we'll be running n ops now */
1477 pdb
->state
&= ~PDB_STOPPED
;
1478 debugee
= pdb
->debugee
;
1481 new_runloop_jump_point(debugee
);
1482 if (setjmp(debugee
->current_runloop
->resume
)) {
1483 Parrot_io_eprintf(pdb
->debugger
, "Unhandled exception while tracing\n");
1484 pdb
->state
|= PDB_STOPPED
;
1488 pdb
->state
|= PDB_TRACING
;
1489 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1491 /* Clear the following when done some testing */
1493 /* we just stopped */
1494 pdb
->state
|= PDB_STOPPED
;
1496 /* If program ended */
1497 if (!pdb
->cur_opcode
)
1498 (void)PDB_program_end(interp
);
1499 pdb
->state
|= PDB_RUNNING
;
1500 pdb
->state
&= ~PDB_STOPPED
;
1502 TRACEDEB_MSG("PDB_trace finished");
1507 =item C<static unsigned short condition_regtype(const char *cmd)>
1513 static unsigned short
1514 condition_regtype(ARGIN(const char *cmd
))
1516 ASSERT_ARGS(condition_regtype
)
1520 return PDB_cond_int
;
1523 return PDB_cond_num
;
1526 return PDB_cond_str
;
1529 return PDB_cond_pmc
;
1537 =item C<PDB_condition_t * PDB_cond(PARROT_INTERP, const char *command)>
1539 Analyzes a condition from the user input.
1545 PARROT_CAN_RETURN_NULL
1547 PDB_cond(PARROT_INTERP
, ARGIN(const char *command
))
1549 ASSERT_ARGS(PDB_cond
)
1550 PDB_condition_t
*condition
;
1552 char str
[DEBUG_CMD_BUFFER_LENGTH
+ 1];
1553 unsigned short cond_argleft
;
1554 unsigned short cond_type
;
1555 unsigned char regleft
;
1558 TRACEDEB_MSG("PDB_cond");
1560 /* Return if no more arguments */
1561 if (!(command
&& *command
)) {
1562 Parrot_io_eprintf(interp
->pdb
->debugger
, "No condition specified\n");
1566 command
= skip_whitespace(command
);
1568 fprintf(stderr
, "PDB_trace: '%s'\n", command
);
1571 cond_argleft
= condition_regtype(command
);
1573 /* get the register number */
1575 regleft
= (unsigned char)get_uint(&command
, 0);
1576 if (auxcmd
== command
) {
1577 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid register\n");
1581 /* Now the condition */
1582 command
= skip_whitespace(command
);
1585 if (*(command
+ 1) == '=')
1586 cond_type
= PDB_cond_ge
;
1588 cond_type
= PDB_cond_gt
;
1591 if (*(command
+ 1) == '=')
1592 cond_type
= PDB_cond_le
;
1594 cond_type
= PDB_cond_lt
;
1597 if (*(command
+ 1) == '=')
1598 cond_type
= PDB_cond_eq
;
1603 if (*(command
+ 1) == '=')
1604 cond_type
= PDB_cond_ne
;
1609 if (cond_argleft
!= PDB_cond_str
&& cond_argleft
!= PDB_cond_pmc
) {
1610 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid null condition\n");
1613 cond_type
= PDB_cond_notnull
;
1616 INV_COND
: Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid condition\n");
1620 /* if there's an '=', skip it */
1621 if (*(command
+ 1) == '=')
1626 command
= skip_whitespace(command
);
1628 /* return if no notnull condition and no more arguments */
1629 if (!(command
&& *command
) && (cond_type
!= PDB_cond_notnull
)) {
1630 Parrot_io_eprintf(interp
->pdb
->debugger
, "Can't compare a register with nothing\n");
1634 /* Allocate new condition */
1635 condition
= mem_allocate_zeroed_typed(PDB_condition_t
);
1637 condition
->type
= cond_argleft
| cond_type
;
1639 if (cond_type
!= PDB_cond_notnull
) {
1641 if (isalpha((unsigned char)*command
)) {
1642 /* It's a register - we first check that it's the correct type */
1644 unsigned short cond_argright
= condition_regtype(command
);
1646 if (cond_argright
!= cond_argleft
) {
1647 Parrot_io_eprintf(interp
->pdb
->debugger
, "Register types don't agree\n");
1648 mem_sys_free(condition
);
1652 /* Now we check and store the register number */
1654 reg_number
= (int)get_uint(&command
, 0);
1655 if (auxcmd
== command
) {
1656 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid register\n");
1657 mem_sys_free(condition
);
1661 if (reg_number
< 0) {
1662 Parrot_io_eprintf(interp
->pdb
->debugger
, "Out-of-bounds register\n");
1663 mem_sys_free(condition
);
1667 condition
->value
= mem_allocate_typed(int);
1668 *(int *)condition
->value
= reg_number
;
1670 /* If the first argument was an integer */
1671 else if (condition
->type
& PDB_cond_int
) {
1672 /* This must be either an integer constant or register */
1673 condition
->value
= mem_allocate_typed(INTVAL
);
1674 *(INTVAL
*)condition
->value
= (INTVAL
)atoi(command
);
1675 condition
->type
|= PDB_cond_const
;
1677 else if (condition
->type
& PDB_cond_num
) {
1678 condition
->value
= mem_allocate_typed(FLOATVAL
);
1679 *(FLOATVAL
*)condition
->value
= (FLOATVAL
)atof(command
);
1680 condition
->type
|= PDB_cond_const
;
1682 else if (condition
->type
& PDB_cond_str
) {
1683 for (i
= 1; ((command
[i
] != '"') && (i
< DEBUG_CMD_BUFFER_LENGTH
)); i
++)
1684 str
[i
- 1] = command
[i
];
1687 fprintf(stderr
, "PDB_break: '%s'\n", str
);
1689 condition
->value
= string_make(interp
, str
, (UINTVAL
)(i
- 1),
1692 condition
->type
|= PDB_cond_const
;
1694 else if (condition
->type
& PDB_cond_pmc
) {
1695 /* TT #1259: Need to figure out what to do in this case.
1696 * For the time being, we just bail. */
1697 Parrot_io_eprintf(interp
->pdb
->debugger
, "Can't compare PMC with constant\n");
1698 mem_sys_free(condition
);
1709 =item C<void PDB_watchpoint(PARROT_INTERP, const char *command)>
1718 PDB_watchpoint(PARROT_INTERP
, ARGIN(const char *command
))
1720 ASSERT_ARGS(PDB_watchpoint
)
1721 PDB_t
* const pdb
= interp
->pdb
;
1722 PDB_condition_t
* const condition
= PDB_cond(interp
, command
);
1727 /* Add it to the head of the list */
1728 if (pdb
->watchpoint
)
1729 condition
->next
= pdb
->watchpoint
;
1730 pdb
->watchpoint
= condition
;
1731 fprintf(stderr
, "Adding watchpoint\n");
1736 =item C<void PDB_set_break(PARROT_INTERP, const char *command)>
1738 Set a break point, the source code file must be loaded.
1745 PDB_set_break(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1747 ASSERT_ARGS(PDB_set_break
)
1748 PDB_t
* const pdb
= interp
->pdb
;
1749 PDB_breakpoint_t
*newbreak
;
1750 PDB_breakpoint_t
**lbreak
;
1751 PDB_line_t
*line
= NULL
;
1753 opcode_t
*breakpos
= NULL
;
1755 unsigned long ln
= get_ulong(& command
, 0);
1757 TRACEDEB_MSG("PDB_set_break");
1759 /* If there is a source file use line number, else opcode position */
1763 TRACEDEB_MSG("PDB_set_break file");
1765 if (!pdb
->file
->size
) {
1766 Parrot_io_eprintf(pdb
->debugger
,
1767 "Can't set a breakpoint in empty file\n");
1771 /* If no line number was specified, set it at the current line */
1775 /* Move to the line where we will set the break point */
1776 line
= pdb
->file
->line
;
1778 for (i
= 1; ((i
< ln
) && (line
->next
)); i
++)
1781 /* Abort if the line number provided doesn't exist */
1782 if (line
== NULL
|| !line
->next
) {
1783 Parrot_io_eprintf(pdb
->debugger
,
1784 "Can't set a breakpoint at line number %li\n", ln
);
1789 /* Get the line to set it */
1790 line
= pdb
->file
->line
;
1792 TRACEDEB_MSG("PDB_set_break reading ops");
1793 while (line
->opcode
!= pdb
->cur_opcode
) {
1796 Parrot_io_eprintf(pdb
->debugger
,
1797 "No current line found and no line number specified\n");
1802 /* Skip lines that are not related to an opcode */
1803 while (line
&& !line
->opcode
)
1805 /* Abort if the line number provided doesn't exist */
1807 Parrot_io_eprintf(pdb
->debugger
,
1808 "Can't set a breakpoint at line number %li\n", ln
);
1812 breakpos
= line
->opcode
;
1815 TRACEDEB_MSG("PDB_set_break no file");
1816 breakpos
= interp
->code
->base
.data
+ ln
;
1819 TRACEDEB_MSG("PDB_set_break allocate breakpoint");
1820 /* Allocate the new break point */
1821 newbreak
= mem_allocate_zeroed_typed(PDB_breakpoint_t
);
1824 /*command = skip_command(command);*/
1827 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
1828 "NULL command passed to PDB_set_break");
1831 /* if there is another argument to break, besides the line number,
1832 * it should be an 'if', so we call another handler. */
1833 if (command
&& *command
) {
1834 command
= skip_whitespace(command
);
1835 while (! isspace((unsigned char)*command
))
1837 command
= skip_whitespace(command
);
1838 newbreak
->condition
= PDB_cond(interp
, command
);
1841 /* Set the address where to stop */
1842 newbreak
->pc
= breakpos
;
1844 /* No next breakpoint */
1845 newbreak
->next
= NULL
;
1847 /* Don't skip (at least initially) */
1850 /* Add the breakpoint to the end of the list */
1852 lbreak
= & pdb
->breakpoint
;
1854 bp_id
= (*lbreak
)->id
+ 1;
1855 lbreak
= & (*lbreak
)->next
;
1857 newbreak
->prev
= *lbreak
;
1859 newbreak
->id
= bp_id
;
1861 /* Show breakpoint position */
1863 Parrot_io_eprintf(pdb
->debugger
, "Breakpoint %li at", newbreak
->id
);
1865 Parrot_io_eprintf(pdb
->debugger
, " line %li", line
->number
);
1866 Parrot_io_eprintf(pdb
->debugger
, " pos %li\n", newbreak
->pc
- interp
->code
->base
.data
);
1871 =item C<static void list_breakpoints(PDB_t *pdb)>
1878 list_breakpoints(ARGIN(PDB_t
*pdb
))
1880 ASSERT_ARGS(list_breakpoints
)
1882 PDB_breakpoint_t
**lbreak
;
1883 for (lbreak
= & pdb
->breakpoint
; *lbreak
; lbreak
= & (*lbreak
)->next
) {
1884 PDB_breakpoint_t
*br
= *lbreak
;
1885 Parrot_io_eprintf(pdb
->debugger
, "Breakpoint %li at", br
->id
);
1886 Parrot_io_eprintf(pdb
->debugger
, " pos %li", br
->pc
- pdb
->debugee
->code
->base
.data
);
1888 Parrot_io_eprintf(pdb
->debugger
, " (disabled)");
1889 Parrot_io_eprintf(pdb
->debugger
, "\n");
1895 =item C<void PDB_init(PARROT_INTERP, const char *command)>
1904 PDB_init(PARROT_INTERP
, SHIM(const char *command
))
1906 ASSERT_ARGS(PDB_init
)
1907 PDB_t
* const pdb
= interp
->pdb
;
1909 /* Restart if we are already running */
1910 if (pdb
->state
& PDB_RUNNING
)
1911 Parrot_io_eprintf(pdb
->debugger
, "Restarting\n");
1913 /* Add the RUNNING state */
1914 pdb
->state
|= PDB_RUNNING
;
1919 =item C<void PDB_continue(PARROT_INTERP, const char *command)>
1921 Continue running the program. If a number is specified, skip that many
1929 PDB_continue(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1931 ASSERT_ARGS(PDB_continue
)
1932 PDB_t
* const pdb
= interp
->pdb
;
1933 unsigned long ln
= 0;
1935 TRACEDEB_MSG("PDB_continue");
1937 /* Skip any breakpoint? */
1939 ln
= get_ulong(& command
, 0);
1942 if (!pdb
->breakpoint
) {
1943 Parrot_io_eprintf(pdb
->debugger
, "No breakpoints to skip\n");
1947 PDB_skip_breakpoint(interp
, ln
);
1950 /* Run while no break point is reached */
1952 while (!PDB_break(interp))
1953 DO_OP(pdb->cur_opcode, pdb->debugee);
1958 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1960 new_internal_exception(pdb
->debugee
);
1961 if (setjmp(pdb
->debugee
->exceptions
->destination
)) {
1962 Parrot_io_eprintf(pdb
->debugee
, "Unhandled exception while debugging: %Ss\n",
1963 pdb
->debugee
->exceptions
->msg
);
1964 pdb
->state
|= PDB_STOPPED
;
1967 runops_int(pdb
->debugee
, pdb
->debugee
->code
->base
.data
- pdb
->cur_opcode
);
1968 if (!pdb
->cur_opcode
)
1969 (void)PDB_program_end(interp
);
1971 pdb
->state
|= PDB_RUNNING
;
1972 pdb
->state
&= ~PDB_BREAK
;
1973 pdb
->state
&= ~PDB_STOPPED
;
1978 =item C<PDB_breakpoint_t * PDB_find_breakpoint(PARROT_INTERP, const char
1981 Find breakpoint number N; returns C<NULL> if the breakpoint doesn't
1982 exist or if no breakpoint was specified.
1988 PARROT_CAN_RETURN_NULL
1989 PARROT_WARN_UNUSED_RESULT
1991 PDB_find_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
1993 ASSERT_ARGS(PDB_find_breakpoint
)
1994 const char *oldcmd
= command
;
1995 const unsigned long n
= get_ulong(&command
, 0);
1996 if (command
!= oldcmd
) {
1997 PDB_breakpoint_t
*breakpoint
= interp
->pdb
->breakpoint
;
1999 while (breakpoint
&& breakpoint
->id
!= n
)
2000 breakpoint
= breakpoint
->next
;
2003 Parrot_io_eprintf(interp
->pdb
->debugger
, "No breakpoint number %ld", n
);
2010 /* Report an appropriate error */
2012 Parrot_io_eprintf(interp
->pdb
->debugger
, "Not a valid breakpoint");
2014 Parrot_io_eprintf(interp
->pdb
->debugger
, "No breakpoint specified");
2022 =item C<void PDB_disable_breakpoint(PARROT_INTERP, const char *command)>
2024 Disable a breakpoint; it can be reenabled with the enable command.
2031 PDB_disable_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2033 ASSERT_ARGS(PDB_disable_breakpoint
)
2034 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2036 /* if the breakpoint exists, disable it. */
2038 breakpoint
->skip
= -1;
2043 =item C<void PDB_enable_breakpoint(PARROT_INTERP, const char *command)>
2045 Reenable a disabled breakpoint; if the breakpoint was not disabled, has
2053 PDB_enable_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2055 ASSERT_ARGS(PDB_enable_breakpoint
)
2056 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2058 /* if the breakpoint exists, and it was disabled, enable it. */
2059 if (breakpoint
&& breakpoint
->skip
== -1)
2060 breakpoint
->skip
= 0;
2065 =item C<void PDB_delete_breakpoint(PARROT_INTERP, const char *command)>
2067 Delete a breakpoint.
2074 PDB_delete_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2076 ASSERT_ARGS(PDB_delete_breakpoint
)
2077 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2078 const PDB_line_t
*line
;
2082 if (!interp
->pdb
->file
)
2083 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No file loaded");
2085 line
= interp
->pdb
->file
->line
;
2086 while (line
->opcode
!= breakpoint
->pc
)
2089 /* Delete the condition structure, if there is one */
2090 if (breakpoint
->condition
) {
2091 PDB_delete_condition(interp
, breakpoint
);
2092 breakpoint
->condition
= NULL
;
2095 /* Remove the breakpoint from the list */
2096 if (breakpoint
->prev
&& breakpoint
->next
) {
2097 breakpoint
->prev
->next
= breakpoint
->next
;
2098 breakpoint
->next
->prev
= breakpoint
->prev
;
2100 else if (breakpoint
->prev
&& !breakpoint
->next
) {
2101 breakpoint
->prev
->next
= NULL
;
2103 else if (!breakpoint
->prev
&& breakpoint
->next
) {
2104 breakpoint
->next
->prev
= NULL
;
2105 interp
->pdb
->breakpoint
= breakpoint
->next
;
2108 interp
->pdb
->breakpoint
= NULL
;
2110 bp_id
= breakpoint
->id
;
2111 /* Kill the breakpoint */
2112 mem_sys_free(breakpoint
);
2114 Parrot_io_eprintf(interp
->pdb
->debugger
, "Breakpoint %li deleted\n", bp_id
);
2120 =item C<void PDB_delete_condition(PARROT_INTERP, PDB_breakpoint_t *breakpoint)>
2122 Delete a condition associated with a breakpoint.
2129 PDB_delete_condition(SHIM_INTERP
, ARGMOD(PDB_breakpoint_t
*breakpoint
))
2131 ASSERT_ARGS(PDB_delete_condition
)
2132 if (breakpoint
->condition
->value
) {
2133 if (breakpoint
->condition
->type
& PDB_cond_str
) {
2134 /* 'value' is a string, so we need to be careful */
2135 PObj_external_CLEAR((STRING
*)breakpoint
->condition
->value
);
2136 PObj_on_free_list_SET((STRING
*)breakpoint
->condition
->value
);
2137 /* it should now be properly garbage collected after
2138 we destroy the condition */
2141 /* 'value' is a float or an int, so we can just free it */
2142 mem_sys_free(breakpoint
->condition
->value
);
2143 breakpoint
->condition
->value
= NULL
;
2147 mem_sys_free(breakpoint
->condition
);
2148 breakpoint
->condition
= NULL
;
2153 =item C<void PDB_skip_breakpoint(PARROT_INTERP, unsigned long i)>
2155 Skip C<i> times all breakpoints.
2162 PDB_skip_breakpoint(PARROT_INTERP
, unsigned long i
)
2164 ASSERT_ARGS(PDB_skip_breakpoint
)
2166 fprintf(stderr
, "PDB_skip_breakpoint: %li\n", i
);
2169 interp
->pdb
->breakpoint_skip
= i
;
2174 =item C<char PDB_program_end(PARROT_INTERP)>
2183 PDB_program_end(PARROT_INTERP
)
2185 ASSERT_ARGS(PDB_program_end
)
2186 PDB_t
* const pdb
= interp
->pdb
;
2188 TRACEDEB_MSG("PDB_program_end");
2190 /* Remove the RUNNING state */
2191 pdb
->state
&= ~PDB_RUNNING
;
2193 Parrot_io_eprintf(pdb
->debugger
, "Program exited.\n");
2199 =item C<char PDB_check_condition(PARROT_INTERP, const PDB_condition_t
2202 Returns true if the condition was met.
2208 PARROT_WARN_UNUSED_RESULT
2210 PDB_check_condition(PARROT_INTERP
, ARGIN(const PDB_condition_t
*condition
))
2212 ASSERT_ARGS(PDB_check_condition
)
2213 PMC
*ctx
= CURRENT_CONTEXT(interp
);
2215 TRACEDEB_MSG("PDB_check_condition");
2219 if (condition
->type
& PDB_cond_int
) {
2221 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_INT
))
2223 i
= CTX_REG_INT(ctx
, condition
->reg
);
2225 if (condition
->type
& PDB_cond_const
)
2226 j
= *(INTVAL
*)condition
->value
;
2228 j
= REG_INT(interp
, *(int *)condition
->value
);
2230 if (((condition
->type
& PDB_cond_gt
) && (i
> j
)) ||
2231 ((condition
->type
& PDB_cond_ge
) && (i
>= j
)) ||
2232 ((condition
->type
& PDB_cond_eq
) && (i
== j
)) ||
2233 ((condition
->type
& PDB_cond_ne
) && (i
!= j
)) ||
2234 ((condition
->type
& PDB_cond_le
) && (i
<= j
)) ||
2235 ((condition
->type
& PDB_cond_lt
) && (i
< j
)))
2240 else if (condition
->type
& PDB_cond_num
) {
2243 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_NUM
))
2245 k
= CTX_REG_NUM(ctx
, condition
->reg
);
2247 if (condition
->type
& PDB_cond_const
)
2248 l
= *(FLOATVAL
*)condition
->value
;
2250 l
= REG_NUM(interp
, *(int *)condition
->value
);
2252 if (((condition
->type
& PDB_cond_gt
) && (k
> l
)) ||
2253 ((condition
->type
& PDB_cond_ge
) && (k
>= l
)) ||
2254 ((condition
->type
& PDB_cond_eq
) && (k
== l
)) ||
2255 ((condition
->type
& PDB_cond_ne
) && (k
!= l
)) ||
2256 ((condition
->type
& PDB_cond_le
) && (k
<= l
)) ||
2257 ((condition
->type
& PDB_cond_lt
) && (k
< l
)))
2262 else if (condition
->type
& PDB_cond_str
) {
2265 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_STR
))
2267 m
= CTX_REG_STR(ctx
, condition
->reg
);
2269 if (condition
->type
& PDB_cond_notnull
)
2270 return ! STRING_IS_NULL(m
);
2272 if (condition
->type
& PDB_cond_const
)
2273 n
= (STRING
*)condition
->value
;
2275 n
= REG_STR(interp
, *(int *)condition
->value
);
2277 if (((condition
->type
& PDB_cond_gt
) &&
2278 (Parrot_str_compare(interp
, m
, n
) > 0)) ||
2279 ((condition
->type
& PDB_cond_ge
) &&
2280 (Parrot_str_compare(interp
, m
, n
) >= 0)) ||
2281 ((condition
->type
& PDB_cond_eq
) &&
2282 (Parrot_str_compare(interp
, m
, n
) == 0)) ||
2283 ((condition
->type
& PDB_cond_ne
) &&
2284 (Parrot_str_compare(interp
, m
, n
) != 0)) ||
2285 ((condition
->type
& PDB_cond_le
) &&
2286 (Parrot_str_compare(interp
, m
, n
) <= 0)) ||
2287 ((condition
->type
& PDB_cond_lt
) &&
2288 (Parrot_str_compare(interp
, m
, n
) < 0)))
2293 else if (condition
->type
& PDB_cond_pmc
) {
2296 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_PMC
))
2298 m
= CTX_REG_PMC(ctx
, condition
->reg
);
2300 if (condition
->type
& PDB_cond_notnull
)
2301 return ! PMC_IS_NULL(m
);
2310 =item C<static PDB_breakpoint_t * current_breakpoint(PDB_t * pdb)>
2312 Returns a pointer to the breakpoint at the current position,
2313 or NULL if there is none.
2319 PARROT_CAN_RETURN_NULL
2320 static PDB_breakpoint_t
*
2321 current_breakpoint(ARGIN(PDB_t
* pdb
))
2323 ASSERT_ARGS(current_breakpoint
)
2324 PDB_breakpoint_t
*breakpoint
= pdb
->breakpoint
;
2325 while (breakpoint
) {
2326 if (pdb
->cur_opcode
== breakpoint
->pc
)
2328 breakpoint
= breakpoint
->next
;
2335 =item C<char PDB_break(PARROT_INTERP)>
2337 Returns true if we have to stop running.
2343 PARROT_WARN_UNUSED_RESULT
2345 PDB_break(PARROT_INTERP
)
2347 ASSERT_ARGS(PDB_break
)
2348 PDB_t
* const pdb
= interp
->pdb
;
2349 PDB_condition_t
*watchpoint
= pdb
->watchpoint
;
2350 PDB_breakpoint_t
*breakpoint
;
2353 TRACEDEB_MSG("PDB_break");
2356 /* Check the watchpoints first. */
2357 while (watchpoint
) {
2358 if (PDB_check_condition(interp
, watchpoint
)) {
2359 pdb
->state
|= PDB_STOPPED
;
2363 watchpoint
= watchpoint
->next
;
2366 /* If program ended */
2367 if (!pdb
->cur_opcode
)
2368 return PDB_program_end(interp
);
2370 /* If the program is STOPPED allow it to continue */
2371 if (pdb
->state
& PDB_STOPPED
) {
2372 pdb
->state
&= ~PDB_STOPPED
;
2376 breakpoint
= current_breakpoint(pdb
);
2378 /* If we have to skip breakpoints, do so. */
2379 if (pdb
->breakpoint_skip
) {
2380 TRACEDEB_MSG("PDB_break skipping");
2381 pdb
->breakpoint_skip
--;
2385 if (breakpoint
->skip
< 0)
2388 /* Check if there is a condition for this breakpoint */
2389 if ((breakpoint
->condition
) &&
2390 (!PDB_check_condition(interp
, breakpoint
->condition
)))
2393 TRACEDEB_MSG("PDB_break stopping");
2395 /* Add the STOPPED state and stop */
2396 pdb
->state
|= PDB_STOPPED
;
2405 =item C<char * PDB_escape(const char *string, UINTVAL length)>
2407 Escapes C<">, C<\r>, C<\n>, C<\t>, C<\a> and C<\\>.
2409 The returned string must be freed.
2415 PARROT_WARN_UNUSED_RESULT
2416 PARROT_CAN_RETURN_NULL
2419 PDB_escape(ARGIN(const char *string
), UINTVAL length
)
2421 ASSERT_ARGS(PDB_escape
)
2425 length
= length
> 20 ? 20 : length
;
2426 end
= string
+ length
;
2428 /* Return if there is no string to escape*/
2432 fill
= _new
= (char *)mem_sys_allocate(length
* 2 + 1);
2434 for (; string
< end
; string
++) {
2465 *(fill
++) = *string
;
2477 =item C<int PDB_unescape(char *string)>
2479 Do inplace unescape of C<\r>, C<\n>, C<\t>, C<\a> and C<\\>.
2486 PDB_unescape(ARGMOD(char *string
))
2488 ASSERT_ARGS(PDB_unescape
)
2491 for (; *string
; string
++) {
2494 if (*string
== '\\') {
2498 switch (string
[1]) {
2520 for (i
= 1; fill
[i
+ 1]; i
++)
2521 fill
[i
] = fill
[i
+ 1];
2532 =item C<size_t PDB_disassemble_op(PARROT_INTERP, char *dest, size_t space, const
2533 op_info_t *info, const opcode_t *op, PDB_file_t *file, const opcode_t
2534 *code_start, int full_name)>
2543 PDB_disassemble_op(PARROT_INTERP
, ARGOUT(char *dest
), size_t space
,
2544 ARGIN(const op_info_t
*info
), ARGIN(const opcode_t
*op
),
2545 ARGMOD_NULLOK(PDB_file_t
*file
), ARGIN_NULLOK(const opcode_t
*code_start
),
2548 ASSERT_ARGS(PDB_disassemble_op
)
2553 /* Write the opcode name */
2554 const char * p
= full_name
? info
->full_name
: info
->name
;
2556 TRACEDEB_MSG("PDB_disassemble_op");
2565 /* Concat the arguments */
2566 for (j
= 1; j
< info
->op_count
; j
++) {
2570 PARROT_ASSERT(size
+ 2 < space
);
2572 switch (info
->types
[j
- 1]) {
2586 /* If the opcode jumps and this is the last argument,
2587 that means this is a label */
2588 if ((j
== info
->op_count
- 1) &&
2589 (info
->jump
& PARROT_JUMP_RELATIVE
)) {
2592 i
= PDB_add_label(file
, op
, op
[j
]);
2594 else if (code_start
) {
2597 i
= op
[j
] + (op
- code_start
);
2606 /* Convert the integer to a string */
2611 PARROT_ASSERT(size
+ 20 < space
);
2613 size
+= sprintf(&dest
[size
], INTVAL_FMT
, i
);
2618 /* Convert the float to a string */
2619 const FLOATVAL f
= interp
->code
->const_table
->constants
[op
[j
]]->u
.number
;
2620 Parrot_snprintf(interp
, buf
, sizeof (buf
), FLOATVAL_FMT
, f
);
2621 strcpy(&dest
[size
], buf
);
2622 size
+= strlen(buf
);
2627 if (interp
->code
->const_table
->constants
[op
[j
]]-> u
.string
->strlen
) {
2628 char * const unescaped
=
2629 Parrot_str_to_cstring(interp
, interp
->code
->
2630 const_table
->constants
[op
[j
]]->u
.string
);
2631 char * const escaped
=
2632 PDB_escape(unescaped
, interp
->code
->const_table
->
2633 constants
[op
[j
]]->u
.string
->strlen
);
2635 strcpy(&dest
[size
], escaped
);
2636 size
+= strlen(escaped
);
2637 mem_sys_free(escaped
);
2639 Parrot_str_free_cstring(unescaped
);
2644 Parrot_snprintf(interp
, buf
, sizeof (buf
), "PMC_CONST(%d)", op
[j
]);
2645 strcpy(&dest
[size
], buf
);
2646 size
+= strlen(buf
);
2649 dest
[size
- 1] = '[';
2650 Parrot_snprintf(interp
, buf
, sizeof (buf
), "P" INTVAL_FMT
, op
[j
]);
2651 strcpy(&dest
[size
], buf
);
2652 size
+= strlen(buf
);
2657 PMC
* k
= interp
->code
->const_table
->constants
[op
[j
]]->u
.key
;
2658 dest
[size
- 1] = '[';
2660 switch (PObj_get_FLAGS(k
)) {
2663 case KEY_integer_FLAG
:
2664 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2665 INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2666 strcpy(&dest
[size
], buf
);
2667 size
+= strlen(buf
);
2669 case KEY_number_FLAG
:
2670 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2671 FLOATVAL_FMT
, VTABLE_get_number(interp
, k
));
2672 strcpy(&dest
[size
], buf
);
2673 size
+= strlen(buf
);
2675 case KEY_string_FLAG
:
2678 char * const temp
= Parrot_str_to_cstring(interp
,
2679 VTABLE_get_string(interp
, k
));
2680 strcpy(&dest
[size
], temp
);
2681 Parrot_str_free_cstring(temp
);
2683 size
+= Parrot_str_byte_length(interp
,
2684 VTABLE_get_string(interp
, (k
)));
2687 case KEY_integer_FLAG
|KEY_register_FLAG
:
2688 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2689 "I" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2690 strcpy(&dest
[size
], buf
);
2691 size
+= strlen(buf
);
2693 case KEY_number_FLAG
|KEY_register_FLAG
:
2694 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2695 "N" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2696 strcpy(&dest
[size
], buf
);
2697 size
+= strlen(buf
);
2699 case KEY_string_FLAG
|KEY_register_FLAG
:
2700 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2701 "S" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2702 strcpy(&dest
[size
], buf
);
2703 size
+= strlen(buf
);
2705 case KEY_pmc_FLAG
|KEY_register_FLAG
:
2706 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2707 "P" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2708 strcpy(&dest
[size
], buf
);
2709 size
+= strlen(buf
);
2715 GETATTR_Key_next_key(interp
, k
, k
);
2723 dest
[size
- 1] = '[';
2724 Parrot_snprintf(interp
, buf
, sizeof (buf
), "I" INTVAL_FMT
, op
[j
]);
2725 strcpy(&dest
[size
], buf
);
2726 size
+= strlen(buf
);
2729 case PARROT_ARG_KIC
:
2730 dest
[size
- 1] = '[';
2731 Parrot_snprintf(interp
, buf
, sizeof (buf
), INTVAL_FMT
, op
[j
]);
2732 strcpy(&dest
[size
], buf
);
2733 size
+= strlen(buf
);
2737 Parrot_ex_throw_from_c_args(interp
, NULL
, 1, "Unknown opcode type");
2740 if (j
!= info
->op_count
- 1)
2744 /* Special decoding for the signature used in args/returns. Such ops have
2745 one fixed parameter (the signature vector), plus a varying number of
2746 registers/constants. For each arg/return, we show the register and its
2747 flags using PIR syntax. */
2748 if (*(op
) == PARROT_OP_set_args_pc
|| *(op
) == PARROT_OP_set_returns_pc
)
2751 /* if it's a retrieving op, specialop = 2, so that later a :flat flag
2752 * can be changed into a :slurpy flag. See flag handling below.
2754 if (*(op
) == PARROT_OP_get_results_pc
|| *(op
) == PARROT_OP_get_params_pc
)
2757 if (specialop
> 0) {
2759 PMC
* const sig
= interp
->code
->const_table
->constants
[op
[1]]->u
.key
;
2760 const int n_values
= VTABLE_elements(interp
, sig
);
2761 /* The flag_names strings come from Call_bits_enum_t (with which it
2762 should probably be colocated); they name the bits from LSB to MSB.
2763 The two least significant bits are not flags; they are the register
2764 type, which is decoded elsewhere. We also want to show unused bits,
2765 which could indicate problems.
2767 PARROT_OBSERVER
const char * const flag_names
[] = {
2773 " :flat", /* should be :slurpy for args */
2782 /* Register decoding. It would be good to abstract this, too. */
2783 PARROT_OBSERVER
static const char regs
[] = "ISPN";
2785 for (j
= 0; j
< n_values
; j
++) {
2787 const int sig_value
= VTABLE_get_integer_keyed_int(interp
, sig
, j
);
2789 /* Print the register name, e.g. P37. */
2792 buf
[idx
++] = regs
[sig_value
& PARROT_ARG_TYPE_MASK
];
2793 Parrot_snprintf(interp
, &buf
[idx
], sizeof (buf
)-idx
,
2794 INTVAL_FMT
, op
[j
+2]);
2797 /* Add flags, if we have any. */
2800 int flags
= sig_value
;
2802 /* End when we run out of flags, off the end of flag_names, or
2803 * get too close to the end of buf.
2804 * 100 is just an estimate of all buf lengths added together.
2806 while (flags
&& idx
< sizeof (buf
) - 100) {
2807 const char * const flag_string
2808 = (specialop
== 2 && STREQ(flag_names
[flag_idx
], " :flat"))
2810 : flag_names
[flag_idx
];
2814 if (flags
& 1 && *flag_string
) {
2815 const size_t n
= strlen(flag_string
);
2816 strcpy(&buf
[idx
], flag_string
);
2824 /* Add it to dest. */
2826 strcpy(&dest
[size
], buf
);
2827 size
+= strlen(buf
);
2837 =item C<void PDB_disassemble(PARROT_INTERP, const char *command)>
2839 Disassemble the bytecode.
2846 PDB_disassemble(PARROT_INTERP
, SHIM(const char *command
))
2848 ASSERT_ARGS(PDB_disassemble
)
2849 PDB_t
* const pdb
= interp
->pdb
;
2850 opcode_t
* pc
= interp
->code
->base
.data
;
2853 PDB_line_t
*pline
, *newline
;
2857 const unsigned int default_size
= 32768;
2858 size_t space
; /* How much space do we have? */
2859 size_t size
, alloced
, n
;
2861 TRACEDEB_MSG("PDB_disassemble");
2863 pfile
= mem_allocate_zeroed_typed(PDB_file_t
);
2864 pline
= mem_allocate_zeroed_typed(PDB_line_t
);
2866 /* If we already got a source, free it */
2868 PDB_free_file(interp
, pdb
->file
);
2872 pfile
->line
= pline
;
2874 pfile
->source
= (char *)mem_sys_allocate(default_size
);
2876 alloced
= space
= default_size
;
2877 code_end
= pc
+ interp
->code
->base
.size
;
2879 while (pc
!= code_end
) {
2881 if (space
< default_size
) {
2882 alloced
+= default_size
;
2883 space
+= default_size
;
2884 pfile
->source
= (char *)mem_sys_realloc(pfile
->source
, alloced
);
2887 size
= PDB_disassemble_op(interp
, pfile
->source
+ pfile
->size
,
2888 space
, &interp
->op_info_table
[*pc
], pc
, pfile
, NULL
, 1);
2890 pfile
->size
+= size
;
2891 pfile
->source
[pfile
->size
- 1] = '\n';
2893 /* Store the opcode of this line */
2895 n
= interp
->op_info_table
[*pc
].op_count
;
2897 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
2900 /* Prepare for next line */
2901 newline
= mem_allocate_typed(PDB_line_t
);
2902 newline
->label
= NULL
;
2903 newline
->next
= NULL
;
2904 newline
->number
= pline
->number
+ 1;
2905 pline
->next
= newline
;
2907 pline
->source_offset
= pfile
->size
;
2910 /* Add labels to the lines they belong to */
2911 label
= pfile
->label
;
2914 /* Get the line to apply the label */
2915 pline
= pfile
->line
;
2917 while (pline
&& pline
->opcode
!= label
->opcode
)
2918 pline
= pline
->next
;
2921 Parrot_io_eprintf(pdb
->debugger
,
2922 "Label number %li out of bounds.\n", label
->number
);
2924 PDB_free_file(interp
, pfile
);
2928 pline
->label
= label
;
2930 label
= label
->next
;
2933 pdb
->state
|= PDB_SRC_LOADED
;
2939 =item C<long PDB_add_label(PDB_file_t *file, const opcode_t *cur_opcode,
2942 Add a label to the label list.
2949 PDB_add_label(ARGMOD(PDB_file_t
*file
), ARGIN(const opcode_t
*cur_opcode
),
2952 ASSERT_ARGS(PDB_add_label
)
2954 PDB_label_t
*label
= file
->label
;
2956 /* See if there is already a label at this line */
2958 if (label
->opcode
== cur_opcode
+ offset
)
2959 return label
->number
;
2960 label
= label
->next
;
2963 /* Allocate a new label */
2964 label
= file
->label
;
2965 _new
= mem_allocate_typed(PDB_label_t
);
2966 _new
->opcode
= cur_opcode
+ offset
;
2971 label
= label
->next
;
2973 _new
->number
= label
->number
+ 1;
2981 return _new
->number
;
2986 =item C<void PDB_free_file(PARROT_INTERP, PDB_file_t *file)>
2988 Frees any allocated source files.
2995 PDB_free_file(SHIM_INTERP
, ARGIN_NULLOK(PDB_file_t
*file
))
2997 ASSERT_ARGS(PDB_free_file
)
2999 /* Free all of the allocated line structures */
3000 PDB_line_t
*line
= file
->line
;
3005 PDB_line_t
* const nline
= line
->next
;
3010 /* Free all of the allocated label structures */
3011 label
= file
->label
;
3014 PDB_label_t
* const nlabel
= label
->next
;
3016 mem_sys_free(label
);
3020 /* Free the remaining allocated portions of the file structure */
3021 if (file
->sourcefilename
)
3022 mem_sys_free(file
->sourcefilename
);
3025 mem_sys_free(file
->source
);
3035 =item C<void PDB_load_source(PARROT_INTERP, const char *command)>
3037 Load a source code file.
3045 PDB_load_source(PARROT_INTERP
, ARGIN(const char *command
))
3047 ASSERT_ARGS(PDB_load_source
)
3049 char f
[DEBUG_CMD_BUFFER_LENGTH
+ 1];
3053 PDB_t
* const pdb
= interp
->pdb
;
3054 opcode_t
*pc
= interp
->code
->base
.data
;
3056 unsigned long size
= 0;
3058 TRACEDEB_MSG("PDB_load_source");
3060 /* If there was a file already loaded or the bytecode was
3061 disassembled, free it */
3063 PDB_free_file(interp
->pdb
->debugee
, interp
->pdb
->debugee
->pdb
->file
);
3064 interp
->pdb
->debugee
->pdb
->file
= NULL
;
3067 /* Get the name of the file */
3068 for (j
= 0; command
[j
] == ' '; ++j
)
3070 for (i
= 0; command
[j
]; i
++, j
++)
3076 file
= fopen(f
, "r");
3078 /* abort if fopen failed */
3080 Parrot_io_eprintf(pdb
->debugger
, "Unable to load '%s'\n", f
);
3084 pfile
= mem_allocate_zeroed_typed(PDB_file_t
);
3085 pline
= mem_allocate_zeroed_typed(PDB_line_t
);
3087 pfile
->source
= (char *)mem_sys_allocate(1024);
3088 pfile
->line
= pline
;
3091 PARROT_ASSERT(interp
->op_info_table
);
3094 while ((c
= fgetc(file
)) != EOF
) {
3096 if (++size
== 1024) {
3097 pfile
->source
= (char *)mem_sys_realloc(pfile
->source
,
3098 (size_t)pfile
->size
+ 1024);
3101 pfile
->source
[pfile
->size
] = (char)c
;
3106 /* If the line has an opcode move to the next one,
3107 otherwise leave it with NULL to skip it. */
3108 PDB_line_t
*newline
= mem_allocate_zeroed_typed(PDB_line_t
);
3110 if (PDB_hasinstruction(pfile
->source
+ pline
->source_offset
)) {
3111 size_t n
= interp
->op_info_table
[*pc
].op_count
;
3113 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
3116 /* don't walk off the end of the program into neverland */
3117 if (pc
>= interp
->code
->base
.data
+ interp
->code
->base
.size
)
3121 newline
->number
= pline
->number
+ 1;
3122 pline
->next
= newline
;
3124 pline
->source_offset
= pfile
->size
;
3125 pline
->opcode
= NULL
;
3126 pline
->label
= NULL
;
3132 pdb
->state
|= PDB_SRC_LOADED
;
3135 TRACEDEB_MSG("PDB_load_source finished");
3140 =item C<char PDB_hasinstruction(const char *c)>
3142 Return true if the line has an instruction.
3148 PARROT_WARN_UNUSED_RESULT
3149 PARROT_PURE_FUNCTION
3151 PDB_hasinstruction(ARGIN(const char *c
))
3153 ASSERT_ARGS(PDB_hasinstruction
)
3156 /* as long as c is not NULL, we're not looking at a comment (#...) or a '\n'... */
3157 while (*c
&& *c
!= '#' && *c
!= '\n') {
3158 /* ... and c is alphanumeric or a quoted string then the line contains
3159 * an instruction. */
3160 if (isalnum((unsigned char) *c
) || *c
== '"') {
3163 else if (*c
== ':') {
3164 /* probably a label */
3176 =item C<static void no_such_register(PARROT_INTERP, char register_type, UINTVAL
3179 Auxiliar error message function.
3186 no_such_register(PARROT_INTERP
, char register_type
, UINTVAL register_num
)
3188 ASSERT_ARGS(no_such_register
)
3190 Parrot_io_eprintf(interp
, "%c%u = no such register\n",
3191 register_type
, register_num
);
3196 =item C<void PDB_assign(PARROT_INTERP, const char *command)>
3198 Assign to registers.
3205 PDB_assign(PARROT_INTERP
, ARGIN(const char *command
))
3207 ASSERT_ARGS(PDB_assign
)
3208 UINTVAL register_num
;
3211 PDB_t
*pdb
= interp
->pdb
;
3212 Interp
*debugger
= pdb
? pdb
->debugger
: interp
;
3213 Interp
*debugee
= pdb
? pdb
->debugee
: interp
;
3215 /* smallest valid commad length is 4, i.e. "I0 1" */
3216 if (strlen(command
) < 4) {
3217 Parrot_io_eprintf(debugger
, "Must give a register number and value to assign\n");
3220 reg_type_id
= (unsigned char) toupper((unsigned char) command
[0]);
3222 register_num
= get_ulong(&command
, 0);
3224 switch (reg_type_id
) {
3226 reg_type
= REGNO_INT
;
3229 reg_type
= REGNO_NUM
;
3232 reg_type
= REGNO_STR
;
3235 reg_type
= REGNO_PMC
;
3236 Parrot_io_eprintf(debugger
, "Assigning to PMCs is not currently supported\n");
3239 Parrot_io_eprintf(debugger
, "Invalid register type %c\n", reg_type_id
);
3242 if (register_num
>= Parrot_pcc_get_regs_used(debugee
,
3243 CURRENT_CONTEXT(debugee
), reg_type
)) {
3244 no_such_register(debugger
, reg_type_id
, register_num
);
3249 IREG(register_num
) = get_ulong(&command
, 0);
3252 NREG(register_num
) = atof(command
);
3255 SREG(register_num
) = Parrot_str_new(debugee
, command
, strlen(command
));
3257 default: ; /* Must never come here */
3259 Parrot_io_eprintf(debugger
, "\n %c%u = ", reg_type_id
, register_num
);
3260 Parrot_io_eprintf(debugger
, "%Ss\n", GDB_print_reg(debugee
, reg_type
, register_num
));
3265 =item C<void PDB_list(PARROT_INTERP, const char *command)>
3267 Show lines from the source code file.
3274 PDB_list(PARROT_INTERP
, ARGIN(const char *command
))
3276 ASSERT_ARGS(PDB_list
)
3278 unsigned long line_number
;
3281 PDB_t
*pdb
= interp
->pdb
;
3282 unsigned long n
= 10;
3284 TRACEDEB_MSG("PDB_list");
3285 if (!pdb
->file
|| !pdb
->file
->line
) {
3286 Parrot_io_eprintf(pdb
->debugger
, "No source file loaded\n");
3290 /* set the list line if provided */
3291 line_number
= get_ulong(&command
, 0);
3292 pdb
->file
->list_line
= (unsigned long) line_number
;
3294 /* set the number of lines to print */
3295 n
= get_ulong(&command
, 10);
3297 /* if n is zero, we simply return, as we don't have to print anything */
3301 line
= pdb
->file
->line
;
3303 for (i
= 0; i
< pdb
->file
->list_line
&& line
->next
; i
++)
3307 while (line
->next
) {
3308 Parrot_io_eprintf(pdb
->debugger
, "%li ", pdb
->file
->list_line
+ i
);
3309 /* If it has a label print it */
3311 Parrot_io_eprintf(pdb
->debugger
, "L%li:\t", line
->label
->number
);
3313 c
= pdb
->file
->source
+ line
->source_offset
;
3316 Parrot_io_eprintf(pdb
->debugger
, "%c", *(c
++));
3318 Parrot_io_eprintf(pdb
->debugger
, "\n");
3327 pdb
->file
->list_line
= 0;
3329 pdb
->file
->list_line
+= n
;
3334 =item C<void PDB_eval(PARROT_INTERP, const char *command)>
3336 C<eval>s an instruction.
3343 PDB_eval(PARROT_INTERP
, ARGIN(const char *command
))
3345 ASSERT_ARGS(PDB_eval
)
3347 PDB_t
*pdb
= interp
->pdb
;
3348 Interp
*warninterp
= (interp
->pdb
&& interp
->pdb
->debugger
) ?
3349 interp
->pdb
->debugger
: interp
;
3350 TRACEDEB_MSG("PDB_eval");
3352 Parrot_io_eprintf(warninterp
, "The eval command is currently unimplemeneted\n");
3357 =item C<opcode_t * PDB_compile(PARROT_INTERP, const char *command)>
3359 Compiles instructions with the PASM compiler.
3361 Appends an C<end> op.
3363 This may be called from C<PDB_eval> above or from the compile opcode
3364 which generates a malloced string.
3370 PARROT_CAN_RETURN_NULL
3372 PDB_compile(PARROT_INTERP
, ARGIN(const char *command
))
3374 ASSERT_ARGS(PDB_compile
)
3377 Parrot_ex_throw_from_c_args(interp
, NULL
,
3378 EXCEPTION_UNIMPLEMENTED
,
3379 "PDB_compile ('PASM1' compiler) has been deprecated");
3384 =item C<void PDB_print(PARROT_INTERP, const char *command)>
3386 Print interp registers.
3393 PDB_print(PARROT_INTERP
, ARGIN(const char *command
))
3395 ASSERT_ARGS(PDB_print
)
3396 const STRING
*s
= GDB_P(interp
->pdb
->debugee
, command
);
3398 TRACEDEB_MSG("PDB_print");
3399 Parrot_io_eprintf(interp
, "%Ss\n", s
);
3405 =item C<void PDB_info(PARROT_INTERP)>
3407 Print the interpreter info.
3414 PDB_info(PARROT_INTERP
)
3416 ASSERT_ARGS(PDB_info
)
3418 /* If a debugger is created, use it for printing and use the
3419 * data in his debugee. Otherwise, use current interpreter
3421 Parrot_Interp itdeb
= interp
->pdb
? interp
->pdb
->debugger
: interp
;
3422 Parrot_Interp itp
= interp
->pdb
? interp
->pdb
->debugee
: interp
;
3424 Parrot_io_eprintf(itdeb
, "Total memory allocated = %ld\n",
3425 interpinfo(itp
, TOTAL_MEM_ALLOC
));
3426 Parrot_io_eprintf(itdeb
, "GC mark runs = %ld\n",
3427 interpinfo(itp
, GC_MARK_RUNS
));
3428 Parrot_io_eprintf(itdeb
, "Lazy gc mark runs = %ld\n",
3429 interpinfo(itp
, GC_LAZY_MARK_RUNS
));
3430 Parrot_io_eprintf(itdeb
, "GC collect runs = %ld\n",
3431 interpinfo(itp
, GC_COLLECT_RUNS
));
3432 Parrot_io_eprintf(itdeb
, "Collect memory = %ld\n",
3433 interpinfo(itp
, TOTAL_COPIED
));
3434 Parrot_io_eprintf(itdeb
, "Active PMCs = %ld\n",
3435 interpinfo(itp
, ACTIVE_PMCS
));
3436 Parrot_io_eprintf(itdeb
, "Extended PMCs = %ld\n",
3437 interpinfo(itp
, EXTENDED_PMCS
));
3438 Parrot_io_eprintf(itdeb
, "Timely GC PMCs = %ld\n",
3439 interpinfo(itp
, IMPATIENT_PMCS
));
3440 Parrot_io_eprintf(itdeb
, "Total PMCs = %ld\n",
3441 interpinfo(itp
, TOTAL_PMCS
));
3442 Parrot_io_eprintf(itdeb
, "Active buffers = %ld\n",
3443 interpinfo(itp
, ACTIVE_BUFFERS
));
3444 Parrot_io_eprintf(itdeb
, "Total buffers = %ld\n",
3445 interpinfo(itp
, TOTAL_BUFFERS
));
3446 Parrot_io_eprintf(itdeb
, "Header allocations since last collect = %ld\n",
3447 interpinfo(itp
, HEADER_ALLOCS_SINCE_COLLECT
));
3448 Parrot_io_eprintf(itdeb
, "Memory allocations since last collect = %ld\n",
3449 interpinfo(itp
, MEM_ALLOCS_SINCE_COLLECT
));
3454 =item C<void PDB_help(PARROT_INTERP, const char *command)>
3456 Print the help text. "Help" with no arguments prints a list of commands.
3457 "Help xxx" prints information on command xxx.
3464 PDB_help(PARROT_INTERP
, ARGIN(const char *command
))
3466 ASSERT_ARGS(PDB_help
)
3467 const DebuggerCmd
*cmd
;
3469 const char * cmdline
= command
;
3470 cmd
= get_cmd(& cmdline
);
3473 Parrot_io_eprintf(interp
->pdb
->debugger
, "%s\n", cmd
->help
);
3476 if (*cmdline
== '\0') {
3478 Parrot_io_eprintf(interp
->pdb
->debugger
, "List of commands:\n");
3479 for (i
= 0; i
< sizeof (DebCmdList
) / sizeof (DebuggerCmdList
); ++i
) {
3480 const DebuggerCmdList
*cmdlist
= DebCmdList
+ i
;
3481 Parrot_io_eprintf(interp
->pdb
->debugger
,
3482 " %-12s-- %s\n", cmdlist
->name
, cmdlist
->cmd
->shorthelp
);
3484 Parrot_io_eprintf(interp
->pdb
->debugger
, "\n"
3485 "Type \"help\" followed by a command name for full documentation.\n\n");
3489 Parrot_io_eprintf(interp
->pdb
->debugger
, "Unknown command: %s\n", command
);
3496 =item C<void PDB_backtrace(PARROT_INTERP)>
3498 Prints a backtrace of the interp's call chain.
3505 PDB_backtrace(PARROT_INTERP
)
3507 ASSERT_ARGS(PDB_backtrace
)
3511 int limit_count
= 0;
3513 /* information about the current sub */
3514 PMC
*sub
= interpinfo_p(interp
, CURRENT_SUB
);
3515 PMC
*ctx
= CURRENT_CONTEXT(interp
);
3517 if (!PMC_IS_NULL(sub
)) {
3518 str
= Parrot_Context_infostr(interp
, ctx
);
3520 Parrot_io_eprintf(interp
, "%Ss", str
);
3521 if (interp
->code
->annotations
) {
3522 PMC
*annot
= PackFile_Annotations_lookup(interp
, interp
->code
->annotations
,
3523 Parrot_pcc_get_pc(interp
, ctx
) - interp
->code
->base
.data
+ 1, NULL
);
3524 if (!PMC_IS_NULL(annot
)) {
3525 PMC
*pfile
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3526 Parrot_str_new_constant(interp
, "file"));
3527 PMC
*pline
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3528 Parrot_str_new_constant(interp
, "line"));
3529 if ((!PMC_IS_NULL(pfile
)) && (!PMC_IS_NULL(pline
))) {
3530 STRING
*file
= VTABLE_get_string(interp
, pfile
);
3531 INTVAL line
= VTABLE_get_integer(interp
, pline
);
3532 Parrot_io_eprintf(interp
, " (%Ss:%li)", file
, (long)line
);
3536 Parrot_io_eprintf(interp
, "\n");
3540 /* backtrace: follow the continuation chain */
3542 Parrot_Continuation_attributes
*sub_cont
;
3544 /* Limit the levels dumped, no segfault on infinite recursion */
3545 if (++limit_count
> RECURSION_LIMIT
)
3548 sub
= Parrot_pcc_get_continuation(interp
, ctx
);
3550 if (PMC_IS_NULL(sub
))
3554 sub_cont
= PARROT_CONTINUATION(sub
);
3560 str
= Parrot_Context_infostr(interp
, Parrot_pcc_get_caller_ctx(interp
, ctx
));
3567 /* recursion detection */
3568 if (ctx
== sub_cont
->to_ctx
) {
3571 else if (!PMC_IS_NULL(old
) && PMC_cont(old
) &&
3572 Parrot_pcc_get_pc(interp
, PMC_cont(old
)->to_ctx
) ==
3573 Parrot_pcc_get_pc(interp
, PMC_cont(sub
)->to_ctx
) &&
3574 Parrot_pcc_get_sub(interp
, PMC_cont(old
)->to_ctx
) ==
3575 Parrot_pcc_get_sub(interp
, PMC_cont(sub
)->to_ctx
)) {
3578 else if (rec_level
!= 0) {
3579 Parrot_io_eprintf(interp
, "... call repeated %d times\n", rec_level
);
3583 /* print the context description */
3584 if (rec_level
== 0) {
3585 PackFile_ByteCode
*seg
= sub_cont
->seg
;
3586 Parrot_io_eprintf(interp
, "%Ss", str
);
3587 if (seg
->annotations
) {
3588 PMC
*annot
= PackFile_Annotations_lookup(interp
, seg
->annotations
,
3589 Parrot_pcc_get_pc(interp
, sub_cont
->to_ctx
) - seg
->base
.data
,
3592 if (!PMC_IS_NULL(annot
)) {
3593 PMC
*pfile
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3594 Parrot_str_new_constant(interp
, "file"));
3595 PMC
*pline
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3596 Parrot_str_new_constant(interp
, "line"));
3597 if ((!PMC_IS_NULL(pfile
)) && (!PMC_IS_NULL(pline
))) {
3598 STRING
*file
= VTABLE_get_string(interp
, pfile
);
3599 INTVAL line
= VTABLE_get_integer(interp
, pline
);
3600 Parrot_io_eprintf(interp
, " (%Ss:%li)", file
, (long)line
);
3604 Parrot_io_eprintf(interp
, "\n");
3607 /* get the next Continuation */
3608 ctx
= Parrot_pcc_get_caller_ctx(interp
, ctx
);
3616 Parrot_io_eprintf(interp
, "... call repeated %d times\n", rec_level
);
3622 * GDB_P gdb> pp $I0 print register I0 value
3624 * RT46139 more, more
3629 =item C<static STRING * GDB_print_reg(PARROT_INTERP, int t, int n)>
3631 Used by GDB_P to convert register values for display. Takes register
3632 type and number as arguments.
3634 Returns a pointer to the start of the string, (except for PMCs, which
3635 print directly and return "").
3641 PARROT_WARN_UNUSED_RESULT
3642 PARROT_CANNOT_RETURN_NULL
3645 GDB_print_reg(PARROT_INTERP
, int t
, int n
)
3647 ASSERT_ARGS(GDB_print_reg
)
3650 if (n
>= 0 && (UINTVAL
)n
< Parrot_pcc_get_regs_used(interp
, CURRENT_CONTEXT(interp
), t
)) {
3653 return Parrot_str_from_int(interp
, IREG(n
));
3655 return Parrot_str_from_num(interp
, NREG(n
));
3657 /* This hack is needed because we occasionally are told
3658 that we have string registers when we actually don't */
3659 string
= (char *) SREG(n
);
3662 return Parrot_str_new(interp
, "", 0);
3666 /* prints directly */
3667 trace_pmc_dump(interp
, PREG(n
));
3668 return Parrot_str_new(interp
, "", 0);
3673 return Parrot_str_new(interp
, "no such register", 0);
3678 =item C<static STRING * GDB_P(PARROT_INTERP, const char *s)>
3680 Used by PDB_print to print register values. Takes a pointer to the
3683 Returns "" or error message.
3689 PARROT_WARN_UNUSED_RESULT
3690 PARROT_CANNOT_RETURN_NULL
3693 GDB_P(PARROT_INTERP
, ARGIN(const char *s
))
3699 TRACEDEB_MSG("GDB_P");
3700 /* Skip leading whitespace. */
3701 while (isspace((unsigned char)*s
))
3704 reg_type
= (unsigned char) toupper((unsigned char)*s
);
3707 case 'I': t
= REGNO_INT
; break;
3708 case 'N': t
= REGNO_NUM
; break;
3709 case 'S': t
= REGNO_STR
; break;
3710 case 'P': t
= REGNO_PMC
; break;
3711 default: return Parrot_str_new(interp
, "Need a register.", 0);
3714 /* Print all registers of this type. */
3715 const int max_reg
= Parrot_pcc_get_regs_used(interp
, CURRENT_CONTEXT(interp
), t
);
3718 for (n
= 0; n
< max_reg
; n
++) {
3719 /* this must be done in two chunks because PMC's print directly. */
3720 Parrot_io_eprintf(interp
, "\n %c%d = ", reg_type
, n
);
3721 Parrot_io_eprintf(interp
, "%Ss", GDB_print_reg(interp
, t
, n
));
3723 return Parrot_str_new(interp
, "", 0);
3725 else if (s
[1] && isdigit((unsigned char)s
[1])) {
3726 const int n
= atoi(s
+ 1);
3727 return GDB_print_reg(interp
, t
, n
);
3730 return Parrot_str_new(interp
, "no such register", 0);
3740 F<include/parrot/debugger.h>, F<src/parrot_debugger.c> and F<ops/debug.ops>.
3746 =item Initial version by Daniel Grunblatt on 2002.5.19.
3748 =item Start of rewrite - leo 2005.02.16
3750 The debugger now uses its own interpreter. User code is run in
3751 Interp *debugee. We have:
3753 debug_interp->pdb->debugee->debugger
3756 +------------- := -----------+
3758 Debug commands are mostly run inside the C<debugger>. User code
3759 runs of course in the C<debugee>.
3770 * c-file-style: "parrot"
3772 * vim: expandtab shiftwidth=4: