xref: /dragonfly/contrib/gdb-7/gdb/exceptions.c (revision ef5ccd6c)
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