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.
This commit is contained in:
Andrew Cagney 2005-01-13 00:12:50 +00:00
parent cd0960cf4e
commit 2a78bfb53c
7 changed files with 139 additions and 55 deletions

View File

@ -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> 2005-01-12 Mark Kettenis <kettenis@gnu.org>
* i386fbsd-tdep.c: Update copyright year. Include "gdbcore.h", * i386fbsd-tdep.c: Update copyright year. Include "gdbcore.h",

View File

@ -734,7 +734,7 @@ insert_catchpoint (struct ui_out *uo, void *args)
} }
if (val < 0) if (val < 0)
throw_exception (RETURN_ERROR); throw_reason (RETURN_ERROR);
return 0; 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 breakpoint support is turned off, throw error. */
if (pending_break_support == AUTO_BOOLEAN_FALSE) 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 /* If pending breakpoint support is auto query and the user selects
no, then simply return the error code. */ no, then simply return the error code. */

View File

@ -65,17 +65,16 @@ enum catcher_action {
struct catcher struct catcher
{ {
enum catcher_state state; enum catcher_state state;
/* Scratch variables used when transitioning a state. */ /* Jump buffer pointing back at the exception handler. */
SIGJMP_BUF buf; SIGJMP_BUF buf;
int reason; /* Status buffer belonging to that exception handler. */
int val; volatile struct exception *exception;
/* Saved/current state. */ /* Saved/current state. */
int mask; int mask;
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; struct ui_out *saved_uiout;
struct cleanup *saved_cleanup_chain; struct cleanup *saved_cleanup_chain;
char **gdberrmsg;
/* Back link. */ /* Back link. */
struct catcher *prev; struct catcher *prev;
}; };
@ -86,12 +85,17 @@ static struct catcher *current_catcher;
static SIGJMP_BUF * static SIGJMP_BUF *
catcher_init (struct ui_out *func_uiout, catcher_init (struct ui_out *func_uiout,
char *errstring, char *errstring,
char **gdberrmsg, volatile struct exception *exception,
return_mask mask) return_mask mask)
{ {
struct catcher *new_catcher = XZALLOC (struct catcher); 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; new_catcher->mask = mask;
/* Override error/quit messages during FUNC. */ /* Override error/quit messages during FUNC. */
@ -194,14 +198,8 @@ catcher_state_machine (enum catcher_action action)
{ {
case CATCH_ITER: case CATCH_ITER:
{ {
int reason = current_catcher->reason; struct exception exception = *current_catcher->exception;
/* If caller wants a copy of the low-level error message, if (current_catcher->mask & RETURN_MASK (exception.reason))
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))
{ {
/* Exit normally if this catcher can handle this /* Exit normally if this catcher can handle this
exception. The caller analyses the func return 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 relay the event to the next containing
catch_errors(). */ catch_errors(). */
catcher_pop (); catcher_pop ();
throw_exception (reason); throw_exception (exception);
} }
default: default:
internal_error (__FILE__, __LINE__, "bad state"); 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 NORETURN void
throw_exception (enum return_reason reason) throw_exception (struct exception exception)
{ {
quit_flag = 0; quit_flag = 0;
immediate_quit = 0; immediate_quit = 0;
@ -243,22 +241,47 @@ throw_exception (enum return_reason reason)
do_exec_error_cleanups (ALL_CLEANUPS); do_exec_error_cleanups (ALL_CLEANUPS);
if (annotation_level > 1) if (annotation_level > 1)
switch (reason) switch (exception.reason)
{ {
case RETURN_QUIT: case RETURN_QUIT:
annotate_quit (); annotate_quit ();
break; break;
case RETURN_ERROR: case RETURN_ERROR:
/* Assume that these are all errors. */
annotate_error (); annotate_error ();
break; break;
default:
internal_error (__FILE__, __LINE__, "Bad switch.");
} }
/* Jump to the containing catch_errors() call, communicating REASON /* Jump to the containing catch_errors() call, communicating REASON
to that call via setjmp's return value. Note that REASON can't to that call via setjmp's return value. Note that REASON can't
be zero, by definition in defs.h. */ be zero, by definition in defs.h. */
catcher_state_machine (CATCH_THROWING); catcher_state_machine (CATCH_THROWING);
current_catcher->reason = reason; *current_catcher->exception = exception;
SIGLONGJMP (current_catcher->buf, current_catcher->reason); 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 /* Call FUNC() with args FUNC_UIOUT and FUNC_ARGS, catching any
@ -304,6 +327,21 @@ catch_exceptions (struct ui_out *uiout,
NULL, mask); 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 int
catch_exceptions_with_msg (struct ui_out *uiout, catch_exceptions_with_msg (struct ui_out *uiout,
catch_exceptions_ftype *func, catch_exceptions_ftype *func,
@ -312,17 +350,22 @@ catch_exceptions_with_msg (struct ui_out *uiout,
char **gdberrmsg, char **gdberrmsg,
return_mask mask) return_mask mask)
{ {
int val = 0; volatile struct exception exception;
enum return_reason caught; volatile int val = 0;
SIGJMP_BUF *catch; SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask);
catch = catcher_init (uiout, errstring, gdberrmsg, mask); for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);)
for (caught = SIGSETJMP ((*catch));
catcher_state_machine (CATCH_ITER);)
val = (*func) (uiout, func_args); val = (*func) (uiout, func_args);
gdb_assert (val >= 0); gdb_assert (val >= 0);
gdb_assert (caught <= 0); gdb_assert (exception.reason <= 0);
if (caught < 0) if (exception.reason < 0)
return caught; {
/* 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; return val;
} }
@ -330,20 +373,15 @@ int
catch_errors (catch_errors_ftype *func, void *func_args, char *errstring, catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
return_mask mask) return_mask mask)
{ {
int val = 0; volatile int val = 0;
enum return_reason caught; volatile struct exception exception;
SIGJMP_BUF *catch; SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask);
catch = catcher_init (uiout, errstring, NULL, mask);
/* This illustrates how it is possible to nest the mechanism and /* This illustrates how it is possible to nest the mechanism and
hence catch "break". Of course this doesn't address the need to hence catch "break". Of course this doesn't address the need to
also catch "return". */ also catch "return". */
for (caught = SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);) for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);)
for (; catcher_state_machine (CATCH_ITER_1);) val = func (func_args);
{ if (exception.reason != 0)
val = func (func_args);
break;
}
if (caught != 0)
return 0; return 0;
return val; return val;
} }

View File

@ -24,7 +24,7 @@
#ifndef EXCEPTIONS_H #ifndef EXCEPTIONS_H
#define 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 must be less than zero. enum value 0 is reserved for internal use
as the return value from an initial setjmp(). The function as the return value from an initial setjmp(). The function
catch_exceptions() reserves values >= 0 as legal results from its 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) #define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
typedef int return_mask; typedef int return_mask;
/* Throw an exception of type RETURN_REASON. Will execute a LONG JUMP /* Describe all exceptions. */
to the inner most containing exception handler established using
catch_exceptions() (or the legacy catch_errors()). 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 Code normally throws an exception using error() et.al. For various
reaons, GDB also contains code that throws an exception directly. reaons, GDB also contains code that throws an exception directly.
For instance, the remote*.c targets contain CNTRL-C signal handlers For instance, the remote*.c targets contain CNTRL-C signal handlers
that propogate the QUIT event up the exception chain. ``This could 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 /* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
handler. If an exception (enum return_reason) is thrown using 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, extern int catch_exceptions (struct ui_out *uiout,
catch_exceptions_ftype *func, void *func_args, catch_exceptions_ftype *func, void *func_args,
char *errstring, return_mask mask); 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, extern int catch_exceptions_with_msg (struct ui_out *uiout,
catch_exceptions_ftype *func, catch_exceptions_ftype *func,
void *func_args, void *func_args,
char *errstring, char **gdberrmsg, char *errstring, char **gdberrmsg,
return_mask mask); 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 /* 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

View File

@ -480,7 +480,7 @@ remote_fileio_ctrl_c_signal_handler (int signo)
remote_fileio_sig_set (SIG_IGN); remote_fileio_sig_set (SIG_IGN);
remote_fio_ctrl_c_flag = 1; remote_fio_ctrl_c_flag = 1;
if (!remote_fio_no_longjmp) if (!remote_fio_no_longjmp)
throw_exception (RETURN_QUIT); throw_reason (RETURN_QUIT);
remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
} }

View File

@ -2257,7 +2257,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
pop_target (); pop_target ();
if (async_p) if (async_p)
wait_forever_enabled_p = 1; wait_forever_enabled_p = 1;
throw_exception (ex); throw_reason (ex);
} }
if (async_p) if (async_p)
@ -2723,7 +2723,7 @@ interrupt_query (void)
Give up (and stop debugging it)? ")) Give up (and stop debugging it)? "))
{ {
target_mourn_inferior (); target_mourn_inferior ();
throw_exception (RETURN_QUIT); throw_reason (RETURN_QUIT);
} }
target_terminal_inferior (); target_terminal_inferior ();

View File

@ -674,7 +674,7 @@ error_silent (const char *string, ...)
ui_file_put (tmp_stream, do_write, gdb_lasterr); ui_file_put (tmp_stream, do_write, gdb_lasterr);
va_end (args); va_end (args);
throw_exception (RETURN_ERROR); throw_reason (RETURN_ERROR);
} }
/* Output an error message including any pre-print text to gdb_stderr. */ /* 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); ui_file_put (stream, do_write, gdb_stderr);
fprintf_filtered (gdb_stderr, "\n"); fprintf_filtered (gdb_stderr, "\n");
throw_exception (reason); throw_reason (reason);
} }
NORETURN void NORETURN void
@ -866,7 +866,7 @@ NORETURN void
internal_verror (const char *file, int line, const char *fmt, va_list ap) internal_verror (const char *file, int line, const char *fmt, va_list ap)
{ {
internal_vproblem (&internal_error_problem, file, line, fmt, ap); internal_vproblem (&internal_error_problem, file, line, fmt, ap);
throw_exception (RETURN_ERROR); throw_reason (RETURN_ERROR);
} }
NORETURN void NORETURN void
@ -1007,7 +1007,7 @@ quit (void)
fprintf_unfiltered (gdb_stderr, fprintf_unfiltered (gdb_stderr,
"Quit (expect signal SIGINT when the program is resumed)\n"); "Quit (expect signal SIGINT when the program is resumed)\n");
#endif #endif
throw_exception (RETURN_QUIT); throw_reason (RETURN_QUIT);
} }
/* Control C comes here */ /* Control C comes here */