* 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>
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;
/* 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);

115
gdb/top.c
View File

@ -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);
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
can't tell what type of event occurred.
struct catch_errors_args
{
catch_errors_ftype *func;
void *func_args;
};
A possible fix is to add a new interface, catch_event(), that
returns enum return_reason after catching an error or a quit.
int
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
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;
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