From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31263 invoked by alias); 12 Aug 2008 18:19:22 -0000 Received: (qmail 31251 invoked by uid 22791); 12 Aug 2008 18:19:19 -0000 X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 12 Aug 2008 18:18:41 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id m7CIId1F029350 for ; Tue, 12 Aug 2008 14:18:39 -0400 Received: from pobox.corp.redhat.com (pobox.corp.redhat.com [10.11.255.20]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m7CIIcG3012502; Tue, 12 Aug 2008 14:18:38 -0400 Received: from opsy.redhat.com (vpn-10-62.bos.redhat.com [10.16.10.62]) by pobox.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m7CIIb62004208; Tue, 12 Aug 2008 14:18:37 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id D3A73378276; Tue, 12 Aug 2008 12:18:32 -0600 (MDT) To: gdb-patches@sourceware.org Subject: RFA: fix PR 1535 From: Tom Tromey Reply-To: tromey@redhat.com X-Attribution: Tom Date: Tue, 12 Aug 2008 18:19:00 -0000 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-08/txt/msg00320.txt.bz2 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 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 * 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 @@ =20 /* Prototypes for local functions. */ =20 -static void catch_command_1 (char *, int, int); - static void enable_delete_command (char *, int); =20 static void enable_delete_breakpoint (struct breakpoint *); @@ -167,8 +165,6 @@ static void stopin_command (char *arg, int from_tty); =20 static void stopat_command (char *arg, int from_tty); =20 -static char *ep_find_event_name_end (char *arg); - static char *ep_parse_optional_if_clause (char **arg); =20 static char *ep_parse_optional_filename (char **arg); @@ -6251,36 +6247,6 @@ ep_skip_leading_whitespace (char **s) *s +=3D 1; } =20 -/* 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 =3D arg; - char *event_name_end =3D NULL; - - /* If we could depend upon the presense of strrpbrk, we'd use that... */ - if (arg =3D=3D 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 !=3D '\0') - { - if (!isalnum (*s) && (*s !=3D '_')) - break; - event_name_end =3D s; - s++; - } - - return event_name_end; -} - - /* This function attempts to parse an optional "if " clause from the arg string. If one is not found, it returns NULL. =20 @@ -6362,6 +6328,8 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char= *arg, int tempflag, { char *cond_string =3D NULL; =20 + if (!arg) + arg =3D ""; ep_skip_leading_whitespace (&arg); =20 /* The allowed syntax is: @@ -6391,10 +6359,12 @@ catch_fork_command_1 (catch_fork_kind fork_kind, ch= ar *arg, int tempflag, } =20 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 =3D NULL; =20 + if (!arg) + arg =3D ""; ep_skip_leading_whitespace (&arg); =20 /* The allowed syntax is: @@ -6413,11 +6383,13 @@ catch_exec_command_1 (char *arg, int tempflag, int = from_tty) } =20 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 =3D NULL; char *cond_string =3D NULL; =20 + if (!arg) + arg =3D ""; ep_skip_leading_whitespace (&arg); =20 /* The allowed syntax is: @@ -6455,11 +6427,13 @@ catch_load_command_1 (char *arg, int tempflag, int = from_tty) } =20 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 =3D NULL; char *cond_string =3D NULL; =20 + if (!arg) + arg =3D ""; ep_skip_leading_whitespace (&arg); =20 /* The allowed syntax is: @@ -6598,6 +6572,8 @@ catch_exception_command_1 (enum exception_event_kind = ex_event, char *arg, char *cond_string =3D NULL; struct symtab_and_line *sal =3D NULL; =20 + if (!arg) + arg =3D ""; ep_skip_leading_whitespace (&arg); =20 cond_string =3D ep_parse_optional_if_clause (&arg); @@ -6664,7 +6640,7 @@ create_ada_exception_breakpoint (struct symtab_and_li= ne sal, /* Implement the "catch exception" command. */ =20 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 =3D NULL; struct breakpoint_ops *ops =3D NULL; =20 + if (!arg) + arg =3D ""; sal =3D 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, in= t from_tty) char *addr_string =3D NULL; struct breakpoint_ops *ops =3D NULL; =20 + if (!arg) + arg =3D ""; sal =3D ada_decode_assert_location (arg, &addr_string, &ops); create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops, tempflag, from_tty); } =20 +/* 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); +} =20 - /* 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. */ =20 - First, try to find the bounds of what might be an event name. */ - char *arg1_start =3D 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); +} =20 - if (arg1_start =3D=3D 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. */ =20 - } - arg1_end =3D ep_find_event_name_end (arg1_start); - if (arg1_end =3D=3D NULL) - error (_("catch requires an event")); - arg1_length =3D 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); +} =20 - /* Try to match what we found against known event names. */ - if (strncmp (arg1_start, "signal", arg1_length) =3D=3D 0) - { - error (_("Catch of signal not yet implemented")); - } - else if (strncmp (arg1_start, "catch", arg1_length) =3D=3D 0) - { - catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,=20 - tempflag, from_tty); - } - else if (strncmp (arg1_start, "throw", arg1_length) =3D=3D 0) - { - catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,=20 - tempflag, from_tty); - } - else if (strncmp (arg1_start, "thread_start", arg1_length) =3D=3D 0) - { - error (_("Catch of thread_start not yet implemented")); - } - else if (strncmp (arg1_start, "thread_exit", arg1_length) =3D=3D 0) - { - error (_("Catch of thread_exit not yet implemented")); - } - else if (strncmp (arg1_start, "thread_join", arg1_length) =3D=3D 0) - { - error (_("Catch of thread_join not yet implemented")); - } - else if (strncmp (arg1_start, "start", arg1_length) =3D=3D 0) - { - error (_("Catch of start not yet implemented")); - } - else if (strncmp (arg1_start, "exit", arg1_length) =3D=3D 0) - { - error (_("Catch of exit not yet implemented")); - } - else if (strncmp (arg1_start, "fork", arg1_length) =3D=3D 0) - { - catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty); - } - else if (strncmp (arg1_start, "vfork", arg1_length) =3D=3D 0) - { - catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty); - } - else if (strncmp (arg1_start, "exec", arg1_length) =3D=3D 0) - { - catch_exec_command_1 (arg1_end + 1, tempflag, from_tty); - } - else if (strncmp (arg1_start, "load", arg1_length) =3D=3D 0) - { - catch_load_command_1 (arg1_end + 1, tempflag, from_tty); - } - else if (strncmp (arg1_start, "unload", arg1_length) =3D=3D 0) - { - catch_unload_command_1 (arg1_end + 1, tempflag, from_tty); - } - else if (strncmp (arg1_start, "stop", arg1_length) =3D=3D 0) - { - error (_("Catch of stop not yet implemented")); - } - else if (strncmp (arg1_start, "exception", arg1_length) =3D=3D 0) - { - catch_ada_exception_command (arg1_end + 1, tempflag, from_tty); - } +/* Implement the "catch vfork" command. */ =20 - else if (strncmp (arg1_start, "assert", arg1_length) =3D=3D 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); +}; =20 - /* 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 =20 - 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) }, =20 - } -} +/* All the "catch" commands. */ +static struct catch_handler_entry permanent_catch_entries[] =3D +{ + TABLE + { NULL, NULL, NULL } +};=20=20 + +/* 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[] =3D +{ + TABLE + { NULL, NULL, NULL } +};=20=20 + +#undef ENTRY +#undef NORMAL_NAME +#undef DEFINE_NORMAL +#undef DEFINE_ONE_CATCH_FUNCTION +#undef DEFINE_UNIMPLEMENTED +#undef UNIMPLEMENTED_NAME +#undef TABLE =20 static void catch_command (char *arg, int from_tty) { - catch_command_1 (arg, 0, from_tty); + error (_("Catch requires an event name.")); } =0C =20 static void tcatch_command (char *arg, int from_tty) { - catch_command_1 (arg, 1, from_tty); + error (_("Catch requires an event name.")); } =20 /* 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 breakpoint= s." =20 +/* 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 =3D 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); =20 - 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 - a particular signal\n\ -Raised exceptions may be caught:\n\ -\tcatch throw - all exceptions, when thrown\n\ -\tcatch throw - a particular exception, when thrown\n\ -\tcatch catch - all exceptions, when caught\n\ -\tcatch catch - 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 - loads of a particular library\n\ -\tcatch unload - unloads of any library\n\ -\tcatch unload - 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 - 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 breakpoint= s.")); - - 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); =20 c =3D 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, whe= n thrown.*catch throw.*exceptname.*a particular exception, when thrown.*cat= ch catch.*all exceptions, when caught.*catch catch.*exceptname.*a particula= r exception, when caught.*Thread or process events may be caught:.*catch th= read_start.*any threads, just after creation.*catch thread_exit.*any thread= s, just before expiration.*catch thread_join.*any threads, just after joins= .*catch start.*any processes, just after creation.*catch exit.*any processe= s, 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.*li= bname.*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.*f= or info on debugging your program.*after a fork or vfork is caught.*Do.*hel= p breakpoints.*for info on other commands dealing with breakpoints." "help = catch" +gdb_test "help catch" "Set catchpoints to catch events.*List of catch subc= ommands:.*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 libr= ary loads.*catch signal -- Catch signals.*catch start -- Catch process at c= reation.*catch stop -- Catch program stopping.*catch thread_exit -- Catch t= hread exit.*catch thread_join -- Catch thread after a join.*catch thread_st= art -- Catch thread start.*catch throw -- Catch an exception.*catch unload = -- Catch library unloads.*catch vfork -- Catch calls to vfork.*Type .help c= atch. followed by catch subcommand name for full documentation.*Type .aprop= os word. to search for commands related to .word..*Command name abbreviatio= ns 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 be= ing debugged\[\r\n\]+until the next time it is started\." "help cd" # test help clear