/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
This file is part of GDB.
#include "common-defs.h"
#include "common-exceptions.h"
-#include "cleanups.h"
+
+const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL };
+
+#ifndef __cplusplus
/* Possible catcher states. */
enum catcher_state {
/* Jump buffer pointing back at the exception handler. */
SIGJMP_BUF buf;
/* Status buffer belonging to the exception handler. */
- volatile struct gdb_exception *exception;
- /* Saved/current state. */
- int mask;
+ struct gdb_exception exception;
struct cleanup *saved_cleanup_chain;
/* Back link. */
struct catcher *prev;
}
SIGJMP_BUF *
-exceptions_state_mc_init (volatile struct gdb_exception *exception,
- return_mask mask)
+exceptions_state_mc_init (void)
{
struct catcher *new_catcher = XCNEW (struct catcher);
- /* Start with no exception, save it's address. */
- exception->reason = 0;
- exception->error = GDB_NO_ERROR;
- exception->message = NULL;
- new_catcher->exception = exception;
-
- new_catcher->mask = mask;
+ /* Start with no exception. */
+ new_catcher->exception = exception_none;
/* Prevent error/quit during FUNC from calling cleanups established
prior to here. */
switch (action)
{
case CATCH_ITER:
- /* No error/quit has occured. Just clean up. */
- catcher_pop ();
+ /* No error/quit has occured. */
return 0;
case CATCH_ITER_1:
current_catcher->state = CATCHER_RUNNING_1;
{
case CATCH_ITER:
/* The did a "break" from the inner while loop. */
- catcher_pop ();
return 0;
case CATCH_ITER_1:
current_catcher->state = CATCHER_RUNNING;
{
case CATCH_ITER:
{
- struct gdb_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
- values. */
- catcher_pop ();
- return 0;
- }
- /* The caller didn't request that the event be caught,
- relay the event to the next containing
- catch_errors(). */
- catcher_pop ();
- throw_exception (exception);
+ /* Exit normally if this catcher can handle this
+ exception. The caller analyses the func return
+ values. */
+ return 0;
}
default:
internal_error (__FILE__, __LINE__, _("bad state"));
}
}
+int
+exceptions_state_mc_catch (struct gdb_exception *exception,
+ int mask)
+{
+ *exception = current_catcher->exception;
+ catcher_pop ();
+
+ if (exception->reason < 0)
+ {
+ if (mask & RETURN_MASK (exception->reason))
+ {
+ /* Exit normally and let the caller handle the
+ exception. */
+ return 1;
+ }
+
+ /* The caller didn't request that the event be caught, relay the
+ event to the next exception_catch/CATCH. */
+ throw_exception (*exception);
+ }
+
+ /* No exception was thrown. */
+ return 0;
+}
+
int
exceptions_state_mc_action_iter (void)
{
return exceptions_state_mc (CATCH_ITER_1);
}
+#else /* !__cplusplus */
+
+/* How many nested TRY blocks we have. See exception_messages and
+ throw_it. */
+
+static int try_scope_depth;
+
+/* Called on entry to a TRY scope. */
+
+void *
+exception_try_scope_entry (void)
+{
+ ++try_scope_depth;
+ return (void *) save_cleanups ();
+}
+
+/* Called on exit of a TRY scope, either normal exit or exception
+ exit. */
+
+void
+exception_try_scope_exit (void *saved_state)
+{
+ restore_cleanups ((struct cleanup *) saved_state);
+ --try_scope_depth;
+}
+
+/* Called by the default catch block. IOW, we'll get here before
+ jumping out to the next outermost scope an exception if a GDB
+ exception is not caught. */
+
+void
+exception_rethrow (void)
+{
+ /* Run this scope's cleanups before re-throwing to the next
+ outermost scope. */
+ prepare_to_throw_exception ();
+ do_cleanups (all_cleanups ());
+ throw;
+}
+
+/* Copy the 'gdb_exception' portion of FROM to TO. */
+
+static void
+gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception *from)
+{
+ *to = *from;
+}
+
+#endif /* !__cplusplus */
+
/* Return EXCEPTION to the nearest containing catch_errors(). */
void
do_cleanups (all_cleanups ());
+#ifndef __cplusplus
/* 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. */
exceptions_state_mc (CATCH_THROWING);
- *current_catcher->exception = exception;
+ current_catcher->exception = exception;
SIGLONGJMP (current_catcher->buf, exception.reason);
+#else
+ if (exception.reason == RETURN_QUIT)
+ {
+ gdb_exception_RETURN_MASK_QUIT ex;
+
+ gdb_exception_sliced_copy (&ex, &exception);
+ throw ex;
+ }
+ else if (exception.reason == RETURN_ERROR)
+ {
+ gdb_exception_RETURN_MASK_ERROR ex;
+
+ gdb_exception_sliced_copy (&ex, &exception);
+ throw ex;
+ }
+ else
+ gdb_assert_not_reached ("invalid return reason");
+#endif
}
/* A stack of exception messages.
{
struct gdb_exception e;
char *new_message;
+#ifndef __cplusplus
int depth = catcher_list_size ();
+#else
+ int depth = try_scope_depth;
+#endif
gdb_assert (depth > 0);