From f9c696d277e3c63524ddd995edac66fa6770395b Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Fri, 7 Sep 2001 21:33:08 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 16 +++++++ gdb/defs.h | 43 ++++++++++++++++--- gdb/top.c | 115 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 134 insertions(+), 40 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 28acf240e89..b9eb663037f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2001-09-07 Andrew Cagney + + * 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 Correctly parse register values provided by the monitor. diff --git a/gdb/defs.h b/gdb/defs.h index 7d717c7b031..a0d6d03e8d2 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -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); diff --git a/gdb/top.c b/gdb/top.c index 5d644dc00b4..d57f0b57317 100644 --- 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 @@ -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 -- 2.30.2