* 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.
This commit is contained in:
Andrew Cagney
2001-09-07 21:33:08 +00:00
parent a2e2dd8055
commit f9c696d277
3 changed files with 134 additions and 40 deletions

View 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> 2001-09-07 Jim Blandy <jimb@redhat.com>
Correctly parse register values provided by the monitor. Correctly parse register values provided by the monitor.

View File

@ -1084,21 +1084,23 @@ extern NORETURN void internal_error (const char *file, int line,
extern NORETURN void nomem (long) ATTR_NORETURN; extern NORETURN void nomem (long) ATTR_NORETURN;
/* Reasons for calling return_to_top_level. Note: enum value 0 is /* Reasons for calling return_to_top_level. NOTE: all reason values
reserved for internal use as the return value from an initial must be less than zero. enum value 0 is reserved for internal use
setjmp(). */ 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 enum return_reason
{ {
/* User interrupt. */ /* User interrupt. */
RETURN_QUIT = 1, RETURN_QUIT = -2,
/* Any other error. */ /* Any other error. */
RETURN_ERROR RETURN_ERROR
}; };
#define ALL_CLEANUPS ((struct cleanup *)0) #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_QUIT RETURN_MASK (RETURN_QUIT)
#define RETURN_MASK_ERROR RETURN_MASK (RETURN_ERROR) #define RETURN_MASK_ERROR RETURN_MASK (RETURN_ERROR)
#define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_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; 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 /* If CATCH_ERRORS_FTYPE throws an error, catch_errors() returns zero
otherwize the result from CATCH_ERRORS_FTYPE is returned. It is otherwize the result from CATCH_ERRORS_FTYPE is returned. It is
probably useful for CATCH_ERRORS_FTYPE to always return a non-zero probably useful for CATCH_ERRORS_FTYPE to always return a non-zero
value. It's unfortunate that, catch_errors() does not return an value. It's unfortunate that, catch_errors() does not return an
indication of the exact exception that it caught - quit_flag might 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); typedef int (catch_errors_ftype) (PTR);
extern int catch_errors (catch_errors_ftype *, PTR, char *, return_mask); extern int catch_errors (catch_errors_ftype *, PTR, char *, return_mask);

115
gdb/top.c
View File

@ -41,6 +41,7 @@
#include "version.h" #include "version.h"
#include "serial.h" #include "serial.h"
#include "doublest.h" #include "doublest.h"
#include "gdb_assert.h"
/* readline include files */ /* readline include files */
#include <readline/readline.h> #include <readline/readline.h>
@ -334,10 +335,11 @@ return_to_top_level (enum return_reason reason)
(NORETURN void) SIGLONGJMP (*catch_return, (int) reason); (NORETURN void) SIGLONGJMP (*catch_return, (int) reason);
} }
/* Call FUNC with arg ARGS, catching any errors. If there is no /* Call FUNC() with args FUNC_UIOUT and FUNC_ARGS, catching any
error, return the value returned by FUNC. If there is an error, errors. Set FUNC_CAUGHT to an ``enum return_reason'' if the
print ERRSTRING, print the specific error message, then return function is aborted (using return_to_top_level() or zero if the
zero. 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 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). 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 be consolidated into a single file instead of being distributed
between utils.c and top.c? */ between utils.c and top.c? */
int static void
catch_errors (catch_errors_ftype *func, void * args, char *errstring, catcher (catch_exceptions_ftype *func,
return_mask mask) 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 *saved_catch;
SIGJMP_BUF catch; SIGJMP_BUF catch;
int val;
struct cleanup *saved_cleanup_chain; struct cleanup *saved_cleanup_chain;
char *saved_error_pre_print; char *saved_error_pre_print;
char *saved_quit_pre_print; char *saved_quit_pre_print;
struct ui_out *saved_uiout;
/* Return value from SIGSETJMP(): enum return_reason if error or /* Return value from SIGSETJMP(): enum return_reason if error or
quit caught, 0 otherwise. */ quit caught, 0 otherwise. */
int caught; 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. */ /* Override error/quit messages during FUNC. */
saved_error_pre_print = error_pre_print; 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) if (mask & RETURN_MASK_QUIT)
quit_pre_print = errstring; 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 /* Prevent error/quit during FUNC from calling cleanups established
prior to here. */ prior to here. */
@ -401,7 +417,7 @@ catch_errors (catch_errors_ftype *func, void * args, char *errstring,
catch_return = &catch; catch_return = &catch;
caught = SIGSETJMP (catch); caught = SIGSETJMP (catch);
if (!caught) if (!caught)
val = (*func) (args); val = (*func) (func_uiout, func_args);
else else
val = 0; val = 0;
catch_return = saved_catch; 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 do_cleanups call (to cover the problem) or an assertion check to
detect bad FUNCs code. */ detect bad FUNCs code. */
/* Restore the cleanup chain and error/quit messages to their /* Restore the cleanup chain, the error/quit messages, and the uiout
original states. */ builder, to their original states. */
restore_cleanups (saved_cleanup_chain); restore_cleanups (saved_cleanup_chain);
uiout = saved_uiout;
if (mask & RETURN_MASK_QUIT) if (mask & RETURN_MASK_QUIT)
quit_pre_print = saved_quit_pre_print; quit_pre_print = saved_quit_pre_print;
if (mask & RETURN_MASK_ERROR) if (mask & RETURN_MASK_ERROR)
error_pre_print = saved_error_pre_print; 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) if (!caught || (mask & RETURN_MASK (caught)))
return val; {
*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(). */ event to the next containing catch_errors(). */
if (!(mask & RETURN_MASK (caught))) return_to_top_level (caught);
return_to_top_level (caught); }
/* Tell the caller that an event was 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;
}
FIXME: nsd/2000-02-22: When MASK is RETURN_MASK_ALL, the caller struct catch_errors_args
can't tell what type of event occurred. {
catch_errors_ftype *func;
void *func_args;
};
A possible fix is to add a new interface, catch_event(), that int
returns enum return_reason after catching an error or a quit. do_catch_errors (struct ui_out *uiout, void *data)
{
struct catch_errors_args *args = data;
return args->func (args->func_args);
}
When returning normally, i.e. without catching an error or a int
quit, catch_event() could return RETURN_NORMAL, which would be catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
added to enum return_reason. FUNC would return information return_mask mask)
exclusively via ARGS. {
int val;
Alternatively, normal catch_event() could return FUNC's return enum return_reason caught;
value. The caller would need to be aware of potential overlap struct catch_errors_args args;
with enum return_reason, which could be publicly restricted to args.func = func;
negative values to simplify return value processing in FUNC and args.func_args = func_args;
in the caller. */ catcher (do_catch_errors, uiout, &args, &val, &caught, errstring, mask);
if (caught != 0)
return 0; return 0;
return val;
} }
struct captured_command_args struct captured_command_args