public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
@ 2021-05-22 16:34 Philippe Waroquiers
  2021-05-23  1:11 ` Simon Marchi
  2021-06-08 20:17 ` Philippe Waroquiers
  0 siblings, 2 replies; 7+ messages in thread
From: Philippe Waroquiers @ 2021-05-22 16:34 UTC (permalink / raw)
  To: gdb-patches

This is an RFC of an alternative approach to the 'ignore-errors' command
proposed by Tom de Vries (see
e.g. https://sourceware.org/pipermail/gdb-patches/2021-May/178944.html).
FTR, a more elaborate try-catch solution was posted here (
https://sourceware.org/bugzilla/show_bug.cgi?id=8487 ).

It is still missing NEWS, documentation and tests.

This implements a new setting 'error-handling':
  (gdb) help set error-handling
  Set error handling for command sequences.
  Indicates how GDB handles an error when executing a sequence of commands
  (such as when sourcing command file or executing a user-defined command).
  When set to "abort-execution" (the default), GDB reports the error and aborts
  the execution of the command sequence.  When set to "print-and-continue",
  GDB reports the error and continues the execution of the command sequence.
  When set to "silently-ignore", GDB silently handles the error and continues
  the execution of the command sequence.
  (gdb)

Some usage examples:
Assuming you define a user command:
  define problem1
    echo coucou\n
    make-some-error
    echo bidule\n
  end

  (gdb) problem1
  coucou
  Undefined command: "make-some-error".  Try "help".
  (gdb) with error-handling print-and-continue -- problem1
  coucou
  Undefined command: "make-some-error".  Try "help".
  bidule
  (gdb) with error-handling silently-ignore -- problem1
  coucou
  bidule
  (gdb) alias S = with error-handling silently-ignore --
  (gdb) alias C = with error-handling print-and-continue --
  (gdb) S problem1
  coucou
  bidule
  (gdb) C problem1
  coucou
  Undefined command: "make-some-error".  Try "help".
  bidule
  (gdb) S source some_command_file_with_errors
  (gdb)

Inside a script, you can control error handling for individual commands,
e.g.:
  (gdb) shell cat runproblem1.gdb
  echo coucou\n
  with error-handling print-and-continue --  make-some-error
  echo bidule\n
  make-some-other-error
  echo machin\n
  (gdb) source runproblem1.gdb
  coucou
  Undefined command: "make-some-error".  Try "help".
  bidule
  runproblem1.gdb:4: Error in sourced command file:
  Undefined command: "make-some-other-error".  Try "help".
  (gdb)

It can also be used to ignore errors or continue on errors in .gdbinit:

  $ gdb -eiex 'set error-handling print-and-continue'
  GNU gdb (GDB) 11.0.50.20210522-git
  ...
  coucou
  Undefined command: "make-some-error".  Try "help".
  bidule
  (gdb)
---
 gdb/top.c | 247 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 141 insertions(+), 106 deletions(-)

diff --git a/gdb/top.c b/gdb/top.c
index b9635368cac..2e968ea9b8e 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -142,6 +142,10 @@ show_confirm (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* How to handle errors when executing a sequence of GDB commands (i.e. a
+   command not from_tty).  */
+static const char *error_handling;
+
 /* Current working directory.  */
 
 char *current_directory;
@@ -578,113 +582,125 @@ execute_command (const char *p, int from_tty)
   while (*p == ' ' || *p == '\t')
     p++;
   if (*p)
-    {
-      const char *cmd = p;
-      const char *arg;
-      std::string default_args;
-      std::string default_args_and_arg;
-      int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
-
-      line = p;
-
-      /* If trace-commands is set then this will print this command.  */
-      print_command_trace ("%s", p);
-
-      c = lookup_cmd (&cmd, cmdlist, "", &default_args, 0, 1);
-      p = cmd;
-
-      scoped_restore save_repeat_args
-	= make_scoped_restore (&repeat_arguments, nullptr);
-      const char *args_pointer = p;
-
-      if (!default_args.empty ())
-	{
-	  if (*p != '\0')
-	    default_args_and_arg = default_args + ' ' + p;
-	  else
-	    default_args_and_arg = default_args;
-	  arg = default_args_and_arg.c_str ();
-	}
-      else
-	{
-	  /* Pass null arg rather than an empty one.  */
-	  arg = *p == '\0' ? nullptr : p;
-	}
-
-      /* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
-	 while the is_complete_command(cfunc) test is just plain
-	 bogus.  They should both be replaced by a test of the form
-	 c->strip_trailing_white_space_p.  */
-      /* NOTE: cagney/2002-02-02: The function.cfunc in the below
-	 can't be replaced with func.  This is because it is the
-	 cfunc, and not the func, that has the value that the
-	 is_complete_command hack is testing for.  */
-      /* Clear off trailing whitespace, except for set and complete
-	 command.  */
-      std::string without_whitespace;
-      if (arg
-	  && c->type != set_cmd
-	  && !is_complete_command (c))
-	{
-	  const char *old_end = arg + strlen (arg) - 1;
-	  p = old_end;
-	  while (p >= arg && (*p == ' ' || *p == '\t'))
-	    p--;
-	  if (p != old_end)
-	    {
-	      without_whitespace = std::string (arg, p + 1);
-	      arg = without_whitespace.c_str ();
-	    }
-	}
-
-      /* If this command has been pre-hooked, run the hook first.  */
-      execute_cmd_pre_hook (c);
-
-      if (c->deprecated_warn_user)
-	deprecated_cmd_warning (line, cmdlist);
-
-      /* c->user_commands would be NULL in the case of a python command.  */
-      if (c->theclass == class_user && c->user_commands)
-	execute_user_command (c, arg);
-      else if (c->theclass == class_user
-	       && c->is_prefix () && !c->allow_unknown)
-	/* If this is a user defined prefix that does not allow unknown
-	   (in other words, C is a prefix command and not a command
-	   that can be followed by its args), report the list of
-	   subcommands.  */
-	{
-	  std::string prefixname = c->prefixname ();
-          std::string prefixname_no_space
-	    = prefixname.substr (0, prefixname.length () - 1);
-	  printf_unfiltered
-	    ("\"%s\" must be followed by the name of a subcommand.\n",
-	     prefixname_no_space.c_str ());
-	  help_list (*c->subcommands, prefixname.c_str (), all_commands,
-		     gdb_stdout);
-	}
-      else if (c->type == set_cmd)
-	do_set_command (arg, from_tty, c);
-      else if (c->type == show_cmd)
-	do_show_command (arg, from_tty, c);
-      else if (c->is_command_class_help ())
-	error (_("That is not a command, just a help topic."));
-      else if (deprecated_call_command_hook)
-	deprecated_call_command_hook (c, arg, from_tty);
-      else
-	cmd_func (c, arg, from_tty);
-
-      maybe_wait_sync_command_done (was_sync);
-
-      /* If this command has been post-hooked, run the hook last.  */
-      execute_cmd_post_hook (c);
+    try
+      {
+	const char *cmd = p;
+	const char *arg;
+	std::string default_args;
+	std::string default_args_and_arg;
+	int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
+
+	line = p;
+
+	/* If trace-commands is set then this will print this command.  */
+	print_command_trace ("%s", p);
+
+	c = lookup_cmd (&cmd, cmdlist, "", &default_args, 0, 1);
+	p = cmd;
+
+	scoped_restore save_repeat_args
+	  = make_scoped_restore (&repeat_arguments, nullptr);
+	const char *args_pointer = p;
+
+	if (!default_args.empty ())
+	  {
+	    if (*p != '\0')
+	      default_args_and_arg = default_args + ' ' + p;
+	    else
+	      default_args_and_arg = default_args;
+	    arg = default_args_and_arg.c_str ();
+	  }
+	else
+	  {
+	    /* Pass null arg rather than an empty one.  */
+	    arg = *p == '\0' ? nullptr : p;
+	  }
+
+	/* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
+	   while the is_complete_command(cfunc) test is just plain
+	   bogus.  They should both be replaced by a test of the form
+	   c->strip_trailing_white_space_p.  */
+	/* NOTE: cagney/2002-02-02: The function.cfunc in the below
+	   can't be replaced with func.  This is because it is the
+	   cfunc, and not the func, that has the value that the
+	   is_complete_command hack is testing for.  */
+	/* Clear off trailing whitespace, except for set and complete
+	   command.  */
+	std::string without_whitespace;
+	if (arg
+	    && c->type != set_cmd
+	    && !is_complete_command (c))
+	  {
+	    const char *old_end = arg + strlen (arg) - 1;
+	    p = old_end;
+	    while (p >= arg && (*p == ' ' || *p == '\t'))
+	      p--;
+	    if (p != old_end)
+	      {
+		without_whitespace = std::string (arg, p + 1);
+		arg = without_whitespace.c_str ();
+	      }
+	  }
+
+	/* If this command has been pre-hooked, run the hook first.  */
+	execute_cmd_pre_hook (c);
+
+	if (c->deprecated_warn_user)
+	  deprecated_cmd_warning (line, cmdlist);
+
+	/* c->user_commands would be NULL in the case of a python command.  */
+	if (c->theclass == class_user && c->user_commands)
+	  execute_user_command (c, arg);
+	else if (c->theclass == class_user
+		 && c->is_prefix () && !c->allow_unknown)
+	  /* If this is a user defined prefix that does not allow unknown
+	     (in other words, C is a prefix command and not a command
+	     that can be followed by its args), report the list of
+	     subcommands.  */
+	  {
+	    std::string prefixname = c->prefixname ();
+	    std::string prefixname_no_space
+	      = prefixname.substr (0, prefixname.length () - 1);
+	    printf_unfiltered
+	      ("\"%s\" must be followed by the name of a subcommand.\n",
+	       prefixname_no_space.c_str ());
+	    help_list (*c->subcommands, prefixname.c_str (), all_commands,
+		       gdb_stdout);
+	  }
+	else if (c->type == set_cmd)
+	  do_set_command (arg, from_tty, c);
+	else if (c->type == show_cmd)
+	  do_show_command (arg, from_tty, c);
+	else if (c->is_command_class_help ())
+	  error (_("That is not a command, just a help topic."));
+	else if (deprecated_call_command_hook)
+	  deprecated_call_command_hook (c, arg, from_tty);
+	else
+	  cmd_func (c, arg, from_tty);
+
+	maybe_wait_sync_command_done (was_sync);
+
+	/* If this command has been post-hooked, run the hook last.  */
+	execute_cmd_post_hook (c);
+
+	if (repeat_arguments != NULL && cmd_start == saved_command_line)
+	  {
+	    gdb_assert (strlen (args_pointer) >= strlen (repeat_arguments));
+	    strcpy (saved_command_line + (args_pointer - cmd_start),
+		    repeat_arguments);
+	  }
+      }
+    catch (const gdb_exception &ex)
+      {
+	if (from_tty || strcmp (error_handling, "abort-execution") == 0)
+	  throw;
+	else if (strcmp (error_handling, "print-and-continue") == 0)
+	  exception_print (gdb_stderr, ex);
+	/* else silently-ignore.  */
 
-      if (repeat_arguments != NULL && cmd_start == saved_command_line)
-	{
-	  gdb_assert (strlen (args_pointer) >= strlen (repeat_arguments));
-	  strcpy (saved_command_line + (args_pointer - cmd_start),
-		  repeat_arguments);
-	}
-    }
+	/* See also execute_gdb_command.  */
+	async_enable_stdin ();
+      }
 
   /* Only perform the frame-language-change check if the command
      we just finished executing did not resume the inferior's execution.
@@ -2203,6 +2219,9 @@ init_gdb_version_vars (void)
 static void
 init_main (void)
 {
+  static const char *const error_handling_names[]
+    = { "abort-execution", "print-and-continue", "silently-ignore", NULL };
+
   struct cmd_list_element *c;
 
   /* Initialize the prompt to a simple "(gdb) " prompt or to whatever
@@ -2356,6 +2375,22 @@ affect future GDB sessions."),
 			       show_startup_quiet,
 			       &setlist, &showlist);
 
+  add_setshow_enum_cmd ("error-handling", class_support, error_handling_names,
+			&error_handling,
+			_("Set error handling for command sequences."),
+			_("Show error handling for command sequences."),
+			_("Indicates how GDB handles an error when executing a sequence of commands\n\
+(such as when sourcing command file or executing a user-defined command).\n\
+When set to \"abort-execution\" (the default), GDB reports the error and aborts\n\
+the execution of the command sequence.  When set to \"print-and-continue\",\n\
+GDB reports the error and continues the execution of the command sequence.\n\
+When set to \"silently-ignore\", GDB silently handles the error and continues\n\
+the execution of the command sequence."),
+			NULL,
+			NULL,
+			&setlist, &showlist);
+  error_handling = "abort-execution";
+
   c = add_cmd ("new-ui", class_support, new_ui_command, _("\
 Create a new UI.\n\
 Usage: new-ui INTERPRETER TTY\n\
-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
  2021-05-22 16:34 [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore Philippe Waroquiers
@ 2021-05-23  1:11 ` Simon Marchi
  2021-05-24 14:49   ` Tom Tromey
  2021-05-24 20:51   ` Philippe Waroquiers
  2021-06-08 20:17 ` Philippe Waroquiers
  1 sibling, 2 replies; 7+ messages in thread
From: Simon Marchi @ 2021-05-23  1:11 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches



On 2021-05-22 12:34 p.m., Philippe Waroquiers via Gdb-patches wrote:
> This is an RFC of an alternative approach to the 'ignore-errors' command
> proposed by Tom de Vries (see
> e.g. https://sourceware.org/pipermail/gdb-patches/2021-May/178944.html).
> FTR, a more elaborate try-catch solution was posted here (
> https://sourceware.org/bugzilla/show_bug.cgi?id=8487 ).
> 
> It is still missing NEWS, documentation and tests.
> 
> This implements a new setting 'error-handling':
>   (gdb) help set error-handling
>   Set error handling for command sequences.
>   Indicates how GDB handles an error when executing a sequence of commands
>   (such as when sourcing command file or executing a user-defined command).
>   When set to "abort-execution" (the default), GDB reports the error and aborts
>   the execution of the command sequence.  When set to "print-and-continue",
>   GDB reports the error and continues the execution of the command sequence.
>   When set to "silently-ignore", GDB silently handles the error and continues
>   the execution of the command sequence.
>   (gdb)
> 
> Some usage examples:
> Assuming you define a user command:
>   define problem1
>     echo coucou\n
>     make-some-error
>     echo bidule\n
>   end
> 
>   (gdb) problem1
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   (gdb) with error-handling print-and-continue -- problem1
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   (gdb) with error-handling silently-ignore -- problem1
>   coucou
>   bidule
>   (gdb) alias S = with error-handling silently-ignore --
>   (gdb) alias C = with error-handling print-and-continue --
>   (gdb) S problem1
>   coucou
>   bidule
>   (gdb) C problem1
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   (gdb) S source some_command_file_with_errors
>   (gdb)
> 
> Inside a script, you can control error handling for individual commands,
> e.g.:
>   (gdb) shell cat runproblem1.gdb
>   echo coucou\n
>   with error-handling print-and-continue --  make-some-error
>   echo bidule\n
>   make-some-other-error
>   echo machin\n
>   (gdb) source runproblem1.gdb
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   runproblem1.gdb:4: Error in sourced command file:
>   Undefined command: "make-some-other-error".  Try "help".
>   (gdb)
> 
> It can also be used to ignore errors or continue on errors in .gdbinit:
> 
>   $ gdb -eiex 'set error-handling print-and-continue'
>   GNU gdb (GDB) 11.0.50.20210522-git
>   ...
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   (gdb)

I didn't look at the implementation, just read the commit log.  But I
like this approach, because it's a bit more general than the command
approach it seems.  And you can define an alias that makes it look as if
it was an "ignore-errors" command.

Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
  2021-05-23  1:11 ` Simon Marchi
@ 2021-05-24 14:49   ` Tom Tromey
  2021-05-24 15:15     ` Philippe Waroquiers
  2021-05-24 20:51   ` Philippe Waroquiers
  1 sibling, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2021-05-24 14:49 UTC (permalink / raw)
  To: Simon Marchi via Gdb-patches

>>>>> "Simon" == Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:

Simon> I didn't look at the implementation, just read the commit log.  But I
Simon> like this approach, because it's a bit more general than the command
Simon> approach it seems.  And you can define an alias that makes it look as if
Simon> it was an "ignore-errors" command.

Perhaps gdb should supply this alias.

Is there really a case where you'd want to disable all error handling by
all commands?  I think that's the critical question for choosing which
patch to land.

thanks,
Tom

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
  2021-05-24 14:49   ` Tom Tromey
@ 2021-05-24 15:15     ` Philippe Waroquiers
  0 siblings, 0 replies; 7+ messages in thread
From: Philippe Waroquiers @ 2021-05-24 15:15 UTC (permalink / raw)
  To: Tom Tromey, Simon Marchi via Gdb-patches

On Mon, 2021-05-24 at 08:49 -0600, Tom Tromey wrote:
> > > > > > "Simon" == Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> Simon> I didn't look at the implementation, just read the commit log.  But I
> Simon> like this approach, because it's a bit more general than the command
> Simon> approach it seems.  And you can define an alias that makes it look as if
> Simon> it was an "ignore-errors" command.
> 
> Perhaps gdb should supply this alias.
This is for sure easy to supply.
Note however that the 'ignore-errors' name is somewhat inconsistent with the terminology 
used by the -s option of 'thread apply' and 'frame apply':
  -c
    Print any error raised by COMMAND and continue.

  -s
    Silently ignore any errors or empty output produced by COMMAND.

The same terminology was used for the setting 'silently-ignore'.
Maybe we should 'extend' the -s and -c option of 'frame/thread apply' to 
-silently-ignore-error and -continue-on-error and use exactly the same words
in this setting ?

> 
> Is there really a case where you'd want to disable all error handling by
> all commands?  I think that's the critical question for choosing which
> patch to land.
The use case is:  source a file (for example .gdbinit) but execute all what works
in this file, whatever the errors.
As far as I understand, with the ignore-errors command,
you have to source the file repetitively and add ignore-errors in front of all
commands that are giving an error.
This then obliges to edit repetitively the file.

Another behavior difference is that the setting applies transitively
and applies to user defined commands.

Philippe





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
  2021-05-23  1:11 ` Simon Marchi
  2021-05-24 14:49   ` Tom Tromey
@ 2021-05-24 20:51   ` Philippe Waroquiers
  1 sibling, 0 replies; 7+ messages in thread
From: Philippe Waroquiers @ 2021-05-24 20:51 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On Sat, 2021-05-22 at 21:11 -0400, Simon Marchi wrote:

> I didn't look at the implementation, just read the commit log.  But I
> like this approach, because it's a bit more general than the command
> approach it seems.  And you can define an alias that makes it look as if
> it was an "ignore-errors" command.
Basically, the implementation consists in adding a 'try/catch' block around
most of the 'execute_command' code:

    try 
     {
        .... the bulk of execute_command ....
     }
    catch (const gdb_exception &ex)
      {
	if (from_tty || strcmp (error_handling, "abort-execution") == 0)
	  throw;
	else if (strcmp (error_handling, "print-and-continue") == 0)
	  exception_print (gdb_stderr, ex);
	/* else silently-ignore.  */

	/* See also execute_gdb_command.  */
	async_enable_stdin ();
      }

So, the diff looks large but this is due to the additional indentation,
all the logic is in the catch block.

Thanks
Philippe
 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
  2021-05-22 16:34 [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore Philippe Waroquiers
  2021-05-23  1:11 ` Simon Marchi
@ 2021-06-08 20:17 ` Philippe Waroquiers
  2021-06-08 21:05   ` Simon Marchi
  1 sibling, 1 reply; 7+ messages in thread
From: Philippe Waroquiers @ 2021-06-08 20:17 UTC (permalink / raw)
  To: gdb-patches

Some feedback about how to go with the below ?

Thanks
Philippe

On Sat, 2021-05-22 at 18:34 +0200, Philippe Waroquiers wrote:
> This is an RFC of an alternative approach to the 'ignore-errors' command
> proposed by Tom de Vries (see
> e.g. https://sourceware.org/pipermail/gdb-patches/2021-May/178944.html).
> FTR, a more elaborate try-catch solution was posted here (
> https://sourceware.org/bugzilla/show_bug.cgi?id=8487 ).
> 
> It is still missing NEWS, documentation and tests.
> 
> This implements a new setting 'error-handling':
>   (gdb) help set error-handling
>   Set error handling for command sequences.
>   Indicates how GDB handles an error when executing a sequence of commands
>   (such as when sourcing command file or executing a user-defined command).
>   When set to "abort-execution" (the default), GDB reports the error and aborts
>   the execution of the command sequence.  When set to "print-and-continue",
>   GDB reports the error and continues the execution of the command sequence.
>   When set to "silently-ignore", GDB silently handles the error and continues
>   the execution of the command sequence.
>   (gdb)
> 
> Some usage examples:
> Assuming you define a user command:
>   define problem1
>     echo coucou\n
>     make-some-error
>     echo bidule\n
>   end
> 
>   (gdb) problem1
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   (gdb) with error-handling print-and-continue -- problem1
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   (gdb) with error-handling silently-ignore -- problem1
>   coucou
>   bidule
>   (gdb) alias S = with error-handling silently-ignore --
>   (gdb) alias C = with error-handling print-and-continue --
>   (gdb) S problem1
>   coucou
>   bidule
>   (gdb) C problem1
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   (gdb) S source some_command_file_with_errors
>   (gdb)
> 
> Inside a script, you can control error handling for individual commands,
> e.g.:
>   (gdb) shell cat runproblem1.gdb
>   echo coucou\n
>   with error-handling print-and-continue --  make-some-error
>   echo bidule\n
>   make-some-other-error
>   echo machin\n
>   (gdb) source runproblem1.gdb
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   runproblem1.gdb:4: Error in sourced command file:
>   Undefined command: "make-some-other-error".  Try "help".
>   (gdb)
> 
> It can also be used to ignore errors or continue on errors in .gdbinit:
> 
>   $ gdb -eiex 'set error-handling print-and-continue'
>   GNU gdb (GDB) 11.0.50.20210522-git
>   ...
>   coucou
>   Undefined command: "make-some-error".  Try "help".
>   bidule
>   (gdb)
> ---
>  gdb/top.c | 247 +++++++++++++++++++++++++++++++-----------------------
>  1 file changed, 141 insertions(+), 106 deletions(-)
> 
> diff --git a/gdb/top.c b/gdb/top.c
> index b9635368cac..2e968ea9b8e 100644
> --- a/gdb/top.c
> +++ b/gdb/top.c
> @@ -142,6 +142,10 @@ show_confirm (struct ui_file *file, int from_tty,
>  		    value);
>  }
>  
> +/* How to handle errors when executing a sequence of GDB commands (i.e. a
> +   command not from_tty).  */
> +static const char *error_handling;
> +
>  /* Current working directory.  */
>  
>  char *current_directory;
> @@ -578,113 +582,125 @@ execute_command (const char *p, int from_tty)
>    while (*p == ' ' || *p == '\t')
>      p++;
>    if (*p)
> -    {
> -      const char *cmd = p;
> -      const char *arg;
> -      std::string default_args;
> -      std::string default_args_and_arg;
> -      int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
> -
> -      line = p;
> -
> -      /* If trace-commands is set then this will print this command.  */
> -      print_command_trace ("%s", p);
> -
> -      c = lookup_cmd (&cmd, cmdlist, "", &default_args, 0, 1);
> -      p = cmd;
> -
> -      scoped_restore save_repeat_args
> -	= make_scoped_restore (&repeat_arguments, nullptr);
> -      const char *args_pointer = p;
> -
> -      if (!default_args.empty ())
> -	{
> -	  if (*p != '\0')
> -	    default_args_and_arg = default_args + ' ' + p;
> -	  else
> -	    default_args_and_arg = default_args;
> -	  arg = default_args_and_arg.c_str ();
> -	}
> -      else
> -	{
> -	  /* Pass null arg rather than an empty one.  */
> -	  arg = *p == '\0' ? nullptr : p;
> -	}
> -
> -      /* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
> -	 while the is_complete_command(cfunc) test is just plain
> -	 bogus.  They should both be replaced by a test of the form
> -	 c->strip_trailing_white_space_p.  */
> -      /* NOTE: cagney/2002-02-02: The function.cfunc in the below
> -	 can't be replaced with func.  This is because it is the
> -	 cfunc, and not the func, that has the value that the
> -	 is_complete_command hack is testing for.  */
> -      /* Clear off trailing whitespace, except for set and complete
> -	 command.  */
> -      std::string without_whitespace;
> -      if (arg
> -	  && c->type != set_cmd
> -	  && !is_complete_command (c))
> -	{
> -	  const char *old_end = arg + strlen (arg) - 1;
> -	  p = old_end;
> -	  while (p >= arg && (*p == ' ' || *p == '\t'))
> -	    p--;
> -	  if (p != old_end)
> -	    {
> -	      without_whitespace = std::string (arg, p + 1);
> -	      arg = without_whitespace.c_str ();
> -	    }
> -	}
> -
> -      /* If this command has been pre-hooked, run the hook first.  */
> -      execute_cmd_pre_hook (c);
> -
> -      if (c->deprecated_warn_user)
> -	deprecated_cmd_warning (line, cmdlist);
> -
> -      /* c->user_commands would be NULL in the case of a python command.  */
> -      if (c->theclass == class_user && c->user_commands)
> -	execute_user_command (c, arg);
> -      else if (c->theclass == class_user
> -	       && c->is_prefix () && !c->allow_unknown)
> -	/* If this is a user defined prefix that does not allow unknown
> -	   (in other words, C is a prefix command and not a command
> -	   that can be followed by its args), report the list of
> -	   subcommands.  */
> -	{
> -	  std::string prefixname = c->prefixname ();
> -          std::string prefixname_no_space
> -	    = prefixname.substr (0, prefixname.length () - 1);
> -	  printf_unfiltered
> -	    ("\"%s\" must be followed by the name of a subcommand.\n",
> -	     prefixname_no_space.c_str ());
> -	  help_list (*c->subcommands, prefixname.c_str (), all_commands,
> -		     gdb_stdout);
> -	}
> -      else if (c->type == set_cmd)
> -	do_set_command (arg, from_tty, c);
> -      else if (c->type == show_cmd)
> -	do_show_command (arg, from_tty, c);
> -      else if (c->is_command_class_help ())
> -	error (_("That is not a command, just a help topic."));
> -      else if (deprecated_call_command_hook)
> -	deprecated_call_command_hook (c, arg, from_tty);
> -      else
> -	cmd_func (c, arg, from_tty);
> -
> -      maybe_wait_sync_command_done (was_sync);
> -
> -      /* If this command has been post-hooked, run the hook last.  */
> -      execute_cmd_post_hook (c);
> +    try
> +      {
> +	const char *cmd = p;
> +	const char *arg;
> +	std::string default_args;
> +	std::string default_args_and_arg;
> +	int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
> +
> +	line = p;
> +
> +	/* If trace-commands is set then this will print this command.  */
> +	print_command_trace ("%s", p);
> +
> +	c = lookup_cmd (&cmd, cmdlist, "", &default_args, 0, 1);
> +	p = cmd;
> +
> +	scoped_restore save_repeat_args
> +	  = make_scoped_restore (&repeat_arguments, nullptr);
> +	const char *args_pointer = p;
> +
> +	if (!default_args.empty ())
> +	  {
> +	    if (*p != '\0')
> +	      default_args_and_arg = default_args + ' ' + p;
> +	    else
> +	      default_args_and_arg = default_args;
> +	    arg = default_args_and_arg.c_str ();
> +	  }
> +	else
> +	  {
> +	    /* Pass null arg rather than an empty one.  */
> +	    arg = *p == '\0' ? nullptr : p;
> +	  }
> +
> +	/* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
> +	   while the is_complete_command(cfunc) test is just plain
> +	   bogus.  They should both be replaced by a test of the form
> +	   c->strip_trailing_white_space_p.  */
> +	/* NOTE: cagney/2002-02-02: The function.cfunc in the below
> +	   can't be replaced with func.  This is because it is the
> +	   cfunc, and not the func, that has the value that the
> +	   is_complete_command hack is testing for.  */
> +	/* Clear off trailing whitespace, except for set and complete
> +	   command.  */
> +	std::string without_whitespace;
> +	if (arg
> +	    && c->type != set_cmd
> +	    && !is_complete_command (c))
> +	  {
> +	    const char *old_end = arg + strlen (arg) - 1;
> +	    p = old_end;
> +	    while (p >= arg && (*p == ' ' || *p == '\t'))
> +	      p--;
> +	    if (p != old_end)
> +	      {
> +		without_whitespace = std::string (arg, p + 1);
> +		arg = without_whitespace.c_str ();
> +	      }
> +	  }
> +
> +	/* If this command has been pre-hooked, run the hook first.  */
> +	execute_cmd_pre_hook (c);
> +
> +	if (c->deprecated_warn_user)
> +	  deprecated_cmd_warning (line, cmdlist);
> +
> +	/* c->user_commands would be NULL in the case of a python command.  */
> +	if (c->theclass == class_user && c->user_commands)
> +	  execute_user_command (c, arg);
> +	else if (c->theclass == class_user
> +		 && c->is_prefix () && !c->allow_unknown)
> +	  /* If this is a user defined prefix that does not allow unknown
> +	     (in other words, C is a prefix command and not a command
> +	     that can be followed by its args), report the list of
> +	     subcommands.  */
> +	  {
> +	    std::string prefixname = c->prefixname ();
> +	    std::string prefixname_no_space
> +	      = prefixname.substr (0, prefixname.length () - 1);
> +	    printf_unfiltered
> +	      ("\"%s\" must be followed by the name of a subcommand.\n",
> +	       prefixname_no_space.c_str ());
> +	    help_list (*c->subcommands, prefixname.c_str (), all_commands,
> +		       gdb_stdout);
> +	  }
> +	else if (c->type == set_cmd)
> +	  do_set_command (arg, from_tty, c);
> +	else if (c->type == show_cmd)
> +	  do_show_command (arg, from_tty, c);
> +	else if (c->is_command_class_help ())
> +	  error (_("That is not a command, just a help topic."));
> +	else if (deprecated_call_command_hook)
> +	  deprecated_call_command_hook (c, arg, from_tty);
> +	else
> +	  cmd_func (c, arg, from_tty);
> +
> +	maybe_wait_sync_command_done (was_sync);
> +
> +	/* If this command has been post-hooked, run the hook last.  */
> +	execute_cmd_post_hook (c);
> +
> +	if (repeat_arguments != NULL && cmd_start == saved_command_line)
> +	  {
> +	    gdb_assert (strlen (args_pointer) >= strlen (repeat_arguments));
> +	    strcpy (saved_command_line + (args_pointer - cmd_start),
> +		    repeat_arguments);
> +	  }
> +      }
> +    catch (const gdb_exception &ex)
> +      {
> +	if (from_tty || strcmp (error_handling, "abort-execution") == 0)
> +	  throw;
> +	else if (strcmp (error_handling, "print-and-continue") == 0)
> +	  exception_print (gdb_stderr, ex);
> +	/* else silently-ignore.  */
>  
> -      if (repeat_arguments != NULL && cmd_start == saved_command_line)
> -	{
> -	  gdb_assert (strlen (args_pointer) >= strlen (repeat_arguments));
> -	  strcpy (saved_command_line + (args_pointer - cmd_start),
> -		  repeat_arguments);
> -	}
> -    }
> +	/* See also execute_gdb_command.  */
> +	async_enable_stdin ();
> +      }
>  
>    /* Only perform the frame-language-change check if the command
>       we just finished executing did not resume the inferior's execution.
> @@ -2203,6 +2219,9 @@ init_gdb_version_vars (void)
>  static void
>  init_main (void)
>  {
> +  static const char *const error_handling_names[]
> +    = { "abort-execution", "print-and-continue", "silently-ignore", NULL };
> +
>    struct cmd_list_element *c;
>  
>    /* Initialize the prompt to a simple "(gdb) " prompt or to whatever
> @@ -2356,6 +2375,22 @@ affect future GDB sessions."),
>  			       show_startup_quiet,
>  			       &setlist, &showlist);
>  
> +  add_setshow_enum_cmd ("error-handling", class_support, error_handling_names,
> +			&error_handling,
> +			_("Set error handling for command sequences."),
> +			_("Show error handling for command sequences."),
> +			_("Indicates how GDB handles an error when executing a sequence of commands\n\
> +(such as when sourcing command file or executing a user-defined command).\n\
> +When set to \"abort-execution\" (the default), GDB reports the error and aborts\n\
> +the execution of the command sequence.  When set to \"print-and-continue\",\n\
> +GDB reports the error and continues the execution of the command sequence.\n\
> +When set to \"silently-ignore\", GDB silently handles the error and continues\n\
> +the execution of the command sequence."),
> +			NULL,
> +			NULL,
> +			&setlist, &showlist);
> +  error_handling = "abort-execution";
> +
>    c = add_cmd ("new-ui", class_support, new_ui_command, _("\
>  Create a new UI.\n\
>  Usage: new-ui INTERPRETER TTY\n\


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore
  2021-06-08 20:17 ` Philippe Waroquiers
@ 2021-06-08 21:05   ` Simon Marchi
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2021-06-08 21:05 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

On 2021-06-08 4:17 p.m., Philippe Waroquiers via Gdb-patches wrote:
> Some feedback about how to go with the below ?

For what it's worth, I already gave my opinion: since the parameter
approach is more general and you can build a command on top of it, it
looks better.  Could we provide an ignore-errors alias (that or some
other name), so that users can use it directly?

Unfortunately, I won't have time to review / babysit this patch,
hopefully you guys can work this out together :).

Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-06-08 21:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-22 16:34 [RFC] Implement 'set|show error-handling abort-execution|print-and-continue|silently-ignore Philippe Waroquiers
2021-05-23  1:11 ` Simon Marchi
2021-05-24 14:49   ` Tom Tromey
2021-05-24 15:15     ` Philippe Waroquiers
2021-05-24 20:51   ` Philippe Waroquiers
2021-06-08 20:17 ` Philippe Waroquiers
2021-06-08 21:05   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).