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"
36 /* Hand switched debugger tracing
37 * Set to 1 to enable tracing to stderr
40 #define TRACE_DEBUGGER 0
43 # define TRACEDEB_MSG(msg) fprintf(stderr, "%s\n", (msg))
45 # define TRACEDEB_MSG(msg)
48 /* Length of command line buffers */
49 #define DEBUG_CMD_BUFFER_LENGTH 255
51 /* Easier register access */
52 #define IREG(i) REG_INT(interp, (i))
53 #define NREG(i) REG_NUM(interp, (i))
54 #define SREG(i) REG_STR(interp, (i))
55 #define PREG(i) REG_PMC(interp, (i))
57 typedef struct DebuggerCmd DebuggerCmd
;
58 typedef struct DebuggerCmdList DebuggerCmdList
;
61 /* HEADERIZER HFILE: include/parrot/debugger.h */
63 /* HEADERIZER BEGIN: static */
64 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
66 static void chop_newline(ARGMOD(char * buf
))
67 __attribute__nonnull__(1)
70 static void close_script_file(PARROT_INTERP
)
71 __attribute__nonnull__(1);
73 static unsigned short condition_regtype(ARGIN(const char *cmd
))
74 __attribute__nonnull__(1);
76 PARROT_CAN_RETURN_NULL
77 static PDB_breakpoint_t
* current_breakpoint(ARGIN(PDB_t
* pdb
))
78 __attribute__nonnull__(1);
80 static void debugger_cmdline(PARROT_INTERP
)
81 __attribute__nonnull__(1);
83 static void dump_string(PARROT_INTERP
, ARGIN_NULLOK(const STRING
*s
))
84 __attribute__nonnull__(1);
86 PARROT_WARN_UNUSED_RESULT
87 PARROT_CANNOT_RETURN_NULL
89 static const char* GDB_P(PARROT_INTERP
, ARGIN(const char *s
))
90 __attribute__nonnull__(1)
91 __attribute__nonnull__(2);
93 PARROT_WARN_UNUSED_RESULT
94 PARROT_CANNOT_RETURN_NULL
96 static const char* GDB_print_reg(PARROT_INTERP
, int t
, int n
)
97 __attribute__nonnull__(1);
99 PARROT_WARN_UNUSED_RESULT
100 PARROT_CAN_RETURN_NULL
101 static const DebuggerCmd
* get_cmd(ARGIN_NULLOK(const char **cmd
));
103 PARROT_WARN_UNUSED_RESULT
104 static unsigned long get_uint(ARGMOD(const char **cmd
), unsigned int def
)
105 __attribute__nonnull__(1)
108 PARROT_WARN_UNUSED_RESULT
109 static unsigned long get_ulong(ARGMOD(const char **cmd
), unsigned long def
)
110 __attribute__nonnull__(1)
113 static void list_breakpoints(ARGIN(PDB_t
*pdb
))
114 __attribute__nonnull__(1);
116 PARROT_CAN_RETURN_NULL
117 PARROT_WARN_UNUSED_RESULT
118 static const char * nextarg(ARGIN_NULLOK(const char *command
));
120 static void no_such_register(PARROT_INTERP
,
122 UINTVAL register_num
)
123 __attribute__nonnull__(1);
125 PARROT_CANNOT_RETURN_NULL
126 PARROT_WARN_UNUSED_RESULT
127 static const char * parse_int(ARGIN(const char *str
), ARGOUT(int *intP
))
128 __attribute__nonnull__(1)
129 __attribute__nonnull__(2)
130 FUNC_MODIFIES(*intP
);
132 PARROT_CAN_RETURN_NULL
133 PARROT_WARN_UNUSED_RESULT
134 static const char* parse_key(PARROT_INTERP
,
135 ARGIN(const char *str
),
137 __attribute__nonnull__(1)
138 __attribute__nonnull__(2)
139 __attribute__nonnull__(3)
140 FUNC_MODIFIES(*keyP
);
142 PARROT_CAN_RETURN_NULL
143 PARROT_WARN_UNUSED_RESULT
144 static const char * parse_string(PARROT_INTERP
,
145 ARGIN(const char *str
),
146 ARGOUT(STRING
**strP
))
147 __attribute__nonnull__(1)
148 __attribute__nonnull__(2)
149 __attribute__nonnull__(3)
150 FUNC_MODIFIES(*strP
);
152 PARROT_CANNOT_RETURN_NULL
153 static const char * skip_command(ARGIN(const char *str
))
154 __attribute__nonnull__(1);
156 PARROT_WARN_UNUSED_RESULT
157 PARROT_CANNOT_RETURN_NULL
158 static const char * skip_whitespace(ARGIN(const char *cmd
))
159 __attribute__nonnull__(1);
161 #define ASSERT_ARGS_chop_newline __attribute__unused__ int _ASSERT_ARGS_CHECK = \
162 PARROT_ASSERT_ARG(buf)
163 #define ASSERT_ARGS_close_script_file __attribute__unused__ int _ASSERT_ARGS_CHECK = \
164 PARROT_ASSERT_ARG(interp)
165 #define ASSERT_ARGS_condition_regtype __attribute__unused__ int _ASSERT_ARGS_CHECK = \
166 PARROT_ASSERT_ARG(cmd)
167 #define ASSERT_ARGS_current_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = \
168 PARROT_ASSERT_ARG(pdb)
169 #define ASSERT_ARGS_debugger_cmdline __attribute__unused__ int _ASSERT_ARGS_CHECK = \
170 PARROT_ASSERT_ARG(interp)
171 #define ASSERT_ARGS_dump_string __attribute__unused__ int _ASSERT_ARGS_CHECK = \
172 PARROT_ASSERT_ARG(interp)
173 #define ASSERT_ARGS_GDB_P __attribute__unused__ int _ASSERT_ARGS_CHECK = \
174 PARROT_ASSERT_ARG(interp) \
175 || PARROT_ASSERT_ARG(s)
176 #define ASSERT_ARGS_GDB_print_reg __attribute__unused__ int _ASSERT_ARGS_CHECK = \
177 PARROT_ASSERT_ARG(interp)
178 #define ASSERT_ARGS_get_cmd __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
179 #define ASSERT_ARGS_get_uint __attribute__unused__ int _ASSERT_ARGS_CHECK = \
180 PARROT_ASSERT_ARG(cmd)
181 #define ASSERT_ARGS_get_ulong __attribute__unused__ int _ASSERT_ARGS_CHECK = \
182 PARROT_ASSERT_ARG(cmd)
183 #define ASSERT_ARGS_list_breakpoints __attribute__unused__ int _ASSERT_ARGS_CHECK = \
184 PARROT_ASSERT_ARG(pdb)
185 #define ASSERT_ARGS_nextarg __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
186 #define ASSERT_ARGS_no_such_register __attribute__unused__ int _ASSERT_ARGS_CHECK = \
187 PARROT_ASSERT_ARG(interp)
188 #define ASSERT_ARGS_parse_int __attribute__unused__ int _ASSERT_ARGS_CHECK = \
189 PARROT_ASSERT_ARG(str) \
190 || PARROT_ASSERT_ARG(intP)
191 #define ASSERT_ARGS_parse_key __attribute__unused__ int _ASSERT_ARGS_CHECK = \
192 PARROT_ASSERT_ARG(interp) \
193 || PARROT_ASSERT_ARG(str) \
194 || PARROT_ASSERT_ARG(keyP)
195 #define ASSERT_ARGS_parse_string __attribute__unused__ int _ASSERT_ARGS_CHECK = \
196 PARROT_ASSERT_ARG(interp) \
197 || PARROT_ASSERT_ARG(str) \
198 || PARROT_ASSERT_ARG(strP)
199 #define ASSERT_ARGS_skip_command __attribute__unused__ int _ASSERT_ARGS_CHECK = \
200 PARROT_ASSERT_ARG(str)
201 #define ASSERT_ARGS_skip_whitespace __attribute__unused__ int _ASSERT_ARGS_CHECK = \
202 PARROT_ASSERT_ARG(cmd)
203 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
204 /* HEADERIZER END: static */
207 * Command functions and help dispatch
210 typedef void (* debugger_func_t
)(PDB_t
* pdb
, const char * cmd
);
212 static int nomoreargs(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
214 if (*skip_whitespace(cmd
) == '\0')
217 Parrot_io_eprintf(pdb
->debugger
, "Spurious arg\n");
222 static void dbg_assign(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
224 TRACEDEB_MSG("dbg_assign");
226 PDB_assign(pdb
->debugee
, cmd
);
229 static void dbg_break(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
231 TRACEDEB_MSG("dbg_break");
233 PDB_set_break(pdb
->debugee
, cmd
);
236 static void dbg_continue(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
238 TRACEDEB_MSG("dbg_continue");
240 PDB_continue(pdb
->debugee
, cmd
);
243 static void dbg_delete(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
245 TRACEDEB_MSG("dbg_delete");
247 PDB_delete_breakpoint(pdb
->debugee
, cmd
);
250 static void dbg_disable(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
252 TRACEDEB_MSG("dbg_disable");
254 PDB_disable_breakpoint(pdb
->debugee
, cmd
);
257 static void dbg_disassemble(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
259 TRACEDEB_MSG("dbg_disassemble");
261 PDB_disassemble(pdb
->debugee
, cmd
);
264 static void dbg_echo(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
266 TRACEDEB_MSG("dbg_echo");
268 if (! nomoreargs(pdb
, cmd
))
271 if (pdb
->state
& PDB_ECHO
) {
272 TRACEDEB_MSG("Disabling echo");
273 pdb
->state
&= ~PDB_ECHO
;
276 TRACEDEB_MSG("Enabling echo");
277 pdb
->state
|= PDB_ECHO
;
281 static void dbg_enable(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
283 PDB_enable_breakpoint(pdb
->debugee
, cmd
);
286 static void dbg_eval(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
288 PDB_eval(pdb
->debugee
, cmd
);
291 static void dbg_gcdebug(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
293 TRACEDEB_MSG("dbg_gcdebug");
295 if (! nomoreargs(pdb
, cmd
))
298 if (pdb
->state
& PDB_GCDEBUG
) {
299 TRACEDEB_MSG("Disabling gcdebug mode");
300 pdb
->state
&= ~PDB_GCDEBUG
;
303 TRACEDEB_MSG("Enabling gcdebug mode");
304 pdb
->state
|= PDB_GCDEBUG
;
308 static void dbg_help(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
310 TRACEDEB_MSG("dbg_help");
312 PDB_help(pdb
->debugee
, cmd
);
315 static void dbg_info(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
317 TRACEDEB_MSG("dbg_info");
319 if (! nomoreargs(pdb
, cmd
))
322 PDB_info(pdb
->debugger
);
325 static void dbg_list(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
327 TRACEDEB_MSG("dbg_list");
329 PDB_list(pdb
->debugee
, cmd
);
332 static void dbg_listbreakpoints(PDB_t
* pdb
, SHIM(const char * cmd
)) /* HEADERIZER SKIP */
334 TRACEDEB_MSG("dbg_list");
336 list_breakpoints(pdb
);
339 static void dbg_load(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
341 TRACEDEB_MSG("dbg_load");
343 PDB_load_source(pdb
->debugee
, cmd
);
346 static void dbg_next(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
348 TRACEDEB_MSG("dbg_next");
350 PDB_next(pdb
->debugee
, cmd
);
353 static void dbg_print(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
355 TRACEDEB_MSG("dbg_print");
357 PDB_print(pdb
->debugee
, cmd
);
360 static void dbg_quit(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
362 TRACEDEB_MSG("dbg_quit");
364 if (! nomoreargs(pdb
, cmd
))
367 pdb
->state
|= PDB_EXIT
;
368 pdb
->state
&= ~PDB_STOPPED
;
371 static void dbg_run(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
373 TRACEDEB_MSG("dbg_run");
375 PDB_init(pdb
->debugee
, cmd
);
376 PDB_continue(pdb
->debugee
, NULL
);
379 static void dbg_script(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
381 TRACEDEB_MSG("dbg_script");
383 PDB_script_file(pdb
->debugee
, cmd
);
386 static void dbg_stack(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
388 TRACEDEB_MSG("dbg_stack");
390 if (! nomoreargs(pdb
, cmd
))
393 PDB_backtrace(pdb
->debugee
);
396 static void dbg_trace(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
398 TRACEDEB_MSG("dbg_trace");
400 PDB_trace(pdb
->debugee
, cmd
);
403 static void dbg_watch(PDB_t
* pdb
, const char * cmd
) /* HEADERIZER SKIP */
405 TRACEDEB_MSG("dbg_watch");
407 PDB_watchpoint(pdb
->debugee
, cmd
);
411 debugger_func_t func
;
412 PARROT_OBSERVER
const char * const shorthelp
;
413 PARROT_OBSERVER
const char * const help
;
416 static const DebuggerCmd
419 "assign to a register",
420 "Assign a value to a register. For example:\n\
423 The first command sets I0 to 42 and the second sets N1 to 3.14."
428 "Set a breakpoint at a given line number (which must be specified).\n\n\
429 Optionally, specify a condition, in which case the breakpoint will only\n\
430 activate if the condition is met. Conditions take the form:\n\n\
431 if [REGISTER] [COMPARISON] [REGISTER or CONSTANT]\n\n\
434 break 10 if I4 > I3\n\n\
435 break 45 if S1 == \"foo\"\n\n\
436 The command returns a number which is the breakpoint identifier."
440 "continue the program execution",
441 "Continue the program execution.\n\n\
442 Without arguments, the program runs until a breakpoint is found\n\
443 (or until the program terminates for some other reason).\n\n\
444 If a number is specified, then skip that many breakpoints.\n\n\
445 If the program has terminated, then \"continue\" will do nothing;\n\
446 use \"run\" to re-run the program."
450 "delete a breakpoint",
451 "Delete a breakpoint.\n\n\
452 The breakpoint to delete must be specified by its breakpoint number.\n\
453 Deleted breakpoints are gone completely. If instead you want to\n\
454 temporarily disable a breakpoint, use \"disable\"."
458 "disable a breakpoint",
459 "Disable a breakpoint.\n\n\
460 The breakpoint to disable must be specified by its breakpoint number.\n\
461 Disabled breakpoints are not forgotten, but have no effect until re-enabled\n\
462 with the \"enable\" command."
466 "disassemble the bytecode",
471 "toggle echo of script commands",
472 "Toggle echo mode.\n\n\
473 In echo mode the script commands are written to stderr before executing."
477 "reenable a disabled breakpoint",
478 "Re-enable a disabled breakpoint."
482 "run an instruction",
483 "No documentation yet"
487 "toggle gcdebug mode",
488 "Toggle gcdebug mode.\n\n\
489 In gcdebug mode a garbage collection cycle is run before each opcocde,\n\
490 same as using the gcdebug core."
495 "Print a list of available commands."
499 "print interpreter information",
500 "Print information about the current interpreter"
504 "list the source code file",
505 "List the source code.\n\n\
506 Optionally specify the line number to begin the listing from and the number\n\
507 of lines to display."
509 cmd_listbreakpoints
= {
510 & dbg_listbreakpoints
,
516 "load a source code file",
517 "Load a source code file."
521 "run the next instruction",
522 "Execute a specified number of instructions.\n\n\
523 If a number is specified with the command (e.g. \"next 5\"), then\n\
524 execute that number of instructions, unless the program reaches a\n\
525 breakpoint, or stops for some other reason.\n\n\
526 If no number is specified, it defaults to 1."
530 "print the interpreter registers",
531 "Print register: e.g. \"p i2\"\n\
532 Note that the register type is case-insensitive. If no digits appear\n\
533 after the register type, all registers of that type are printed."
543 "Run (or restart) the program being debugged.\n\n\
544 Arguments specified after \"run\" are passed as command line arguments to\n\
549 "interprets a file as user commands",
550 "Interprets a file s user commands.\n\
552 (pdb) script file.script"
557 "Print a stack trace of the parrot VM"
561 "trace the next instruction",
562 "Similar to \"next\", but prints additional trace information.\n\
563 This is the same as the information you get when running Parrot with\n\
572 struct DebuggerCmdList
{
573 PARROT_OBSERVER
const char * const name
;
575 PARROT_OBSERVER
const DebuggerCmd
* const cmd
;
578 DebuggerCmdList DebCmdList
[] = {
579 { "assign", 'a', &cmd_assign
},
580 { "break", '\0', &cmd_break
},
581 { "continue", '\0', &cmd_continue
},
582 { "delete", 'd', &cmd_delete
},
583 { "disable", '\0', &cmd_disable
},
584 { "disassemble", '\0', &cmd_disassemble
},
585 { "e", '\0', &cmd_eval
},
586 { "echo", '\0', &cmd_echo
},
587 { "enable", '\0', &cmd_enable
},
588 { "eval", '\0', &cmd_eval
},
589 { "f", '\0', &cmd_script
},
590 { "gcdebug", '\0', &cmd_gcdebug
},
591 { "help", '\0', &cmd_help
},
592 { "info", '\0', &cmd_info
},
593 { "L", '\0', &cmd_listbreakpoints
},
594 { "list", 'l', &cmd_list
},
595 { "load", '\0', &cmd_load
},
596 { "next", '\0', &cmd_next
},
597 { "print", '\0', &cmd_print
},
598 { "quit", '\0', &cmd_quit
},
599 { "run", '\0', &cmd_run
},
600 { "script", '\0', &cmd_script
},
601 { "stack", 's', &cmd_stack
},
602 { "trace", '\0', &cmd_trace
},
603 { "watch", '\0', &cmd_watch
}
608 =item C<static const DebuggerCmd * get_cmd(const char **cmd)>
614 PARROT_WARN_UNUSED_RESULT
615 PARROT_CAN_RETURN_NULL
616 static const DebuggerCmd
*
617 get_cmd(ARGIN_NULLOK(const char **cmd
))
621 const char * const start
= skip_whitespace(*cmd
);
622 const char *next
= start
;
629 for (; (c
= *next
) != '\0' && !isspace((unsigned char)c
); ++next
)
634 for (i
= 0; i
< sizeof (DebCmdList
) / sizeof (DebuggerCmdList
); ++i
) {
635 const DebuggerCmdList
* const cmdlist
= DebCmdList
+ i
;
636 if (l
== 1 && cmdlist
->shortname
== (*cmd
)[0]) {
641 if (strncmp(*cmd
, cmdlist
->name
, l
) == 0) {
642 if (strlen(cmdlist
->name
) == l
) {
654 *cmd
= skip_whitespace(next
);
655 return DebCmdList
[found
].cmd
;
663 =item C<static const char * skip_whitespace(const char *cmd)>
669 PARROT_WARN_UNUSED_RESULT
670 PARROT_CANNOT_RETURN_NULL
672 skip_whitespace(ARGIN(const char *cmd
))
674 ASSERT_ARGS(skip_whitespace
)
675 while (*cmd
&& isspace((unsigned char)*cmd
))
682 =item C<static unsigned long get_uint(const char **cmd, unsigned int def)>
689 PARROT_WARN_UNUSED_RESULT
691 get_uint(ARGMOD(const char **cmd
), unsigned int def
)
693 ASSERT_ARGS(get_uint
)
695 unsigned int result
= strtoul(skip_whitespace(* cmd
), & cmdnext
, 0);
705 =item C<static unsigned long get_ulong(const char **cmd, unsigned long def)>
712 PARROT_WARN_UNUSED_RESULT
714 get_ulong(ARGMOD(const char **cmd
), unsigned long def
)
716 ASSERT_ARGS(get_ulong
)
718 unsigned long result
= strtoul(skip_whitespace(* cmd
), & cmdnext
, 0);
719 if (cmdnext
!= * cmd
)
728 =item C<static void chop_newline(char * buf)>
730 If the C string argument end with a newline, delete it.
737 chop_newline(ARGMOD(char * buf
))
739 ASSERT_ARGS(chop_newline
)
740 const size_t l
= strlen(buf
);
742 if (l
> 0 && buf
[l
- 1] == '\n')
748 =item C<static const char * nextarg(const char *command)>
750 Returns the position just past the current argument in the PASM instruction
751 C<command>. This is not the same as C<skip_command()>, which is intended for
752 debugger commands. This function is used for C<eval>.
758 PARROT_CAN_RETURN_NULL
759 PARROT_WARN_UNUSED_RESULT
761 nextarg(ARGIN_NULLOK(const char *command
))
764 /* as long as the character pointed to by command is not NULL,
765 * and it is either alphanumeric, a comma or a closing bracket,
766 * continue looking for the next argument.
769 while (isalnum((unsigned char) *command
) || *command
== ',' || *command
== ']')
772 /* eat as much space as possible */
773 command
= skip_whitespace(command
);
781 =item C<static const char * skip_command(const char *str)>
783 Returns the pointer past the current debugger command. (This is an
784 alternative to the C<skip_command()> macro above.)
790 PARROT_CANNOT_RETURN_NULL
792 skip_command(ARGIN(const char *str
))
794 ASSERT_ARGS(skip_command
)
795 /* while str is not null and it contains a command (no spaces),
798 while (*str
&& !isspace((unsigned char) *str
))
801 /* eat all space after that */
802 return skip_whitespace(str
);
807 =item C<static const char * parse_int(const char *str, int *intP)>
809 Parse an C<int> out of a string and return a pointer to just after the C<int>.
810 The output parameter C<intP> contains the parsed value.
816 PARROT_CANNOT_RETURN_NULL
817 PARROT_WARN_UNUSED_RESULT
819 parse_int(ARGIN(const char *str
), ARGOUT(int *intP
))
821 ASSERT_ARGS(parse_int
)
824 *intP
= strtol(str
, &end
, 0);
831 =item C<static const char * parse_string(PARROT_INTERP, const char *str, STRING
834 Parse a double-quoted string out of a C string and return a pointer to
835 just after the string. The parsed string is converted to a Parrot
836 C<STRING> and placed in the output parameter C<strP>.
842 PARROT_CAN_RETURN_NULL
843 PARROT_WARN_UNUSED_RESULT
845 parse_string(PARROT_INTERP
, ARGIN(const char *str
), ARGOUT(STRING
**strP
))
847 ASSERT_ARGS(parse_string
)
848 const char *string_start
;
850 /* if this is not a quoted string, there's nothing to parse */
859 /* parse while there's no closing quote */
860 while (*str
&& *str
!= '"') {
861 /* skip any potentially escaped quotes */
862 if (*str
== '\\' && str
[1])
868 /* create the output STRING */
869 *strP
= string_make(interp
, string_start
, (UINTVAL
)(str
- string_start
),
872 /* skip the closing quote */
881 =item C<static const char* parse_key(PARROT_INTERP, const char *str, PMC
884 Parse an aggregate key out of a string and return a pointer to just
885 after the key. Currently only string and integer keys are allowed.
891 PARROT_CAN_RETURN_NULL
892 PARROT_WARN_UNUSED_RESULT
894 parse_key(PARROT_INTERP
, ARGIN(const char *str
), ARGOUT(PMC
**keyP
))
896 ASSERT_ARGS(parse_key
)
897 /* clear output parameter */
900 /* make sure it's a key */
907 /* if this is a string key, create a Parrot STRING */
909 STRING
*parrot_string
;
910 str
= parse_string(interp
, str
, &parrot_string
);
911 *keyP
= key_new_string(interp
, parrot_string
);
913 /* if this is a numeric key */
914 else if (isdigit((unsigned char) *str
)) {
916 str
= parse_int(str
, &value
);
917 *keyP
= key_new_integer(interp
, (INTVAL
) value
);
919 /* unsupported case; neither a string nor a numeric key */
924 /* hm, but if this doesn't match, it's probably an error */
925 /* XXX str can be NULL from parse_string() */
929 /* skip the closing brace on the key */
935 =item C<static void debugger_cmdline(PARROT_INTERP)>
937 Debugger command line.
939 Gets and executes commands, looping until the debugger state
940 is changed, either to exit or to start executing code.
947 debugger_cmdline(PARROT_INTERP
)
949 ASSERT_ARGS(debugger_cmdline
)
950 TRACEDEB_MSG("debugger_cmdline");
952 /*while (!(interp->pdb->state & PDB_EXIT)) {*/
953 while (interp
->pdb
->state
& PDB_STOPPED
) {
954 const char * command
;
955 interp
->pdb
->state
&= ~PDB_TRACING
;
956 PDB_get_command(interp
);
957 command
= interp
->pdb
->cur_command
;
958 if (command
[0] == '\0')
959 command
= interp
->pdb
->last_command
;
961 PDB_run_command(interp
, command
);
963 TRACEDEB_MSG("debugger_cmdline finished");
968 =item C<static void close_script_file(PARROT_INTERP)>
970 Close the script file, returning to command prompt mode.
977 close_script_file(PARROT_INTERP
)
979 ASSERT_ARGS(close_script_file
)
980 TRACEDEB_MSG("Closing debugger script file");
981 if (interp
->pdb
->script_file
) {
982 fclose(interp
->pdb
->script_file
);
983 interp
->pdb
->script_file
= NULL
;
984 interp
->pdb
->state
|= PDB_STOPPED
;
985 interp
->pdb
->last_command
[0] = '\0';
986 interp
->pdb
->cur_command
[0] = '\0';
992 =item C<void Parrot_debugger_init(PARROT_INTERP)>
994 Initializes the Parrot debugger, if it's not already initialized.
1002 Parrot_debugger_init(PARROT_INTERP
)
1004 ASSERT_ARGS(Parrot_debugger_init
)
1005 TRACEDEB_MSG("Parrot_debugger_init");
1007 if (! interp
->pdb
) {
1008 PDB_t
*pdb
= mem_allocate_zeroed_typed(PDB_t
);
1009 Parrot_Interp debugger
= Parrot_new(interp
);
1011 debugger
->pdb
= pdb
;
1012 pdb
->debugee
= interp
;
1013 pdb
->debugger
= debugger
;
1015 /* Allocate space for command line buffers, NUL terminated c strings */
1016 pdb
->cur_command
= (char *)mem_sys_allocate_zeroed(DEBUG_CMD_BUFFER_LENGTH
+ 1);
1017 pdb
->last_command
= (char *)mem_sys_allocate_zeroed(DEBUG_CMD_BUFFER_LENGTH
+ 1);
1018 pdb
->file
= mem_allocate_zeroed_typed(PDB_file_t
);
1021 /* PDB_disassemble(interp, NULL); */
1023 interp
->pdb
->state
|= PDB_RUNNING
;
1028 =item C<void Parrot_debugger_destroy(PARROT_INTERP)>
1030 Destroy the current Parrot debugger instance.
1038 Parrot_debugger_destroy(PARROT_INTERP
)
1040 ASSERT_ARGS(Parrot_debugger_destroy
)
1042 Free all debugger allocated resources.
1044 PDB_t
*pdb
= interp
->pdb
;
1046 TRACEDEB_MSG("Parrot_debugger_destroy");
1049 PARROT_ASSERT(pdb
->debugee
== interp
);
1051 mem_sys_free(pdb
->last_command
);
1052 mem_sys_free(pdb
->cur_command
);
1060 =item C<void Parrot_debugger_load(PARROT_INTERP, STRING *filename)>
1062 Loads a Parrot source file for the current program.
1070 Parrot_debugger_load(PARROT_INTERP
, ARGIN_NULLOK(STRING
*filename
))
1072 ASSERT_ARGS(Parrot_debugger_load
)
1075 TRACEDEB_MSG("Parrot_debugger_load");
1078 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No debugger");
1080 file
= Parrot_str_to_cstring(interp
, filename
);
1081 PDB_load_source(interp
, file
);
1082 Parrot_str_free_cstring(file
);
1087 =item C<void Parrot_debugger_start(PARROT_INTERP, opcode_t * cur_opcode)>
1097 Parrot_debugger_start(PARROT_INTERP
, ARGIN(opcode_t
* cur_opcode
))
1099 ASSERT_ARGS(Parrot_debugger_start
)
1100 TRACEDEB_MSG("Parrot_debugger_start");
1103 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No debugger");
1105 interp
->pdb
->cur_opcode
= interp
->code
->base
.data
;
1107 if (interp
->pdb
->state
& PDB_ENTER
) {
1108 if (!interp
->pdb
->file
) {
1109 /* PDB_disassemble(interp, NULL); */
1111 interp
->pdb
->state
&= ~PDB_ENTER
;
1114 interp
->pdb
->cur_opcode
= cur_opcode
;
1116 interp
->pdb
->state
|= PDB_STOPPED
;
1118 debugger_cmdline(interp
);
1120 if (interp
->pdb
->state
& PDB_EXIT
) {
1121 TRACEDEB_MSG("Parrot_debugger_start Parrot_exit");
1122 Parrot_exit(interp
, 0);
1124 TRACEDEB_MSG("Parrot_debugger_start ends");
1129 =item C<void Parrot_debugger_break(PARROT_INTERP, opcode_t * cur_opcode)>
1131 Breaks execution and drops into the debugger. If we are already into the
1132 debugger and it is the first call, set a breakpoint.
1134 When you re run/continue the program being debugged it will pay no attention to
1137 RT #42377: clone the interpreter to allow people to play into the
1138 debugger and then continue the normal execution of the program.
1146 Parrot_debugger_break(PARROT_INTERP
, ARGIN(opcode_t
* cur_opcode
))
1148 ASSERT_ARGS(Parrot_debugger_break
)
1149 TRACEDEB_MSG("Parrot_debugger_break");
1152 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No debugger");
1154 if (!interp
->pdb
->file
)
1155 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No file loaded to debug");
1157 if (!(interp
->pdb
->state
& PDB_BREAK
)) {
1158 TRACEDEB_MSG("Parrot_debugger_break - in BREAK state");
1159 new_runloop_jump_point(interp
);
1160 if (setjmp(interp
->current_runloop
->resume
)) {
1161 fprintf(stderr
, "Unhandled exception in debugger\n");
1165 interp
->pdb
->state
|= PDB_BREAK
;
1166 interp
->pdb
->state
|= PDB_STOPPED
;
1167 interp
->pdb
->cur_opcode
= (opcode_t
*)cur_opcode
+ 1;
1169 /*PDB_set_break(interp, NULL);*/
1171 debugger_cmdline(interp
);
1173 /* RT #42378 this is not ok */
1174 /* exit(EXIT_SUCCESS); */
1177 interp
->pdb
->cur_opcode
= (opcode_t
*)cur_opcode
+ 1;
1178 /*PDB_set_break(interp, NULL);*/
1180 TRACEDEB_MSG("Parrot_debugger_break done");
1185 =item C<void PDB_get_command(PARROT_INTERP)>
1187 Get a command from the user input to execute.
1189 It saves the last command executed (in C<< pdb->last_command >>), so it
1190 first frees the old one and updates it with the current one.
1192 Also prints the next line to run if the program is still active.
1194 The user input can't be longer than DEBUG_CMD_BUFFER_LENGTH characters.
1196 The input is saved in C<< pdb->cur_command >>.
1203 PDB_get_command(PARROT_INTERP
)
1205 ASSERT_ARGS(PDB_get_command
)
1209 PDB_t
* const pdb
= interp
->pdb
;
1211 /***********************************
1216 ***********************************/
1218 /* flush the buffered data */
1221 TRACEDEB_MSG("PDB_get_command");
1223 PARROT_ASSERT(pdb
->last_command
);
1224 PARROT_ASSERT(pdb
->cur_command
);
1226 if (interp
->pdb
->script_file
) {
1227 FILE *fd
= interp
->pdb
->script_file
;
1228 char buf
[DEBUG_CMD_BUFFER_LENGTH
+1];
1232 if (fgets(buf
, DEBUG_CMD_BUFFER_LENGTH
, fd
) == NULL
) {
1233 close_script_file(interp
);
1239 fprintf(stderr
, "script (%lu): '%s'\n", pdb
->script_line
, buf
);
1243 ptr
= skip_whitespace(buf
);
1245 /* skip blank and commented lines */
1246 } while (*ptr
== '\0' || *ptr
== '#');
1248 if (pdb
->state
& PDB_ECHO
)
1249 Parrot_io_eprintf(pdb
->debugger
, "[%lu %s]\n", pdb
->script_line
, buf
);
1252 fprintf(stderr
, "(script) %s\n", buf
);
1255 strcpy(pdb
->cur_command
, buf
);
1259 /* update the last command */
1260 if (pdb
->cur_command
[0] != '\0')
1261 strcpy(pdb
->last_command
, pdb
->cur_command
);
1265 c
= pdb
->cur_command
;
1267 /*Parrot_io_eprintf(pdb->debugger, "\n(pdb) ");*/
1268 Parrot_io_eprintf(pdb
->debugger
, "\n");
1270 /* skip leading whitespace */
1274 } while (isspace((unsigned char)ch) && ch != '\n');
1277 Interp
* interpdeb
= interp
->pdb
->debugger
;
1278 STRING
* readline
= CONST_STRING(interpdeb
, "readline_interactive");
1279 STRING
* prompt
= CONST_STRING(interpdeb
, "(pdb) ");
1280 STRING
*s
= Parrot_str_new(interpdeb
, NULL
, 0);
1281 PMC
*tmp_stdin
= Parrot_io_stdhandle(interpdeb
, 0, NULL
);
1283 Parrot_PCCINVOKE(interpdeb
,
1284 tmp_stdin
, readline
,
1285 "S->S", prompt
, & s
);
1287 char * aux
= Parrot_str_to_cstring(interpdeb
, s
);
1289 Parrot_str_free_cstring(aux
);
1294 /* generate string (no more than buffer length) */
1296 while (ch != EOF && ch != '\n' && (i < DEBUG_CMD_BUFFER_LENGTH)) {
1298 ch = fgetc(tmp_stdin);
1310 =item C<void PDB_script_file(PARROT_INTERP, const char *command)>
1312 Interprets the contents of a file as user input commands
1320 PDB_script_file(PARROT_INTERP
, ARGIN(const char *command
))
1322 ASSERT_ARGS(PDB_script_file
)
1325 TRACEDEB_MSG("PDB_script_file");
1327 /* If already executing a script, close it */
1328 close_script_file(interp
);
1330 TRACEDEB_MSG("Opening debugger script file");
1332 fd
= fopen(command
, "r");
1334 Parrot_io_eprintf(interp
->pdb
->debugger
,
1335 "Error reading script file %s.\n",
1339 interp
->pdb
->script_file
= fd
;
1340 interp
->pdb
->script_line
= 0;
1341 TRACEDEB_MSG("PDB_script_file finished");
1346 =item C<int PDB_run_command(PARROT_INTERP, const char *command)>
1350 Hash the command to make a simple switch calling the correct handler.
1356 PARROT_IGNORABLE_RESULT
1358 PDB_run_command(PARROT_INTERP
, ARGIN(const char *command
))
1360 ASSERT_ARGS(PDB_run_command
)
1361 PDB_t
* const pdb
= interp
->pdb
;
1362 const DebuggerCmd
*cmd
;
1364 /* keep a pointer to the command, in case we need to report an error */
1366 const char * cmdline
= command
;
1368 TRACEDEB_MSG("PDB_run_command");
1369 cmd
= get_cmd(& cmdline
);
1372 (* cmd
->func
)(pdb
, cmdline
);
1376 if (*cmdline
== '\0') {
1380 Parrot_io_eprintf(pdb
->debugger
,
1381 "Undefined command: \"%s\"", command
);
1382 if (pdb
->script_file
)
1383 Parrot_io_eprintf(pdb
->debugger
, " in line %lu", pdb
->script_line
);
1384 Parrot_io_eprintf(pdb
->debugger
, ". Try \"help\".");
1385 close_script_file(interp
);
1393 =item C<void PDB_next(PARROT_INTERP, const char *command)>
1395 Execute the next N operation(s).
1397 Inits the program if needed, runs the next N >= 1 operations and stops.
1404 PDB_next(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1406 ASSERT_ARGS(PDB_next
)
1408 PDB_t
* const pdb
= interp
->pdb
;
1411 TRACEDEB_MSG("PDB_next");
1413 /* Init the program if it's not running */
1414 if (!(pdb
->state
& PDB_RUNNING
))
1415 PDB_init(interp
, command
);
1417 /* Get the number of operations to execute if any */
1418 n
= get_ulong(& command
, 1);
1420 /* Erase the stopped flag */
1421 pdb
->state
&= ~PDB_STOPPED
;
1423 /* Testing use of the debugger runloop */
1427 for (; n
&& pdb
->cur_opcode
; n
--)
1428 DO_OP(pdb
->cur_opcode
, pdb
->debugee
);
1430 /* Set the stopped flag */
1431 pdb
->state
|= PDB_STOPPED
;
1433 /* If program ended */
1436 * RT #46119 this doesn't handle resume opcodes
1438 if (!pdb
->cur_opcode
)
1439 (void)PDB_program_end(interp
);
1442 debugee
= pdb
->debugee
;
1444 new_runloop_jump_point(debugee
);
1445 if (setjmp(debugee
->current_runloop
->resume
)) {
1446 Parrot_io_eprintf(pdb
->debugger
, "Unhandled exception while tracing\n");
1447 pdb
->state
|= PDB_STOPPED
;
1452 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1454 TRACEDEB_MSG("PDB_next finished");
1459 =item C<void PDB_trace(PARROT_INTERP, const char *command)>
1461 Execute the next N operations; if no number is specified, it defaults to 1.
1468 PDB_trace(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1470 ASSERT_ARGS(PDB_trace
)
1472 PDB_t
* const pdb
= interp
->pdb
;
1475 TRACEDEB_MSG("PDB_trace");
1477 /* if debugger is not running yet, initialize */
1479 if (!(pdb->state & PDB_RUNNING))
1480 PDB_init(interp, command);
1483 /* ge the number of ops to run, if specified */
1484 n
= get_ulong(& command
, 1);
1486 /* clear the PDB_STOPPED flag, we'll be running n ops now */
1487 pdb
->state
&= ~PDB_STOPPED
;
1488 debugee
= pdb
->debugee
;
1491 new_runloop_jump_point(debugee
);
1492 if (setjmp(debugee
->current_runloop
->resume
)) {
1493 Parrot_io_eprintf(pdb
->debugger
, "Unhandled exception while tracing\n");
1494 pdb
->state
|= PDB_STOPPED
;
1498 pdb
->state
|= PDB_TRACING
;
1499 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1501 /* Clear the following when done some testing */
1503 /* we just stopped */
1504 pdb
->state
|= PDB_STOPPED
;
1506 /* If program ended */
1507 if (!pdb
->cur_opcode
)
1508 (void)PDB_program_end(interp
);
1509 pdb
->state
|= PDB_RUNNING
;
1510 pdb
->state
&= ~PDB_STOPPED
;
1512 TRACEDEB_MSG("PDB_trace finished");
1517 =item C<static unsigned short condition_regtype(const char *cmd)>
1523 static unsigned short
1524 condition_regtype(ARGIN(const char *cmd
))
1526 ASSERT_ARGS(condition_regtype
)
1530 return PDB_cond_int
;
1533 return PDB_cond_num
;
1536 return PDB_cond_str
;
1539 return PDB_cond_pmc
;
1547 =item C<PDB_condition_t * PDB_cond(PARROT_INTERP, const char *command)>
1549 Analyzes a condition from the user input.
1555 PARROT_CAN_RETURN_NULL
1557 PDB_cond(PARROT_INTERP
, ARGIN(const char *command
))
1559 ASSERT_ARGS(PDB_cond
)
1560 PDB_condition_t
*condition
;
1562 char str
[DEBUG_CMD_BUFFER_LENGTH
+ 1];
1563 unsigned short cond_argleft
;
1564 unsigned short cond_type
;
1565 unsigned char regleft
;
1568 TRACEDEB_MSG("PDB_cond");
1570 /* Return if no more arguments */
1571 if (!(command
&& *command
)) {
1572 Parrot_io_eprintf(interp
->pdb
->debugger
, "No condition specified\n");
1576 command
= skip_whitespace(command
);
1578 fprintf(stderr
, "PDB_trace: '%s'\n", command
);
1581 cond_argleft
= condition_regtype(command
);
1583 /* get the register number */
1585 regleft
= (unsigned char)get_uint(&command
, 0);
1586 if (auxcmd
== command
) {
1587 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid register\n");
1591 /* Now the condition */
1592 command
= skip_whitespace(command
);
1595 if (*(command
+ 1) == '=')
1596 cond_type
= PDB_cond_ge
;
1598 cond_type
= PDB_cond_gt
;
1601 if (*(command
+ 1) == '=')
1602 cond_type
= PDB_cond_le
;
1604 cond_type
= PDB_cond_lt
;
1607 if (*(command
+ 1) == '=')
1608 cond_type
= PDB_cond_eq
;
1613 if (*(command
+ 1) == '=')
1614 cond_type
= PDB_cond_ne
;
1619 if (cond_argleft
!= PDB_cond_str
&& cond_argleft
!= PDB_cond_pmc
) {
1620 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid null condition\n");
1623 cond_type
= PDB_cond_notnull
;
1626 INV_COND
: Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid condition\n");
1630 /* if there's an '=', skip it */
1631 if (*(command
+ 1) == '=')
1636 command
= skip_whitespace(command
);
1638 /* return if no notnull condition and no more arguments */
1639 if (!(command
&& *command
) && (cond_type
!= PDB_cond_notnull
)) {
1640 Parrot_io_eprintf(interp
->pdb
->debugger
, "Can't compare a register with nothing\n");
1644 /* Allocate new condition */
1645 condition
= mem_allocate_zeroed_typed(PDB_condition_t
);
1647 condition
->type
= cond_argleft
| cond_type
;
1649 if (cond_type
!= PDB_cond_notnull
) {
1651 if (isalpha((unsigned char)*command
)) {
1652 /* It's a register - we first check that it's the correct type */
1654 unsigned short cond_argright
= condition_regtype(command
);
1656 if (cond_argright
!= cond_argleft
) {
1657 Parrot_io_eprintf(interp
->pdb
->debugger
, "Register types don't agree\n");
1658 mem_sys_free(condition
);
1662 /* Now we check and store the register number */
1664 reg_number
= (int)get_uint(&command
, 0);
1665 if (auxcmd
== command
) {
1666 Parrot_io_eprintf(interp
->pdb
->debugger
, "Invalid register\n");
1667 mem_sys_free(condition
);
1671 if (reg_number
< 0) {
1672 Parrot_io_eprintf(interp
->pdb
->debugger
, "Out-of-bounds register\n");
1673 mem_sys_free(condition
);
1677 condition
->value
= mem_allocate_typed(int);
1678 *(int *)condition
->value
= reg_number
;
1680 /* If the first argument was an integer */
1681 else if (condition
->type
& PDB_cond_int
) {
1682 /* This must be either an integer constant or register */
1683 condition
->value
= mem_allocate_typed(INTVAL
);
1684 *(INTVAL
*)condition
->value
= (INTVAL
)atoi(command
);
1685 condition
->type
|= PDB_cond_const
;
1687 else if (condition
->type
& PDB_cond_num
) {
1688 condition
->value
= mem_allocate_typed(FLOATVAL
);
1689 *(FLOATVAL
*)condition
->value
= (FLOATVAL
)atof(command
);
1690 condition
->type
|= PDB_cond_const
;
1692 else if (condition
->type
& PDB_cond_str
) {
1693 for (i
= 1; ((command
[i
] != '"') && (i
< DEBUG_CMD_BUFFER_LENGTH
)); i
++)
1694 str
[i
- 1] = command
[i
];
1697 fprintf(stderr
, "PDB_break: '%s'\n", str
);
1699 condition
->value
= string_make(interp
, str
, (UINTVAL
)(i
- 1),
1702 condition
->type
|= PDB_cond_const
;
1704 else if (condition
->type
& PDB_cond_pmc
) {
1705 /* RT #46123 Need to figure out what to do in this case.
1706 * For the time being, we just bail. */
1707 Parrot_io_eprintf(interp
->pdb
->debugger
, "Can't compare PMC with constant\n");
1708 mem_sys_free(condition
);
1719 =item C<void PDB_watchpoint(PARROT_INTERP, const char *command)>
1728 PDB_watchpoint(PARROT_INTERP
, ARGIN(const char *command
))
1730 ASSERT_ARGS(PDB_watchpoint
)
1731 PDB_t
* const pdb
= interp
->pdb
;
1732 PDB_condition_t
* const condition
= PDB_cond(interp
, command
);
1737 /* Add it to the head of the list */
1738 if (pdb
->watchpoint
)
1739 condition
->next
= pdb
->watchpoint
;
1740 pdb
->watchpoint
= condition
;
1741 fprintf(stderr
, "Adding watchpoint\n");
1746 =item C<void PDB_set_break(PARROT_INTERP, const char *command)>
1748 Set a break point, the source code file must be loaded.
1755 PDB_set_break(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1757 ASSERT_ARGS(PDB_set_break
)
1758 PDB_t
* const pdb
= interp
->pdb
;
1759 PDB_breakpoint_t
*newbreak
;
1760 PDB_breakpoint_t
**lbreak
;
1761 PDB_line_t
*line
= NULL
;
1763 opcode_t
*breakpos
= NULL
;
1765 unsigned long ln
= get_ulong(& command
, 0);
1767 TRACEDEB_MSG("PDB_set_break");
1769 /* If there is a source file use line number, else opcode position */
1773 TRACEDEB_MSG("PDB_set_break file");
1775 if (!pdb
->file
->size
) {
1776 Parrot_io_eprintf(pdb
->debugger
,
1777 "Can't set a breakpoint in empty file\n");
1781 /* If no line number was specified, set it at the current line */
1785 /* Move to the line where we will set the break point */
1786 line
= pdb
->file
->line
;
1788 for (i
= 1; ((i
< ln
) && (line
->next
)); i
++)
1791 /* Abort if the line number provided doesn't exist */
1792 if (line
== NULL
|| !line
->next
) {
1793 Parrot_io_eprintf(pdb
->debugger
,
1794 "Can't set a breakpoint at line number %li\n", ln
);
1799 /* Get the line to set it */
1800 line
= pdb
->file
->line
;
1802 TRACEDEB_MSG("PDB_set_break reading ops");
1803 while (line
->opcode
!= pdb
->cur_opcode
) {
1806 Parrot_io_eprintf(pdb
->debugger
,
1807 "No current line found and no line number specified\n");
1812 /* Skip lines that are not related to an opcode */
1813 while (line
&& !line
->opcode
)
1815 /* Abort if the line number provided doesn't exist */
1817 Parrot_io_eprintf(pdb
->debugger
,
1818 "Can't set a breakpoint at line number %li\n", ln
);
1822 breakpos
= line
->opcode
;
1825 TRACEDEB_MSG("PDB_set_break no file");
1826 breakpos
= interp
->code
->base
.data
+ ln
;
1829 TRACEDEB_MSG("PDB_set_break allocate breakpoint");
1830 /* Allocate the new break point */
1831 newbreak
= mem_allocate_zeroed_typed(PDB_breakpoint_t
);
1834 /*command = skip_command(command);*/
1837 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
1838 "NULL command passed to PDB_set_break");
1841 /* if there is another argument to break, besides the line number,
1842 * it should be an 'if', so we call another handler. */
1843 if (command
&& *command
) {
1844 command
= skip_whitespace(command
);
1845 while (! isspace((unsigned char)*command
))
1847 command
= skip_whitespace(command
);
1848 newbreak
->condition
= PDB_cond(interp
, command
);
1851 /* Set the address where to stop */
1852 newbreak
->pc
= breakpos
;
1854 /* No next breakpoint */
1855 newbreak
->next
= NULL
;
1857 /* Don't skip (at least initially) */
1860 /* Add the breakpoint to the end of the list */
1862 lbreak
= & pdb
->breakpoint
;
1864 bp_id
= (*lbreak
)->id
+ 1;
1865 lbreak
= & (*lbreak
)->next
;
1867 newbreak
->prev
= *lbreak
;
1869 newbreak
->id
= bp_id
;
1871 /* Show breakpoint position */
1873 Parrot_io_eprintf(pdb
->debugger
, "Breakpoint %li at", newbreak
->id
);
1875 Parrot_io_eprintf(pdb
->debugger
, " line %li", line
->number
);
1876 Parrot_io_eprintf(pdb
->debugger
, " pos %li\n", newbreak
->pc
- interp
->code
->base
.data
);
1881 =item C<static void list_breakpoints(PDB_t *pdb)>
1888 list_breakpoints(ARGIN(PDB_t
*pdb
))
1890 ASSERT_ARGS(list_breakpoints
)
1892 PDB_breakpoint_t
**lbreak
;
1893 for (lbreak
= & pdb
->breakpoint
; *lbreak
; lbreak
= & (*lbreak
)->next
) {
1894 PDB_breakpoint_t
*br
= *lbreak
;
1895 Parrot_io_eprintf(pdb
->debugger
, "Breakpoint %li at", br
->id
);
1896 Parrot_io_eprintf(pdb
->debugger
, " pos %li", br
->pc
- pdb
->debugee
->code
->base
.data
);
1898 Parrot_io_eprintf(pdb
->debugger
, " (disabled)");
1899 Parrot_io_eprintf(pdb
->debugger
, "\n");
1905 =item C<void PDB_init(PARROT_INTERP, const char *command)>
1914 PDB_init(PARROT_INTERP
, SHIM(const char *command
))
1916 ASSERT_ARGS(PDB_init
)
1917 PDB_t
* const pdb
= interp
->pdb
;
1919 /* Restart if we are already running */
1920 if (pdb
->state
& PDB_RUNNING
)
1921 Parrot_io_eprintf(pdb
->debugger
, "Restarting\n");
1923 /* Add the RUNNING state */
1924 pdb
->state
|= PDB_RUNNING
;
1929 =item C<void PDB_continue(PARROT_INTERP, const char *command)>
1931 Continue running the program. If a number is specified, skip that many
1939 PDB_continue(PARROT_INTERP
, ARGIN_NULLOK(const char *command
))
1941 ASSERT_ARGS(PDB_continue
)
1942 PDB_t
* const pdb
= interp
->pdb
;
1943 unsigned long ln
= 0;
1945 TRACEDEB_MSG("PDB_continue");
1947 /* Skip any breakpoint? */
1949 ln
= get_ulong(& command
, 0);
1952 if (!pdb
->breakpoint
) {
1953 Parrot_io_eprintf(pdb
->debugger
, "No breakpoints to skip\n");
1957 PDB_skip_breakpoint(interp
, ln
);
1960 /* Run while no break point is reached */
1962 while (!PDB_break(interp))
1963 DO_OP(pdb->cur_opcode, pdb->debugee);
1968 Parrot_runcore_switch(pdb
->debugee
, CONST_STRING(interp
, "debugger"));
1970 new_internal_exception(pdb
->debugee
);
1971 if (setjmp(pdb
->debugee
->exceptions
->destination
)) {
1972 Parrot_io_eprintf(pdb
->debugee
, "Unhandled exception while debugging: %Ss\n",
1973 pdb
->debugee
->exceptions
->msg
);
1974 pdb
->state
|= PDB_STOPPED
;
1977 runops_int(pdb
->debugee
, pdb
->debugee
->code
->base
.data
- pdb
->cur_opcode
);
1978 if (!pdb
->cur_opcode
)
1979 (void)PDB_program_end(interp
);
1981 pdb
->state
|= PDB_RUNNING
;
1982 pdb
->state
&= ~PDB_BREAK
;
1983 pdb
->state
&= ~PDB_STOPPED
;
1988 =item C<PDB_breakpoint_t * PDB_find_breakpoint(PARROT_INTERP, const char
1991 Find breakpoint number N; returns C<NULL> if the breakpoint doesn't
1992 exist or if no breakpoint was specified.
1998 PARROT_CAN_RETURN_NULL
1999 PARROT_WARN_UNUSED_RESULT
2001 PDB_find_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2003 ASSERT_ARGS(PDB_find_breakpoint
)
2004 const char *oldcmd
= command
;
2005 const unsigned long n
= get_ulong(&command
, 0);
2006 if (command
!= oldcmd
) {
2007 PDB_breakpoint_t
*breakpoint
= interp
->pdb
->breakpoint
;
2009 while (breakpoint
&& breakpoint
->id
!= n
)
2010 breakpoint
= breakpoint
->next
;
2013 Parrot_io_eprintf(interp
->pdb
->debugger
, "No breakpoint number %ld", n
);
2020 /* Report an appropriate error */
2022 Parrot_io_eprintf(interp
->pdb
->debugger
, "Not a valid breakpoint");
2024 Parrot_io_eprintf(interp
->pdb
->debugger
, "No breakpoint specified");
2032 =item C<void PDB_disable_breakpoint(PARROT_INTERP, const char *command)>
2034 Disable a breakpoint; it can be reenabled with the enable command.
2041 PDB_disable_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2043 ASSERT_ARGS(PDB_disable_breakpoint
)
2044 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2046 /* if the breakpoint exists, disable it. */
2048 breakpoint
->skip
= -1;
2053 =item C<void PDB_enable_breakpoint(PARROT_INTERP, const char *command)>
2055 Reenable a disabled breakpoint; if the breakpoint was not disabled, has
2063 PDB_enable_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2065 ASSERT_ARGS(PDB_enable_breakpoint
)
2066 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2068 /* if the breakpoint exists, and it was disabled, enable it. */
2069 if (breakpoint
&& breakpoint
->skip
== -1)
2070 breakpoint
->skip
= 0;
2075 =item C<void PDB_delete_breakpoint(PARROT_INTERP, const char *command)>
2077 Delete a breakpoint.
2084 PDB_delete_breakpoint(PARROT_INTERP
, ARGIN(const char *command
))
2086 ASSERT_ARGS(PDB_delete_breakpoint
)
2087 PDB_breakpoint_t
* const breakpoint
= PDB_find_breakpoint(interp
, command
);
2088 const PDB_line_t
*line
;
2092 if (!interp
->pdb
->file
)
2093 Parrot_ex_throw_from_c_args(interp
, NULL
, 0, "No file loaded");
2095 line
= interp
->pdb
->file
->line
;
2096 while (line
->opcode
!= breakpoint
->pc
)
2099 /* Delete the condition structure, if there is one */
2100 if (breakpoint
->condition
) {
2101 PDB_delete_condition(interp
, breakpoint
);
2102 breakpoint
->condition
= NULL
;
2105 /* Remove the breakpoint from the list */
2106 if (breakpoint
->prev
&& breakpoint
->next
) {
2107 breakpoint
->prev
->next
= breakpoint
->next
;
2108 breakpoint
->next
->prev
= breakpoint
->prev
;
2110 else if (breakpoint
->prev
&& !breakpoint
->next
) {
2111 breakpoint
->prev
->next
= NULL
;
2113 else if (!breakpoint
->prev
&& breakpoint
->next
) {
2114 breakpoint
->next
->prev
= NULL
;
2115 interp
->pdb
->breakpoint
= breakpoint
->next
;
2118 interp
->pdb
->breakpoint
= NULL
;
2120 bp_id
= breakpoint
->id
;
2121 /* Kill the breakpoint */
2122 mem_sys_free(breakpoint
);
2124 Parrot_io_eprintf(interp
->pdb
->debugger
, "Breakpoint %li deleted\n", bp_id
);
2130 =item C<void PDB_delete_condition(PARROT_INTERP, PDB_breakpoint_t *breakpoint)>
2132 Delete a condition associated with a breakpoint.
2139 PDB_delete_condition(SHIM_INTERP
, ARGMOD(PDB_breakpoint_t
*breakpoint
))
2141 ASSERT_ARGS(PDB_delete_condition
)
2142 if (breakpoint
->condition
->value
) {
2143 if (breakpoint
->condition
->type
& PDB_cond_str
) {
2144 /* 'value' is a string, so we need to be careful */
2145 PObj_external_CLEAR((STRING
*)breakpoint
->condition
->value
);
2146 PObj_on_free_list_SET((STRING
*)breakpoint
->condition
->value
);
2147 /* it should now be properly garbage collected after
2148 we destroy the condition */
2151 /* 'value' is a float or an int, so we can just free it */
2152 mem_sys_free(breakpoint
->condition
->value
);
2153 breakpoint
->condition
->value
= NULL
;
2157 mem_sys_free(breakpoint
->condition
);
2158 breakpoint
->condition
= NULL
;
2163 =item C<void PDB_skip_breakpoint(PARROT_INTERP, unsigned long i)>
2165 Skip C<i> times all breakpoints.
2172 PDB_skip_breakpoint(PARROT_INTERP
, unsigned long i
)
2174 ASSERT_ARGS(PDB_skip_breakpoint
)
2176 fprintf(stderr
, "PDB_skip_breakpoint: %li\n", i
);
2179 interp
->pdb
->breakpoint_skip
= i
;
2184 =item C<char PDB_program_end(PARROT_INTERP)>
2193 PDB_program_end(PARROT_INTERP
)
2195 ASSERT_ARGS(PDB_program_end
)
2196 PDB_t
* const pdb
= interp
->pdb
;
2198 TRACEDEB_MSG("PDB_program_end");
2200 /* Remove the RUNNING state */
2201 pdb
->state
&= ~PDB_RUNNING
;
2203 Parrot_io_eprintf(pdb
->debugger
, "Program exited.\n");
2209 =item C<char PDB_check_condition(PARROT_INTERP, const PDB_condition_t
2212 Returns true if the condition was met.
2218 PARROT_WARN_UNUSED_RESULT
2220 PDB_check_condition(PARROT_INTERP
, ARGIN(const PDB_condition_t
*condition
))
2222 ASSERT_ARGS(PDB_check_condition
)
2223 PMC
*ctx
= CURRENT_CONTEXT(interp
);
2225 TRACEDEB_MSG("PDB_check_condition");
2229 if (condition
->type
& PDB_cond_int
) {
2231 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_INT
))
2233 i
= CTX_REG_INT(ctx
, condition
->reg
);
2235 if (condition
->type
& PDB_cond_const
)
2236 j
= *(INTVAL
*)condition
->value
;
2238 j
= REG_INT(interp
, *(int *)condition
->value
);
2240 if (((condition
->type
& PDB_cond_gt
) && (i
> j
)) ||
2241 ((condition
->type
& PDB_cond_ge
) && (i
>= j
)) ||
2242 ((condition
->type
& PDB_cond_eq
) && (i
== j
)) ||
2243 ((condition
->type
& PDB_cond_ne
) && (i
!= j
)) ||
2244 ((condition
->type
& PDB_cond_le
) && (i
<= j
)) ||
2245 ((condition
->type
& PDB_cond_lt
) && (i
< j
)))
2250 else if (condition
->type
& PDB_cond_num
) {
2253 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_NUM
))
2255 k
= CTX_REG_NUM(ctx
, condition
->reg
);
2257 if (condition
->type
& PDB_cond_const
)
2258 l
= *(FLOATVAL
*)condition
->value
;
2260 l
= REG_NUM(interp
, *(int *)condition
->value
);
2262 if (((condition
->type
& PDB_cond_gt
) && (k
> l
)) ||
2263 ((condition
->type
& PDB_cond_ge
) && (k
>= l
)) ||
2264 ((condition
->type
& PDB_cond_eq
) && (k
== l
)) ||
2265 ((condition
->type
& PDB_cond_ne
) && (k
!= l
)) ||
2266 ((condition
->type
& PDB_cond_le
) && (k
<= l
)) ||
2267 ((condition
->type
& PDB_cond_lt
) && (k
< l
)))
2272 else if (condition
->type
& PDB_cond_str
) {
2275 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_STR
))
2277 m
= CTX_REG_STR(ctx
, condition
->reg
);
2279 if (condition
->type
& PDB_cond_notnull
)
2280 return ! STRING_IS_NULL(m
);
2282 if (condition
->type
& PDB_cond_const
)
2283 n
= (STRING
*)condition
->value
;
2285 n
= REG_STR(interp
, *(int *)condition
->value
);
2287 if (((condition
->type
& PDB_cond_gt
) &&
2288 (Parrot_str_compare(interp
, m
, n
) > 0)) ||
2289 ((condition
->type
& PDB_cond_ge
) &&
2290 (Parrot_str_compare(interp
, m
, n
) >= 0)) ||
2291 ((condition
->type
& PDB_cond_eq
) &&
2292 (Parrot_str_compare(interp
, m
, n
) == 0)) ||
2293 ((condition
->type
& PDB_cond_ne
) &&
2294 (Parrot_str_compare(interp
, m
, n
) != 0)) ||
2295 ((condition
->type
& PDB_cond_le
) &&
2296 (Parrot_str_compare(interp
, m
, n
) <= 0)) ||
2297 ((condition
->type
& PDB_cond_lt
) &&
2298 (Parrot_str_compare(interp
, m
, n
) < 0)))
2303 else if (condition
->type
& PDB_cond_pmc
) {
2306 if (condition
->reg
>= Parrot_pcc_get_regs_used(interp
, ctx
, REGNO_PMC
))
2308 m
= CTX_REG_PMC(ctx
, condition
->reg
);
2310 if (condition
->type
& PDB_cond_notnull
)
2311 return ! PMC_IS_NULL(m
);
2320 =item C<static PDB_breakpoint_t * current_breakpoint(PDB_t * pdb)>
2322 Returns a pointer to the breakpoint at the current position,
2323 or NULL if there is none.
2329 PARROT_CAN_RETURN_NULL
2330 static PDB_breakpoint_t
*
2331 current_breakpoint(ARGIN(PDB_t
* pdb
))
2333 ASSERT_ARGS(current_breakpoint
)
2334 PDB_breakpoint_t
*breakpoint
= pdb
->breakpoint
;
2335 while (breakpoint
) {
2336 if (pdb
->cur_opcode
== breakpoint
->pc
)
2338 breakpoint
= breakpoint
->next
;
2345 =item C<char PDB_break(PARROT_INTERP)>
2347 Returns true if we have to stop running.
2353 PARROT_WARN_UNUSED_RESULT
2355 PDB_break(PARROT_INTERP
)
2357 ASSERT_ARGS(PDB_break
)
2358 PDB_t
* const pdb
= interp
->pdb
;
2359 PDB_condition_t
*watchpoint
= pdb
->watchpoint
;
2360 PDB_breakpoint_t
*breakpoint
;
2363 TRACEDEB_MSG("PDB_break");
2366 /* Check the watchpoints first. */
2367 while (watchpoint
) {
2368 if (PDB_check_condition(interp
, watchpoint
)) {
2369 pdb
->state
|= PDB_STOPPED
;
2373 watchpoint
= watchpoint
->next
;
2376 /* If program ended */
2377 if (!pdb
->cur_opcode
)
2378 return PDB_program_end(interp
);
2380 /* If the program is STOPPED allow it to continue */
2381 if (pdb
->state
& PDB_STOPPED
) {
2382 pdb
->state
&= ~PDB_STOPPED
;
2386 breakpoint
= current_breakpoint(pdb
);
2388 /* If we have to skip breakpoints, do so. */
2389 if (pdb
->breakpoint_skip
) {
2390 TRACEDEB_MSG("PDB_break skipping");
2391 pdb
->breakpoint_skip
--;
2395 if (breakpoint
->skip
< 0)
2398 /* Check if there is a condition for this breakpoint */
2399 if ((breakpoint
->condition
) &&
2400 (!PDB_check_condition(interp
, breakpoint
->condition
)))
2403 TRACEDEB_MSG("PDB_break stopping");
2405 /* Add the STOPPED state and stop */
2406 pdb
->state
|= PDB_STOPPED
;
2415 =item C<char * PDB_escape(const char *string, UINTVAL length)>
2417 Escapes C<">, C<\r>, C<\n>, C<\t>, C<\a> and C<\\>.
2419 The returned string must be freed.
2425 PARROT_WARN_UNUSED_RESULT
2426 PARROT_CAN_RETURN_NULL
2429 PDB_escape(ARGIN(const char *string
), UINTVAL length
)
2431 ASSERT_ARGS(PDB_escape
)
2435 length
= length
> 20 ? 20 : length
;
2436 end
= string
+ length
;
2438 /* Return if there is no string to escape*/
2442 fill
= _new
= (char *)mem_sys_allocate(length
* 2 + 1);
2444 for (; string
< end
; string
++) {
2475 *(fill
++) = *string
;
2487 =item C<int PDB_unescape(char *string)>
2489 Do inplace unescape of C<\r>, C<\n>, C<\t>, C<\a> and C<\\>.
2496 PDB_unescape(ARGMOD(char *string
))
2498 ASSERT_ARGS(PDB_unescape
)
2501 for (; *string
; string
++) {
2504 if (*string
== '\\') {
2508 switch (string
[1]) {
2530 for (i
= 1; fill
[i
+ 1]; i
++)
2531 fill
[i
] = fill
[i
+ 1];
2542 =item C<size_t PDB_disassemble_op(PARROT_INTERP, char *dest, size_t space, const
2543 op_info_t *info, const opcode_t *op, PDB_file_t *file, const opcode_t
2544 *code_start, int full_name)>
2553 PDB_disassemble_op(PARROT_INTERP
, ARGOUT(char *dest
), size_t space
,
2554 ARGIN(const op_info_t
*info
), ARGIN(const opcode_t
*op
),
2555 ARGMOD_NULLOK(PDB_file_t
*file
), ARGIN_NULLOK(const opcode_t
*code_start
),
2558 ASSERT_ARGS(PDB_disassemble_op
)
2563 /* Write the opcode name */
2564 const char * p
= full_name
? info
->full_name
: info
->name
;
2566 TRACEDEB_MSG("PDB_disassemble_op");
2575 /* Concat the arguments */
2576 for (j
= 1; j
< info
->op_count
; j
++) {
2580 PARROT_ASSERT(size
+ 2 < space
);
2582 switch (info
->types
[j
- 1]) {
2596 /* If the opcode jumps and this is the last argument,
2597 that means this is a label */
2598 if ((j
== info
->op_count
- 1) &&
2599 (info
->jump
& PARROT_JUMP_RELATIVE
)) {
2602 i
= PDB_add_label(file
, op
, op
[j
]);
2604 else if (code_start
) {
2607 i
= op
[j
] + (op
- code_start
);
2616 /* Convert the integer to a string */
2621 PARROT_ASSERT(size
+ 20 < space
);
2623 size
+= sprintf(&dest
[size
], INTVAL_FMT
, i
);
2628 /* Convert the float to a string */
2629 const FLOATVAL f
= interp
->code
->const_table
->constants
[op
[j
]]->u
.number
;
2630 Parrot_snprintf(interp
, buf
, sizeof (buf
), FLOATVAL_FMT
, f
);
2631 strcpy(&dest
[size
], buf
);
2632 size
+= strlen(buf
);
2637 if (interp
->code
->const_table
->constants
[op
[j
]]-> u
.string
->strlen
) {
2638 char * const escaped
=
2639 PDB_escape(interp
->code
->const_table
->
2640 constants
[op
[j
]]->u
.string
->strstart
,
2641 interp
->code
->const_table
->
2642 constants
[op
[j
]]->u
.string
->strlen
);
2644 strcpy(&dest
[size
], escaped
);
2645 size
+= strlen(escaped
);
2646 mem_sys_free(escaped
);
2652 Parrot_snprintf(interp
, buf
, sizeof (buf
), "PMC_CONST(%d)", op
[j
]);
2653 strcpy(&dest
[size
], buf
);
2654 size
+= strlen(buf
);
2657 dest
[size
- 1] = '[';
2658 Parrot_snprintf(interp
, buf
, sizeof (buf
), "P" INTVAL_FMT
, op
[j
]);
2659 strcpy(&dest
[size
], buf
);
2660 size
+= strlen(buf
);
2665 PMC
* k
= interp
->code
->const_table
->constants
[op
[j
]]->u
.key
;
2666 dest
[size
- 1] = '[';
2668 switch (PObj_get_FLAGS(k
)) {
2671 case KEY_integer_FLAG
:
2672 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2673 INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2674 strcpy(&dest
[size
], buf
);
2675 size
+= strlen(buf
);
2677 case KEY_number_FLAG
:
2678 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2679 FLOATVAL_FMT
, VTABLE_get_number(interp
, k
));
2680 strcpy(&dest
[size
], buf
);
2681 size
+= strlen(buf
);
2683 case KEY_string_FLAG
:
2686 char * const temp
= Parrot_str_to_cstring(interp
,
2687 VTABLE_get_string(interp
, k
));
2688 strcpy(&dest
[size
], temp
);
2689 Parrot_str_free_cstring(temp
);
2691 size
+= Parrot_str_byte_length(interp
,
2692 VTABLE_get_string(interp
, (k
)));
2695 case KEY_integer_FLAG
|KEY_register_FLAG
:
2696 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2697 "I" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2698 strcpy(&dest
[size
], buf
);
2699 size
+= strlen(buf
);
2701 case KEY_number_FLAG
|KEY_register_FLAG
:
2702 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2703 "N" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2704 strcpy(&dest
[size
], buf
);
2705 size
+= strlen(buf
);
2707 case KEY_string_FLAG
|KEY_register_FLAG
:
2708 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2709 "S" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2710 strcpy(&dest
[size
], buf
);
2711 size
+= strlen(buf
);
2713 case KEY_pmc_FLAG
|KEY_register_FLAG
:
2714 Parrot_snprintf(interp
, buf
, sizeof (buf
),
2715 "P" INTVAL_FMT
, VTABLE_get_integer(interp
, k
));
2716 strcpy(&dest
[size
], buf
);
2717 size
+= strlen(buf
);
2723 GETATTR_Key_next_key(interp
, k
, k
);
2731 dest
[size
- 1] = '[';
2732 Parrot_snprintf(interp
, buf
, sizeof (buf
), "I" INTVAL_FMT
, op
[j
]);
2733 strcpy(&dest
[size
], buf
);
2734 size
+= strlen(buf
);
2737 case PARROT_ARG_KIC
:
2738 dest
[size
- 1] = '[';
2739 Parrot_snprintf(interp
, buf
, sizeof (buf
), INTVAL_FMT
, op
[j
]);
2740 strcpy(&dest
[size
], buf
);
2741 size
+= strlen(buf
);
2745 Parrot_ex_throw_from_c_args(interp
, NULL
, 1, "Unknown opcode type");
2748 if (j
!= info
->op_count
- 1)
2752 /* Special decoding for the signature used in args/returns. Such ops have
2753 one fixed parameter (the signature vector), plus a varying number of
2754 registers/constants. For each arg/return, we show the register and its
2755 flags using PIR syntax. */
2756 if (*(op
) == PARROT_OP_set_args_pc
|| *(op
) == PARROT_OP_set_returns_pc
)
2759 /* if it's a retrieving op, specialop = 2, so that later a :flat flag
2760 * can be changed into a :slurpy flag. See flag handling below.
2762 if (*(op
) == PARROT_OP_get_results_pc
|| *(op
) == PARROT_OP_get_params_pc
)
2765 if (specialop
> 0) {
2767 PMC
* const sig
= interp
->code
->const_table
->constants
[op
[1]]->u
.key
;
2768 const int n_values
= VTABLE_elements(interp
, sig
);
2769 /* The flag_names strings come from Call_bits_enum_t (with which it
2770 should probably be colocated); they name the bits from LSB to MSB.
2771 The two least significant bits are not flags; they are the register
2772 type, which is decoded elsewhere. We also want to show unused bits,
2773 which could indicate problems.
2775 PARROT_OBSERVER
const char * const flag_names
[] = {
2781 " :flat", /* should be :slurpy for args */
2790 /* Register decoding. It would be good to abstract this, too. */
2791 PARROT_OBSERVER
static const char regs
[] = "ISPN";
2793 for (j
= 0; j
< n_values
; j
++) {
2795 const int sig_value
= VTABLE_get_integer_keyed_int(interp
, sig
, j
);
2797 /* Print the register name, e.g. P37. */
2800 buf
[idx
++] = regs
[sig_value
& PARROT_ARG_TYPE_MASK
];
2801 Parrot_snprintf(interp
, &buf
[idx
], sizeof (buf
)-idx
,
2802 INTVAL_FMT
, op
[j
+2]);
2805 /* Add flags, if we have any. */
2808 int flags
= sig_value
;
2810 /* End when we run out of flags, off the end of flag_names, or
2811 * get too close to the end of buf.
2812 * 100 is just an estimate of all buf lengths added together.
2814 while (flags
&& idx
< sizeof (buf
) - 100) {
2815 const char * const flag_string
2816 = (specialop
== 2 && STREQ(flag_names
[flag_idx
], " :flat"))
2818 : flag_names
[flag_idx
];
2822 if (flags
& 1 && *flag_string
) {
2823 const size_t n
= strlen(flag_string
);
2824 strcpy(&buf
[idx
], flag_string
);
2832 /* Add it to dest. */
2834 strcpy(&dest
[size
], buf
);
2835 size
+= strlen(buf
);
2845 =item C<void PDB_disassemble(PARROT_INTERP, const char *command)>
2847 Disassemble the bytecode.
2854 PDB_disassemble(PARROT_INTERP
, SHIM(const char *command
))
2856 ASSERT_ARGS(PDB_disassemble
)
2857 PDB_t
* const pdb
= interp
->pdb
;
2858 opcode_t
* pc
= interp
->code
->base
.data
;
2861 PDB_line_t
*pline
, *newline
;
2865 const unsigned int default_size
= 32768;
2866 size_t space
; /* How much space do we have? */
2867 size_t size
, alloced
, n
;
2869 TRACEDEB_MSG("PDB_disassemble");
2871 pfile
= mem_allocate_zeroed_typed(PDB_file_t
);
2872 pline
= mem_allocate_zeroed_typed(PDB_line_t
);
2874 /* If we already got a source, free it */
2876 PDB_free_file(interp
, pdb
->file
);
2880 pfile
->line
= pline
;
2882 pfile
->source
= (char *)mem_sys_allocate(default_size
);
2884 alloced
= space
= default_size
;
2885 code_end
= pc
+ interp
->code
->base
.size
;
2887 while (pc
!= code_end
) {
2889 if (space
< default_size
) {
2890 alloced
+= default_size
;
2891 space
+= default_size
;
2892 pfile
->source
= (char *)mem_sys_realloc(pfile
->source
, alloced
);
2895 size
= PDB_disassemble_op(interp
, pfile
->source
+ pfile
->size
,
2896 space
, &interp
->op_info_table
[*pc
], pc
, pfile
, NULL
, 1);
2898 pfile
->size
+= size
;
2899 pfile
->source
[pfile
->size
- 1] = '\n';
2901 /* Store the opcode of this line */
2903 n
= interp
->op_info_table
[*pc
].op_count
;
2905 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
2908 /* Prepare for next line */
2909 newline
= mem_allocate_typed(PDB_line_t
);
2910 newline
->label
= NULL
;
2911 newline
->next
= NULL
;
2912 newline
->number
= pline
->number
+ 1;
2913 pline
->next
= newline
;
2915 pline
->source_offset
= pfile
->size
;
2918 /* Add labels to the lines they belong to */
2919 label
= pfile
->label
;
2922 /* Get the line to apply the label */
2923 pline
= pfile
->line
;
2925 while (pline
&& pline
->opcode
!= label
->opcode
)
2926 pline
= pline
->next
;
2929 Parrot_io_eprintf(pdb
->debugger
,
2930 "Label number %li out of bounds.\n", label
->number
);
2932 PDB_free_file(interp
, pfile
);
2936 pline
->label
= label
;
2938 label
= label
->next
;
2941 pdb
->state
|= PDB_SRC_LOADED
;
2947 =item C<long PDB_add_label(PDB_file_t *file, const opcode_t *cur_opcode,
2950 Add a label to the label list.
2957 PDB_add_label(ARGMOD(PDB_file_t
*file
), ARGIN(const opcode_t
*cur_opcode
),
2960 ASSERT_ARGS(PDB_add_label
)
2962 PDB_label_t
*label
= file
->label
;
2964 /* See if there is already a label at this line */
2966 if (label
->opcode
== cur_opcode
+ offset
)
2967 return label
->number
;
2968 label
= label
->next
;
2971 /* Allocate a new label */
2972 label
= file
->label
;
2973 _new
= mem_allocate_typed(PDB_label_t
);
2974 _new
->opcode
= cur_opcode
+ offset
;
2979 label
= label
->next
;
2981 _new
->number
= label
->number
+ 1;
2989 return _new
->number
;
2994 =item C<void PDB_free_file(PARROT_INTERP, PDB_file_t *file)>
2996 Frees any allocated source files.
3003 PDB_free_file(SHIM_INTERP
, ARGIN_NULLOK(PDB_file_t
*file
))
3005 ASSERT_ARGS(PDB_free_file
)
3007 /* Free all of the allocated line structures */
3008 PDB_line_t
*line
= file
->line
;
3013 PDB_line_t
* const nline
= line
->next
;
3018 /* Free all of the allocated label structures */
3019 label
= file
->label
;
3022 PDB_label_t
* const nlabel
= label
->next
;
3024 mem_sys_free(label
);
3028 /* Free the remaining allocated portions of the file structure */
3029 if (file
->sourcefilename
)
3030 mem_sys_free(file
->sourcefilename
);
3033 mem_sys_free(file
->source
);
3043 =item C<void PDB_load_source(PARROT_INTERP, const char *command)>
3045 Load a source code file.
3053 PDB_load_source(PARROT_INTERP
, ARGIN(const char *command
))
3055 ASSERT_ARGS(PDB_load_source
)
3057 char f
[DEBUG_CMD_BUFFER_LENGTH
+ 1];
3061 PDB_t
* const pdb
= interp
->pdb
;
3062 opcode_t
*pc
= interp
->code
->base
.data
;
3064 unsigned long size
= 0;
3066 TRACEDEB_MSG("PDB_load_source");
3068 /* If there was a file already loaded or the bytecode was
3069 disassembled, free it */
3071 PDB_free_file(interp
->pdb
->debugee
, interp
->pdb
->debugee
->pdb
->file
);
3072 interp
->pdb
->debugee
->pdb
->file
= NULL
;
3075 /* Get the name of the file */
3076 for (j
= 0; command
[j
] == ' '; ++j
)
3078 for (i
= 0; command
[j
]; i
++, j
++)
3084 file
= fopen(f
, "r");
3086 /* abort if fopen failed */
3088 Parrot_io_eprintf(pdb
->debugger
, "Unable to load '%s'\n", f
);
3092 pfile
= mem_allocate_zeroed_typed(PDB_file_t
);
3093 pline
= mem_allocate_zeroed_typed(PDB_line_t
);
3095 pfile
->source
= (char *)mem_sys_allocate(1024);
3096 pfile
->line
= pline
;
3099 PARROT_ASSERT(interp
->op_info_table
);
3102 while ((c
= fgetc(file
)) != EOF
) {
3104 if (++size
== 1024) {
3105 pfile
->source
= (char *)mem_sys_realloc(pfile
->source
,
3106 (size_t)pfile
->size
+ 1024);
3109 pfile
->source
[pfile
->size
] = (char)c
;
3114 /* If the line has an opcode move to the next one,
3115 otherwise leave it with NULL to skip it. */
3116 PDB_line_t
*newline
= mem_allocate_zeroed_typed(PDB_line_t
);
3118 if (PDB_hasinstruction(pfile
->source
+ pline
->source_offset
)) {
3119 size_t n
= interp
->op_info_table
[*pc
].op_count
;
3121 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
3124 /* don't walk off the end of the program into neverland */
3125 if (pc
>= interp
->code
->base
.data
+ interp
->code
->base
.size
)
3129 newline
->number
= pline
->number
+ 1;
3130 pline
->next
= newline
;
3132 pline
->source_offset
= pfile
->size
;
3133 pline
->opcode
= NULL
;
3134 pline
->label
= NULL
;
3140 pdb
->state
|= PDB_SRC_LOADED
;
3143 TRACEDEB_MSG("PDB_load_source finished");
3148 =item C<char PDB_hasinstruction(const char *c)>
3150 Return true if the line has an instruction.
3156 =item * This should take the line, get an instruction, get the opcode for
3157 that instruction and check that is the correct one.
3159 =item * Decide what to do with macros if anything.
3167 PARROT_WARN_UNUSED_RESULT
3168 PARROT_PURE_FUNCTION
3170 PDB_hasinstruction(ARGIN(const char *c
))
3172 ASSERT_ARGS(PDB_hasinstruction
)
3175 /* as long as c is not NULL, we're not looking at a comment (#...) or a '\n'... */
3176 while (*c
&& *c
!= '#' && *c
!= '\n') {
3177 /* ... and c is alphanumeric or a quoted string then the line contains
3178 * an instruction. */
3179 if (isalnum((unsigned char) *c
) || *c
== '"') {
3182 else if (*c
== ':') {
3183 /* this is a label. RT #46137 right? */
3195 =item C<static void no_such_register(PARROT_INTERP, char register_type, UINTVAL
3198 Auxiliar error message function.
3205 no_such_register(PARROT_INTERP
, char register_type
, UINTVAL register_num
)
3207 ASSERT_ARGS(no_such_register
)
3209 Parrot_io_eprintf(interp
, "%c%u = no such register\n",
3210 register_type
, register_num
);
3215 =item C<void PDB_assign(PARROT_INTERP, const char *command)>
3217 Assign to registers.
3224 PDB_assign(PARROT_INTERP
, ARGIN(const char *command
))
3226 ASSERT_ARGS(PDB_assign
)
3227 UINTVAL register_num
;
3230 PDB_t
*pdb
= interp
->pdb
;
3231 Interp
*debugger
= pdb
? pdb
->debugger
: interp
;
3232 Interp
*debugee
= pdb
? pdb
->debugee
: interp
;
3234 /* smallest valid commad length is 4, i.e. "I0 1" */
3235 if (strlen(command
) < 4) {
3236 Parrot_io_eprintf(debugger
, "Must give a register number and value to assign\n");
3239 reg_type_id
= (char) command
[0];
3241 register_num
= get_ulong(&command
, 0);
3243 switch (reg_type_id
) {
3245 reg_type
= REGNO_INT
;
3248 reg_type
= REGNO_NUM
;
3251 reg_type
= REGNO_STR
;
3254 reg_type
= REGNO_PMC
;
3255 Parrot_io_eprintf(debugger
, "Assigning to PMCs is not currently supported\n");
3258 Parrot_io_eprintf(debugger
, "Invalid register type %c\n", reg_type_id
);
3261 if (register_num
>= Parrot_pcc_get_regs_used(debugee
,
3262 CURRENT_CONTEXT(debugee
), reg_type
)) {
3263 no_such_register(debugger
, reg_type_id
, register_num
);
3268 IREG(register_num
) = get_ulong(&command
, 0);
3271 NREG(register_num
) = atof(command
);
3274 SREG(register_num
) = Parrot_str_new(debugee
, command
, strlen(command
));
3276 default: ; /* Must never come here */
3278 Parrot_io_eprintf(debugger
, "\n %c%u = ", reg_type_id
, register_num
);
3279 Parrot_io_eprintf(debugger
, "%s\n", GDB_print_reg(debugee
, reg_type
, register_num
));
3284 =item C<void PDB_list(PARROT_INTERP, const char *command)>
3286 Show lines from the source code file.
3293 PDB_list(PARROT_INTERP
, ARGIN(const char *command
))
3295 ASSERT_ARGS(PDB_list
)
3297 unsigned long line_number
;
3300 PDB_t
*pdb
= interp
->pdb
;
3301 unsigned long n
= 10;
3303 TRACEDEB_MSG("PDB_list");
3304 if (!pdb
->file
|| !pdb
->file
->line
) {
3305 Parrot_io_eprintf(pdb
->debugger
, "No source file loaded\n");
3309 /* set the list line if provided */
3310 line_number
= get_ulong(&command
, 0);
3311 pdb
->file
->list_line
= (unsigned long) line_number
;
3313 /* set the number of lines to print */
3314 n
= get_ulong(&command
, 10);
3316 /* if n is zero, we simply return, as we don't have to print anything */
3320 line
= pdb
->file
->line
;
3322 for (i
= 0; i
< pdb
->file
->list_line
&& line
->next
; i
++)
3326 while (line
->next
) {
3327 Parrot_io_eprintf(pdb
->debugger
, "%li ", pdb
->file
->list_line
+ i
);
3328 /* If it has a label print it */
3330 Parrot_io_eprintf(pdb
->debugger
, "L%li:\t", line
->label
->number
);
3332 c
= pdb
->file
->source
+ line
->source_offset
;
3335 Parrot_io_eprintf(pdb
->debugger
, "%c", *(c
++));
3337 Parrot_io_eprintf(pdb
->debugger
, "\n");
3346 pdb
->file
->list_line
= 0;
3348 pdb
->file
->list_line
+= n
;
3353 =item C<void PDB_eval(PARROT_INTERP, const char *command)>
3355 C<eval>s an instruction.
3362 PDB_eval(PARROT_INTERP
, ARGIN(const char *command
))
3364 ASSERT_ARGS(PDB_eval
)
3366 PDB_t
*pdb
= interp
->pdb
;
3367 Interp
*warninterp
= (interp
->pdb
&& interp
->pdb
->debugger
) ?
3368 interp
->pdb
->debugger
: interp
;
3369 TRACEDEB_MSG("PDB_eval");
3371 Parrot_io_eprintf(warninterp
, "The eval command is currently unimplemeneted\n");
3376 =item C<opcode_t * PDB_compile(PARROT_INTERP, const char *command)>
3378 Compiles instructions with the PASM compiler.
3380 Appends an C<end> op.
3382 This may be called from C<PDB_eval> above or from the compile opcode
3383 which generates a malloced string.
3389 PARROT_CAN_RETURN_NULL
3391 PDB_compile(PARROT_INTERP
, ARGIN(const char *command
))
3393 ASSERT_ARGS(PDB_compile
)
3396 Parrot_ex_throw_from_c_args(interp
, NULL
,
3397 EXCEPTION_UNIMPLEMENTED
,
3398 "PDB_compile ('PASM1' compiler) has been deprecated");
3403 =item C<static void dump_string(PARROT_INTERP, const STRING *s)>
3405 Dumps the buflen, flags, bufused, strlen, and offset associated with a string
3406 and the string itself.
3413 dump_string(PARROT_INTERP
, ARGIN_NULLOK(const STRING
*s
))
3415 ASSERT_ARGS(dump_string
)
3419 Parrot_io_eprintf(interp
, "\tBuflen =\t%12ld\n", Buffer_buflen(s
));
3420 Parrot_io_eprintf(interp
, "\tFlags =\t%12ld\n", PObj_get_FLAGS(s
));
3421 Parrot_io_eprintf(interp
, "\tBufused =\t%12ld\n", s
->bufused
);
3422 Parrot_io_eprintf(interp
, "\tStrlen =\t%12ld\n", s
->strlen
);
3423 Parrot_io_eprintf(interp
, "\tOffset =\t%12ld\n",
3424 (char*) s
->strstart
- (char*) Buffer_bufstart(s
));
3425 Parrot_io_eprintf(interp
, "\tString =\t%S\n", s
);
3430 =item C<void PDB_print(PARROT_INTERP, const char *command)>
3432 Print interp registers.
3439 PDB_print(PARROT_INTERP
, ARGIN(const char *command
))
3441 ASSERT_ARGS(PDB_print
)
3442 const char * const s
= GDB_P(interp
->pdb
->debugee
, command
);
3444 TRACEDEB_MSG("PDB_print");
3445 Parrot_io_eprintf(interp
, "%s\n", s
);
3451 =item C<void PDB_info(PARROT_INTERP)>
3453 Print the interpreter info.
3460 PDB_info(PARROT_INTERP
)
3462 ASSERT_ARGS(PDB_info
)
3464 /* If a debugger is created, use it for printing and use the
3465 * data in his debugee. Otherwise, use current interpreter
3467 Parrot_Interp itdeb
= interp
->pdb
? interp
->pdb
->debugger
: interp
;
3468 Parrot_Interp itp
= interp
->pdb
? interp
->pdb
->debugee
: interp
;
3470 Parrot_io_eprintf(itdeb
, "Total memory allocated = %ld\n",
3471 interpinfo(itp
, TOTAL_MEM_ALLOC
));
3472 Parrot_io_eprintf(itdeb
, "GC mark runs = %ld\n",
3473 interpinfo(itp
, GC_MARK_RUNS
));
3474 Parrot_io_eprintf(itdeb
, "Lazy gc mark runs = %ld\n",
3475 interpinfo(itp
, GC_LAZY_MARK_RUNS
));
3476 Parrot_io_eprintf(itdeb
, "GC collect runs = %ld\n",
3477 interpinfo(itp
, GC_COLLECT_RUNS
));
3478 Parrot_io_eprintf(itdeb
, "Collect memory = %ld\n",
3479 interpinfo(itp
, TOTAL_COPIED
));
3480 Parrot_io_eprintf(itdeb
, "Active PMCs = %ld\n",
3481 interpinfo(itp
, ACTIVE_PMCS
));
3482 Parrot_io_eprintf(itdeb
, "Extended PMCs = %ld\n",
3483 interpinfo(itp
, EXTENDED_PMCS
));
3484 Parrot_io_eprintf(itdeb
, "Timely GC PMCs = %ld\n",
3485 interpinfo(itp
, IMPATIENT_PMCS
));
3486 Parrot_io_eprintf(itdeb
, "Total PMCs = %ld\n",
3487 interpinfo(itp
, TOTAL_PMCS
));
3488 Parrot_io_eprintf(itdeb
, "Active buffers = %ld\n",
3489 interpinfo(itp
, ACTIVE_BUFFERS
));
3490 Parrot_io_eprintf(itdeb
, "Total buffers = %ld\n",
3491 interpinfo(itp
, TOTAL_BUFFERS
));
3492 Parrot_io_eprintf(itdeb
, "Header allocations since last collect = %ld\n",
3493 interpinfo(itp
, HEADER_ALLOCS_SINCE_COLLECT
));
3494 Parrot_io_eprintf(itdeb
, "Memory allocations since last collect = %ld\n",
3495 interpinfo(itp
, MEM_ALLOCS_SINCE_COLLECT
));
3500 =item C<void PDB_help(PARROT_INTERP, const char *command)>
3502 Print the help text. "Help" with no arguments prints a list of commands.
3503 "Help xxx" prints information on command xxx.
3510 PDB_help(PARROT_INTERP
, ARGIN(const char *command
))
3512 ASSERT_ARGS(PDB_help
)
3513 const DebuggerCmd
*cmd
;
3515 const char * cmdline
= command
;
3516 cmd
= get_cmd(& cmdline
);
3519 Parrot_io_eprintf(interp
->pdb
->debugger
, "%s\n", cmd
->help
);
3522 if (*cmdline
== '\0') {
3524 Parrot_io_eprintf(interp
->pdb
->debugger
, "List of commands:\n");
3525 for (i
= 0; i
< sizeof (DebCmdList
) / sizeof (DebuggerCmdList
); ++i
) {
3526 const DebuggerCmdList
*cmdlist
= DebCmdList
+ i
;
3527 Parrot_io_eprintf(interp
->pdb
->debugger
,
3528 " %-12s-- %s\n", cmdlist
->name
, cmdlist
->cmd
->shorthelp
);
3530 Parrot_io_eprintf(interp
->pdb
->debugger
, "\n"
3531 "Type \"help\" followed by a command name for full documentation.\n\n");
3535 Parrot_io_eprintf(interp
->pdb
->debugger
, "Unknown command: %s\n", command
);
3542 =item C<void PDB_backtrace(PARROT_INTERP)>
3544 Prints a backtrace of the interp's call chain.
3551 PDB_backtrace(PARROT_INTERP
)
3553 ASSERT_ARGS(PDB_backtrace
)
3558 /* information about the current sub */
3559 PMC
*sub
= interpinfo_p(interp
, CURRENT_SUB
);
3560 PMC
*ctx
= CURRENT_CONTEXT(interp
);
3562 if (!PMC_IS_NULL(sub
)) {
3563 str
= Parrot_Context_infostr(interp
, ctx
);
3565 Parrot_io_eprintf(interp
, "%Ss", str
);
3566 if (interp
->code
->annotations
) {
3567 PMC
*annot
= PackFile_Annotations_lookup(interp
, interp
->code
->annotations
,
3568 Parrot_pcc_get_pc(interp
, ctx
) - interp
->code
->base
.data
+ 1, NULL
);
3569 if (!PMC_IS_NULL(annot
)) {
3570 PMC
*pfile
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3571 Parrot_str_new_constant(interp
, "file"));
3572 PMC
*pline
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3573 Parrot_str_new_constant(interp
, "line"));
3574 if ((!PMC_IS_NULL(pfile
)) && (!PMC_IS_NULL(pline
))) {
3575 STRING
*file
= VTABLE_get_string(interp
, pfile
);
3576 INTVAL line
= VTABLE_get_integer(interp
, pline
);
3577 Parrot_io_eprintf(interp
, " (%Ss:%li)", file
, (long)line
);
3581 Parrot_io_eprintf(interp
, "\n");
3585 /* backtrace: follow the continuation chain */
3587 Parrot_Continuation_attributes
*sub_cont
;
3588 sub
= Parrot_pcc_get_continuation(interp
, ctx
);
3590 if (PMC_IS_NULL(sub
))
3593 sub_cont
= PARROT_CONTINUATION(sub
);
3598 str
= Parrot_Context_infostr(interp
, sub_cont
->to_ctx
);
3603 /* recursion detection */
3604 if (!PMC_IS_NULL(old
) && PMC_cont(old
) &&
3605 Parrot_pcc_get_pc(interp
, PMC_cont(old
)->to_ctx
) ==
3606 Parrot_pcc_get_pc(interp
, PMC_cont(sub
)->to_ctx
) &&
3607 Parrot_pcc_get_sub(interp
, PMC_cont(old
)->to_ctx
) ==
3608 Parrot_pcc_get_sub(interp
, PMC_cont(sub
)->to_ctx
)) {
3611 else if (rec_level
!= 0) {
3612 Parrot_io_eprintf(interp
, "... call repeated %d times\n", rec_level
);
3616 /* print the context description */
3617 if (rec_level
== 0) {
3618 Parrot_io_eprintf(interp
, "%Ss", str
);
3619 if (interp
->code
->annotations
) {
3620 PMC
*annot
= PackFile_Annotations_lookup(interp
, interp
->code
->annotations
,
3621 Parrot_pcc_get_pc(interp
, sub_cont
->to_ctx
) - interp
->code
->base
.data
+ 1,
3624 if (!PMC_IS_NULL(annot
)) {
3625 PMC
*pfile
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3626 Parrot_str_new_constant(interp
, "file"));
3627 PMC
*pline
= VTABLE_get_pmc_keyed_str(interp
, annot
,
3628 Parrot_str_new_constant(interp
, "line"));
3629 if ((!PMC_IS_NULL(pfile
)) && (!PMC_IS_NULL(pline
))) {
3630 STRING
*file
= VTABLE_get_string(interp
, pfile
);
3631 INTVAL line
= VTABLE_get_integer(interp
, pline
);
3632 Parrot_io_eprintf(interp
, " (%Ss:%li)", file
, (long)line
);
3636 Parrot_io_eprintf(interp
, "\n");
3639 /* get the next Continuation */
3640 ctx
= PARROT_CONTINUATION(sub
)->to_ctx
;
3648 Parrot_io_eprintf(interp
, "... call repeated %d times\n", rec_level
);
3654 * GDB_P gdb> pp $I0 print register I0 value
3656 * RT46139 more, more
3661 =item C<static const char* GDB_print_reg(PARROT_INTERP, int t, int n)>
3663 Used by GDB_P to convert register values for display. Takes register
3664 type and number as arguments.
3666 Returns a pointer to the start of the string, (except for PMCs, which
3667 print directly and return "").
3673 PARROT_WARN_UNUSED_RESULT
3674 PARROT_CANNOT_RETURN_NULL
3677 GDB_print_reg(PARROT_INTERP
, int t
, int n
)
3679 ASSERT_ARGS(GDB_print_reg
)
3682 if (n
>= 0 && (UINTVAL
)n
< Parrot_pcc_get_regs_used(interp
, CURRENT_CONTEXT(interp
), t
)) {
3685 return Parrot_str_from_int(interp
, IREG(n
))->strstart
;
3687 return Parrot_str_from_num(interp
, NREG(n
))->strstart
;
3689 /* This hack is needed because we occasionally are told
3690 that we have string registers when we actually don't */
3691 string
= (char *) SREG(n
);
3696 return SREG(n
)->strstart
;
3698 /* prints directly */
3699 trace_pmc_dump(interp
, PREG(n
));
3705 return "no such register";
3710 =item C<static const char* GDB_P(PARROT_INTERP, const char *s)>
3712 Used by PDB_print to print register values. Takes a pointer to the
3715 Returns "" or error message.
3721 PARROT_WARN_UNUSED_RESULT
3722 PARROT_CANNOT_RETURN_NULL
3725 GDB_P(PARROT_INTERP
, ARGIN(const char *s
))
3731 TRACEDEB_MSG("GDB_P");
3732 /* Skip leading whitespace. */
3733 while (isspace((unsigned char)*s
))
3736 reg_type
= (unsigned char) toupper((unsigned char)*s
);
3739 case 'I': t
= REGNO_INT
; break;
3740 case 'N': t
= REGNO_NUM
; break;
3741 case 'S': t
= REGNO_STR
; break;
3742 case 'P': t
= REGNO_PMC
; break;
3743 default: return "Need a register.";
3746 /* Print all registers of this type. */
3747 const int max_reg
= Parrot_pcc_get_regs_used(interp
, CURRENT_CONTEXT(interp
), t
);
3750 for (n
= 0; n
< max_reg
; n
++) {
3751 /* this must be done in two chunks because PMC's print directly. */
3752 Parrot_io_eprintf(interp
, "\n %c%d = ", reg_type
, n
);
3753 Parrot_io_eprintf(interp
, "%s", GDB_print_reg(interp
, t
, n
));
3757 else if (s
[1] && isdigit((unsigned char)s
[1])) {
3758 const int n
= atoi(s
+ 1);
3759 return GDB_print_reg(interp
, t
, n
);
3762 return "no such register";
3772 F<include/parrot/debugger.h>, F<src/parrot_debugger.c> and F<ops/debug.ops>.
3778 =item Initial version by Daniel Grunblatt on 2002.5.19.
3780 =item Start of rewrite - leo 2005.02.16
3782 The debugger now uses its own interpreter. User code is run in
3783 Interp *debugee. We have:
3785 debug_interp->pdb->debugee->debugger
3788 +------------- := -----------+
3790 Debug commands are mostly run inside the C<debugger>. User code
3791 runs of course in the C<debugee>.
3802 * c-file-style: "parrot"
3804 * vim: expandtab shiftwidth=4: