diff options
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/breakpoint.c | 4 | ||||
-rw-r--r-- | gdb/exceptions.c | 118 | ||||
-rw-r--r-- | gdb/exceptions.h | 38 | ||||
-rw-r--r-- | gdb/remote-fileio.c | 2 | ||||
-rw-r--r-- | gdb/remote.c | 4 | ||||
-rw-r--r-- | gdb/utils.c | 8 |
7 files changed, 139 insertions, 55 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cb86d9c..2dee79c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2005-01-12 Andrew Cagney <cagney@gnu.org> + + * exceptions.h (throw_reason): Rename throw_exception. + (enum errors, struct exception): Define. + (catch_exception_ftype): Define. + (catch_exception, throw_exception): Declare. + * exceptions.c (throw_exception): Rewrite. + (throw_reason): New function. + (struct catcher, catcher_state_machine): Replace "reason" with + "exception", delete "gdberrmsg". + (catch_exception): New function. + (catcher_init): Replace "gdberrmsg" parameter with "exception". + (catch_errors, catch_exceptions_with_msg): Re-implement passing + exception to catcher_init. + * utils.c (error_silent, error_stream_1): Use throw_reason. + (internal_verror, quit): Ditto. + * breakpoint.c (insert_catchpoint, break_command_1): Ditto. + * remote-fileio.c (remote_fileio_ctrl_c_signal_handler): Ditto. + * remote.c (remote_open_1, interrupt_query): Ditto. + 2005-01-12 Mark Kettenis <kettenis@gnu.org> * i386fbsd-tdep.c: Update copyright year. Include "gdbcore.h", diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 77eae55..b05bf4e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -734,7 +734,7 @@ insert_catchpoint (struct ui_out *uo, void *args) } if (val < 0) - throw_exception (RETURN_ERROR); + throw_reason (RETURN_ERROR); return 0; } @@ -5153,7 +5153,7 @@ break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_b /* If pending breakpoint support is turned off, throw error. */ if (pending_break_support == AUTO_BOOLEAN_FALSE) - throw_exception (RETURN_ERROR); + throw_reason (RETURN_ERROR); /* If pending breakpoint support is auto query and the user selects no, then simply return the error code. */ diff --git a/gdb/exceptions.c b/gdb/exceptions.c index 3ec2128..2964f76 100644 --- a/gdb/exceptions.c +++ b/gdb/exceptions.c @@ -65,17 +65,16 @@ enum catcher_action { struct catcher { enum catcher_state state; - /* Scratch variables used when transitioning a state. */ + /* Jump buffer pointing back at the exception handler. */ SIGJMP_BUF buf; - int reason; - int val; + /* Status buffer belonging to that exception handler. */ + volatile struct exception *exception; /* Saved/current state. */ int mask; char *saved_error_pre_print; char *saved_quit_pre_print; struct ui_out *saved_uiout; struct cleanup *saved_cleanup_chain; - char **gdberrmsg; /* Back link. */ struct catcher *prev; }; @@ -86,12 +85,17 @@ static struct catcher *current_catcher; static SIGJMP_BUF * catcher_init (struct ui_out *func_uiout, char *errstring, - char **gdberrmsg, + volatile struct exception *exception, return_mask mask) { struct catcher *new_catcher = XZALLOC (struct catcher); - new_catcher->gdberrmsg = gdberrmsg; + /* Start with no exception, save it's address. */ + exception->reason = 0; + exception->error = NO_ERROR; + exception->message = NULL; + new_catcher->exception = exception; + new_catcher->mask = mask; /* Override error/quit messages during FUNC. */ @@ -194,14 +198,8 @@ catcher_state_machine (enum catcher_action action) { case CATCH_ITER: { - int reason = current_catcher->reason; - /* If caller wants a copy of the low-level error message, - make one. This is used in the case of a silent error - whereby the caller may optionally want to issue the - message. */ - if (current_catcher->gdberrmsg != NULL) - *(current_catcher->gdberrmsg) = error_last_message (); - if (current_catcher->mask & RETURN_MASK (reason)) + struct exception exception = *current_catcher->exception; + if (current_catcher->mask & RETURN_MASK (exception.reason)) { /* Exit normally if this catcher can handle this exception. The caller analyses the func return @@ -213,7 +211,7 @@ catcher_state_machine (enum catcher_action action) relay the event to the next containing catch_errors(). */ catcher_pop (); - throw_exception (reason); + throw_exception (exception); } default: internal_error (__FILE__, __LINE__, "bad state"); @@ -223,10 +221,10 @@ catcher_state_machine (enum catcher_action action) } } -/* Return for reason REASON to the nearest containing catch_errors(). */ +/* Return EXCEPTION to the nearest containing catch_errors(). */ NORETURN void -throw_exception (enum return_reason reason) +throw_exception (struct exception exception) { quit_flag = 0; immediate_quit = 0; @@ -243,22 +241,47 @@ throw_exception (enum return_reason reason) do_exec_error_cleanups (ALL_CLEANUPS); if (annotation_level > 1) - switch (reason) + switch (exception.reason) { case RETURN_QUIT: annotate_quit (); break; case RETURN_ERROR: + /* Assume that these are all errors. */ annotate_error (); break; + default: + internal_error (__FILE__, __LINE__, "Bad switch."); } /* 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. */ catcher_state_machine (CATCH_THROWING); - current_catcher->reason = reason; - SIGLONGJMP (current_catcher->buf, current_catcher->reason); + *current_catcher->exception = exception; + SIGLONGJMP (current_catcher->buf, exception.reason); +} + +NORETURN void +throw_reason (enum return_reason reason) +{ + struct exception exception; + memset (&exception, 0, sizeof exception); + + exception.reason = reason; + switch (reason) + { + case RETURN_QUIT: + break; + case RETURN_ERROR: + exception.error = GENERIC_ERROR; + exception.message = error_last_message (); + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } + + throw_exception (exception); } /* Call FUNC() with args FUNC_UIOUT and FUNC_ARGS, catching any @@ -304,6 +327,21 @@ catch_exceptions (struct ui_out *uiout, NULL, mask); } +struct exception +catch_exception (struct ui_out *uiout, + catch_exception_ftype *func, + void *func_args, + return_mask mask) +{ + volatile struct exception exception; + SIGJMP_BUF *catch; + catch = catcher_init (uiout, NULL, &exception, mask); + for (SIGSETJMP ((*catch)); + catcher_state_machine (CATCH_ITER);) + (*func) (uiout, func_args); + return exception; +} + int catch_exceptions_with_msg (struct ui_out *uiout, catch_exceptions_ftype *func, @@ -312,17 +350,22 @@ catch_exceptions_with_msg (struct ui_out *uiout, char **gdberrmsg, return_mask mask) { - int val = 0; - enum return_reason caught; - SIGJMP_BUF *catch; - catch = catcher_init (uiout, errstring, gdberrmsg, mask); - for (caught = SIGSETJMP ((*catch)); - catcher_state_machine (CATCH_ITER);) + volatile struct exception exception; + volatile int val = 0; + SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask); + for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);) val = (*func) (uiout, func_args); gdb_assert (val >= 0); - gdb_assert (caught <= 0); - if (caught < 0) - return caught; + gdb_assert (exception.reason <= 0); + if (exception.reason < 0) + { + /* If caller wants a copy of the low-level error message, make + one. This is used in the case of a silent error whereby the + caller may optionally want to issue the message. */ + if (gdberrmsg != NULL) + *gdberrmsg = exception.message; + return exception.reason; + } return val; } @@ -330,20 +373,15 @@ int catch_errors (catch_errors_ftype *func, void *func_args, char *errstring, return_mask mask) { - int val = 0; - enum return_reason caught; - SIGJMP_BUF *catch; - catch = catcher_init (uiout, errstring, NULL, mask); + volatile int val = 0; + volatile struct exception exception; + SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask); /* This illustrates how it is possible to nest the mechanism and hence catch "break". Of course this doesn't address the need to also catch "return". */ - for (caught = SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);) - for (; catcher_state_machine (CATCH_ITER_1);) - { - val = func (func_args); - break; - } - if (caught != 0) + for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);) + val = func (func_args); + if (exception.reason != 0) return 0; return val; } diff --git a/gdb/exceptions.h b/gdb/exceptions.h index 5ebde66..b5d8fd5 100644 --- a/gdb/exceptions.h +++ b/gdb/exceptions.h @@ -24,7 +24,7 @@ #ifndef EXCEPTIONS_H #define EXCEPTIONS_H -/* Reasons for calling throw_exception(). NOTE: all reason values +/* Reasons for calling throw_exceptions(). 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 @@ -44,17 +44,38 @@ enum return_reason #define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR) typedef int return_mask; -/* Throw an exception of type RETURN_REASON. Will execute a LONG JUMP - to the inner most containing exception handler established using - catch_exceptions() (or the legacy catch_errors()). +/* Describe all exceptions. */ + +enum errors { + NO_ERROR, + /* Any generic error, the corresponding text is in + exception.message. */ + GENERIC_ERROR, + /* Add more errors here. */ + NR_ERRORS +}; + +struct exception +{ + enum return_reason reason; + enum errors error; + char *message; +}; + +/* Throw an exception (as described by "struct exception"). Will + execute a LONG JUMP to the inner most containing exception handler + established using catch_exceptions() (or similar). Code normally throws an exception using error() et.al. For various reaons, GDB also contains code that throws an exception directly. For instance, the remote*.c targets contain CNTRL-C signal handlers that propogate the QUIT event up the exception chain. ``This could - be a good thing or a dangerous thing.'' -- the Existential Wombat. */ + be a good thing or a dangerous thing.'' -- the Existential + Wombat. */ + +extern NORETURN void throw_exception (struct exception exception) ATTR_NORETURN; +extern NORETURN void throw_reason (enum return_reason reason) ATTR_NORETURN; -extern NORETURN void throw_exception (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 @@ -87,11 +108,16 @@ 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); +typedef void (catch_exception_ftype) (struct ui_out *ui_out, void *args); extern int catch_exceptions_with_msg (struct ui_out *uiout, catch_exceptions_ftype *func, void *func_args, char *errstring, char **gdberrmsg, return_mask mask); +extern struct exception catch_exception (struct ui_out *uiout, + catch_exception_ftype *func, + void *func_args, + 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 diff --git a/gdb/remote-fileio.c b/gdb/remote-fileio.c index 3d35f56..d7657b3 100644 --- a/gdb/remote-fileio.c +++ b/gdb/remote-fileio.c @@ -480,7 +480,7 @@ remote_fileio_ctrl_c_signal_handler (int signo) remote_fileio_sig_set (SIG_IGN); remote_fio_ctrl_c_flag = 1; if (!remote_fio_no_longjmp) - throw_exception (RETURN_QUIT); + throw_reason (RETURN_QUIT); remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); } diff --git a/gdb/remote.c b/gdb/remote.c index 1a6f8b5..178c0a0 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -2257,7 +2257,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, pop_target (); if (async_p) wait_forever_enabled_p = 1; - throw_exception (ex); + throw_reason (ex); } if (async_p) @@ -2723,7 +2723,7 @@ interrupt_query (void) Give up (and stop debugging it)? ")) { target_mourn_inferior (); - throw_exception (RETURN_QUIT); + throw_reason (RETURN_QUIT); } target_terminal_inferior (); diff --git a/gdb/utils.c b/gdb/utils.c index 17c2e5e..a42939fd 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -674,7 +674,7 @@ error_silent (const char *string, ...) ui_file_put (tmp_stream, do_write, gdb_lasterr); va_end (args); - throw_exception (RETURN_ERROR); + throw_reason (RETURN_ERROR); } /* Output an error message including any pre-print text to gdb_stderr. */ @@ -711,7 +711,7 @@ error_stream_1 (struct ui_file *stream, enum return_reason reason) ui_file_put (stream, do_write, gdb_stderr); fprintf_filtered (gdb_stderr, "\n"); - throw_exception (reason); + throw_reason (reason); } NORETURN void @@ -866,7 +866,7 @@ NORETURN void internal_verror (const char *file, int line, const char *fmt, va_list ap) { internal_vproblem (&internal_error_problem, file, line, fmt, ap); - throw_exception (RETURN_ERROR); + throw_reason (RETURN_ERROR); } NORETURN void @@ -1007,7 +1007,7 @@ quit (void) fprintf_unfiltered (gdb_stderr, "Quit (expect signal SIGINT when the program is resumed)\n"); #endif - throw_exception (RETURN_QUIT); + throw_reason (RETURN_QUIT); } /* Control C comes here */ |