mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-05-31 01:45:52 +08:00
* top.c (SIGJMP_BUF, SIGSETJMP, SIGLONGJMP): Update comments.
(error_return, quit_return): Merge into catch_return pointer. (return_to_top_level): Update comment. Longjmp to *catch_errors, and communicate reason to catch_errors via setjmp return value. (catch_errors): Always catch both quit and error, and if a catch wasn't requested by caller, throw it to the next catch_error. Replace dual longjmp buffer memcpy with single pointer change. Add FIXME for possibly adding new interface to tell caller what event was caught. Add extensive comments. * defs.h (enum return_reason): Reserve 0 for use as initial setjmp() return value. (RETURN_MASK): New public macro to generate RETURN_MASK_* from enum return_reason. (RETURN_MASK_QUIT, RETURN_MASK_ERROR): Define using RETURN_MASK.
This commit is contained in:
@ -1,3 +1,20 @@
|
||||
Wed Feb 23 19:01:45 EST 2000 Nicholas Duffek <nsd@cygnus.com>
|
||||
|
||||
* top.c (SIGJMP_BUF, SIGSETJMP, SIGLONGJMP): Update comments.
|
||||
(error_return, quit_return): Merge into catch_return pointer.
|
||||
(return_to_top_level): Update comment. Longjmp to *catch_errors,
|
||||
and communicate reason to catch_errors via setjmp return value.
|
||||
(catch_errors): Always catch both quit and error, and if a catch
|
||||
wasn't requested by caller, throw it to the next catch_error.
|
||||
Replace dual longjmp buffer memcpy with single pointer change.
|
||||
Add FIXME for possibly adding new interface to tell caller what
|
||||
event was caught. Add extensive comments.
|
||||
* defs.h (enum return_reason): Reserve 0 for use as initial
|
||||
setjmp() return value.
|
||||
(RETURN_MASK): New public macro to generate RETURN_MASK_* from
|
||||
enum return_reason.
|
||||
(RETURN_MASK_QUIT, RETURN_MASK_ERROR): Define using RETURN_MASK.
|
||||
|
||||
2000-02-23 Fernando Nasser <fnasser@cygnus.com>
|
||||
|
||||
* infcmd.c (run_stack_dummy): Do not pop frame on random signal.
|
||||
|
13
gdb/defs.h
13
gdb/defs.h
@ -801,21 +801,24 @@ extern NORETURN void internal_error (char *, ...) ATTR_NORETURN;
|
||||
|
||||
extern NORETURN void nomem (long) ATTR_NORETURN;
|
||||
|
||||
/* Reasons for calling return_to_top_level. */
|
||||
/* 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,
|
||||
RETURN_QUIT = 1,
|
||||
/* Any other error. */
|
||||
RETURN_ERROR
|
||||
};
|
||||
|
||||
#define ALL_CLEANUPS ((struct cleanup *)0)
|
||||
|
||||
#define RETURN_MASK_QUIT (1 << (int)RETURN_QUIT)
|
||||
#define RETURN_MASK_ERROR (1 << (int)RETURN_ERROR)
|
||||
#define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
|
||||
#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;
|
||||
|
||||
extern NORETURN void return_to_top_level (enum return_reason) ATTR_NORETURN;
|
||||
|
135
gdb/top.c
135
gdb/top.c
@ -482,8 +482,8 @@ NORETURN void (*error_hook)
|
||||
PARAMS ((void)) ATTR_NORETURN;
|
||||
|
||||
|
||||
/* Generally one should use catch_errors rather than manipulating these
|
||||
directly. The exception is main(). */
|
||||
/* One should use catch_errors rather than manipulating these
|
||||
directly. */
|
||||
#if defined(HAVE_SIGSETJMP)
|
||||
#define SIGJMP_BUF sigjmp_buf
|
||||
#define SIGSETJMP(buf) sigsetjmp(buf, 1)
|
||||
@ -494,13 +494,10 @@ PARAMS ((void)) ATTR_NORETURN;
|
||||
#define SIGLONGJMP(buf,val) longjmp(buf,val)
|
||||
#endif
|
||||
|
||||
/* Where to go for return_to_top_level (RETURN_ERROR). */
|
||||
static SIGJMP_BUF error_return;
|
||||
/* Where to go for return_to_top_level (RETURN_QUIT). */
|
||||
static SIGJMP_BUF quit_return;
|
||||
/* Where to go for return_to_top_level. */
|
||||
static SIGJMP_BUF *catch_return;
|
||||
|
||||
/* Return for reason REASON. This generally gets back to the command
|
||||
loop, but can be caught via catch_errors. */
|
||||
/* Return for reason REASON to the nearest containing catch_errors(). */
|
||||
|
||||
NORETURN void
|
||||
return_to_top_level (reason)
|
||||
@ -531,8 +528,11 @@ return_to_top_level (reason)
|
||||
break;
|
||||
}
|
||||
|
||||
(NORETURN void) SIGLONGJMP
|
||||
(reason == RETURN_ERROR ? error_return : quit_return, 1);
|
||||
/* Jump to the containing catch_errors() call, communicating REASON
|
||||
to that call via setjmp's return value. Note that REASON can't
|
||||
be zero, by definition in defs.h. */
|
||||
|
||||
(NORETURN void) SIGLONGJMP (*catch_return, (int)reason);
|
||||
}
|
||||
|
||||
/* Call FUNC with arg ARGS, catching any errors. If there is no
|
||||
@ -562,13 +562,6 @@ return_to_top_level (reason)
|
||||
code also randomly used a SET_TOP_LEVEL macro that directly
|
||||
initialize the longjmp buffers. */
|
||||
|
||||
/* MAYBE: cagney/1999-11-05: Since the SET_TOP_LEVEL macro has been
|
||||
eliminated it is now possible to use the stack to directly store
|
||||
each longjmp buffer. The global code would just need to update a
|
||||
pointer (onto the stack - ulgh!?) indicating the current longjmp
|
||||
buffers. It would certainly improve the performance of the longjmp
|
||||
code since the memcpy's would be eliminated. */
|
||||
|
||||
/* MAYBE: cagney/1999-11-05: Should the catch_erros and cleanups code
|
||||
be consolidated into a single file instead of being distributed
|
||||
between utils.c and top.c? */
|
||||
@ -580,61 +573,89 @@ catch_errors (func, args, errstring, mask)
|
||||
char *errstring;
|
||||
return_mask mask;
|
||||
{
|
||||
SIGJMP_BUF saved_error;
|
||||
SIGJMP_BUF saved_quit;
|
||||
SIGJMP_BUF tmp_jmp;
|
||||
SIGJMP_BUF *saved_catch;
|
||||
SIGJMP_BUF catch;
|
||||
int val;
|
||||
struct cleanup *saved_cleanup_chain;
|
||||
char *saved_error_pre_print;
|
||||
char *saved_quit_pre_print;
|
||||
|
||||
saved_cleanup_chain = save_cleanups ();
|
||||
/* 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;
|
||||
saved_quit_pre_print = quit_pre_print;
|
||||
|
||||
if (mask & RETURN_MASK_ERROR)
|
||||
{
|
||||
memcpy ((char *) saved_error, (char *) error_return, sizeof (SIGJMP_BUF));
|
||||
error_pre_print = errstring;
|
||||
}
|
||||
error_pre_print = errstring;
|
||||
if (mask & RETURN_MASK_QUIT)
|
||||
{
|
||||
memcpy (saved_quit, quit_return, sizeof (SIGJMP_BUF));
|
||||
quit_pre_print = errstring;
|
||||
}
|
||||
quit_pre_print = errstring;
|
||||
|
||||
if (SIGSETJMP (tmp_jmp) == 0)
|
||||
{
|
||||
if (mask & RETURN_MASK_ERROR)
|
||||
memcpy (error_return, tmp_jmp, sizeof (SIGJMP_BUF));
|
||||
if (mask & RETURN_MASK_QUIT)
|
||||
memcpy (quit_return, tmp_jmp, sizeof (SIGJMP_BUF));
|
||||
val = (*func) (args);
|
||||
/* FIXME: cagney/1999-11-05: A correct FUNC implementaton will
|
||||
clean things up (restoring the cleanup chain) to the state
|
||||
they were just prior to the call. Technically, this means
|
||||
that the below restore_cleanups call is redundant.
|
||||
Unfortunatly, many FUNC's are not that well behaved.
|
||||
restore_cleanups should either be replaced with a do_cleanups
|
||||
call (to cover the problem) or an assertion check to detect
|
||||
bad FUNCs code. */
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
/* Prevent error/quit during FUNC from calling cleanups established
|
||||
prior to here. */
|
||||
|
||||
saved_cleanup_chain = save_cleanups ();
|
||||
|
||||
/* Call FUNC, catching error/quit events. */
|
||||
|
||||
saved_catch = catch_return;
|
||||
catch_return = &catch;
|
||||
caught = SIGSETJMP (catch);
|
||||
if (!caught)
|
||||
val = (*func) (args);
|
||||
catch_return = saved_catch;
|
||||
|
||||
/* FIXME: cagney/1999-11-05: A correct FUNC implementaton will
|
||||
clean things up (restoring the cleanup chain) to the state they
|
||||
were just prior to the call. Unfortunatly, many FUNC's are not
|
||||
that well behaved. This could be fixed by adding either a
|
||||
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_ERROR)
|
||||
{
|
||||
memcpy (error_return, saved_error, sizeof (SIGJMP_BUF));
|
||||
error_pre_print = saved_error_pre_print;
|
||||
}
|
||||
if (mask & RETURN_MASK_QUIT)
|
||||
{
|
||||
memcpy (quit_return, saved_quit, sizeof (SIGJMP_BUF));
|
||||
quit_pre_print = saved_quit_pre_print;
|
||||
}
|
||||
return val;
|
||||
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
|
||||
|
Reference in New Issue
Block a user