* RFA: fix PR 1535
@ 2008-08-12 18:19 Tom Tromey
2008-08-12 21:18 ` Tom Tromey
0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2008-08-12 18:19 UTC (permalink / raw)
To: gdb-patches
This patch fixes PR 1535.
The bug here is that CLI tab completion does not work for "catch"
commands.
Initially I implemented a custom completer for "catch", but eventually
I realized I could just make catch sub-commands into real commands on
their own.
I did this using a table and some macros. It seemed nicer this way,
since it avoided a lot of extra typing. If you prefer I guess I can
hand-expand this into explicitly-maintained tables.
Built and regression tested on x86-64 (compile farm).
This needed a test suite tweak (included).
Ok?
Tom
:ADDPATCH breakpoints:
2008-08-12 Tom Tromey <tromey@redhat.com>
PR gdb/1535:
* breakpoint.c (ep_find_event_name_end): Remove.
(catch_fork_command_1): Handle NULL 'arg'.
(catch_exec_command): Rename from catch_exec_command_1. Handle
NULL 'arg'.
(catch_load_command): Rename from catch_load_command_1. Handle
NULL 'arg'.
(catch_unload_command): Rename from catch_unload_command_1.
Handle NULL 'arg'.
(catch_exception_command_1): Handle NULL 'arg'.
(catch_exception_command): Rename from
catch_ada_exception_command. Handle NULL 'arg'.
(catch_assert_command): Handle NULL 'arg'.
(catch_catch_command): New function.
(catch_throw_command): Likewise.
(catch_fork_command): Likewise.
(catch_vfork_command): Likewise.
(TABLE): New macro.
(UNIMPLEMENTED_NAME): Likewise.
(DEFINE_UNIMPLEMENTED): Likewise.
(DEFINE_ONE_CATCH_FUNCTION): Likewise.
(DEFINE_NORMAL): Likewise.
(ENTRY): Likewise.
(struct catch_handler_entry): New type.
(NORMAL_NAME): New define.
(permanent_catch_entries): New global.
(temporary_catch_entries): Likewise.
(catch_command_1): Remove.
(catch_command): Just call error.
(tcatch_command): Likewise.
(catch_cmdlist): New global.
(tcatch_cmdlist): Likewise.
(add_catch_commands): New function.
(_initialize_breakpoint): Use add_catch_commands. Create "catch"
and "tcatch" as prefix commands.
2008-08-12 Tom Tromey <tromey@redhat.com>
* gdb.base/help.exp (help catch): Rewrite.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 2a10d61..7fa58f9 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -61,8 +61,6 @@
/* Prototypes for local functions. */
-static void catch_command_1 (char *, int, int);
-
static void enable_delete_command (char *, int);
static void enable_delete_breakpoint (struct breakpoint *);
@@ -167,8 +165,6 @@ static void stopin_command (char *arg, int from_tty);
static void stopat_command (char *arg, int from_tty);
-static char *ep_find_event_name_end (char *arg);
-
static char *ep_parse_optional_if_clause (char **arg);
static char *ep_parse_optional_filename (char **arg);
@@ -6251,36 +6247,6 @@ ep_skip_leading_whitespace (char **s)
*s += 1;
}
-/* This function examines a string, and attempts to find a token
- that might be an event name in the leading characters. If a
- possible match is found, a pointer to the last character of
- the token is returned. Else, NULL is returned. */
-
-static char *
-ep_find_event_name_end (char *arg)
-{
- char *s = arg;
- char *event_name_end = NULL;
-
- /* If we could depend upon the presense of strrpbrk, we'd use that... */
- if (arg == NULL)
- return NULL;
-
- /* We break out of the loop when we find a token delimiter.
- Basically, we're looking for alphanumerics and underscores;
- anything else delimites the token. */
- while (*s != '\0')
- {
- if (!isalnum (*s) && (*s != '_'))
- break;
- event_name_end = s;
- s++;
- }
-
- return event_name_end;
-}
-
-
/* This function attempts to parse an optional "if <cond>" clause
from the arg string. If one is not found, it returns NULL.
@@ -6362,6 +6328,8 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
{
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6391,10 +6359,12 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
}
static void
-catch_exec_command_1 (char *arg, int tempflag, int from_tty)
+catch_exec_command (char *arg, int tempflag, int from_tty)
{
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6413,11 +6383,13 @@ catch_exec_command_1 (char *arg, int tempflag, int from_tty)
}
static void
-catch_load_command_1 (char *arg, int tempflag, int from_tty)
+catch_load_command (char *arg, int tempflag, int from_tty)
{
char *dll_pathname = NULL;
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6455,11 +6427,13 @@ catch_load_command_1 (char *arg, int tempflag, int from_tty)
}
static void
-catch_unload_command_1 (char *arg, int tempflag, int from_tty)
+catch_unload_command (char *arg, int tempflag, int from_tty)
{
char *dll_pathname = NULL;
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6598,6 +6572,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
char *cond_string = NULL;
struct symtab_and_line *sal = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
@@ -6664,7 +6640,7 @@ create_ada_exception_breakpoint (struct symtab_and_line sal,
/* Implement the "catch exception" command. */
static void
-catch_ada_exception_command (char *arg, int tempflag, int from_tty)
+catch_exception_command (char *arg, int tempflag, int from_tty)
{
struct symtab_and_line sal;
enum bptype type;
@@ -6674,6 +6650,8 @@ catch_ada_exception_command (char *arg, int tempflag, int from_tty)
struct expression *cond = NULL;
struct breakpoint_ops *ops = NULL;
+ if (!arg)
+ arg = "";
sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
&cond_string, &cond, &ops);
create_ada_exception_breakpoint (sal, addr_string, exp_string,
@@ -6690,132 +6668,161 @@ catch_assert_command (char *arg, int tempflag, int from_tty)
char *addr_string = NULL;
struct breakpoint_ops *ops = NULL;
+ if (!arg)
+ arg = "";
sal = ada_decode_assert_location (arg, &addr_string, &ops);
create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops,
tempflag, from_tty);
}
+/* Implement the "catch catch" command. */
+
static void
-catch_command_1 (char *arg, int tempflag, int from_tty)
+catch_catch_command (char *arg, int tempflag, int from_tty)
{
+ catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
+}
- /* The first argument may be an event name, such as "start" or "load".
- If so, then handle it as such. If it doesn't match an event name,
- then attempt to interpret it as an exception name. (This latter is
- the v4.16-and-earlier GDB meaning of the "catch" command.)
+/* Implement the "catch throw" command. */
- First, try to find the bounds of what might be an event name. */
- char *arg1_start = arg;
- char *arg1_end;
- int arg1_length;
+static void
+catch_throw_command (char *arg, int tempflag, int from_tty)
+{
+ catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
+}
- if (arg1_start == NULL)
- {
- /* Old behaviour was to use pre-v-4.16 syntax */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* return; */
- /* Now, this is not allowed */
- error (_("Catch requires an event name."));
+/* Implement the "catch fork" command. */
- }
- arg1_end = ep_find_event_name_end (arg1_start);
- if (arg1_end == NULL)
- error (_("catch requires an event"));
- arg1_length = arg1_end + 1 - arg1_start;
+static void
+catch_fork_command (char *arg, int tempflag, int from_tty)
+{
+ catch_fork_command_1 (catch_fork, arg, tempflag, from_tty);
+}
- /* Try to match what we found against known event names. */
- if (strncmp (arg1_start, "signal", arg1_length) == 0)
- {
- error (_("Catch of signal not yet implemented"));
- }
- else if (strncmp (arg1_start, "catch", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "throw", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
- {
- error (_("Catch of thread_start not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
- {
- error (_("Catch of thread_exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
- {
- error (_("Catch of thread_join not yet implemented"));
- }
- else if (strncmp (arg1_start, "start", arg1_length) == 0)
- {
- error (_("Catch of start not yet implemented"));
- }
- else if (strncmp (arg1_start, "exit", arg1_length) == 0)
- {
- error (_("Catch of exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "fork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "exec", arg1_length) == 0)
- {
- catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "load", arg1_length) == 0)
- {
- catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "unload", arg1_length) == 0)
- {
- catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "stop", arg1_length) == 0)
- {
- error (_("Catch of stop not yet implemented"));
- }
- else if (strncmp (arg1_start, "exception", arg1_length) == 0)
- {
- catch_ada_exception_command (arg1_end + 1, tempflag, from_tty);
- }
+/* Implement the "catch vfork" command. */
- else if (strncmp (arg1_start, "assert", arg1_length) == 0)
- {
- catch_assert_command (arg1_end + 1, tempflag, from_tty);
- }
+static void
+catch_vfork_command (char *arg, int tempflag, int from_tty)
+{
+ catch_fork_command_1 (catch_vfork, arg, tempflag, from_tty);
+}
+
+/* A table holding information about all "catch" events. Each entry
+ holds the name of the event, whether the event is implemented or
+ not, and documentation for the event. */
+#define TABLE \
+ ENTRY (signal, UNIMPLEMENTED, N_("Catch signals.")) \
+ ENTRY (thread_start, UNIMPLEMENTED, N_("Catch thread start.")) \
+ ENTRY (thread_exit, UNIMPLEMENTED, N_("Catch thread exit.")) \
+ ENTRY (thread_join, UNIMPLEMENTED, N_("Catch thread after a join.")) \
+ ENTRY (start, UNIMPLEMENTED, N_("Catch process at creation.")) \
+ ENTRY (stop, UNIMPLEMENTED, N_("Catch program stopping.")) \
+ ENTRY (catch, NORMAL, N_("Catch an exception, when caught.\n\
+With an argument, catch only exceptions with the given name.")) \
+ ENTRY (throw, NORMAL, N_("Catch an exception, when thrown.\n\
+With an exception, catch only exceptions with the given name.")) \
+ ENTRY (fork, NORMAL, N_("Catch calls to fork.")) \
+ ENTRY (vfork, NORMAL, N_("Catch calls to vfork.")) \
+ ENTRY (exec, NORMAL, N_("Catch calls to exec.")) \
+ ENTRY (load, NORMAL, N_("Catch library loads.\n\
+With an argument, catch only loads of that library.")) \
+ ENTRY (unload, NORMAL, N_("Catch library unloads.\n\
+With an argument, catch only unloads of that library.")) \
+ ENTRY (exception, NORMAL, N_("Catch Ada exceptions, when raised.\n\
+With an argument, catch only exceptions with the given name.")) \
+ ENTRY (assert, NORMAL, N_("Catch failed Ada assertions, when raised.\n\
+With an argument, catch only exceptions with the given name."))
+
+/* This macro computes the name of a function which is used for an
+ unimplemented catch command. */
+#define UNIMPLEMENTED_NAME(NAME) unimplemented_catch_ ## NAME
+
+/* Define a new function for an unimplemented catch event. */
+#define DEFINE_UNIMPLEMENTED(NAME) \
+ static void UNIMPLEMENTED_NAME (NAME) (char *arg, int from_tty) \
+ { \
+ error (_("Catch of " #NAME " not yet implemented")); \
+ }
+
+/* Define a new function that calls a catch handler function with an
+ extra argument. */
+#define DEFINE_ONE_CATCH_FUNCTION(NAME, TEMP) \
+ static void do_catch_ ## NAME ## TEMP (char *arg, int from_tty) \
+ { \
+ catch_ ## NAME ## _command (arg, TEMP, from_tty); \
+ }
+
+/* Define a pair of catch functions, one temporary, one not. */
+#define DEFINE_NORMAL(NAME) \
+ DEFINE_ONE_CATCH_FUNCTION (NAME, 0) \
+ DEFINE_ONE_CATCH_FUNCTION (NAME, 1)
+
+/* This is used to expand all the "catch" commands into a series of
+ function definitions. */
+#define ENTRY(NAME, TYPE, DOC) DEFINE_ ## TYPE (NAME)
+
+/* Emit all function definitions. */
+TABLE
+
+/* This is the type of a single entry in a table of "catch" event
+ commands. */
+struct catch_handler_entry
+{
+ /* Name of the command. */
+ char *name;
+ /* Documentation for the command. */
+ char *doc;
+ /* Function which implements the command. */
+ void (*handler) (char *arg, int from_tty);
+};
- /* This doesn't appear to be an event name */
+/* How to compute the name of the function which implements an
+ ordinary, permanent catch event. */
+#define NORMAL_NAME(NAME) do_catch_ ## NAME ## 0
- else
- {
- /* Pre-v.4.16 behaviour was to treat the argument
- as the name of an exception */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* Now this is not allowed */
- error (_("Unknown event kind specified for catch"));
+/* Redefine ENTRY so that it expands to a struct catch_handler_entry. */
+#undef ENTRY
+#define ENTRY(NAME, TYPE, DOC) \
+ { #NAME, DOC, TYPE ## _NAME (NAME) },
- }
-}
+/* All the "catch" commands. */
+static struct catch_handler_entry permanent_catch_entries[] =
+{
+ TABLE
+ { NULL, NULL, NULL }
+};
+
+/* How to compute the name of the function which implements an
+ ordinary, temporary catch event. */
+#undef NORMAL_NAME
+#define NORMAL_NAME(NAME) do_catch_ ## NAME ## 1
+
+/* All the "tcatch" commands. */
+static struct catch_handler_entry temporary_catch_entries[] =
+{
+ TABLE
+ { NULL, NULL, NULL }
+};
+
+#undef ENTRY
+#undef NORMAL_NAME
+#undef DEFINE_NORMAL
+#undef DEFINE_ONE_CATCH_FUNCTION
+#undef DEFINE_UNIMPLEMENTED
+#undef UNIMPLEMENTED_NAME
+#undef TABLE
static void
catch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 0, from_tty);
+ error (_("Catch requires an event name."));
}
\f
static void
tcatch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 1, from_tty);
+ error (_("Catch requires an event name."));
}
/* Delete breakpoints by address or line. */
@@ -8222,6 +8229,24 @@ Multiple breakpoints at one place are permitted, and useful if conditional.\n\
\n\
Do \"help breakpoints\" for info on other commands dealing with breakpoints."
+/* List of subcommands for "catch". */
+static struct cmd_list_element *catch_cmdlist;
+
+/* List of subcommands for "tcatch". */
+static struct cmd_list_element *tcatch_cmdlist;
+
+/* Add all the catch commands from TABLE to CMDLIST. */
+static void
+add_catch_commands (struct cmd_list_element **cmdlist,
+ struct catch_handler_entry *table)
+{
+ int i;
+
+ for (i = 0; table[i].name; ++i)
+ add_cmd (table[i].name, class_breakpoint, table[i].handler,
+ _(table[i].doc), cmdlist);
+}
+
void
_initialize_breakpoint (void)
{
@@ -8479,52 +8504,17 @@ Convenience variable \"$bpnum\" contains the number of the last\n\
breakpoint set."),
&maintenanceinfolist);
- add_com ("catch", class_breakpoint, catch_command, _("\
-Set catchpoints to catch events.\n\
-Raised signals may be caught:\n\
-\tcatch signal - all signals\n\
-\tcatch signal <signame> - a particular signal\n\
-Raised exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch throw <exceptname> - a particular exception, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-\tcatch catch <exceptname> - a particular exception, when caught\n\
-Thread or process events may be caught:\n\
-\tcatch thread_start - any threads, just after creation\n\
-\tcatch thread_exit - any threads, just before expiration\n\
-\tcatch thread_join - any threads, just after joins\n\
-Process events may be caught:\n\
-\tcatch start - any processes, just after creation\n\
-\tcatch exit - any processes, just before expiration\n\
-\tcatch fork - calls to fork()\n\
-\tcatch vfork - calls to vfork()\n\
-\tcatch exec - calls to exec()\n\
-Dynamically-linked library events may be caught:\n\
-\tcatch load - loads of any library\n\
-\tcatch load <libname> - loads of a particular library\n\
-\tcatch unload - unloads of any library\n\
-\tcatch unload <libname> - unloads of a particular library\n\
-The act of your program's execution stopping may also be caught:\n\
-\tcatch stop\n\n\
-C++ exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-Ada exceptions may be caught:\n\
-\tcatch exception - all exceptions, when raised\n\
-\tcatch exception <name> - a particular exception, when raised\n\
-\tcatch exception unhandled - all unhandled exceptions, when raised\n\
-\tcatch assert - all failed assertions, when raised\n\
-\n\
-Do \"help set follow-fork-mode\" for info on debugging your program\n\
-after a fork or vfork is caught.\n\n\
-Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
-
- add_com ("tcatch", class_breakpoint, tcatch_command, _("\
-Set temporary catchpoints to catch events.\n\
-Args like \"catch\" command.\n\
-Like \"catch\" except the catchpoint is only temporary,\n\
-so it will be deleted when hit. Equivalent to \"catch\" followed\n\
-by using \"enable delete\" on the catchpoint number."));
+ add_prefix_cmd ("catch", class_breakpoint, catch_command, _("\
+Set catchpoints to catch events."),
+ &catch_cmdlist, "catch ",
+ 0/*allow-unknown*/, &cmdlist);
+ add_catch_commands (&catch_cmdlist, permanent_catch_entries);
+
+ add_prefix_cmd ("tcatch", class_breakpoint, tcatch_command, _("\
+Set temporary catchpoints to catch events."),
+ &tcatch_cmdlist, "tcatch ",
+ 0/*allow-unknown*/, &cmdlist);
+ add_catch_commands (&tcatch_cmdlist, temporary_catch_entries);
c = add_com ("watch", class_breakpoint, watch_command, _("\
Set a watchpoint for an expression.\n\
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
index c427b31..ef07667 100644
--- a/gdb/testsuite/gdb.base/help.exp
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -68,7 +68,7 @@ gdb_test "help continue" "Continue program being debugged.*" "help continue"
# test help call
gdb_test "help call" "Call a function.*" "help call"
# test help catch
-gdb_test "help catch" "Set catchpoints to catch events.*Raised signals may be caught:.*catch signal.*all signals.*catch signal.*signame.*a particular signal.*Raised exceptions may be caught:.*catch throw.*all exceptions, when thrown.*catch throw.*exceptname.*a particular exception, when thrown.*catch catch.*all exceptions, when caught.*catch catch.*exceptname.*a particular exception, when caught.*Thread or process events may be caught:.*catch thread_start.*any threads, just after creation.*catch thread_exit.*any threads, just before expiration.*catch thread_join.*any threads, just after joins.*catch start.*any processes, just after creation.*catch exit.*any processes, just before expiration.*catch fork.*calls to fork.*catch vfork.*calls to vfork.*catch exec.*calls to exec.*Dynamically.linked library events may be caught:.*catch load.*loads of any library.*catch load.*libname.*loads of a particular library.*catch unload.*unloads of any library.*catch unload.*libname.*unloads of a particular library.*The act of your program's execution stopping may also be caught:.*catch stop.*Do.*help set follow-fork-mode.*for info on debugging your program.*after a fork or vfork is caught.*Do.*help breakpoints.*for info on other commands dealing with breakpoints." "help catch"
+gdb_test "help catch" "Set catchpoints to catch events.*List of catch subcommands:.*catch assert -- Catch failed Ada assertions.*catch catch -- Catch an exception.*catch exception -- Catch Ada exceptions.*catch exec -- Catch calls to exec.*catch fork -- Catch calls to fork.*catch load -- Catch library loads.*catch signal -- Catch signals.*catch start -- Catch process at creation.*catch stop -- Catch program stopping.*catch thread_exit -- Catch thread exit.*catch thread_join -- Catch thread after a join.*catch thread_start -- Catch thread start.*catch throw -- Catch an exception.*catch unload -- Catch library unloads.*catch vfork -- Catch calls to vfork.*Type .help catch. followed by catch subcommand name for full documentation.*Type .apropos word. to search for commands related to .word..*Command name abbreviations are allowed if unambiguous.*" "help catch"
# test help cd
gdb_test "help cd" "Set working directory to DIR for debugger and program being debugged\.\[\r\n\]+The change does not take effect for the program being debugged\[\r\n\]+until the next time it is started\." "help cd"
# test help clear
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-12 18:19 RFA: fix PR 1535 Tom Tromey
@ 2008-08-12 21:18 ` Tom Tromey
2008-08-14 17:49 ` Daniel Jacobowitz
0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2008-08-12 21:18 UTC (permalink / raw)
To: gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
Tom> This patch fixes PR 1535.
Tom> The bug here is that CLI tab completion does not work for "catch"
Tom> commands.
After sending this I noticed a gettext snafu in the
DEFINE_UNIMPLEMENTED macro -- stringization can't reasonably work
here.
The fix is to change the error call to use %s instead.
I ran 'make gdb.pot' and looked at the result to verify that this
change worked.
Tom
2008-08-12 Tom Tromey <tromey@redhat.com>
PR gdb/1535:
* breakpoint.c (ep_find_event_name_end): Remove.
(catch_fork_command_1): Handle NULL 'arg'.
(catch_exec_command): Rename from catch_exec_command_1. Handle
NULL 'arg'.
(catch_load_command): Rename from catch_load_command_1. Handle
NULL 'arg'.
(catch_unload_command): Rename from catch_unload_command_1.
Handle NULL 'arg'.
(catch_exception_command_1): Handle NULL 'arg'.
(catch_exception_command): Rename from
catch_ada_exception_command. Handle NULL 'arg'.
(catch_assert_command): Handle NULL 'arg'.
(catch_catch_command): New function.
(catch_throw_command): Likewise.
(catch_fork_command): Likewise.
(catch_vfork_command): Likewise.
(TABLE): New macro.
(UNIMPLEMENTED_NAME): Likewise.
(DEFINE_UNIMPLEMENTED): Likewise.
(DEFINE_ONE_CATCH_FUNCTION): Likewise.
(DEFINE_NORMAL): Likewise.
(ENTRY): Likewise.
(struct catch_handler_entry): New type.
(NORMAL_NAME): New define.
(permanent_catch_entries): New global.
(temporary_catch_entries): Likewise.
(catch_command_1): Remove.
(catch_command): Just call error.
(tcatch_command): Likewise.
(catch_cmdlist): New global.
(tcatch_cmdlist): Likewise.
(add_catch_commands): New function.
(_initialize_breakpoint): Use add_catch_commands. Create "catch"
and "tcatch" as prefix commands.
2008-08-12 Tom Tromey <tromey@redhat.com>
* gdb.base/help.exp (help catch): Rewrite.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 2a10d61..e49530d 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -61,8 +61,6 @@
/* Prototypes for local functions. */
-static void catch_command_1 (char *, int, int);
-
static void enable_delete_command (char *, int);
static void enable_delete_breakpoint (struct breakpoint *);
@@ -167,8 +165,6 @@ static void stopin_command (char *arg, int from_tty);
static void stopat_command (char *arg, int from_tty);
-static char *ep_find_event_name_end (char *arg);
-
static char *ep_parse_optional_if_clause (char **arg);
static char *ep_parse_optional_filename (char **arg);
@@ -6251,36 +6247,6 @@ ep_skip_leading_whitespace (char **s)
*s += 1;
}
-/* This function examines a string, and attempts to find a token
- that might be an event name in the leading characters. If a
- possible match is found, a pointer to the last character of
- the token is returned. Else, NULL is returned. */
-
-static char *
-ep_find_event_name_end (char *arg)
-{
- char *s = arg;
- char *event_name_end = NULL;
-
- /* If we could depend upon the presense of strrpbrk, we'd use that... */
- if (arg == NULL)
- return NULL;
-
- /* We break out of the loop when we find a token delimiter.
- Basically, we're looking for alphanumerics and underscores;
- anything else delimites the token. */
- while (*s != '\0')
- {
- if (!isalnum (*s) && (*s != '_'))
- break;
- event_name_end = s;
- s++;
- }
-
- return event_name_end;
-}
-
-
/* This function attempts to parse an optional "if <cond>" clause
from the arg string. If one is not found, it returns NULL.
@@ -6362,6 +6328,8 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
{
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6391,10 +6359,12 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
}
static void
-catch_exec_command_1 (char *arg, int tempflag, int from_tty)
+catch_exec_command (char *arg, int tempflag, int from_tty)
{
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6413,11 +6383,13 @@ catch_exec_command_1 (char *arg, int tempflag, int from_tty)
}
static void
-catch_load_command_1 (char *arg, int tempflag, int from_tty)
+catch_load_command (char *arg, int tempflag, int from_tty)
{
char *dll_pathname = NULL;
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6455,11 +6427,13 @@ catch_load_command_1 (char *arg, int tempflag, int from_tty)
}
static void
-catch_unload_command_1 (char *arg, int tempflag, int from_tty)
+catch_unload_command (char *arg, int tempflag, int from_tty)
{
char *dll_pathname = NULL;
char *cond_string = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6598,6 +6572,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
char *cond_string = NULL;
struct symtab_and_line *sal = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
@@ -6664,7 +6640,7 @@ create_ada_exception_breakpoint (struct symtab_and_line sal,
/* Implement the "catch exception" command. */
static void
-catch_ada_exception_command (char *arg, int tempflag, int from_tty)
+catch_exception_command (char *arg, int tempflag, int from_tty)
{
struct symtab_and_line sal;
enum bptype type;
@@ -6674,6 +6650,8 @@ catch_ada_exception_command (char *arg, int tempflag, int from_tty)
struct expression *cond = NULL;
struct breakpoint_ops *ops = NULL;
+ if (!arg)
+ arg = "";
sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
&cond_string, &cond, &ops);
create_ada_exception_breakpoint (sal, addr_string, exp_string,
@@ -6690,132 +6668,161 @@ catch_assert_command (char *arg, int tempflag, int from_tty)
char *addr_string = NULL;
struct breakpoint_ops *ops = NULL;
+ if (!arg)
+ arg = "";
sal = ada_decode_assert_location (arg, &addr_string, &ops);
create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops,
tempflag, from_tty);
}
+/* Implement the "catch catch" command. */
+
static void
-catch_command_1 (char *arg, int tempflag, int from_tty)
+catch_catch_command (char *arg, int tempflag, int from_tty)
{
+ catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
+}
- /* The first argument may be an event name, such as "start" or "load".
- If so, then handle it as such. If it doesn't match an event name,
- then attempt to interpret it as an exception name. (This latter is
- the v4.16-and-earlier GDB meaning of the "catch" command.)
+/* Implement the "catch throw" command. */
- First, try to find the bounds of what might be an event name. */
- char *arg1_start = arg;
- char *arg1_end;
- int arg1_length;
+static void
+catch_throw_command (char *arg, int tempflag, int from_tty)
+{
+ catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
+}
- if (arg1_start == NULL)
- {
- /* Old behaviour was to use pre-v-4.16 syntax */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* return; */
- /* Now, this is not allowed */
- error (_("Catch requires an event name."));
+/* Implement the "catch fork" command. */
- }
- arg1_end = ep_find_event_name_end (arg1_start);
- if (arg1_end == NULL)
- error (_("catch requires an event"));
- arg1_length = arg1_end + 1 - arg1_start;
+static void
+catch_fork_command (char *arg, int tempflag, int from_tty)
+{
+ catch_fork_command_1 (catch_fork, arg, tempflag, from_tty);
+}
- /* Try to match what we found against known event names. */
- if (strncmp (arg1_start, "signal", arg1_length) == 0)
- {
- error (_("Catch of signal not yet implemented"));
- }
- else if (strncmp (arg1_start, "catch", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "throw", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
- {
- error (_("Catch of thread_start not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
- {
- error (_("Catch of thread_exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
- {
- error (_("Catch of thread_join not yet implemented"));
- }
- else if (strncmp (arg1_start, "start", arg1_length) == 0)
- {
- error (_("Catch of start not yet implemented"));
- }
- else if (strncmp (arg1_start, "exit", arg1_length) == 0)
- {
- error (_("Catch of exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "fork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "exec", arg1_length) == 0)
- {
- catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "load", arg1_length) == 0)
- {
- catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "unload", arg1_length) == 0)
- {
- catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "stop", arg1_length) == 0)
- {
- error (_("Catch of stop not yet implemented"));
- }
- else if (strncmp (arg1_start, "exception", arg1_length) == 0)
- {
- catch_ada_exception_command (arg1_end + 1, tempflag, from_tty);
- }
+/* Implement the "catch vfork" command. */
- else if (strncmp (arg1_start, "assert", arg1_length) == 0)
- {
- catch_assert_command (arg1_end + 1, tempflag, from_tty);
- }
+static void
+catch_vfork_command (char *arg, int tempflag, int from_tty)
+{
+ catch_fork_command_1 (catch_vfork, arg, tempflag, from_tty);
+}
+
+/* A table holding information about all "catch" events. Each entry
+ holds the name of the event, whether the event is implemented or
+ not, and documentation for the event. */
+#define TABLE \
+ ENTRY (signal, UNIMPLEMENTED, N_("Catch signals.")) \
+ ENTRY (thread_start, UNIMPLEMENTED, N_("Catch thread start.")) \
+ ENTRY (thread_exit, UNIMPLEMENTED, N_("Catch thread exit.")) \
+ ENTRY (thread_join, UNIMPLEMENTED, N_("Catch thread after a join.")) \
+ ENTRY (start, UNIMPLEMENTED, N_("Catch process at creation.")) \
+ ENTRY (stop, UNIMPLEMENTED, N_("Catch program stopping.")) \
+ ENTRY (catch, NORMAL, N_("Catch an exception, when caught.\n\
+With an argument, catch only exceptions with the given name.")) \
+ ENTRY (throw, NORMAL, N_("Catch an exception, when thrown.\n\
+With an exception, catch only exceptions with the given name.")) \
+ ENTRY (fork, NORMAL, N_("Catch calls to fork.")) \
+ ENTRY (vfork, NORMAL, N_("Catch calls to vfork.")) \
+ ENTRY (exec, NORMAL, N_("Catch calls to exec.")) \
+ ENTRY (load, NORMAL, N_("Catch library loads.\n\
+With an argument, catch only loads of that library.")) \
+ ENTRY (unload, NORMAL, N_("Catch library unloads.\n\
+With an argument, catch only unloads of that library.")) \
+ ENTRY (exception, NORMAL, N_("Catch Ada exceptions, when raised.\n\
+With an argument, catch only exceptions with the given name.")) \
+ ENTRY (assert, NORMAL, N_("Catch failed Ada assertions, when raised.\n\
+With an argument, catch only exceptions with the given name."))
+
+/* This macro computes the name of a function which is used for an
+ unimplemented catch command. */
+#define UNIMPLEMENTED_NAME(NAME) unimplemented_catch_ ## NAME
+
+/* Define a new function for an unimplemented catch event. */
+#define DEFINE_UNIMPLEMENTED(NAME) \
+ static void UNIMPLEMENTED_NAME (NAME) (char *arg, int from_tty) \
+ { \
+ error (_("Catch of %s not yet implemented"), #NAME); \
+ }
+
+/* Define a new function that calls a catch handler function with an
+ extra argument. */
+#define DEFINE_ONE_CATCH_FUNCTION(NAME, TEMP) \
+ static void do_catch_ ## NAME ## TEMP (char *arg, int from_tty) \
+ { \
+ catch_ ## NAME ## _command (arg, TEMP, from_tty); \
+ }
+
+/* Define a pair of catch functions, one temporary, one not. */
+#define DEFINE_NORMAL(NAME) \
+ DEFINE_ONE_CATCH_FUNCTION (NAME, 0) \
+ DEFINE_ONE_CATCH_FUNCTION (NAME, 1)
+
+/* This is used to expand all the "catch" commands into a series of
+ function definitions. */
+#define ENTRY(NAME, TYPE, DOC) DEFINE_ ## TYPE (NAME)
+
+/* Emit all function definitions. */
+TABLE
+
+/* This is the type of a single entry in a table of "catch" event
+ commands. */
+struct catch_handler_entry
+{
+ /* Name of the command. */
+ char *name;
+ /* Documentation for the command. */
+ char *doc;
+ /* Function which implements the command. */
+ void (*handler) (char *arg, int from_tty);
+};
- /* This doesn't appear to be an event name */
+/* How to compute the name of the function which implements an
+ ordinary, permanent catch event. */
+#define NORMAL_NAME(NAME) do_catch_ ## NAME ## 0
- else
- {
- /* Pre-v.4.16 behaviour was to treat the argument
- as the name of an exception */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* Now this is not allowed */
- error (_("Unknown event kind specified for catch"));
+/* Redefine ENTRY so that it expands to a struct catch_handler_entry. */
+#undef ENTRY
+#define ENTRY(NAME, TYPE, DOC) \
+ { #NAME, DOC, TYPE ## _NAME (NAME) },
- }
-}
+/* All the "catch" commands. */
+static struct catch_handler_entry permanent_catch_entries[] =
+{
+ TABLE
+ { NULL, NULL, NULL }
+};
+
+/* How to compute the name of the function which implements an
+ ordinary, temporary catch event. */
+#undef NORMAL_NAME
+#define NORMAL_NAME(NAME) do_catch_ ## NAME ## 1
+
+/* All the "tcatch" commands. */
+static struct catch_handler_entry temporary_catch_entries[] =
+{
+ TABLE
+ { NULL, NULL, NULL }
+};
+
+#undef ENTRY
+#undef NORMAL_NAME
+#undef DEFINE_NORMAL
+#undef DEFINE_ONE_CATCH_FUNCTION
+#undef DEFINE_UNIMPLEMENTED
+#undef UNIMPLEMENTED_NAME
+#undef TABLE
static void
catch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 0, from_tty);
+ error (_("Catch requires an event name."));
}
\f
static void
tcatch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 1, from_tty);
+ error (_("Catch requires an event name."));
}
/* Delete breakpoints by address or line. */
@@ -8222,6 +8229,24 @@ Multiple breakpoints at one place are permitted, and useful if conditional.\n\
\n\
Do \"help breakpoints\" for info on other commands dealing with breakpoints."
+/* List of subcommands for "catch". */
+static struct cmd_list_element *catch_cmdlist;
+
+/* List of subcommands for "tcatch". */
+static struct cmd_list_element *tcatch_cmdlist;
+
+/* Add all the catch commands from TABLE to CMDLIST. */
+static void
+add_catch_commands (struct cmd_list_element **cmdlist,
+ struct catch_handler_entry *table)
+{
+ int i;
+
+ for (i = 0; table[i].name; ++i)
+ add_cmd (table[i].name, class_breakpoint, table[i].handler,
+ _(table[i].doc), cmdlist);
+}
+
void
_initialize_breakpoint (void)
{
@@ -8479,52 +8504,17 @@ Convenience variable \"$bpnum\" contains the number of the last\n\
breakpoint set."),
&maintenanceinfolist);
- add_com ("catch", class_breakpoint, catch_command, _("\
-Set catchpoints to catch events.\n\
-Raised signals may be caught:\n\
-\tcatch signal - all signals\n\
-\tcatch signal <signame> - a particular signal\n\
-Raised exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch throw <exceptname> - a particular exception, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-\tcatch catch <exceptname> - a particular exception, when caught\n\
-Thread or process events may be caught:\n\
-\tcatch thread_start - any threads, just after creation\n\
-\tcatch thread_exit - any threads, just before expiration\n\
-\tcatch thread_join - any threads, just after joins\n\
-Process events may be caught:\n\
-\tcatch start - any processes, just after creation\n\
-\tcatch exit - any processes, just before expiration\n\
-\tcatch fork - calls to fork()\n\
-\tcatch vfork - calls to vfork()\n\
-\tcatch exec - calls to exec()\n\
-Dynamically-linked library events may be caught:\n\
-\tcatch load - loads of any library\n\
-\tcatch load <libname> - loads of a particular library\n\
-\tcatch unload - unloads of any library\n\
-\tcatch unload <libname> - unloads of a particular library\n\
-The act of your program's execution stopping may also be caught:\n\
-\tcatch stop\n\n\
-C++ exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-Ada exceptions may be caught:\n\
-\tcatch exception - all exceptions, when raised\n\
-\tcatch exception <name> - a particular exception, when raised\n\
-\tcatch exception unhandled - all unhandled exceptions, when raised\n\
-\tcatch assert - all failed assertions, when raised\n\
-\n\
-Do \"help set follow-fork-mode\" for info on debugging your program\n\
-after a fork or vfork is caught.\n\n\
-Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
-
- add_com ("tcatch", class_breakpoint, tcatch_command, _("\
-Set temporary catchpoints to catch events.\n\
-Args like \"catch\" command.\n\
-Like \"catch\" except the catchpoint is only temporary,\n\
-so it will be deleted when hit. Equivalent to \"catch\" followed\n\
-by using \"enable delete\" on the catchpoint number."));
+ add_prefix_cmd ("catch", class_breakpoint, catch_command, _("\
+Set catchpoints to catch events."),
+ &catch_cmdlist, "catch ",
+ 0/*allow-unknown*/, &cmdlist);
+ add_catch_commands (&catch_cmdlist, permanent_catch_entries);
+
+ add_prefix_cmd ("tcatch", class_breakpoint, tcatch_command, _("\
+Set temporary catchpoints to catch events."),
+ &tcatch_cmdlist, "tcatch ",
+ 0/*allow-unknown*/, &cmdlist);
+ add_catch_commands (&tcatch_cmdlist, temporary_catch_entries);
c = add_com ("watch", class_breakpoint, watch_command, _("\
Set a watchpoint for an expression.\n\
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
index c427b31..ef07667 100644
--- a/gdb/testsuite/gdb.base/help.exp
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -68,7 +68,7 @@ gdb_test "help continue" "Continue program being debugged.*" "help continue"
# test help call
gdb_test "help call" "Call a function.*" "help call"
# test help catch
-gdb_test "help catch" "Set catchpoints to catch events.*Raised signals may be caught:.*catch signal.*all signals.*catch signal.*signame.*a particular signal.*Raised exceptions may be caught:.*catch throw.*all exceptions, when thrown.*catch throw.*exceptname.*a particular exception, when thrown.*catch catch.*all exceptions, when caught.*catch catch.*exceptname.*a particular exception, when caught.*Thread or process events may be caught:.*catch thread_start.*any threads, just after creation.*catch thread_exit.*any threads, just before expiration.*catch thread_join.*any threads, just after joins.*catch start.*any processes, just after creation.*catch exit.*any processes, just before expiration.*catch fork.*calls to fork.*catch vfork.*calls to vfork.*catch exec.*calls to exec.*Dynamically.linked library events may be caught:.*catch load.*loads of any library.*catch load.*libname.*loads of a particular library.*catch unload.*unloads of any library.*catch unload.*libname.*unloads of a particular library.*The act of your program's execution stopping may also be caught:.*catch stop.*Do.*help set follow-fork-mode.*for info on debugging your program.*after a fork or vfork is caught.*Do.*help breakpoints.*for info on other commands dealing with breakpoints." "help catch"
+gdb_test "help catch" "Set catchpoints to catch events.*List of catch subcommands:.*catch assert -- Catch failed Ada assertions.*catch catch -- Catch an exception.*catch exception -- Catch Ada exceptions.*catch exec -- Catch calls to exec.*catch fork -- Catch calls to fork.*catch load -- Catch library loads.*catch signal -- Catch signals.*catch start -- Catch process at creation.*catch stop -- Catch program stopping.*catch thread_exit -- Catch thread exit.*catch thread_join -- Catch thread after a join.*catch thread_start -- Catch thread start.*catch throw -- Catch an exception.*catch unload -- Catch library unloads.*catch vfork -- Catch calls to vfork.*Type .help catch. followed by catch subcommand name for full documentation.*Type .apropos word. to search for commands related to .word..*Command name abbreviations are allowed if unambiguous.*" "help catch"
# test help cd
gdb_test "help cd" "Set working directory to DIR for debugger and program being debugged\.\[\r\n\]+The change does not take effect for the program being debugged\[\r\n\]+until the next time it is started\." "help cd"
# test help clear
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-12 21:18 ` Tom Tromey
@ 2008-08-14 17:49 ` Daniel Jacobowitz
2008-08-14 18:00 ` Tom Tromey
2008-08-14 23:24 ` Tom Tromey
0 siblings, 2 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2008-08-14 17:49 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Tue, Aug 12, 2008 at 03:17:58PM -0600, Tom Tromey wrote:
> >>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
>
> Tom> This patch fixes PR 1535.
> Tom> The bug here is that CLI tab completion does not work for "catch"
> Tom> commands.
>
> After sending this I noticed a gettext snafu in the
> DEFINE_UNIMPLEMENTED macro -- stringization can't reasonably work
> here.
>
> The fix is to change the error call to use %s instead.
>
> I ran 'make gdb.pot' and looked at the result to verify that this
> change worked.
Just my taste, but I think this is pretty ugly. Manually expanded
tables wouldn't be any better. I think it's not as much extra typing
as you'd think to do it all without the tables.
Something like this: add_catch_command which takes normal add_cmd-like
arguments and adds the command to both catch and tcatch. A single,
manually written "catch_unimplemented" for the unimplemented commands
- or just remove them, what value do they add? And the other
functions are pretty simple. Most of the bulk of TABLE is the
docstrings.
In other words, make it as much like other commands as possible.
WDYT?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-14 17:49 ` Daniel Jacobowitz
@ 2008-08-14 18:00 ` Tom Tromey
2008-08-14 18:15 ` Tom Tromey
2008-08-14 23:24 ` Tom Tromey
1 sibling, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2008-08-14 18:00 UTC (permalink / raw)
To: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> Something like this: add_catch_command which takes normal
Daniel> add_cmd-like arguments and adds the command to both catch and
Daniel> tcatch.
No problem, I'll do this.
The thing is, we still need two versions of each function, because
AFAIK there is no way to pass a bit of "user data" along with a
command callback. This is a minor inconvenience of course -- though I
seem to run into it quite a bit.
Daniel> A single, manually written "catch_unimplemented" for the
Daniel> unimplemented commands - or just remove them, what value do
Daniel> they add?
I did not want to change this at all, basically to keep the patch
focused on one thing. But I agree, these non-functioning commands are
pointless. I'll go ahead and remove them.
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-14 18:00 ` Tom Tromey
@ 2008-08-14 18:15 ` Tom Tromey
0 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2008-08-14 18:15 UTC (permalink / raw)
To: gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
Tom> AFAIK there is no way to pass a bit of "user data" along with a
Tom> command callback.
Aha. We can set_cmd_cfunc and then use get_cmd_context.
Perhaps I will do that.
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-14 17:49 ` Daniel Jacobowitz
2008-08-14 18:00 ` Tom Tromey
@ 2008-08-14 23:24 ` Tom Tromey
2008-08-15 4:20 ` Daniel Jacobowitz
1 sibling, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2008-08-14 23:24 UTC (permalink / raw)
To: gdb-patches
Daniel> Just my taste, but I think this is pretty ugly. Manually expanded
Daniel> tables wouldn't be any better. I think it's not as much extra typing
Daniel> as you'd think to do it all without the tables.
Yeah, you're right.
How pedantically C is gdb? Here I cast some small integers to
'void*'. Alternatively I could turn the "context" into a union, or
make some globals.
This patch also deletes the unimplemented catch subcommands.
Also, I notice that hardly anything else uses the 'sfunc' code. Is
the intent to restrict this just to 'set' functions? IOW, is this an
abuse?
Tested on x86-64 (compile farm).
Ok?
Tom
2008-08-14 Tom Tromey <tromey@redhat.com>
PR gdb/1535:
* breakpoint.c (CATCH_PERMANENT, CATCH_TEMPORARY): New macros.
(ep_find_event_name_end): Remove.
(catch_fork_temporary, catch_vfork_temporary,
catch_fork_permanent, catch_vfork_permanent): New constants.
(catch_vfork, catch_fork): Remove.
(catch_fork_command_1): Add 'command' argument. Remove
'fork_kind' and 'tempflag'. Handle NULL 'arg'. Update switch for
all cases.
(catch_exec_command_1): Add 'command' argument; remove
'tempflag'. Handle NULL 'arg'.
(catch_load_command_1): Likewise.
(catch_unload_command_1): Likewise.
(catch_ada_exception_command): Likewise.
(catch_assert_command): Likewise.
(catch_catch_command): New function.
(catch_throw_command): Likewise.
(catch_command_1): Remove.
(catch_command): Just call error.
(tcatch_command): Likewise.
(catch_cmdlist): New global.
(tcatch_cmdlist): Likewise.
(add_catch_command): New function.
(_initialize_breakpoint): Create "catch" and "tcatch" as prefix
commands. Create all catch sub-commands.
2008-08-14 Tom Tromey <tromey@redhat.com>
* gdb.base/help.exp (help catch): Rewrite.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 2a10d61..528f623 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -59,9 +59,11 @@
#include "mi/mi-common.h"
-/* Prototypes for local functions. */
+/* Arguments to pass as context to some catch command handlers. */
+#define CATCH_PERMANENT ((void *) 0)
+#define CATCH_TEMPORARY ((void *) 1)
-static void catch_command_1 (char *, int, int);
+/* Prototypes for local functions. */
static void enable_delete_command (char *, int);
@@ -167,8 +169,6 @@ static void stopin_command (char *arg, int from_tty);
static void stopat_command (char *arg, int from_tty);
-static char *ep_find_event_name_end (char *arg);
-
static char *ep_parse_optional_if_clause (char **arg);
static char *ep_parse_optional_filename (char **arg);
@@ -6251,36 +6251,6 @@ ep_skip_leading_whitespace (char **s)
*s += 1;
}
-/* This function examines a string, and attempts to find a token
- that might be an event name in the leading characters. If a
- possible match is found, a pointer to the last character of
- the token is returned. Else, NULL is returned. */
-
-static char *
-ep_find_event_name_end (char *arg)
-{
- char *s = arg;
- char *event_name_end = NULL;
-
- /* If we could depend upon the presense of strrpbrk, we'd use that... */
- if (arg == NULL)
- return NULL;
-
- /* We break out of the loop when we find a token delimiter.
- Basically, we're looking for alphanumerics and underscores;
- anything else delimites the token. */
- while (*s != '\0')
- {
- if (!isalnum (*s) && (*s != '_'))
- break;
- event_name_end = s;
- s++;
- }
-
- return event_name_end;
-}
-
-
/* This function attempts to parse an optional "if <cond>" clause
from the arg string. If one is not found, it returns NULL.
@@ -6352,16 +6322,24 @@ ep_parse_optional_filename (char **arg)
typedef enum
{
- catch_fork, catch_vfork
+ catch_fork_temporary, catch_vfork_temporary,
+ catch_fork_permanent, catch_vfork_permanent
}
catch_fork_kind;
static void
-catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
- int from_tty)
+catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
{
char *cond_string = NULL;
+ catch_fork_kind fork_kind;
+ int tempflag;
+
+ fork_kind = (catch_fork_kind) get_cmd_context (command);
+ tempflag = (fork_kind == catch_fork_temporary
+ || fork_kind == catch_vfork_temporary);
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6378,10 +6356,12 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
and enable reporting of such events. */
switch (fork_kind)
{
- case catch_fork:
+ case catch_fork_temporary:
+ case catch_fork_permanent:
create_fork_event_catchpoint (tempflag, cond_string);
break;
- case catch_vfork:
+ case catch_vfork_temporary:
+ case catch_vfork_permanent:
create_vfork_event_catchpoint (tempflag, cond_string);
break;
default:
@@ -6391,10 +6371,15 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
}
static void
-catch_exec_command_1 (char *arg, int tempflag, int from_tty)
+catch_exec_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
{
+ int tempflag;
char *cond_string = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6413,11 +6398,16 @@ catch_exec_command_1 (char *arg, int tempflag, int from_tty)
}
static void
-catch_load_command_1 (char *arg, int tempflag, int from_tty)
+catch_load_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
{
+ int tempflag;
char *dll_pathname = NULL;
char *cond_string = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6455,11 +6445,17 @@ catch_load_command_1 (char *arg, int tempflag, int from_tty)
}
static void
-catch_unload_command_1 (char *arg, int tempflag, int from_tty)
+catch_unload_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
+ int tempflag;
char *dll_pathname = NULL;
char *cond_string = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6598,6 +6594,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
char *cond_string = NULL;
struct symtab_and_line *sal = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
@@ -6615,6 +6613,24 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
warning (_("Unsupported with this platform/compiler combination."));
}
+/* Implementation of "catch catch" command. */
+
+static void
+catch_catch_command (char *arg, int from_tty, struct cmd_list_element *command)
+{
+ int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+ catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
+}
+
+/* Implementation of "catch throw" command. */
+
+static void
+catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
+{
+ int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+ catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
+}
+
/* Create a breakpoint struct for Ada exception catchpoints. */
static void
@@ -6664,8 +6680,10 @@ create_ada_exception_breakpoint (struct symtab_and_line sal,
/* Implement the "catch exception" command. */
static void
-catch_ada_exception_command (char *arg, int tempflag, int from_tty)
+catch_ada_exception_command (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
+ int tempflag;
struct symtab_and_line sal;
enum bptype type;
char *addr_string = NULL;
@@ -6674,6 +6692,10 @@ catch_ada_exception_command (char *arg, int tempflag, int from_tty)
struct expression *cond = NULL;
struct breakpoint_ops *ops = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
&cond_string, &cond, &ops);
create_ada_exception_breakpoint (sal, addr_string, exp_string,
@@ -6684,138 +6706,33 @@ catch_ada_exception_command (char *arg, int tempflag, int from_tty)
/* Implement the "catch assert" command. */
static void
-catch_assert_command (char *arg, int tempflag, int from_tty)
+catch_assert_command (char *arg, int from_tty, struct cmd_list_element *command)
{
+ int tempflag;
struct symtab_and_line sal;
char *addr_string = NULL;
struct breakpoint_ops *ops = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
sal = ada_decode_assert_location (arg, &addr_string, &ops);
create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops,
tempflag, from_tty);
}
static void
-catch_command_1 (char *arg, int tempflag, int from_tty)
-{
-
- /* The first argument may be an event name, such as "start" or "load".
- If so, then handle it as such. If it doesn't match an event name,
- then attempt to interpret it as an exception name. (This latter is
- the v4.16-and-earlier GDB meaning of the "catch" command.)
-
- First, try to find the bounds of what might be an event name. */
- char *arg1_start = arg;
- char *arg1_end;
- int arg1_length;
-
- if (arg1_start == NULL)
- {
- /* Old behaviour was to use pre-v-4.16 syntax */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* return; */
- /* Now, this is not allowed */
- error (_("Catch requires an event name."));
-
- }
- arg1_end = ep_find_event_name_end (arg1_start);
- if (arg1_end == NULL)
- error (_("catch requires an event"));
- arg1_length = arg1_end + 1 - arg1_start;
-
- /* Try to match what we found against known event names. */
- if (strncmp (arg1_start, "signal", arg1_length) == 0)
- {
- error (_("Catch of signal not yet implemented"));
- }
- else if (strncmp (arg1_start, "catch", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "throw", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
- {
- error (_("Catch of thread_start not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
- {
- error (_("Catch of thread_exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
- {
- error (_("Catch of thread_join not yet implemented"));
- }
- else if (strncmp (arg1_start, "start", arg1_length) == 0)
- {
- error (_("Catch of start not yet implemented"));
- }
- else if (strncmp (arg1_start, "exit", arg1_length) == 0)
- {
- error (_("Catch of exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "fork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "exec", arg1_length) == 0)
- {
- catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "load", arg1_length) == 0)
- {
- catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "unload", arg1_length) == 0)
- {
- catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "stop", arg1_length) == 0)
- {
- error (_("Catch of stop not yet implemented"));
- }
- else if (strncmp (arg1_start, "exception", arg1_length) == 0)
- {
- catch_ada_exception_command (arg1_end + 1, tempflag, from_tty);
- }
-
- else if (strncmp (arg1_start, "assert", arg1_length) == 0)
- {
- catch_assert_command (arg1_end + 1, tempflag, from_tty);
- }
-
- /* This doesn't appear to be an event name */
-
- else
- {
- /* Pre-v.4.16 behaviour was to treat the argument
- as the name of an exception */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* Now this is not allowed */
- error (_("Unknown event kind specified for catch"));
-
- }
-}
-
-static void
catch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 0, from_tty);
+ error (_("Catch requires an event name."));
}
\f
static void
tcatch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 1, from_tty);
+ error (_("Catch requires an event name."));
}
/* Delete breakpoints by address or line. */
@@ -8222,6 +8139,34 @@ Multiple breakpoints at one place are permitted, and useful if conditional.\n\
\n\
Do \"help breakpoints\" for info on other commands dealing with breakpoints."
+/* List of subcommands for "catch". */
+static struct cmd_list_element *catch_cmdlist;
+
+/* List of subcommands for "tcatch". */
+static struct cmd_list_element *tcatch_cmdlist;
+
+/* Like add_cmd, but add the command to both the "catch" and "tcatch"
+ lists, and pass some additional user data to the command function. */
+static void
+add_catch_command (char *name, char *docstring,
+ void (*sfunc) (char *args, int from_tty,
+ struct cmd_list_element *command),
+ void *user_data_catch,
+ void *user_data_tcatch)
+{
+ struct cmd_list_element *command;
+
+ command = add_cmd (name, class_breakpoint, NULL, docstring,
+ &catch_cmdlist);
+ set_cmd_sfunc (command, sfunc);
+ set_cmd_context (command, user_data_catch);
+
+ command = add_cmd (name, class_breakpoint, NULL, docstring,
+ &tcatch_cmdlist);
+ set_cmd_sfunc (command, sfunc);
+ set_cmd_context (command, user_data_tcatch);
+}
+
void
_initialize_breakpoint (void)
{
@@ -8479,52 +8424,65 @@ Convenience variable \"$bpnum\" contains the number of the last\n\
breakpoint set."),
&maintenanceinfolist);
- add_com ("catch", class_breakpoint, catch_command, _("\
-Set catchpoints to catch events.\n\
-Raised signals may be caught:\n\
-\tcatch signal - all signals\n\
-\tcatch signal <signame> - a particular signal\n\
-Raised exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch throw <exceptname> - a particular exception, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-\tcatch catch <exceptname> - a particular exception, when caught\n\
-Thread or process events may be caught:\n\
-\tcatch thread_start - any threads, just after creation\n\
-\tcatch thread_exit - any threads, just before expiration\n\
-\tcatch thread_join - any threads, just after joins\n\
-Process events may be caught:\n\
-\tcatch start - any processes, just after creation\n\
-\tcatch exit - any processes, just before expiration\n\
-\tcatch fork - calls to fork()\n\
-\tcatch vfork - calls to vfork()\n\
-\tcatch exec - calls to exec()\n\
-Dynamically-linked library events may be caught:\n\
-\tcatch load - loads of any library\n\
-\tcatch load <libname> - loads of a particular library\n\
-\tcatch unload - unloads of any library\n\
-\tcatch unload <libname> - unloads of a particular library\n\
-The act of your program's execution stopping may also be caught:\n\
-\tcatch stop\n\n\
-C++ exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-Ada exceptions may be caught:\n\
-\tcatch exception - all exceptions, when raised\n\
-\tcatch exception <name> - a particular exception, when raised\n\
-\tcatch exception unhandled - all unhandled exceptions, when raised\n\
-\tcatch assert - all failed assertions, when raised\n\
-\n\
-Do \"help set follow-fork-mode\" for info on debugging your program\n\
-after a fork or vfork is caught.\n\n\
-Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
-
- add_com ("tcatch", class_breakpoint, tcatch_command, _("\
-Set temporary catchpoints to catch events.\n\
-Args like \"catch\" command.\n\
-Like \"catch\" except the catchpoint is only temporary,\n\
-so it will be deleted when hit. Equivalent to \"catch\" followed\n\
-by using \"enable delete\" on the catchpoint number."));
+ add_prefix_cmd ("catch", class_breakpoint, catch_command, _("\
+Set catchpoints to catch events."),
+ &catch_cmdlist, "catch ",
+ 0/*allow-unknown*/, &cmdlist);
+
+ add_prefix_cmd ("tcatch", class_breakpoint, tcatch_command, _("\
+Set temporary catchpoints to catch events."),
+ &tcatch_cmdlist, "tcatch ",
+ 0/*allow-unknown*/, &cmdlist);
+
+ /* Add catch and tcatch sub-commands. */
+ add_catch_command ("catch", _("\
+Catch an exception, when caught.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_catch_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("throw", _("\
+Catch an exception, when thrown.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_throw_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("fork", _("Catch calls to fork."),
+ catch_fork_command_1,
+ (void *) catch_fork_permanent,
+ (void *) catch_fork_temporary);
+ add_catch_command ("vfork", _("Catch calls to vfork."),
+ catch_fork_command_1,
+ (void *) catch_vfork_permanent,
+ (void *) catch_vfork_temporary);
+ add_catch_command ("exec", _("Catch calls to exec."),
+ catch_exec_command_1,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("load", _("\
+Catch library loads.\n\
+With an argument, catch only loads of that library."),
+ catch_load_command_1,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("unload", _("\
+Catch library unloads.\n\
+With an argument, catch only unloads of that library."),
+ catch_unload_command_1,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("exception", _("\
+Catch Ada exceptions, when raised.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_ada_exception_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("assert", _("\
+Catch failed Ada assertions, when raised.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_assert_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
c = add_com ("watch", class_breakpoint, watch_command, _("\
Set a watchpoint for an expression.\n\
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
index c427b31..bd2f9a6 100644
--- a/gdb/testsuite/gdb.base/help.exp
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -68,7 +68,7 @@ gdb_test "help continue" "Continue program being debugged.*" "help continue"
# test help call
gdb_test "help call" "Call a function.*" "help call"
# test help catch
-gdb_test "help catch" "Set catchpoints to catch events.*Raised signals may be caught:.*catch signal.*all signals.*catch signal.*signame.*a particular signal.*Raised exceptions may be caught:.*catch throw.*all exceptions, when thrown.*catch throw.*exceptname.*a particular exception, when thrown.*catch catch.*all exceptions, when caught.*catch catch.*exceptname.*a particular exception, when caught.*Thread or process events may be caught:.*catch thread_start.*any threads, just after creation.*catch thread_exit.*any threads, just before expiration.*catch thread_join.*any threads, just after joins.*catch start.*any processes, just after creation.*catch exit.*any processes, just before expiration.*catch fork.*calls to fork.*catch vfork.*calls to vfork.*catch exec.*calls to exec.*Dynamically.linked library events may be caught:.*catch load.*loads of any library.*catch load.*libname.*loads of a particular library.*catch unload.*unloads of any library.*catch unload.*libname.*unloads of a particular library.*The act of your program's execution stopping may also be caught:.*catch stop.*Do.*help set follow-fork-mode.*for info on debugging your program.*after a fork or vfork is caught.*Do.*help breakpoints.*for info on other commands dealing with breakpoints." "help catch"
+gdb_test "help catch" "Set catchpoints to catch events.*List of catch subcommands:.*catch assert -- Catch failed Ada assertions.*catch catch -- Catch an exception.*catch exception -- Catch Ada exceptions.*catch exec -- Catch calls to exec.*catch fork -- Catch calls to fork.*catch load -- Catch library loads.*catch throw -- Catch an exception.*catch unload -- Catch library unloads.*catch vfork -- Catch calls to vfork.*Type .help catch. followed by catch subcommand name for full documentation.*Type .apropos word. to search for commands related to .word..*Command name abbreviations are allowed if unambiguous.*" "help catch"
# test help cd
gdb_test "help cd" "Set working directory to DIR for debugger and program being debugged\.\[\r\n\]+The change does not take effect for the program being debugged\[\r\n\]+until the next time it is started\." "help cd"
# test help clear
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-14 23:24 ` Tom Tromey
@ 2008-08-15 4:20 ` Daniel Jacobowitz
2008-08-15 8:44 ` Andreas Schwab
2008-08-17 17:40 ` Tom Tromey
0 siblings, 2 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2008-08-15 4:20 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Thu, Aug 14, 2008 at 05:23:54PM -0600, Tom Tromey wrote:
> How pedantically C is gdb? Here I cast some small integers to
> 'void*'. Alternatively I could turn the "context" into a union, or
> make some globals.
Go through uintptr_t, please. I've made stdint.h always available and that
will be the right size; if you go int -> void * you will break
x86_64. Well, you tested x86_64. But I'm not sure why you didn't get
a warning for (void *) 1.
> Also, I notice that hardly anything else uses the 'sfunc' code. Is
> the intent to restrict this just to 'set' functions? IOW, is this an
> abuse?
I dont know, but it looks entirely reasonable to me. Patch is OK.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-15 4:20 ` Daniel Jacobowitz
@ 2008-08-15 8:44 ` Andreas Schwab
2008-08-17 17:40 ` Tom Tromey
1 sibling, 0 replies; 9+ messages in thread
From: Andreas Schwab @ 2008-08-15 8:44 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Daniel Jacobowitz <drow@false.org> writes:
> But I'm not sure why you didn't get a warning for (void *) 1.
GCC doesn't warn for pointer casts of literals, since the value is known
and it's a common idiom (SIG_IGN uses it, for example).
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, MaxfeldstraÃe 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: RFA: fix PR 1535
2008-08-15 4:20 ` Daniel Jacobowitz
2008-08-15 8:44 ` Andreas Schwab
@ 2008-08-17 17:40 ` Tom Tromey
1 sibling, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2008-08-17 17:40 UTC (permalink / raw)
To: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> Go through uintptr_t, please.
No problem.
>> Also, I notice that hardly anything else uses the 'sfunc' code. Is
>> the intent to restrict this just to 'set' functions? IOW, is this an
>> abuse?
Daniel> I dont know, but it looks entirely reasonable to me. Patch is OK.
For the record here is what I am checking in.
Tom
ChangeLog:
2008-08-17 Tom Tromey <tromey@redhat.com>
PR gdb/1535:
* breakpoint.c (CATCH_PERMANENT, CATCH_TEMPORARY): New macros.
(ep_find_event_name_end): Remove.
(catch_fork_temporary, catch_vfork_temporary,
catch_fork_permanent, catch_vfork_permanent): New constants.
(catch_vfork, catch_fork): Remove.
(catch_fork_command_1): Add 'command' argument. Remove
'fork_kind' and 'tempflag'. Handle NULL 'arg'. Update switch for
all cases.
(catch_exec_command_1): Add 'command' argument; remove
'tempflag'. Handle NULL 'arg'.
(catch_load_command_1): Likewise.
(catch_unload_command_1): Likewise.
(catch_ada_exception_command): Likewise.
(catch_assert_command): Likewise.
(catch_catch_command): New function.
(catch_throw_command): Likewise.
(catch_command_1): Remove.
(catch_command): Just call error.
(tcatch_command): Likewise.
(catch_cmdlist): New global.
(tcatch_cmdlist): Likewise.
(add_catch_command): New function.
(_initialize_breakpoint): Create "catch" and "tcatch" as prefix
commands. Create all catch sub-commands.
testsuite/ChangeLog:
2008-08-17 Tom Tromey <tromey@redhat.com>
* gdb.base/help.exp (help catch): Rewrite.
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.342
diff -u -r1.342 breakpoint.c
--- breakpoint.c 16 Aug 2008 20:36:29 -0000 1.342
+++ breakpoint.c 17 Aug 2008 16:52:41 -0000
@@ -59,9 +59,11 @@
#include "mi/mi-common.h"
-/* Prototypes for local functions. */
+/* Arguments to pass as context to some catch command handlers. */
+#define CATCH_PERMANENT ((void *) (uintptr_t) 0)
+#define CATCH_TEMPORARY ((void *) (uintptr_t) 1)
-static void catch_command_1 (char *, int, int);
+/* Prototypes for local functions. */
static void enable_delete_command (char *, int);
@@ -167,8 +169,6 @@
static void stopat_command (char *arg, int from_tty);
-static char *ep_find_event_name_end (char *arg);
-
static char *ep_parse_optional_if_clause (char **arg);
static char *ep_parse_optional_filename (char **arg);
@@ -6274,36 +6274,6 @@
*s += 1;
}
-/* This function examines a string, and attempts to find a token
- that might be an event name in the leading characters. If a
- possible match is found, a pointer to the last character of
- the token is returned. Else, NULL is returned. */
-
-static char *
-ep_find_event_name_end (char *arg)
-{
- char *s = arg;
- char *event_name_end = NULL;
-
- /* If we could depend upon the presense of strrpbrk, we'd use that... */
- if (arg == NULL)
- return NULL;
-
- /* We break out of the loop when we find a token delimiter.
- Basically, we're looking for alphanumerics and underscores;
- anything else delimites the token. */
- while (*s != '\0')
- {
- if (!isalnum (*s) && (*s != '_'))
- break;
- event_name_end = s;
- s++;
- }
-
- return event_name_end;
-}
-
-
/* This function attempts to parse an optional "if <cond>" clause
from the arg string. If one is not found, it returns NULL.
@@ -6375,16 +6345,24 @@
typedef enum
{
- catch_fork, catch_vfork
+ catch_fork_temporary, catch_vfork_temporary,
+ catch_fork_permanent, catch_vfork_permanent
}
catch_fork_kind;
static void
-catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
- int from_tty)
+catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
{
char *cond_string = NULL;
+ catch_fork_kind fork_kind;
+ int tempflag;
+
+ fork_kind = (catch_fork_kind) (uintptr_t) get_cmd_context (command);
+ tempflag = (fork_kind == catch_fork_temporary
+ || fork_kind == catch_vfork_temporary);
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6401,10 +6379,12 @@
and enable reporting of such events. */
switch (fork_kind)
{
- case catch_fork:
+ case catch_fork_temporary:
+ case catch_fork_permanent:
create_fork_event_catchpoint (tempflag, cond_string);
break;
- case catch_vfork:
+ case catch_vfork_temporary:
+ case catch_vfork_permanent:
create_vfork_event_catchpoint (tempflag, cond_string);
break;
default:
@@ -6414,10 +6394,15 @@
}
static void
-catch_exec_command_1 (char *arg, int tempflag, int from_tty)
+catch_exec_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
{
+ int tempflag;
char *cond_string = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6436,11 +6421,16 @@
}
static void
-catch_load_command_1 (char *arg, int tempflag, int from_tty)
+catch_load_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
{
+ int tempflag;
char *dll_pathname = NULL;
char *cond_string = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6478,11 +6468,17 @@
}
static void
-catch_unload_command_1 (char *arg, int tempflag, int from_tty)
+catch_unload_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
+ int tempflag;
char *dll_pathname = NULL;
char *cond_string = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
/* The allowed syntax is:
@@ -6621,6 +6617,8 @@
char *cond_string = NULL;
struct symtab_and_line *sal = NULL;
+ if (!arg)
+ arg = "";
ep_skip_leading_whitespace (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
@@ -6638,6 +6636,24 @@
warning (_("Unsupported with this platform/compiler combination."));
}
+/* Implementation of "catch catch" command. */
+
+static void
+catch_catch_command (char *arg, int from_tty, struct cmd_list_element *command)
+{
+ int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+ catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
+}
+
+/* Implementation of "catch throw" command. */
+
+static void
+catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
+{
+ int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+ catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
+}
+
/* Create a breakpoint struct for Ada exception catchpoints. */
static void
@@ -6687,8 +6703,10 @@
/* Implement the "catch exception" command. */
static void
-catch_ada_exception_command (char *arg, int tempflag, int from_tty)
+catch_ada_exception_command (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
+ int tempflag;
struct symtab_and_line sal;
enum bptype type;
char *addr_string = NULL;
@@ -6697,6 +6715,10 @@
struct expression *cond = NULL;
struct breakpoint_ops *ops = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
&cond_string, &cond, &ops);
create_ada_exception_breakpoint (sal, addr_string, exp_string,
@@ -6707,138 +6729,33 @@
/* Implement the "catch assert" command. */
static void
-catch_assert_command (char *arg, int tempflag, int from_tty)
+catch_assert_command (char *arg, int from_tty, struct cmd_list_element *command)
{
+ int tempflag;
struct symtab_and_line sal;
char *addr_string = NULL;
struct breakpoint_ops *ops = NULL;
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
sal = ada_decode_assert_location (arg, &addr_string, &ops);
create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops,
tempflag, from_tty);
}
static void
-catch_command_1 (char *arg, int tempflag, int from_tty)
-{
-
- /* The first argument may be an event name, such as "start" or "load".
- If so, then handle it as such. If it doesn't match an event name,
- then attempt to interpret it as an exception name. (This latter is
- the v4.16-and-earlier GDB meaning of the "catch" command.)
-
- First, try to find the bounds of what might be an event name. */
- char *arg1_start = arg;
- char *arg1_end;
- int arg1_length;
-
- if (arg1_start == NULL)
- {
- /* Old behaviour was to use pre-v-4.16 syntax */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* return; */
- /* Now, this is not allowed */
- error (_("Catch requires an event name."));
-
- }
- arg1_end = ep_find_event_name_end (arg1_start);
- if (arg1_end == NULL)
- error (_("catch requires an event"));
- arg1_length = arg1_end + 1 - arg1_start;
-
- /* Try to match what we found against known event names. */
- if (strncmp (arg1_start, "signal", arg1_length) == 0)
- {
- error (_("Catch of signal not yet implemented"));
- }
- else if (strncmp (arg1_start, "catch", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "throw", arg1_length) == 0)
- {
- catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,
- tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
- {
- error (_("Catch of thread_start not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
- {
- error (_("Catch of thread_exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
- {
- error (_("Catch of thread_join not yet implemented"));
- }
- else if (strncmp (arg1_start, "start", arg1_length) == 0)
- {
- error (_("Catch of start not yet implemented"));
- }
- else if (strncmp (arg1_start, "exit", arg1_length) == 0)
- {
- error (_("Catch of exit not yet implemented"));
- }
- else if (strncmp (arg1_start, "fork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
- {
- catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "exec", arg1_length) == 0)
- {
- catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "load", arg1_length) == 0)
- {
- catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "unload", arg1_length) == 0)
- {
- catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
- }
- else if (strncmp (arg1_start, "stop", arg1_length) == 0)
- {
- error (_("Catch of stop not yet implemented"));
- }
- else if (strncmp (arg1_start, "exception", arg1_length) == 0)
- {
- catch_ada_exception_command (arg1_end + 1, tempflag, from_tty);
- }
-
- else if (strncmp (arg1_start, "assert", arg1_length) == 0)
- {
- catch_assert_command (arg1_end + 1, tempflag, from_tty);
- }
-
- /* This doesn't appear to be an event name */
-
- else
- {
- /* Pre-v.4.16 behaviour was to treat the argument
- as the name of an exception */
- /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
- /* Now this is not allowed */
- error (_("Unknown event kind specified for catch"));
-
- }
-}
-
-static void
catch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 0, from_tty);
+ error (_("Catch requires an event name."));
}
\f
static void
tcatch_command (char *arg, int from_tty)
{
- catch_command_1 (arg, 1, from_tty);
+ error (_("Catch requires an event name."));
}
/* Delete breakpoints by address or line. */
@@ -8240,6 +8157,34 @@
\n\
Do \"help breakpoints\" for info on other commands dealing with breakpoints."
+/* List of subcommands for "catch". */
+static struct cmd_list_element *catch_cmdlist;
+
+/* List of subcommands for "tcatch". */
+static struct cmd_list_element *tcatch_cmdlist;
+
+/* Like add_cmd, but add the command to both the "catch" and "tcatch"
+ lists, and pass some additional user data to the command function. */
+static void
+add_catch_command (char *name, char *docstring,
+ void (*sfunc) (char *args, int from_tty,
+ struct cmd_list_element *command),
+ void *user_data_catch,
+ void *user_data_tcatch)
+{
+ struct cmd_list_element *command;
+
+ command = add_cmd (name, class_breakpoint, NULL, docstring,
+ &catch_cmdlist);
+ set_cmd_sfunc (command, sfunc);
+ set_cmd_context (command, user_data_catch);
+
+ command = add_cmd (name, class_breakpoint, NULL, docstring,
+ &tcatch_cmdlist);
+ set_cmd_sfunc (command, sfunc);
+ set_cmd_context (command, user_data_tcatch);
+}
+
void
_initialize_breakpoint (void)
{
@@ -8497,52 +8442,65 @@
breakpoint set."),
&maintenanceinfolist);
- add_com ("catch", class_breakpoint, catch_command, _("\
-Set catchpoints to catch events.\n\
-Raised signals may be caught:\n\
-\tcatch signal - all signals\n\
-\tcatch signal <signame> - a particular signal\n\
-Raised exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch throw <exceptname> - a particular exception, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-\tcatch catch <exceptname> - a particular exception, when caught\n\
-Thread or process events may be caught:\n\
-\tcatch thread_start - any threads, just after creation\n\
-\tcatch thread_exit - any threads, just before expiration\n\
-\tcatch thread_join - any threads, just after joins\n\
-Process events may be caught:\n\
-\tcatch start - any processes, just after creation\n\
-\tcatch exit - any processes, just before expiration\n\
-\tcatch fork - calls to fork()\n\
-\tcatch vfork - calls to vfork()\n\
-\tcatch exec - calls to exec()\n\
-Dynamically-linked library events may be caught:\n\
-\tcatch load - loads of any library\n\
-\tcatch load <libname> - loads of a particular library\n\
-\tcatch unload - unloads of any library\n\
-\tcatch unload <libname> - unloads of a particular library\n\
-The act of your program's execution stopping may also be caught:\n\
-\tcatch stop\n\n\
-C++ exceptions may be caught:\n\
-\tcatch throw - all exceptions, when thrown\n\
-\tcatch catch - all exceptions, when caught\n\
-Ada exceptions may be caught:\n\
-\tcatch exception - all exceptions, when raised\n\
-\tcatch exception <name> - a particular exception, when raised\n\
-\tcatch exception unhandled - all unhandled exceptions, when raised\n\
-\tcatch assert - all failed assertions, when raised\n\
-\n\
-Do \"help set follow-fork-mode\" for info on debugging your program\n\
-after a fork or vfork is caught.\n\n\
-Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
-
- add_com ("tcatch", class_breakpoint, tcatch_command, _("\
-Set temporary catchpoints to catch events.\n\
-Args like \"catch\" command.\n\
-Like \"catch\" except the catchpoint is only temporary,\n\
-so it will be deleted when hit. Equivalent to \"catch\" followed\n\
-by using \"enable delete\" on the catchpoint number."));
+ add_prefix_cmd ("catch", class_breakpoint, catch_command, _("\
+Set catchpoints to catch events."),
+ &catch_cmdlist, "catch ",
+ 0/*allow-unknown*/, &cmdlist);
+
+ add_prefix_cmd ("tcatch", class_breakpoint, tcatch_command, _("\
+Set temporary catchpoints to catch events."),
+ &tcatch_cmdlist, "tcatch ",
+ 0/*allow-unknown*/, &cmdlist);
+
+ /* Add catch and tcatch sub-commands. */
+ add_catch_command ("catch", _("\
+Catch an exception, when caught.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_catch_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("throw", _("\
+Catch an exception, when thrown.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_throw_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("fork", _("Catch calls to fork."),
+ catch_fork_command_1,
+ (void *) (uintptr_t) catch_fork_permanent,
+ (void *) (uintptr_t) catch_fork_temporary);
+ add_catch_command ("vfork", _("Catch calls to vfork."),
+ catch_fork_command_1,
+ (void *) (uintptr_t) catch_vfork_permanent,
+ (void *) (uintptr_t) catch_vfork_temporary);
+ add_catch_command ("exec", _("Catch calls to exec."),
+ catch_exec_command_1,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("load", _("\
+Catch library loads.\n\
+With an argument, catch only loads of that library."),
+ catch_load_command_1,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("unload", _("\
+Catch library unloads.\n\
+With an argument, catch only unloads of that library."),
+ catch_unload_command_1,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("exception", _("\
+Catch Ada exceptions, when raised.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_ada_exception_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("assert", _("\
+Catch failed Ada assertions, when raised.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_assert_command,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
c = add_com ("watch", class_breakpoint, watch_command, _("\
Set a watchpoint for an expression.\n\
Index: testsuite/gdb.base/help.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/help.exp,v
retrieving revision 1.29
diff -u -r1.29 help.exp
--- testsuite/gdb.base/help.exp 6 Aug 2008 12:52:07 -0000 1.29
+++ testsuite/gdb.base/help.exp 17 Aug 2008 16:52:42 -0000
@@ -68,7 +68,7 @@
# test help call
gdb_test "help call" "Call a function.*" "help call"
# test help catch
-gdb_test "help catch" "Set catchpoints to catch events.*Raised signals may be caught:.*catch signal.*all signals.*catch signal.*signame.*a particular signal.*Raised exceptions may be caught:.*catch throw.*all exceptions, when thrown.*catch throw.*exceptname.*a particular exception, when thrown.*catch catch.*all exceptions, when caught.*catch catch.*exceptname.*a particular exception, when caught.*Thread or process events may be caught:.*catch thread_start.*any threads, just after creation.*catch thread_exit.*any threads, just before expiration.*catch thread_join.*any threads, just after joins.*catch start.*any processes, just after creation.*catch exit.*any processes, just before expiration.*catch fork.*calls to fork.*catch vfork.*calls to vfork.*catch exec.*calls to exec.*Dynamically.linked library events may be caught:.*catch load.*loads of any library.*catch load.*libname.*loads of a particular library.*catch unload.*unloads of any library.*catch unload.*libname.*unloads of a particular library.*The act of your program's execution stopping may also be caught:.*catch stop.*Do.*help set follow-fork-mode.*for info on debugging your program.*after a fork or vfork is caught.*Do.*help breakpoints.*for info on other commands dealing with breakpoints." "help catch"
+gdb_test "help catch" "Set catchpoints to catch events.*List of catch subcommands:.*catch assert -- Catch failed Ada assertions.*catch catch -- Catch an exception.*catch exception -- Catch Ada exceptions.*catch exec -- Catch calls to exec.*catch fork -- Catch calls to fork.*catch load -- Catch library loads.*catch throw -- Catch an exception.*catch unload -- Catch library unloads.*catch vfork -- Catch calls to vfork.*Type .help catch. followed by catch subcommand name for full documentation.*Type .apropos word. to search for commands related to .word..*Command name abbreviations are allowed if unambiguous.*" "help catch"
# test help cd
gdb_test "help cd" "Set working directory to DIR for debugger and program being debugged\.\[\r\n\]+The change does not take effect for the program being debugged\[\r\n\]+until the next time it is started\." "help cd"
# test help clear
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-08-17 17:40 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-12 18:19 RFA: fix PR 1535 Tom Tromey
2008-08-12 21:18 ` Tom Tromey
2008-08-14 17:49 ` Daniel Jacobowitz
2008-08-14 18:00 ` Tom Tromey
2008-08-14 18:15 ` Tom Tromey
2008-08-14 23:24 ` Tom Tromey
2008-08-15 4:20 ` Daniel Jacobowitz
2008-08-15 8:44 ` Andreas Schwab
2008-08-17 17:40 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox