15796c8dcSSimon Schubert /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 1986-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "exceptions.h"
225796c8dcSSimon Schubert #include "breakpoint.h"
235796c8dcSSimon Schubert #include "target.h"
245796c8dcSSimon Schubert #include "inferior.h"
255796c8dcSSimon Schubert #include "annotate.h"
265796c8dcSSimon Schubert #include "ui-out.h"
275796c8dcSSimon Schubert #include "gdb_assert.h"
285796c8dcSSimon Schubert #include "gdb_string.h"
295796c8dcSSimon Schubert #include "serial.h"
305796c8dcSSimon Schubert #include "gdbthread.h"
315796c8dcSSimon Schubert
325796c8dcSSimon Schubert const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL };
335796c8dcSSimon Schubert
345796c8dcSSimon Schubert /* Possible catcher states. */
355796c8dcSSimon Schubert enum catcher_state {
365796c8dcSSimon Schubert /* Initial state, a new catcher has just been created. */
375796c8dcSSimon Schubert CATCHER_CREATED,
385796c8dcSSimon Schubert /* The catch code is running. */
395796c8dcSSimon Schubert CATCHER_RUNNING,
405796c8dcSSimon Schubert CATCHER_RUNNING_1,
415796c8dcSSimon Schubert /* The catch code threw an exception. */
425796c8dcSSimon Schubert CATCHER_ABORTING
435796c8dcSSimon Schubert };
445796c8dcSSimon Schubert
455796c8dcSSimon Schubert /* Possible catcher actions. */
465796c8dcSSimon Schubert enum catcher_action {
475796c8dcSSimon Schubert CATCH_ITER,
485796c8dcSSimon Schubert CATCH_ITER_1,
495796c8dcSSimon Schubert CATCH_THROWING
505796c8dcSSimon Schubert };
515796c8dcSSimon Schubert
525796c8dcSSimon Schubert struct catcher
535796c8dcSSimon Schubert {
545796c8dcSSimon Schubert enum catcher_state state;
555796c8dcSSimon Schubert /* Jump buffer pointing back at the exception handler. */
565796c8dcSSimon Schubert EXCEPTIONS_SIGJMP_BUF buf;
575796c8dcSSimon Schubert /* Status buffer belonging to the exception handler. */
585796c8dcSSimon Schubert volatile struct gdb_exception *exception;
595796c8dcSSimon Schubert /* Saved/current state. */
605796c8dcSSimon Schubert int mask;
615796c8dcSSimon Schubert struct cleanup *saved_cleanup_chain;
625796c8dcSSimon Schubert /* Back link. */
635796c8dcSSimon Schubert struct catcher *prev;
645796c8dcSSimon Schubert };
655796c8dcSSimon Schubert
665796c8dcSSimon Schubert /* Where to go for throw_exception(). */
675796c8dcSSimon Schubert static struct catcher *current_catcher;
685796c8dcSSimon Schubert
69*ef5ccd6cSJohn Marino /* Return length of current_catcher list. */
70*ef5ccd6cSJohn Marino
71*ef5ccd6cSJohn Marino static int
catcher_list_size(void)72*ef5ccd6cSJohn Marino catcher_list_size (void)
73*ef5ccd6cSJohn Marino {
74*ef5ccd6cSJohn Marino int size;
75*ef5ccd6cSJohn Marino struct catcher *catcher;
76*ef5ccd6cSJohn Marino
77*ef5ccd6cSJohn Marino for (size = 0, catcher = current_catcher;
78*ef5ccd6cSJohn Marino catcher != NULL;
79*ef5ccd6cSJohn Marino catcher = catcher->prev)
80*ef5ccd6cSJohn Marino ++size;
81*ef5ccd6cSJohn Marino
82*ef5ccd6cSJohn Marino return size;
83*ef5ccd6cSJohn Marino }
84*ef5ccd6cSJohn Marino
855796c8dcSSimon Schubert EXCEPTIONS_SIGJMP_BUF *
exceptions_state_mc_init(volatile struct gdb_exception * exception,return_mask mask)86a45ae5f8SJohn Marino exceptions_state_mc_init (volatile struct gdb_exception *exception,
875796c8dcSSimon Schubert return_mask mask)
885796c8dcSSimon Schubert {
895796c8dcSSimon Schubert struct catcher *new_catcher = XZALLOC (struct catcher);
905796c8dcSSimon Schubert
915796c8dcSSimon Schubert /* Start with no exception, save it's address. */
925796c8dcSSimon Schubert exception->reason = 0;
935796c8dcSSimon Schubert exception->error = GDB_NO_ERROR;
945796c8dcSSimon Schubert exception->message = NULL;
955796c8dcSSimon Schubert new_catcher->exception = exception;
965796c8dcSSimon Schubert
975796c8dcSSimon Schubert new_catcher->mask = mask;
985796c8dcSSimon Schubert
995796c8dcSSimon Schubert /* Prevent error/quit during FUNC from calling cleanups established
1005796c8dcSSimon Schubert prior to here. */
1015796c8dcSSimon Schubert new_catcher->saved_cleanup_chain = save_cleanups ();
1025796c8dcSSimon Schubert
1035796c8dcSSimon Schubert /* Push this new catcher on the top. */
1045796c8dcSSimon Schubert new_catcher->prev = current_catcher;
1055796c8dcSSimon Schubert current_catcher = new_catcher;
1065796c8dcSSimon Schubert new_catcher->state = CATCHER_CREATED;
1075796c8dcSSimon Schubert
1085796c8dcSSimon Schubert return &new_catcher->buf;
1095796c8dcSSimon Schubert }
1105796c8dcSSimon Schubert
1115796c8dcSSimon Schubert static void
catcher_pop(void)1125796c8dcSSimon Schubert catcher_pop (void)
1135796c8dcSSimon Schubert {
1145796c8dcSSimon Schubert struct catcher *old_catcher = current_catcher;
115cf7f2e2dSJohn Marino
1165796c8dcSSimon Schubert current_catcher = old_catcher->prev;
1175796c8dcSSimon Schubert
1185796c8dcSSimon Schubert /* Restore the cleanup chain, the error/quit messages, and the uiout
1195796c8dcSSimon Schubert builder, to their original states. */
1205796c8dcSSimon Schubert
1215796c8dcSSimon Schubert restore_cleanups (old_catcher->saved_cleanup_chain);
1225796c8dcSSimon Schubert
1235796c8dcSSimon Schubert xfree (old_catcher);
1245796c8dcSSimon Schubert }
1255796c8dcSSimon Schubert
1265796c8dcSSimon Schubert /* Catcher state machine. Returns non-zero if the m/c should be run
1275796c8dcSSimon Schubert again, zero if it should abort. */
1285796c8dcSSimon Schubert
1295796c8dcSSimon Schubert static int
exceptions_state_mc(enum catcher_action action)1305796c8dcSSimon Schubert exceptions_state_mc (enum catcher_action action)
1315796c8dcSSimon Schubert {
1325796c8dcSSimon Schubert switch (current_catcher->state)
1335796c8dcSSimon Schubert {
1345796c8dcSSimon Schubert case CATCHER_CREATED:
1355796c8dcSSimon Schubert switch (action)
1365796c8dcSSimon Schubert {
1375796c8dcSSimon Schubert case CATCH_ITER:
1385796c8dcSSimon Schubert /* Allow the code to run the catcher. */
1395796c8dcSSimon Schubert current_catcher->state = CATCHER_RUNNING;
1405796c8dcSSimon Schubert return 1;
1415796c8dcSSimon Schubert default:
1425796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad state"));
1435796c8dcSSimon Schubert }
1445796c8dcSSimon Schubert case CATCHER_RUNNING:
1455796c8dcSSimon Schubert switch (action)
1465796c8dcSSimon Schubert {
1475796c8dcSSimon Schubert case CATCH_ITER:
1485796c8dcSSimon Schubert /* No error/quit has occured. Just clean up. */
1495796c8dcSSimon Schubert catcher_pop ();
1505796c8dcSSimon Schubert return 0;
1515796c8dcSSimon Schubert case CATCH_ITER_1:
1525796c8dcSSimon Schubert current_catcher->state = CATCHER_RUNNING_1;
1535796c8dcSSimon Schubert return 1;
1545796c8dcSSimon Schubert case CATCH_THROWING:
1555796c8dcSSimon Schubert current_catcher->state = CATCHER_ABORTING;
1565796c8dcSSimon Schubert /* See also throw_exception. */
1575796c8dcSSimon Schubert return 1;
1585796c8dcSSimon Schubert default:
1595796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad switch"));
1605796c8dcSSimon Schubert }
1615796c8dcSSimon Schubert case CATCHER_RUNNING_1:
1625796c8dcSSimon Schubert switch (action)
1635796c8dcSSimon Schubert {
1645796c8dcSSimon Schubert case CATCH_ITER:
1655796c8dcSSimon Schubert /* The did a "break" from the inner while loop. */
1665796c8dcSSimon Schubert catcher_pop ();
1675796c8dcSSimon Schubert return 0;
1685796c8dcSSimon Schubert case CATCH_ITER_1:
1695796c8dcSSimon Schubert current_catcher->state = CATCHER_RUNNING;
1705796c8dcSSimon Schubert return 0;
1715796c8dcSSimon Schubert case CATCH_THROWING:
1725796c8dcSSimon Schubert current_catcher->state = CATCHER_ABORTING;
1735796c8dcSSimon Schubert /* See also throw_exception. */
1745796c8dcSSimon Schubert return 1;
1755796c8dcSSimon Schubert default:
1765796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad switch"));
1775796c8dcSSimon Schubert }
1785796c8dcSSimon Schubert case CATCHER_ABORTING:
1795796c8dcSSimon Schubert switch (action)
1805796c8dcSSimon Schubert {
1815796c8dcSSimon Schubert case CATCH_ITER:
1825796c8dcSSimon Schubert {
1835796c8dcSSimon Schubert struct gdb_exception exception = *current_catcher->exception;
184cf7f2e2dSJohn Marino
1855796c8dcSSimon Schubert if (current_catcher->mask & RETURN_MASK (exception.reason))
1865796c8dcSSimon Schubert {
1875796c8dcSSimon Schubert /* Exit normally if this catcher can handle this
1885796c8dcSSimon Schubert exception. The caller analyses the func return
1895796c8dcSSimon Schubert values. */
1905796c8dcSSimon Schubert catcher_pop ();
1915796c8dcSSimon Schubert return 0;
1925796c8dcSSimon Schubert }
1935796c8dcSSimon Schubert /* The caller didn't request that the event be caught,
1945796c8dcSSimon Schubert relay the event to the next containing
1955796c8dcSSimon Schubert catch_errors(). */
1965796c8dcSSimon Schubert catcher_pop ();
1975796c8dcSSimon Schubert throw_exception (exception);
1985796c8dcSSimon Schubert }
1995796c8dcSSimon Schubert default:
2005796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad state"));
2015796c8dcSSimon Schubert }
2025796c8dcSSimon Schubert default:
2035796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad switch"));
2045796c8dcSSimon Schubert }
2055796c8dcSSimon Schubert }
2065796c8dcSSimon Schubert
2075796c8dcSSimon Schubert int
exceptions_state_mc_action_iter(void)2085796c8dcSSimon Schubert exceptions_state_mc_action_iter (void)
2095796c8dcSSimon Schubert {
2105796c8dcSSimon Schubert return exceptions_state_mc (CATCH_ITER);
2115796c8dcSSimon Schubert }
2125796c8dcSSimon Schubert
2135796c8dcSSimon Schubert int
exceptions_state_mc_action_iter_1(void)2145796c8dcSSimon Schubert exceptions_state_mc_action_iter_1 (void)
2155796c8dcSSimon Schubert {
2165796c8dcSSimon Schubert return exceptions_state_mc (CATCH_ITER_1);
2175796c8dcSSimon Schubert }
2185796c8dcSSimon Schubert
2195796c8dcSSimon Schubert /* Return EXCEPTION to the nearest containing catch_errors(). */
2205796c8dcSSimon Schubert
221cf7f2e2dSJohn Marino void
throw_exception(struct gdb_exception exception)2225796c8dcSSimon Schubert throw_exception (struct gdb_exception exception)
2235796c8dcSSimon Schubert {
224*ef5ccd6cSJohn Marino clear_quit_flag ();
2255796c8dcSSimon Schubert immediate_quit = 0;
2265796c8dcSSimon Schubert
227*ef5ccd6cSJohn Marino do_cleanups (all_cleanups ());
2285796c8dcSSimon Schubert
2295796c8dcSSimon Schubert /* Jump to the containing catch_errors() call, communicating REASON
2305796c8dcSSimon Schubert to that call via setjmp's return value. Note that REASON can't
2315796c8dcSSimon Schubert be zero, by definition in defs.h. */
2325796c8dcSSimon Schubert exceptions_state_mc (CATCH_THROWING);
2335796c8dcSSimon Schubert *current_catcher->exception = exception;
2345796c8dcSSimon Schubert EXCEPTIONS_SIGLONGJMP (current_catcher->buf, exception.reason);
2355796c8dcSSimon Schubert }
2365796c8dcSSimon Schubert
237cf7f2e2dSJohn Marino void
deprecated_throw_reason(enum return_reason reason)2385796c8dcSSimon Schubert deprecated_throw_reason (enum return_reason reason)
2395796c8dcSSimon Schubert {
2405796c8dcSSimon Schubert struct gdb_exception exception;
241cf7f2e2dSJohn Marino
2425796c8dcSSimon Schubert memset (&exception, 0, sizeof exception);
2435796c8dcSSimon Schubert
2445796c8dcSSimon Schubert exception.reason = reason;
2455796c8dcSSimon Schubert switch (reason)
2465796c8dcSSimon Schubert {
2475796c8dcSSimon Schubert case RETURN_QUIT:
2485796c8dcSSimon Schubert break;
2495796c8dcSSimon Schubert case RETURN_ERROR:
2505796c8dcSSimon Schubert exception.error = GENERIC_ERROR;
2515796c8dcSSimon Schubert break;
2525796c8dcSSimon Schubert default:
2535796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad switch"));
2545796c8dcSSimon Schubert }
2555796c8dcSSimon Schubert
2565796c8dcSSimon Schubert throw_exception (exception);
2575796c8dcSSimon Schubert }
2585796c8dcSSimon Schubert
2595796c8dcSSimon Schubert static void
print_flush(void)2605796c8dcSSimon Schubert print_flush (void)
2615796c8dcSSimon Schubert {
2625796c8dcSSimon Schubert struct serial *gdb_stdout_serial;
2635796c8dcSSimon Schubert
2645796c8dcSSimon Schubert if (deprecated_error_begin_hook)
2655796c8dcSSimon Schubert deprecated_error_begin_hook ();
2665796c8dcSSimon Schubert target_terminal_ours ();
2675796c8dcSSimon Schubert
2685796c8dcSSimon Schubert /* We want all output to appear now, before we print the error. We
2695796c8dcSSimon Schubert have 3 levels of buffering we have to flush (it's possible that
2705796c8dcSSimon Schubert some of these should be changed to flush the lower-level ones
2715796c8dcSSimon Schubert too): */
2725796c8dcSSimon Schubert
2735796c8dcSSimon Schubert /* 1. The _filtered buffer. */
2745796c8dcSSimon Schubert wrap_here ("");
2755796c8dcSSimon Schubert
2765796c8dcSSimon Schubert /* 2. The stdio buffer. */
2775796c8dcSSimon Schubert gdb_flush (gdb_stdout);
2785796c8dcSSimon Schubert gdb_flush (gdb_stderr);
2795796c8dcSSimon Schubert
2805796c8dcSSimon Schubert /* 3. The system-level buffer. */
2815796c8dcSSimon Schubert gdb_stdout_serial = serial_fdopen (1);
2825796c8dcSSimon Schubert if (gdb_stdout_serial)
2835796c8dcSSimon Schubert {
2845796c8dcSSimon Schubert serial_drain_output (gdb_stdout_serial);
2855796c8dcSSimon Schubert serial_un_fdopen (gdb_stdout_serial);
2865796c8dcSSimon Schubert }
2875796c8dcSSimon Schubert
2885796c8dcSSimon Schubert annotate_error_begin ();
2895796c8dcSSimon Schubert }
2905796c8dcSSimon Schubert
2915796c8dcSSimon Schubert static void
print_exception(struct ui_file * file,struct gdb_exception e)2925796c8dcSSimon Schubert print_exception (struct ui_file *file, struct gdb_exception e)
2935796c8dcSSimon Schubert {
2945796c8dcSSimon Schubert /* KLUGE: cagney/2005-01-13: Write the string out one line at a time
2955796c8dcSSimon Schubert as that way the MI's behavior is preserved. */
2965796c8dcSSimon Schubert const char *start;
2975796c8dcSSimon Schubert const char *end;
298cf7f2e2dSJohn Marino
2995796c8dcSSimon Schubert for (start = e.message; start != NULL; start = end)
3005796c8dcSSimon Schubert {
3015796c8dcSSimon Schubert end = strchr (start, '\n');
3025796c8dcSSimon Schubert if (end == NULL)
3035796c8dcSSimon Schubert fputs_filtered (start, file);
3045796c8dcSSimon Schubert else
3055796c8dcSSimon Schubert {
3065796c8dcSSimon Schubert end++;
3075796c8dcSSimon Schubert ui_file_write (file, start, end - start);
3085796c8dcSSimon Schubert }
3095796c8dcSSimon Schubert }
3105796c8dcSSimon Schubert fprintf_filtered (file, "\n");
3115796c8dcSSimon Schubert
3125796c8dcSSimon Schubert /* Now append the annotation. */
3135796c8dcSSimon Schubert switch (e.reason)
3145796c8dcSSimon Schubert {
3155796c8dcSSimon Schubert case RETURN_QUIT:
3165796c8dcSSimon Schubert annotate_quit ();
3175796c8dcSSimon Schubert break;
3185796c8dcSSimon Schubert case RETURN_ERROR:
3195796c8dcSSimon Schubert /* Assume that these are all errors. */
3205796c8dcSSimon Schubert annotate_error ();
3215796c8dcSSimon Schubert break;
3225796c8dcSSimon Schubert default:
3235796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("Bad switch."));
3245796c8dcSSimon Schubert }
3255796c8dcSSimon Schubert }
3265796c8dcSSimon Schubert
3275796c8dcSSimon Schubert void
exception_print(struct ui_file * file,struct gdb_exception e)3285796c8dcSSimon Schubert exception_print (struct ui_file *file, struct gdb_exception e)
3295796c8dcSSimon Schubert {
3305796c8dcSSimon Schubert if (e.reason < 0 && e.message != NULL)
3315796c8dcSSimon Schubert {
3325796c8dcSSimon Schubert print_flush ();
3335796c8dcSSimon Schubert print_exception (file, e);
3345796c8dcSSimon Schubert }
3355796c8dcSSimon Schubert }
3365796c8dcSSimon Schubert
3375796c8dcSSimon Schubert void
exception_fprintf(struct ui_file * file,struct gdb_exception e,const char * prefix,...)3385796c8dcSSimon Schubert exception_fprintf (struct ui_file *file, struct gdb_exception e,
3395796c8dcSSimon Schubert const char *prefix, ...)
3405796c8dcSSimon Schubert {
3415796c8dcSSimon Schubert if (e.reason < 0 && e.message != NULL)
3425796c8dcSSimon Schubert {
3435796c8dcSSimon Schubert va_list args;
3445796c8dcSSimon Schubert
3455796c8dcSSimon Schubert print_flush ();
3465796c8dcSSimon Schubert
3475796c8dcSSimon Schubert /* Print the prefix. */
3485796c8dcSSimon Schubert va_start (args, prefix);
3495796c8dcSSimon Schubert vfprintf_filtered (file, prefix, args);
3505796c8dcSSimon Schubert va_end (args);
3515796c8dcSSimon Schubert
3525796c8dcSSimon Schubert print_exception (file, e);
3535796c8dcSSimon Schubert }
3545796c8dcSSimon Schubert }
3555796c8dcSSimon Schubert
3565796c8dcSSimon Schubert static void
print_any_exception(struct ui_file * file,const char * prefix,struct gdb_exception e)3575796c8dcSSimon Schubert print_any_exception (struct ui_file *file, const char *prefix,
3585796c8dcSSimon Schubert struct gdb_exception e)
3595796c8dcSSimon Schubert {
3605796c8dcSSimon Schubert if (e.reason < 0 && e.message != NULL)
3615796c8dcSSimon Schubert {
3625796c8dcSSimon Schubert target_terminal_ours ();
363c50c785cSJohn Marino wrap_here (""); /* Force out any buffered output. */
3645796c8dcSSimon Schubert gdb_flush (gdb_stdout);
3655796c8dcSSimon Schubert annotate_error_begin ();
3665796c8dcSSimon Schubert
3675796c8dcSSimon Schubert /* Print the prefix. */
3685796c8dcSSimon Schubert if (prefix != NULL && prefix[0] != '\0')
3695796c8dcSSimon Schubert fputs_filtered (prefix, file);
3705796c8dcSSimon Schubert print_exception (file, e);
3715796c8dcSSimon Schubert }
3725796c8dcSSimon Schubert }
3735796c8dcSSimon Schubert
374*ef5ccd6cSJohn Marino /* A stack of exception messages.
375*ef5ccd6cSJohn Marino This is needed to handle nested calls to throw_it: we don't want to
376*ef5ccd6cSJohn Marino xfree space for a message before it's used.
377*ef5ccd6cSJohn Marino This can happen if we throw an exception during a cleanup:
378*ef5ccd6cSJohn Marino An outer TRY_CATCH may have an exception message it wants to print,
379*ef5ccd6cSJohn Marino but while doing cleanups further calls to throw_it are made.
380*ef5ccd6cSJohn Marino
381*ef5ccd6cSJohn Marino This is indexed by the size of the current_catcher list.
382*ef5ccd6cSJohn Marino It is a dynamically allocated array so that we don't care how deeply
383*ef5ccd6cSJohn Marino GDB nests its TRY_CATCHs. */
384*ef5ccd6cSJohn Marino static char **exception_messages;
385*ef5ccd6cSJohn Marino
386*ef5ccd6cSJohn Marino /* The number of currently allocated entries in exception_messages. */
387*ef5ccd6cSJohn Marino static int exception_messages_size;
388*ef5ccd6cSJohn Marino
389cf7f2e2dSJohn Marino static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
throw_it(enum return_reason reason,enum errors error,const char * fmt,va_list ap)3905796c8dcSSimon Schubert throw_it (enum return_reason reason, enum errors error, const char *fmt,
3915796c8dcSSimon Schubert va_list ap)
3925796c8dcSSimon Schubert {
3935796c8dcSSimon Schubert struct gdb_exception e;
3945796c8dcSSimon Schubert char *new_message;
395*ef5ccd6cSJohn Marino int depth = catcher_list_size ();
3965796c8dcSSimon Schubert
397*ef5ccd6cSJohn Marino gdb_assert (depth > 0);
398*ef5ccd6cSJohn Marino
399*ef5ccd6cSJohn Marino /* Note: The new message may use an old message's text. */
4005796c8dcSSimon Schubert new_message = xstrvprintf (fmt, ap);
401*ef5ccd6cSJohn Marino
402*ef5ccd6cSJohn Marino if (depth > exception_messages_size)
403*ef5ccd6cSJohn Marino {
404*ef5ccd6cSJohn Marino int old_size = exception_messages_size;
405*ef5ccd6cSJohn Marino
406*ef5ccd6cSJohn Marino exception_messages_size = depth + 10;
407*ef5ccd6cSJohn Marino exception_messages = (char **) xrealloc (exception_messages,
408*ef5ccd6cSJohn Marino exception_messages_size
409*ef5ccd6cSJohn Marino * sizeof (char *));
410*ef5ccd6cSJohn Marino memset (exception_messages + old_size, 0,
411*ef5ccd6cSJohn Marino (exception_messages_size - old_size) * sizeof (char *));
412*ef5ccd6cSJohn Marino }
413*ef5ccd6cSJohn Marino
414*ef5ccd6cSJohn Marino xfree (exception_messages[depth - 1]);
415*ef5ccd6cSJohn Marino exception_messages[depth - 1] = new_message;
4165796c8dcSSimon Schubert
4175796c8dcSSimon Schubert /* Create the exception. */
4185796c8dcSSimon Schubert e.reason = reason;
4195796c8dcSSimon Schubert e.error = error;
420*ef5ccd6cSJohn Marino e.message = new_message;
4215796c8dcSSimon Schubert
4225796c8dcSSimon Schubert /* Throw the exception. */
4235796c8dcSSimon Schubert throw_exception (e);
4245796c8dcSSimon Schubert }
4255796c8dcSSimon Schubert
426cf7f2e2dSJohn Marino void
throw_verror(enum errors error,const char * fmt,va_list ap)4275796c8dcSSimon Schubert throw_verror (enum errors error, const char *fmt, va_list ap)
4285796c8dcSSimon Schubert {
4295796c8dcSSimon Schubert throw_it (RETURN_ERROR, error, fmt, ap);
4305796c8dcSSimon Schubert }
4315796c8dcSSimon Schubert
432cf7f2e2dSJohn Marino void
throw_vfatal(const char * fmt,va_list ap)4335796c8dcSSimon Schubert throw_vfatal (const char *fmt, va_list ap)
4345796c8dcSSimon Schubert {
4355796c8dcSSimon Schubert throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
4365796c8dcSSimon Schubert }
4375796c8dcSSimon Schubert
438cf7f2e2dSJohn Marino void
throw_error(enum errors error,const char * fmt,...)4395796c8dcSSimon Schubert throw_error (enum errors error, const char *fmt, ...)
4405796c8dcSSimon Schubert {
4415796c8dcSSimon Schubert va_list args;
442cf7f2e2dSJohn Marino
4435796c8dcSSimon Schubert va_start (args, fmt);
4445796c8dcSSimon Schubert throw_it (RETURN_ERROR, error, fmt, args);
4455796c8dcSSimon Schubert va_end (args);
4465796c8dcSSimon Schubert }
4475796c8dcSSimon Schubert
4485796c8dcSSimon Schubert /* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
4495796c8dcSSimon Schubert handler. If an exception (enum return_reason) is thrown using
4505796c8dcSSimon Schubert throw_exception() than all cleanups installed since
4515796c8dcSSimon Schubert catch_exceptions() was entered are invoked, the (-ve) exception
4525796c8dcSSimon Schubert value is then returned by catch_exceptions. If FUNC() returns
4535796c8dcSSimon Schubert normally (with a positive or zero return value) then that value is
4545796c8dcSSimon Schubert returned by catch_exceptions(). It is an internal_error() for
4555796c8dcSSimon Schubert FUNC() to return a negative value.
4565796c8dcSSimon Schubert
4575796c8dcSSimon Schubert See exceptions.h for further usage details.
4585796c8dcSSimon Schubert
4595796c8dcSSimon Schubert Must not be called with immediate_quit in effect (bad things might
4605796c8dcSSimon Schubert happen, say we got a signal in the middle of a memcpy to quit_return).
4615796c8dcSSimon Schubert This is an OK restriction; with very few exceptions immediate_quit can
4625796c8dcSSimon Schubert be replaced by judicious use of QUIT. */
4635796c8dcSSimon Schubert
4645796c8dcSSimon Schubert /* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with
465a45ae5f8SJohn Marino error() et al. could maintain a set of flags that indicate the
4665796c8dcSSimon Schubert current state of each of the longjmp buffers. This would give the
4675796c8dcSSimon Schubert longjmp code the chance to detect a longjmp botch (before it gets
4685796c8dcSSimon Schubert to longjmperror()). Prior to 1999-11-05 this wasn't possible as
4695796c8dcSSimon Schubert code also randomly used a SET_TOP_LEVEL macro that directly
470c50c785cSJohn Marino initialized the longjmp buffers. */
4715796c8dcSSimon Schubert
4725796c8dcSSimon Schubert int
catch_exceptions(struct ui_out * uiout,catch_exceptions_ftype * func,void * func_args,return_mask mask)4735796c8dcSSimon Schubert catch_exceptions (struct ui_out *uiout,
4745796c8dcSSimon Schubert catch_exceptions_ftype *func,
4755796c8dcSSimon Schubert void *func_args,
4765796c8dcSSimon Schubert return_mask mask)
4775796c8dcSSimon Schubert {
4785796c8dcSSimon Schubert return catch_exceptions_with_msg (uiout, func, func_args, NULL, mask);
4795796c8dcSSimon Schubert }
4805796c8dcSSimon Schubert
4815796c8dcSSimon Schubert int
catch_exceptions_with_msg(struct ui_out * func_uiout,catch_exceptions_ftype * func,void * func_args,char ** gdberrmsg,return_mask mask)482a45ae5f8SJohn Marino catch_exceptions_with_msg (struct ui_out *func_uiout,
4835796c8dcSSimon Schubert catch_exceptions_ftype *func,
4845796c8dcSSimon Schubert void *func_args,
4855796c8dcSSimon Schubert char **gdberrmsg,
4865796c8dcSSimon Schubert return_mask mask)
4875796c8dcSSimon Schubert {
4885796c8dcSSimon Schubert volatile struct gdb_exception exception;
4895796c8dcSSimon Schubert volatile int val = 0;
490a45ae5f8SJohn Marino struct ui_out *saved_uiout;
491cf7f2e2dSJohn Marino
492a45ae5f8SJohn Marino /* Save and override the global ``struct ui_out'' builder. */
493a45ae5f8SJohn Marino saved_uiout = current_uiout;
494a45ae5f8SJohn Marino current_uiout = func_uiout;
495a45ae5f8SJohn Marino
496a45ae5f8SJohn Marino TRY_CATCH (exception, RETURN_MASK_ALL)
4975796c8dcSSimon Schubert {
498a45ae5f8SJohn Marino val = (*func) (current_uiout, func_args);
4995796c8dcSSimon Schubert }
500a45ae5f8SJohn Marino
501a45ae5f8SJohn Marino /* Restore the global builder. */
502a45ae5f8SJohn Marino current_uiout = saved_uiout;
503a45ae5f8SJohn Marino
504a45ae5f8SJohn Marino if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0)
505a45ae5f8SJohn Marino {
506a45ae5f8SJohn Marino /* The caller didn't request that the event be caught.
507a45ae5f8SJohn Marino Rethrow. */
508a45ae5f8SJohn Marino throw_exception (exception);
509a45ae5f8SJohn Marino }
510a45ae5f8SJohn Marino
5115796c8dcSSimon Schubert print_any_exception (gdb_stderr, NULL, exception);
5125796c8dcSSimon Schubert gdb_assert (val >= 0);
5135796c8dcSSimon Schubert gdb_assert (exception.reason <= 0);
5145796c8dcSSimon Schubert if (exception.reason < 0)
5155796c8dcSSimon Schubert {
5165796c8dcSSimon Schubert /* If caller wants a copy of the low-level error message, make
5175796c8dcSSimon Schubert one. This is used in the case of a silent error whereby the
5185796c8dcSSimon Schubert caller may optionally want to issue the message. */
5195796c8dcSSimon Schubert if (gdberrmsg != NULL)
5205796c8dcSSimon Schubert {
5215796c8dcSSimon Schubert if (exception.message != NULL)
5225796c8dcSSimon Schubert *gdberrmsg = xstrdup (exception.message);
5235796c8dcSSimon Schubert else
5245796c8dcSSimon Schubert *gdberrmsg = NULL;
5255796c8dcSSimon Schubert }
5265796c8dcSSimon Schubert return exception.reason;
5275796c8dcSSimon Schubert }
5285796c8dcSSimon Schubert return val;
5295796c8dcSSimon Schubert }
5305796c8dcSSimon Schubert
5315796c8dcSSimon Schubert /* This function is superseded by catch_exceptions(). */
5325796c8dcSSimon Schubert
5335796c8dcSSimon Schubert int
catch_errors(catch_errors_ftype * func,void * func_args,char * errstring,return_mask mask)5345796c8dcSSimon Schubert catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
5355796c8dcSSimon Schubert return_mask mask)
5365796c8dcSSimon Schubert {
5375796c8dcSSimon Schubert volatile int val = 0;
5385796c8dcSSimon Schubert volatile struct gdb_exception exception;
539a45ae5f8SJohn Marino struct ui_out *saved_uiout;
540cf7f2e2dSJohn Marino
541a45ae5f8SJohn Marino /* Save the global ``struct ui_out'' builder. */
542a45ae5f8SJohn Marino saved_uiout = current_uiout;
543a45ae5f8SJohn Marino
544a45ae5f8SJohn Marino TRY_CATCH (exception, RETURN_MASK_ALL)
5455796c8dcSSimon Schubert {
5465796c8dcSSimon Schubert val = func (func_args);
5475796c8dcSSimon Schubert }
548a45ae5f8SJohn Marino
549a45ae5f8SJohn Marino /* Restore the global builder. */
550a45ae5f8SJohn Marino current_uiout = saved_uiout;
551a45ae5f8SJohn Marino
552a45ae5f8SJohn Marino if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0)
553a45ae5f8SJohn Marino {
554a45ae5f8SJohn Marino /* The caller didn't request that the event be caught.
555a45ae5f8SJohn Marino Rethrow. */
556a45ae5f8SJohn Marino throw_exception (exception);
557a45ae5f8SJohn Marino }
558a45ae5f8SJohn Marino
5595796c8dcSSimon Schubert print_any_exception (gdb_stderr, errstring, exception);
5605796c8dcSSimon Schubert if (exception.reason != 0)
5615796c8dcSSimon Schubert return 0;
5625796c8dcSSimon Schubert return val;
5635796c8dcSSimon Schubert }
5645796c8dcSSimon Schubert
5655796c8dcSSimon Schubert int
catch_command_errors(catch_command_errors_ftype * command,char * arg,int from_tty,return_mask mask)5665796c8dcSSimon Schubert catch_command_errors (catch_command_errors_ftype * command,
5675796c8dcSSimon Schubert char *arg, int from_tty, return_mask mask)
5685796c8dcSSimon Schubert {
5695796c8dcSSimon Schubert volatile struct gdb_exception e;
570cf7f2e2dSJohn Marino
5715796c8dcSSimon Schubert TRY_CATCH (e, mask)
5725796c8dcSSimon Schubert {
5735796c8dcSSimon Schubert command (arg, from_tty);
5745796c8dcSSimon Schubert }
5755796c8dcSSimon Schubert print_any_exception (gdb_stderr, NULL, e);
5765796c8dcSSimon Schubert if (e.reason < 0)
5775796c8dcSSimon Schubert return 0;
5785796c8dcSSimon Schubert return 1;
5795796c8dcSSimon Schubert }
580