aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorNicholas Duffek <nsd@redhat.com>2000-02-24 00:04:03 +0000
committerNicholas Duffek <nsd@redhat.com>2000-02-24 00:04:03 +0000
commit99eeeb0ff7898f8987188e510b2612de1fcfa454 (patch)
treec6dfb641a5501748c99f36b6448c00a5e372398a /gdb
parenteaba1dd3fb01d2964da9695f159e82a3c4596e63 (diff)
downloadfsf-binutils-gdb-99eeeb0ff7898f8987188e510b2612de1fcfa454.zip
fsf-binutils-gdb-99eeeb0ff7898f8987188e510b2612de1fcfa454.tar.gz
fsf-binutils-gdb-99eeeb0ff7898f8987188e510b2612de1fcfa454.tar.bz2
* 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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/defs.h13
-rw-r--r--gdb/top.c135
3 files changed, 103 insertions, 62 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c861278..eed3df1 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/defs.h b/gdb/defs.h
index fa9f540..c4756f1 100644
--- a/gdb/defs.h
+++ b/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;
diff --git a/gdb/top.c b/gdb/top.c
index 6bd7648..4acf4db 100644
--- a/gdb/top.c
+++ b/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