* defs.h (enum return_reason): Renumber so that all values are
authorAndrew Cagney <cagney@redhat.com>
Fri, 7 Sep 2001 21:33:08 +0000 (21:33 +0000)
committerAndrew Cagney <cagney@redhat.com>
Fri, 7 Sep 2001 21:33:08 +0000 (21:33 +0000)
negative.
(RETURN_MASK): Negate reason.
(catch_exception_ftype): Declare.
(catch_exceptions): Declare.
* top.c (catcher): New function, based on catch_errors.  Add in
parameter func_uiout and out parameters func_val, func_caught and
func_cleanup.  Change type of func to catch_exceptions_ftype.
Save/restore uiout.
(struct catch_errors_args): Define.
(do_catch_errors): New function.
(catch_errors): Rewrite, use do_catch_errors and catcher.
(catch_exceptions): New function, use catcher.

gdb/ChangeLog
gdb/defs.h
gdb/top.c

index 28acf24..b9eb663 100644 (file)
@@ -1,3 +1,19 @@
+2001-09-07  Andrew Cagney  <ac131313@redhat.com>
+
+       * defs.h (enum return_reason): Renumber so that all values are
+       negative.
+       (RETURN_MASK): Negate reason.
+       (catch_exception_ftype): Declare.
+       (catch_exceptions): Declare.
+       * top.c (catcher): New function, based on catch_errors.  Add in
+       parameter func_uiout and out parameters func_val, func_caught and
+       func_cleanup.  Change type of func to catch_exceptions_ftype.
+       Save/restore uiout.
+       (struct catch_errors_args): Define.
+       (do_catch_errors): New function.
+       (catch_errors): Rewrite, use do_catch_errors and catcher.
+       (catch_exceptions): New function, use catcher.
+
 2001-09-07  Jim Blandy  <jimb@redhat.com>
 
        Correctly parse register values provided by the monitor.
index 7d717c7..a0d6d03 100644 (file)
@@ -1084,21 +1084,23 @@ extern NORETURN void internal_error (const char *file, int line,
 
 extern NORETURN void nomem (long) ATTR_NORETURN;
 
-/* Reasons for calling return_to_top_level.  Note: enum value 0 is
-   reserved for internal use as the return value from an initial
-   setjmp().  */
+/* Reasons for calling return_to_top_level.  NOTE: all reason values
+   must be less than zero.  enum value 0 is reserved for internal use
+   as the return value from an initial setjmp().  The function
+   catch_exceptions() reserves values >= 0 as legal results from its
+   wrapped function.  */
 
 enum return_reason
   {
     /* User interrupt.  */
-    RETURN_QUIT = 1,
+    RETURN_QUIT = -2,
     /* Any other error.  */
     RETURN_ERROR
   };
 
 #define        ALL_CLEANUPS    ((struct cleanup *)0)
 
-#define RETURN_MASK(reason)    (1 << (int)(reason))
+#define RETURN_MASK(reason)    (1 << (int)(-reason))
 #define RETURN_MASK_QUIT       RETURN_MASK (RETURN_QUIT)
 #define RETURN_MASK_ERROR      RETURN_MASK (RETURN_ERROR)
 #define RETURN_MASK_ALL                (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
@@ -1106,12 +1108,41 @@ typedef int return_mask;
 
 extern NORETURN void return_to_top_level (enum return_reason) ATTR_NORETURN;
 
+/* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
+   handler.  If an exception (enum return_reason) is thrown using
+   return_to_top_level() than all cleanups installed since
+   catch_exceptions() was entered are invoked, the (-ve) exception
+   value is then returned by catch_exceptions.  If FUNC() returns
+   normally (with a postive or zero return value) then that value is
+   returned by catch_exceptions().  It is an internal_error() for
+   FUNC() to return a negative value.
+
+   For the period of the FUNC() call: UIOUT is installed as the output
+   builder; ERRSTRING is installed as the error/quit message; and a
+   new cleanup_chain is established.  The old values are restored
+   before catch_exceptions() returns.
+
+   FIXME; cagney/2001-08-13: The need to override the global UIOUT
+   builder variable should just go away.
+
+   This function superseeds catch_errors().
+
+   This function uses SETJMP() and LONGJUMP().  */
+
+struct ui_out;
+typedef int (catch_exceptions_ftype) (struct ui_out *ui_out, void *args);
+extern int catch_exceptions (struct ui_out *uiout,
+                            catch_exceptions_ftype *func, void *func_args,
+                            char *errstring, return_mask mask);
+
 /* If CATCH_ERRORS_FTYPE throws an error, catch_errors() returns zero
    otherwize the result from CATCH_ERRORS_FTYPE is returned. It is
    probably useful for CATCH_ERRORS_FTYPE to always return a non-zero
    value. It's unfortunate that, catch_errors() does not return an
    indication of the exact exception that it caught - quit_flag might
-   help. */
+   help.
+
+   This function is superseeded by catch_exceptions().  */
 
 typedef int (catch_errors_ftype) (PTR);
 extern int catch_errors (catch_errors_ftype *, PTR, char *, return_mask);
index 5d644dc..d57f0b5 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -41,6 +41,7 @@
 #include "version.h"
 #include "serial.h"
 #include "doublest.h"
+#include "gdb_assert.h"
 
 /* readline include files */
 #include <readline/readline.h>
@@ -334,10 +335,11 @@ return_to_top_level (enum return_reason reason)
   (NORETURN void) SIGLONGJMP (*catch_return, (int) reason);
 }
 
