Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: Don Howard <dhoward@redhat.com>
To: <gdb@sources.redhat.com>
Subject: Re: error-catching mechanism for scripts
Date: Tue, 27 Nov 2001 08:43:00 -0000	[thread overview]
Message-ID: <Pine.LNX.4.33.0111270827180.2426-100000@theotherone.redhat-remotie.org> (raw)

> I've been trying to find a way to make gdb command scripts handle errors
> in a flexible way -- either making continue-on-error an option or some
> kind of simple exception catching mechanism:
>
>
> set script-continue-on-error 1
>
>   -- or --
>
> try
>   commands
> catch
>   commands
> end
>
>
> I'd like to know what others think.



Ok, I've got a partial implementation of the try/catch idea that I'd like
to get some feedback on.  (Let me know if I'm headed the right way before
I spend too much time on this)

I know that the keywords try/catch (esp catch) won't work, as gdb already
has a catch command.  I'd appreciate a suggestion on what to name this
command.  For now I've simple gone with CATCH (all caps) to avoid name 
collisions.


Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.64
diff -p -u -w -r1.64 defs.h
--- defs.h	2001/10/17 20:35:31	1.64
+++ defs.h	2001/11/27 08:07:06
@@ -815,16 +815,18 @@ enum misc_command_type
     ok_command,
     end_command,
     else_command,
+    CATCH_command,
     nop_command
   };
 
 enum command_control_type
   {
-    simple_control,
+    simple_control = 1,
     break_control,
     continue_control,
     while_control,
     if_control,
+    try_control,
     invalid_control
   };

Index: cli/cli-cmds.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-cmds.c,v
retrieving revision 1.10
diff -p -u -w -r1.10 cli-cmds.c
--- cli-cmds.c	2001/09/01 21:38:05	1.10
+++ cli-cmds.c	2001/11/27 08:07:07
@@ -721,6 +721,9 @@ The conditional expression must follow t
 followed by a new line.  The nested commands must be entered one per line,\n\
 and should be terminated by the word `end'.");
 
+  add_com ("try", class_support, try_command,
+	   "Try/Catch support");
+
   add_com ("if", class_support, if_command,
 	   "Execute nested commands once IF the conditional expression is non zero.\n\
 The conditional expression must follow the word `if' and must in turn be\n\
Index: cli/cli-script.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-script.c,v
retrieving revision 1.7
diff -p -u -w -r1.7 cli-script.c
--- cli-script.c	2001/06/17 15:16:12	1.7
+++ cli-script.c	2001/11/27 08:07:08
@@ -210,6 +210,34 @@ print_command_lines (struct ui_out *uiou
 	  continue;
 	}
 
+      /* A try command.  Recursively print the try and catch blocks
+	 before continuing.  */
+      if (list->control_type == try_control)
+	{
+	  ui_out_text (uiout, "try");
+	  ui_out_field_fmt (uiout, NULL, "try\n");
+	  ui_out_text (uiout, "\n");
+	  /* The true arm. */
+	  print_command_lines (uiout, list->body_list[0], depth + 1);
+
+	  /* Show the false arm if it exists.  */
+	  if (list->body_count == 2)
+	    {
+	      if (depth)
+		ui_out_spaces (uiout, 2 * depth);
+	      ui_out_field_string (uiout, NULL, "CATCH");
+	      ui_out_text (uiout, "CATCH\n");
+	      print_command_lines (uiout, list->body_list[1], depth + 1);
+	    }
+
+	  ui_out_field_string (uiout, NULL, "end");
+	  if (depth)
+	    ui_out_spaces (uiout, 2 * depth);
+	  ui_out_text (uiout, "end\n");
+	  list = list->next;
+	  continue;
+	}
+
       /* ignore illegal command type and try next */
       list = list->next;
     }				/* while (list) */
@@ -292,6 +320,33 @@ print_command_line (struct command_line 
 	}
       fputs_filtered ("end\n", stream);
     }
+
+  /* A try command.  Recursively print both try and catch blocks.  */
+  if (cmd->control_type == try_control)
+    {
+      fputs_filtered ("try", stream);
+      fputs_filtered (cmd->line, stream);
+      fputs_filtered ("\n", stream);
+      /* The true arm. */
+      print_command_line (cmd->body_list[0], depth + 1, stream);
+
+      /* Show the catch block if it exists.  */
+      if (cmd->body_count == 2)
+	{
+	  if (depth)
+	    {
+	      for (i = 0; i < depth; i++)
+		fputs_filtered ("  ", stream);
+	    }
+	  fputs_filtered ("CATCH\n", stream);
+	  print_command_line (cmd->body_list[1], depth + 1, stream);
+	}
+      if (depth)
+	{
+	  for (i = 0; i < depth; i++)
+	    fputs_filtered ("  ", stream);
+	}
+      fputs_filtered ("end\n", stream);    }
 }
 #endif
 
