Add cast to exception_none
[external/binutils.git] / gdb / common / common-exceptions.c
1 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2
3    Copyright (C) 1986-2015 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "common-defs.h"
21 #include "common-exceptions.h"
22
23 const struct gdb_exception exception_none = { (enum return_reason) 0, GDB_NO_ERROR, NULL };
24
25 #ifndef __cplusplus
26
27 /* Possible catcher states.  */
28 enum catcher_state {
29   /* Initial state, a new catcher has just been created.  */
30   CATCHER_CREATED,
31   /* The catch code is running.  */
32   CATCHER_RUNNING,
33   CATCHER_RUNNING_1,
34   /* The catch code threw an exception.  */
35   CATCHER_ABORTING
36 };
37
38 /* Possible catcher actions.  */
39 enum catcher_action {
40   CATCH_ITER,
41   CATCH_ITER_1,
42   CATCH_THROWING
43 };
44
45 struct catcher
46 {
47   enum catcher_state state;
48   /* Jump buffer pointing back at the exception handler.  */
49   SIGJMP_BUF buf;
50   /* Status buffer belonging to the exception handler.  */
51   struct gdb_exception exception;
52   struct cleanup *saved_cleanup_chain;
53   /* Back link.  */
54   struct catcher *prev;
55 };
56
57 /* Where to go for throw_exception().  */
58 static struct catcher *current_catcher;
59
60 /* Return length of current_catcher list.  */
61
62 static int
63 catcher_list_size (void)
64 {
65   int size;
66   struct catcher *catcher;
67
68   for (size = 0, catcher = current_catcher;
69        catcher != NULL;
70        catcher = catcher->prev)
71     ++size;
72
73   return size;
74 }
75
76 SIGJMP_BUF *
77 exceptions_state_mc_init (void)
78 {
79   struct catcher *new_catcher = XCNEW (struct catcher);
80
81   /* Start with no exception.  */
82   new_catcher->exception = exception_none;
83
84   /* Prevent error/quit during FUNC from calling cleanups established
85      prior to here.  */
86   new_catcher->saved_cleanup_chain = save_cleanups ();
87
88   /* Push this new catcher on the top.  */
89   new_catcher->prev = current_catcher;
90   current_catcher = new_catcher;
91   new_catcher->state = CATCHER_CREATED;
92
93   return &new_catcher->buf;
94 }
95
96 static void
97 catcher_pop (void)
98 {
99   struct catcher *old_catcher = current_catcher;
100
101   current_catcher = old_catcher->prev;
102
103   /* Restore the cleanup chain, the error/quit messages, and the uiout
104      builder, to their original states.  */
105
106   restore_cleanups (old_catcher->saved_cleanup_chain);
107
108   xfree (old_catcher);
109 }
110
111 /* Catcher state machine.  Returns non-zero if the m/c should be run
112    again, zero if it should abort.  */
113
114 static int
115 exceptions_state_mc (enum catcher_action action)
116 {
117   switch (current_catcher->state)
118     {
119     case CATCHER_CREATED:
120       switch (action)
121         {
122         case CATCH_ITER:
123           /* Allow the code to run the catcher.  */
124           current_catcher->state = CATCHER_RUNNING;
125           return 1;
126         default:
127           internal_error (__FILE__, __LINE__, _("bad state"));
128         }
129     case CATCHER_RUNNING:
130       switch (action)
131         {
132         case CATCH_ITER:
133           /* No error/quit has occured.  */
134           return 0;
135         case CATCH_ITER_1:
136           current_catcher->state = CATCHER_RUNNING_1;
137           return 1;
138         case CATCH_THROWING:
139           current_catcher->state = CATCHER_ABORTING;
140           /* See also throw_exception.  */
141           return 1;
142         default:
143           internal_error (__FILE__, __LINE__, _("bad switch"));
144         }
145     case CATCHER_RUNNING_1:
146       switch (action)
147         {
148         case CATCH_ITER:
149           /* The did a "break" from the inner while loop.  */
150           return 0;
151         case CATCH_ITER_1:
152           current_catcher->state = CATCHER_RUNNING;
153           return 0;
154         case CATCH_THROWING:
155           current_catcher->state = CATCHER_ABORTING;
156           /* See also throw_exception.  */
157           return 1;
158         default:
159           internal_error (__FILE__, __LINE__, _("bad switch"));
160         }
161     case CATCHER_ABORTING:
162       switch (action)
163         {
164         case CATCH_ITER:
165           {
166             /* Exit normally if this catcher can handle this
167                exception.  The caller analyses the func return
168                values.  */
169             return 0;
170           }
171         default:
172           internal_error (__FILE__, __LINE__, _("bad state"));
173         }
174     default:
175       internal_error (__FILE__, __LINE__, _("bad switch"));
176     }
177 }
178
179 int
180 exceptions_state_mc_catch (struct gdb_exception *exception,
181                            int mask)
182 {
183   *exception = current_catcher->exception;
184   catcher_pop ();
185
186   if (exception->reason < 0)
187     {
188       if (mask & RETURN_MASK (exception->reason))
189         {
190           /* Exit normally and let the caller handle the
191              exception.  */
192           return 1;
193         }
194
195       /* The caller didn't request that the event be caught, relay the
196          event to the next exception_catch/CATCH.  */
197       throw_exception (*exception);
198     }
199
200   /* No exception was thrown.  */
201   return 0;
202 }
203
204 int
205 exceptions_state_mc_action_iter (void)
206 {
207   return exceptions_state_mc (CATCH_ITER);
208 }
209
210 int
211 exceptions_state_mc_action_iter_1 (void)
212 {
213   return exceptions_state_mc (CATCH_ITER_1);
214 }
215
216 #else /* !__cplusplus */
217
218 /* How many nested TRY blocks we have.  See exception_messages and
219    throw_it.  */
220
221 static int try_scope_depth;
222
223 /* Called on entry to a TRY scope.  */
224
225 void *
226 exception_try_scope_entry (void)
227 {
228   ++try_scope_depth;
229   return (void *) save_cleanups ();
230 }
231
232 /* Called on exit of a TRY scope, either normal exit or exception
233    exit.  */
234
235 void
236 exception_try_scope_exit (void *saved_state)
237 {
238   restore_cleanups ((struct cleanup *) saved_state);
239   --try_scope_depth;
240 }
241
242 /* Called by the default catch block.  IOW, we'll get here before
243    jumping out to the next outermost scope an exception if a GDB
244    exception is not caught.  */
245
246 void
247 exception_rethrow (void)
248 {
249   /* Run this scope's cleanups before re-throwing to the next
250      outermost scope.  */
251   prepare_to_throw_exception ();
252   do_cleanups (all_cleanups ());
253   throw;
254 }
255
256 /* Copy the 'gdb_exception' portion of FROM to TO.  */
257
258 static void
259 gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception *from)
260 {
261   *to = *from;
262 }
263
264 #endif /* !__cplusplus */
265
266 /* Return EXCEPTION to the nearest containing catch_errors().  */
267
268 void
269 throw_exception (struct gdb_exception exception)
270 {
271   prepare_to_throw_exception ();
272
273   do_cleanups (all_cleanups ());
274
275 #ifndef __cplusplus
276   /* Jump to the containing catch_errors() call, communicating REASON
277      to that call via setjmp's return value.  Note that REASON can't
278      be zero, by definition in defs.h.  */
279   exceptions_state_mc (CATCH_THROWING);
280   current_catcher->exception = exception;
281   SIGLONGJMP (current_catcher->buf, exception.reason);
282 #else
283   if (exception.reason == RETURN_QUIT)
284     {
285       gdb_exception_RETURN_MASK_QUIT ex;
286
287       gdb_exception_sliced_copy (&ex, &exception);
288       throw ex;
289     }
290   else if (exception.reason == RETURN_ERROR)
291     {
292       gdb_exception_RETURN_MASK_ERROR ex;
293
294       gdb_exception_sliced_copy (&ex, &exception);
295       throw ex;
296     }
297   else
298     gdb_assert_not_reached ("invalid return reason");
299 #endif
300 }
301
302 /* A stack of exception messages.
303    This is needed to handle nested calls to throw_it: we don't want to
304    xfree space for a message before it's used.
305    This can happen if we throw an exception during a cleanup:
306    An outer TRY_CATCH may have an exception message it wants to print,
307    but while doing cleanups further calls to throw_it are made.
308
309    This is indexed by the size of the current_catcher list.
310    It is a dynamically allocated array so that we don't care how deeply
311    GDB nests its TRY_CATCHs.  */
312 static char **exception_messages;
313
314 /* The number of currently allocated entries in exception_messages.  */
315 static int exception_messages_size;
316
317 static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
318 throw_it (enum return_reason reason, enum errors error, const char *fmt,
319           va_list ap)
320 {
321   struct gdb_exception e;
322   char *new_message;
323 #ifndef __cplusplus
324   int depth = catcher_list_size ();
325 #else
326   int depth = try_scope_depth;
327 #endif
328
329   gdb_assert (depth > 0);
330
331   /* Note: The new message may use an old message's text.  */
332   new_message = xstrvprintf (fmt, ap);
333
334   if (depth > exception_messages_size)
335     {
336       int old_size = exception_messages_size;
337
338       exception_messages_size = depth + 10;
339       exception_messages = XRESIZEVEC (char *, exception_messages,
340                                        exception_messages_size);
341       memset (exception_messages + old_size, 0,
342               (exception_messages_size - old_size) * sizeof (char *));
343     }
344
345   xfree (exception_messages[depth - 1]);
346   exception_messages[depth - 1] = new_message;
347
348   /* Create the exception.  */
349   e.reason = reason;
350   e.error = error;
351   e.message = new_message;
352
353   /* Throw the exception.  */
354   throw_exception (e);
355 }
356
357 void
358 throw_verror (enum errors error, const char *fmt, va_list ap)
359 {
360   throw_it (RETURN_ERROR, error, fmt, ap);
361 }
362
363 void
364 throw_vquit (const char *fmt, va_list ap)
365 {
366   throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
367 }
368
369 void
370 throw_error (enum errors error, const char *fmt, ...)
371 {
372   va_list args;
373
374   va_start (args, fmt);
375   throw_verror (error, fmt, args);
376   va_end (args);
377 }
378
379 void
380 throw_quit (const char *fmt, ...)
381 {
382   va_list args;
383
384   va_start (args, fmt);
385   throw_vquit (fmt, args);
386   va_end (args);
387 }