-/* Call FUNC with arg ARGS, catching any errors.  If there is no
-   error, return the value returned by FUNC.  If there is an error,
-   print ERRSTRING, print the specific error message, then return
-   zero.
+/* Call FUNC() with args FUNC_UIOUT and FUNC_ARGS, catching any
+   errors.  Set FUNC_CAUGHT to an ``enum return_reason'' if the
+   function is aborted (using return_to_top_level() or zero if the
+   function returns normally.  Set FUNC_VAL to the value returned by
+   the function or 0 if the function was aborted.
 
    Must not be called with immediate_quit in effect (bad things might
    happen, say we got a signal in the middle of a memcpy to quit_return).
@@ -365,21 +367,30 @@ return_to_top_level (enum return_reason reason)
    be consolidated into a single file instead of being distributed
    between utils.c and top.c? */
 
-int
-catch_errors (catch_errors_ftype *func, void * args, char *errstring,
-             return_mask mask)
+static void
+catcher (catch_exceptions_ftype *func,
+        struct ui_out *func_uiout,
+        void *func_args,
+        int *func_val,
+        enum return_reason *func_caught,
+        char *errstring,
+        return_mask mask)
 {
   SIGJMP_BUF *saved_catch;
   SIGJMP_BUF catch;
-  int val;
   struct cleanup *saved_cleanup_chain;
   char *saved_error_pre_print;
   char *saved_quit_pre_print;
+  struct ui_out *saved_uiout;
 
   /* Return value from SIGSETJMP(): enum return_reason if error or
      quit caught, 0 otherwise. */
   int caught;
 
+  /* Return value from FUNC(): Hopefully non-zero. Explicitly set to
+     zero if an error quit was caught.  */
+  int val;
+
   /* Override error/quit messages during FUNC. */
 
   saved_error_pre_print = error_pre_print;
@@ -390,6 +401,11 @@ catch_errors (catch_errors_ftype *func, void * args, char *errstring,
   if (mask & RETURN_MASK_QUIT)
     quit_pre_print = errstring;
 
+  /* Override the global ``struct ui_out'' builder.  */
+
+  saved_uiout = uiout;
+  uiout = func_uiout;
+
   /* Prevent error/quit during FUNC from calling cleanups established
      prior to here. */
 
@@ -401,7 +417,7 @@ catch_errors (catch_errors_ftype *func, void * args, char *errstring,
   catch_return = &catch;
   caught = SIGSETJMP (catch);
   if (!caught)
-    val = (*func) (args);
+    val = (*func) (func_uiout, func_args);
   else
     val = 0;
   catch_return = saved_catch;
@@ -413,47 +429,78 @@ catch_errors (catch_errors_ftype *func, void * args, char *errstring,
      do_cleanups call (to cover the problem) or an assertion check to
      detect bad FUNCs code. */
 
-  /* Restore the cleanup chain and error/quit messages to their
-     original states. */
+  /* Restore the cleanup chain, the error/quit messages, and the uiout
+     builder, to their original states. */
 
   restore_cleanups (saved_cleanup_chain);
 
+  uiout = saved_uiout;
+
   if (mask & RETURN_MASK_QUIT)
     quit_pre_print = saved_quit_pre_print;
   if (mask & RETURN_MASK_ERROR)
     error_pre_print = saved_error_pre_print;
 
-  /* Return normally if no error/quit event occurred. */
+  /* Return normally if no error/quit event occurred or this catcher
+     can handle this exception.  The caller analyses the func return
+     values.  */
 
-  if (!caught)
-    return val;
+  if (!caught || (mask & RETURN_MASK (caught)))
+    {
+      *func_val = val;
+      *func_caught = caught;
+      return;
+    }
 
-  /* If the caller didn't request that the event be caught, relay the
+  /* The caller didn't request that the event be caught, relay the
      event to the next containing catch_errors(). */
 
-  if (!(mask & RETURN_MASK (caught)))
-    return_to_top_level (caught);
-
-  /* Tell the caller that an event was caught.
-
-     FIXME: nsd/2000-02-22: When MASK is RETURN_MASK_ALL, the caller
-     can't tell what type of event occurred.
+  return_to_top_level (caught);
+}
 
-     A possible fix is to add a new interface, catch_event(), that
-     returns enum return_reason after catching an error or a quit.
+int
+catch_exceptions (struct ui_out *uiout,
+                 catch_exceptions_ftype *func,
+                 void *func_args,
+                 char *errstring,
+                 return_mask mask)
+{
+  int val;
+  enum return_reason caught;
+  catcher (func, uiout, func_args, &val, &caught, errstring, mask);
+  gdb_assert (val >= 0);
+  gdb_assert (caught <= 0);
+  if (caught < 0)
+    return caught;
+  return val;
+}
 
-     When returning normally, i.e. without catching an error or a
-     quit, catch_event() could return RETURN_NORMAL, which would be
-     added to enum return_reason.  FUNC would return information
-     exclusively via ARGS.
+struct catch_errors_args
+{
+  catch_errors_ftype *func;
+  void *func_args;
+};
 
-     Alternatively, normal catch_event() could return FUNC's return
-     value.  The caller would need to be aware of potential overlap
-     with enum return_reason, which could be publicly restricted to
-     negative values to simplify return value processing in FUNC and
-     in the caller. */
+int
+do_catch_errors (struct ui_out *uiout, void *data)
+{
+  struct catch_errors_args *args = data;
+  return args->func (args->func_args);
+}
 
-  return 0;
+int
+catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
+             return_mask mask)
+{
+  int val;
+  enum return_reason caught;
+  struct catch_errors_args args;
+  args.func = func;
+  args.func_args = func_args;
+  catcher (do_catch_errors, uiout, &args, &val, &caught, errstring, mask);
+  if (caught != 0)
+    return 0;
+  return val;
 }
 
 struct captured_command_args