@@ -461,6 +516,24 @@ execute_control_command (struct command_
 	break;
       }
 
+    case try_control:
+      {
+	for (current = cmd->body_list[0]; current; current = current->next)
+	  {
+	    ret = catch_errors (execute_control_command, current, 
+				"try -> CATCH", 0);
+
+	    if (ret == 0 || ret == invalid_control)
+	      {
+		if (cmd->body_count == 2)
+		  current = cmd->body_list[1];
+		else
+		  current = NULL;
+	      }
+	  }
+	break;
+      }
+
     default:
       warning ("Invalid control type in command structure.");
       return invalid_control;
@@ -508,6 +581,21 @@ if_command (char *arg, int from_tty)
   free_command_lines (&command);
 }
 
+void
+try_command (char *block, int from_tty)
+{
+  struct command_line *command = NULL;
+
+  control_level = 1;
+  command = get_command_line (try_control, block);
+
+  if (command == NULL)
+    return;
+
+  execute_control_command (command);
+  free_command_lines (&command);
+}
+
 /* Cleanup */
 static void
 arg_cleanup (void *ignore)
@@ -760,12 +848,18 @@ read_next_line (struct command_line **co
   if (p1 - p == 4 && !strncmp (p, "else", 4))
     return else_command;
 
+  /* Is the catch clause of an if try structure?  */
+  if (p1 - p == 5 && !strncmp (p, "CATCH", 5))
+    return CATCH_command;
+
   /* Check for while, if, break, continue, etc and build a new command
      line structure for them.  */
   if (p1 - p > 5 && !strncmp (p, "while", 5))
     *command = build_command_line (while_control, p + 6);
   else if (p1 - p > 2 && !strncmp (p, "if", 2))
     *command = build_command_line (if_control, p + 3);
+  else if (p1 - p > 3 && !strncmp (p, "try", 3))
+    *command = build_command_line (if_control, p + 4);
   else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
     {
       *command = (struct command_line *)
@@ -847,7 +941,8 @@ recurse_read_control_structure (struct c
       if (val == end_command)
 	{
 	  if (current_cmd->control_type == while_control
-	      || current_cmd->control_type == if_control)
+	      || current_cmd->control_type == if_control
+	      || current_cmd->control_type == try_control)
 	    {
 	      /* Success reading an entire control structure.  */
 	      ret = simple_control;
@@ -877,6 +972,23 @@ recurse_read_control_structure (struct c
 	      break;
 	    }
 	}
+      else if (val == CATCH_command)
+	{
+	  if (current_cmd->control_type == try_control
+	      && current_body == 1)
+	    {
+	      realloc_body_list (current_cmd, 2);
+	      current_body = 2;
+	      child_tail = NULL;
+	      continue;
+	    }
+	  else
+	    {
+	      ret = invalid_control;
+	      break;
+	    }
+	}
+
 
       if (child_tail)
 	{
@@ -897,7 +1009,8 @@ recurse_read_control_structure (struct c
       /* If the latest line is another control structure, then recurse
          on it.  */
       if (next->control_type == while_control
-	  || next->control_type == if_control)
+	  || next->control_type == if_control
+	  || next->control_type == try_control)
 	{
 	  control_level++;
 	  ret = recurse_read_control_structure (next);
@@ -964,7 +1077,8 @@ read_command_lines (char *prompt_arg, in
 	}
 
       if (next->control_type == while_control
-	  || next->control_type == if_control)
+	  || next->control_type == if_control
+	  || next->control_type == try_control)
 	{
 	  control_level++;
 	  ret = recurse_read_control_structure (next);
Index: cli/cli-script.h
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-script.h,v
retrieving revision 1.2
diff -p -u -w -r1.2 cli-script.h
--- cli-script.h	2001/03/06 08:21:20	1.2
+++ cli-script.h	2001/11/27 08:07:08
@@ -31,6 +31,8 @@ extern void while_command (char *arg, in
 
 extern void if_command (char *arg, int from_tty);
 
+extern void try_command (char *block, int from_tty);
+
 extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
 
 /* Exported to gdb/breakpoint.c */


-- 
dhoward@redhat.com
gdb engineering



WARNING: multiple messages have this Message-ID
From: Don Howard <dhoward@redhat.com>
To: <gdb@sources.redhat.com>
Subject: Re: error-catching mechanism for scripts
Date: Sat, 17 Nov 2001 12:21:00 -0000	[thread overview]
Message-ID: <Pine.LNX.4.33.0111270827180.2426-100000@theotherone.redhat-remotie.org> (raw)
Message-ID: <20011117122100.lzfV9EijqdIORR9LaJWJtFkWoXNFjL_WD099YwwL_7A@z> (raw)



> I've been trying to find a way to make gdb command scripts handle errors
> in a flexible way -- either making continue-on-error an option or some
> kind of simple exception catching mechanism:
>
>
> set script-continue-on-error 1
>
>   -- or --
>
> try
>   commands
> catch
>   commands
> end
>
>
> I'd like to know what others think.



Ok, I've got a partial implementation of the try/catch idea that I'd like
to get some feedback on.  (Let me know if I'm headed the right way before
I spend too much time on this)

I know that the keywords try/catch (esp catch) won't work, as gdb already
has a catch command.  I'd appreciate a suggestion on what to name this
command.  For now I've simple gone with CATCH (all caps) to avoid name 
collisions.


Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.64
diff -p -u -w -r1.64 defs.h
--- defs.h	2001/10/17 20:35:31	1.64
+++ defs.h	2001/11/27 08:07:06
@@ -815,16 +815,18 @@ enum misc_command_type
     ok_command,
     end_command,
     else_command,
+    CATCH_command,
     nop_command
   };
 
 enum command_control_type
   {
-    simple_control,
+    simple_control = 1,
     break_control,
     continue_control,
     while_control,
     if_control,
+    try_control,
     invalid_control
   };

Index: cli/cli-cmds.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-cmds.c,v
retrieving revision 1.10
diff -p -u -w -r1.10 cli-cmds.c
--- cli-cmds.c	2001/09/01 21:38:05	1.10
+++ cli-cmds.c	2001/11/27 08:07:07
@@ -721,6 +721,9 @@ The conditional expression must follow t
 followed by a new line.  The nested commands must be entered one per line,\n\
 and should be terminated by the word `end'.");
 
+  add_com ("try", class_support, try_command,
+	   "Try/Catch support");
+
   add_com ("if", class_support, if_command,
 	   "Execute nested commands once IF the conditional expression is non zero.\n\
 The conditional expression must follow the word `if' and must in turn be\n\
Index: cli/cli-script.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-script.c,v
retrieving revision 1.7
diff -p -u -w -r1.7 cli-script.c
--- cli-script.c	2001/06/17 15:16:12	1.7
+++ cli-script.c	2001/11/27 08:07:08
@@ -210,6 +210,34 @@ print_command_lines (struct ui_out *uiou
 	  continue;
 	}
 
+      /* A try command.  Recursively print the try and catch blocks
+	 before continuing.  */
+      if (list->control_type == try_control)
+	{
+	  ui_out_text (uiout, "try");
+	  ui_out_field_fmt (uiout, NULL, "try\n");
+	  ui_out_text (uiout, "\n");
+	  /* The true arm. */
+	  print_command_lines (uiout, list->body_list[0], depth + 1);
+
+	  /* Show the false arm if it exists.  */
+	  if (list->body_count == 2)
+	    {
+	      if (depth)
+		ui_out_spaces (uiout, 2 * depth);
+	      ui_out_field_string (uiout, NULL, "CATCH");
+	      ui_out_text (uiout, "CATCH\n");
+	      print_command_lines (uiout, list->body_list[1], depth + 1);
+	    }
+
+	  ui_out_field_string (uiout, NULL, "end");
+	  if (depth)
+	    ui_out_spaces (uiout, 2 * depth);
+	  ui_out_text (uiout, "end\n");
+	  list = list->next;
+	  continue;
+	}
+
       /* ignore illegal command type and try next */
       list = list->next;
     }				/* while (list) */
@@ -292,6 +320,33 @@ print_command_line (struct command_line 
 	}
       fputs_filtered ("end\n", stream);
     }
+
+  /* A try command.  Recursively print both try and catch blocks.  */
+  if (cmd->control_type == try_control)
+    {
+      fputs_filtered ("try", stream);
+      fputs_filtered (cmd->line, stream);
+      fputs_filtered ("\n", stream);
+      /* The true arm. */
+      print_command_line (cmd->body_list[0], depth + 1, stream);
+
+      /* Show the catch block if it exists.  */
+      if (cmd->body_count == 2)
+	{
+	  if (depth)
+	    {
+	      for (i = 0; i < depth; i++)
+		fputs_filtered ("  ", stream);
+	    }
+	  fputs_filtered ("CATCH\n", stream);
+	  print_command_line (cmd->body_list[1], depth + 1, stream);
+	}
+      if (depth)
+	{
+	  for (i = 0; i < depth; i++)
+	    fputs_filtered ("  ", stream);
+	}
+      fputs_filtered ("end\n", stream);    }
 }
 #endif
 
@@ -461,6 +516,24 @@ execute_control_command (struct command_
 	break;
       }
 
+    case try_control:
+      {
+	for (current = cmd->body_list[0]; current; current = current->next)
+	  {
+	    ret = catch_errors (execute_control_command, current, 
+				"try -> CATCH", 0);
+
+	    if (ret == 0 || ret == invalid_control)
+	      {
+		if (cmd->body_count == 2)
+		  current = cmd->body_list[1];
+		else
+		  current = NULL;
+	      }
+	  }
+	break;
+      }
+
     default:
       warning ("Invalid control type in command structure.");
       return invalid_control;
@@ -508,6 +581,21 @@ if_command (char *arg, int from_tty)
   free_command_lines (&command);
 }
 
+void
+try_command (char *block, int from_tty)
+{
+  struct command_line *command = NULL;
+
+  control_level = 1;
+  command = get_command_line (try_control, block);
+
+  if (command == NULL)
+    return;
+
+  execute_control_command (command);
+  free_command_lines (&command);
+}
+
 /* Cleanup */
 static void
 arg_cleanup (void *ignore)
@@ -760,12 +848,18 @@ read_next_line (struct command_line **co
   if (p1 - p == 4 && !strncmp (p, "else", 4))
     return else_command;
 
+  /* Is the catch clause of an if try structure?  */
+  if (p1 - p == 5 && !strncmp (p, "CATCH", 5))
+    return CATCH_command;
+
   /* Check for while, if, break, continue, etc and build a new command
      line structure for them.  */
   if (p1 - p > 5 && !strncmp (p, "while", 5))
     *command = build_command_line (while_control, p + 6);
   else if (p1 - p > 2 && !strncmp (p, "if", 2))
     *command = build_command_line (if_control, p + 3);
+  else if (p1 - p > 3 && !strncmp (p, "try", 3))
+    *command = build_command_line (if_control, p + 4);
   else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
     {
       *command = (struct command_line *)
@@ -847,7 +941,8 @@ recurse_read_control_structure (struct c
       if (val == end_command)
 	{
 	  if (current_cmd->control_type == while_control
-	      || current_cmd->control_type == if_control)
+	      || current_cmd->control_type == if_control
+	      || current_cmd->control_type == try_control)
 	    {
 	      /* Success reading an entire control structure.  */
 	      ret = simple_control;
@@ -877,6 +972,23 @@ recurse_read_control_structure (struct c
 	      break;
 	    }
 	}
+      else if (val == CATCH_command)
+	{
+	  if (current_cmd->control_type == try_control
+	      && current_body == 1)
+	    {
+	      realloc_body_list (current_cmd, 2);
+	      current_body = 2;
+	      child_tail = NULL;
+	      continue;
+	    }
+	  else
+	    {
+	      ret = invalid_control;
+	      break;
+	    }
+	}
+
 
       if (child_tail)
 	{
@@ -897,7 +1009,8 @@ recurse_read_control_structure (struct c
       /* If the latest line is another control structure, then recurse
          on it.  */
       if (next->control_type == while_control
-	  || next->control_type == if_control)
+	  || next->control_type == if_control
+	  || next->control_type == try_control)
 	{
 	  control_level++;
 	  ret = recurse_read_control_structure (next);
@@ -964,7 +1077,8 @@ read_command_lines (char *prompt_arg, in
 	}
 
       if (next->control_type == while_control
-	  || next->control_type == if_control)
+	  || next->control_type == if_control
+	  || next->control_type == try_control)
 	{
 	  control_level++;
 	  ret = recurse_read_control_structure (next);
Index: cli/cli-script.h
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-script.h,v
retrieving revision 1.2
diff -p -u -w -r1.2 cli-script.h
--- cli-script.h	2001/03/06 08:21:20	1.2
+++ cli-script.h	2001/11/27 08:07:08
@@ -31,6 +31,8 @@ extern void while_command (char *arg, in
 
 extern void if_command (char *arg, int from_tty);
 
+extern void try_command (char *block, int from_tty);
+
 extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
 
 /* Exported to gdb/breakpoint.c */


-- 
dhoward@redhat.com
gdb engineering



             reply	other threads:[~2001-11-27  8:43 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-11-27  8:43 Don Howard [this message]
2001-11-17 12:21 ` Don Howard
2001-11-27 20:17 ` Andrew Cagney
2001-11-18 10:57   ` Andrew Cagney
2001-11-19 15:11   ` Fernando Nasser
2001-11-28  6:52     ` Fernando Nasser
2001-11-28  6:57     ` Arnaud Charlet
2001-11-20  8:44       ` Arnaud Charlet
  -- strict thread matches above, loose matches on Subject: below --
2001-11-02  6:11 Don Howard
2001-11-02  8:33 ` Andrew Cagney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.4.33.0111270827180.2426-100000@theotherone.redhat-remotie.org \
    --to=dhoward@redhat.com \
    --cc=gdb@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox