This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [rfa] catch_exceptions()


Andrew Cagney writes:
 > Hello,
 > 
 > Following up on my last e-mail, here is a tested patch that adds 
 > catch_exceptions() to top.c
 > 
 > If this is approved, I think I'll add catch_errors() to the ARI (under 
 > warnings).
 > 
 > 	Andrew


Sure, approved. (there is a typo in a comment, see below).

Thanks
Elena


 > 2001-08-13  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.
 > 
 > Index: defs.h
 > ===================================================================
 > RCS file: /cvs/src/src/gdb/defs.h,v
 > retrieving revision 1.62
 > diff -p -r1.62 defs.h
 > *** defs.h	2001/08/02 20:57:19	1.62
 > --- defs.h	2001/08/15 17:49:33
 > *************** extern NORETURN void internal_error (con
 > *** 1084,1104 ****
 >   
 >   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().  */
 >   
 >   enum return_reason
 >     {
 >       /* User interrupt.  */
 > !     RETURN_QUIT = 1,
 >       /* Any other error.  */
 >       RETURN_ERROR
 >     };
 >   
 >   #define	ALL_CLEANUPS	((struct cleanup *)0)
 >   
 > ! #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)
 > --- 1084,1106 ----
 >   
 >   extern NORETURN void nomem (long) ATTR_NORETURN;
 >   
 > ! /* 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 functioin
                                                           ^^^^^^^^^


 > !    catch_exceptions() reserves values >= 0 as legal results from its
 > !    wrapped function.  */
 >   
 >   enum return_reason
 >     {
 >       /* User interrupt.  */
 > !     RETURN_QUIT = -2,
 >       /* Any other error.  */
 >       RETURN_ERROR
 >     };
 >   
 >   #define	ALL_CLEANUPS	((struct cleanup *)0)
 >   
 > ! #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)
 > *************** typedef int return_mask;
 > *** 1106,1117 ****
 >   
 >   extern NORETURN void return_to_top_level (enum return_reason) ATTR_NORETURN;
 >   
 >   /* 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. */
 >   
 >   typedef int (catch_errors_ftype) (PTR);
 >   extern int catch_errors (catch_errors_ftype *, PTR, char *, return_mask);
 > --- 1108,1148 ----
 >   
 >   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.
 > ! 
 > !    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: top.c
 > ===================================================================
 > RCS file: /cvs/src/src/gdb/top.c,v
 > retrieving revision 1.42
 > diff -p -r1.42 top.c
 > *** top.c	2001/08/01 18:39:23	1.42
 > --- top.c	2001/08/15 17:49:40
 > ***************
 > *** 41,46 ****
 > --- 41,47 ----
 >   #include "version.h"
 >   #include "serial.h"
 >   #include "doublest.h"
 > + #include "gdb_assert.h"
 >   
 >   /* readline include files */
 >   #include <readline/readline.h>
 > *************** return_to_top_level (enum return_reason 
 > *** 347,356 ****
 >     (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.
 >   
 >      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).
 > --- 348,358 ----
 >     (NORETURN void) SIGLONGJMP (*catch_return, (int) reason);
 >   }
 >   
 > ! /* 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).
 > *************** return_to_top_level (enum return_reason 
 > *** 378,398 ****
 >      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)
 >   {
 >     SIGJMP_BUF *saved_catch;
 >     SIGJMP_BUF catch;
 > -   int val;
 >     struct cleanup *saved_cleanup_chain;
 >     char *saved_error_pre_print;
 >     char *saved_quit_pre_print;
 >   
 >     /* Return value from SIGSETJMP(): enum return_reason if error or
 >        quit caught, 0 otherwise. */
 >     int caught;
 >   
 >     /* Override error/quit messages during FUNC. */
 >   
 >     saved_error_pre_print = error_pre_print;
 > --- 380,409 ----
 >      be consolidated into a single file instead of being distributed
 >      between utils.c and top.c? */
 >   
 > ! 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;
 >     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;
 > *************** catch_errors (catch_errors_ftype *func, 
 > *** 403,408 ****
 > --- 414,424 ----
 >     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. */
 >   
 > *************** catch_errors (catch_errors_ftype *func, 
 > *** 414,420 ****
 >     catch_return = &catch;
 >     caught = SIGSETJMP (catch);
 >     if (!caught)
 > !     val = (*func) (args);
 >     else
 >       val = 0;
 >     catch_return = saved_catch;
 > --- 430,436 ----
 >     catch_return = &catch;
 >     caught = SIGSETJMP (catch);
 >     if (!caught)
 > !     val = (*func) (func_uiout, func_args);
 >     else
 >       val = 0;
 >     catch_return = saved_catch;
 > *************** catch_errors (catch_errors_ftype *func, 
 > *** 426,472 ****
 >        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_cleanups (saved_cleanup_chain);
 >   
 >     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. */
 >   
 > !   if (!caught)
 > !     return val;
 >   
 > !   /* If 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.
 >   
 > !      A possible fix is to add a new interface, catch_event(), that
 > !      returns enum return_reason after catching an error or a quit.
 >   
 > !      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.
 >   
 > !      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. */
 >   
 > !   return 0;
 >   }
 >   
 >   struct captured_command_args
 > --- 442,519 ----
 >        do_cleanups call (to cover the problem) or an assertion check to
 >        detect bad FUNCs code. */
 >   
 > !   /* 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 or this catcher
 > !      can handle this exception.  The caller analyses the func return
 > !      values.  */
 > ! 
 > !   if (!caught || (mask & RETURN_MASK (caught)))
 > !     {
 > !       *func_val = val;
 > !       *func_caught = caught;
 > !       return;
 > !     }
 >   
 > !   /* The caller didn't request that the event be caught, relay the
 >        event to the next containing catch_errors(). */
 >   
 > !   return_to_top_level (caught);
 > ! }
 >   
 > ! 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;
 > ! }
 >   
 > ! struct catch_errors_args
 > ! {
 > !   catch_errors_ftype *func;
 > !   void *func_args;
 > ! };
 >   
 > ! int
 > ! do_catch_errors (struct ui_out *uiout, void *data)
 > ! {
 > !   struct catch_errors_args *args = data;
 > !   return args->func (args->func_args);
 > ! }
 >   
 > ! 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]