OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [exceptions.c] - Blame information for rev 861

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2
 
3
   Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
4
   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
5
   2009, 2010 Free Software Foundation, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include "defs.h"
23
#include "exceptions.h"
24
#include "breakpoint.h"
25
#include "target.h"
26
#include "inferior.h"
27
#include "annotate.h"
28
#include "ui-out.h"
29
#include "gdb_assert.h"
30
#include "gdb_string.h"
31
#include "serial.h"
32
#include "gdbthread.h"
33
 
34
const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL };
35
 
36
/* Possible catcher states.  */
37
enum catcher_state {
38
  /* Initial state, a new catcher has just been created.  */
39
  CATCHER_CREATED,
40
  /* The catch code is running.  */
41
  CATCHER_RUNNING,
42
  CATCHER_RUNNING_1,
43
  /* The catch code threw an exception.  */
44
  CATCHER_ABORTING
45
};
46
 
47
/* Possible catcher actions.  */
48
enum catcher_action {
49
  CATCH_ITER,
50
  CATCH_ITER_1,
51
  CATCH_THROWING
52
};
53
 
54
struct catcher
55
{
56
  enum catcher_state state;
57
  /* Jump buffer pointing back at the exception handler.  */
58
  EXCEPTIONS_SIGJMP_BUF buf;
59
  /* Status buffer belonging to the exception handler.  */
60
  volatile struct gdb_exception *exception;
61
  /* Saved/current state.  */
62
  int mask;
63
  struct ui_out *saved_uiout;
64
  struct cleanup *saved_cleanup_chain;
65
  /* Back link.  */
66
  struct catcher *prev;
67
};
68
 
69
/* Where to go for throw_exception().  */
70
static struct catcher *current_catcher;
71
 
72
EXCEPTIONS_SIGJMP_BUF *
73
exceptions_state_mc_init (struct ui_out *func_uiout,
74
                          volatile struct gdb_exception *exception,
75
                          return_mask mask)
76
{
77
  struct catcher *new_catcher = XZALLOC (struct catcher);
78
 
79
  /* Start with no exception, save it's address.  */
80
  exception->reason = 0;
81
  exception->error = GDB_NO_ERROR;
82
  exception->message = NULL;
83
  new_catcher->exception = exception;
84
 
85
  new_catcher->mask = mask;
86
 
87
  /* Override the global ``struct ui_out'' builder.  */
88
  new_catcher->saved_uiout = uiout;
89
  uiout = func_uiout;
90
 
91
  /* Prevent error/quit during FUNC from calling cleanups established
92
     prior to here. */
93
  new_catcher->saved_cleanup_chain = save_cleanups ();
94
 
95
  /* Push this new catcher on the top.  */
96
  new_catcher->prev = current_catcher;
97
  current_catcher = new_catcher;
98
  new_catcher->state = CATCHER_CREATED;
99
 
100
  return &new_catcher->buf;
101
}
102
 
103
static void
104
catcher_pop (void)
105
{
106
  struct catcher *old_catcher = current_catcher;
107
 
108
  current_catcher = old_catcher->prev;
109
 
110
  /* Restore the cleanup chain, the error/quit messages, and the uiout
111
     builder, to their original states. */
112
 
113
  restore_cleanups (old_catcher->saved_cleanup_chain);
114
 
115
  uiout = old_catcher->saved_uiout;
116
 
117
  xfree (old_catcher);
118
}
119
 
120
/* Catcher state machine.  Returns non-zero if the m/c should be run
121
   again, zero if it should abort.  */
122
 
123
static int
124
exceptions_state_mc (enum catcher_action action)
125
{
126
  switch (current_catcher->state)
127
    {
128
    case CATCHER_CREATED:
129
      switch (action)
130
        {
131
        case CATCH_ITER:
132
          /* Allow the code to run the catcher.  */
133
          current_catcher->state = CATCHER_RUNNING;
134
          return 1;
135
        default:
136
          internal_error (__FILE__, __LINE__, _("bad state"));
137
        }
138
    case CATCHER_RUNNING:
139
      switch (action)
140
        {
141
        case CATCH_ITER:
142
          /* No error/quit has occured.  Just clean up.  */
143
          catcher_pop ();
144
          return 0;
145
        case CATCH_ITER_1:
146
          current_catcher->state = CATCHER_RUNNING_1;
147
          return 1;
148
        case CATCH_THROWING:
149
          current_catcher->state = CATCHER_ABORTING;
150
          /* See also throw_exception.  */
151
          return 1;
152
        default:
153
          internal_error (__FILE__, __LINE__, _("bad switch"));
154
        }
155
    case CATCHER_RUNNING_1:
156
      switch (action)
157
        {
158
        case CATCH_ITER:
159
          /* The did a "break" from the inner while loop.  */
160
          catcher_pop ();
161
          return 0;
162
        case CATCH_ITER_1:
163
          current_catcher->state = CATCHER_RUNNING;
164
          return 0;
165
        case CATCH_THROWING:
166
          current_catcher->state = CATCHER_ABORTING;
167
          /* See also throw_exception.  */
168
          return 1;
169
        default:
170
          internal_error (__FILE__, __LINE__, _("bad switch"));
171
        }
172
    case CATCHER_ABORTING:
173
      switch (action)
174
        {
175
        case CATCH_ITER:
176
          {
177
            struct gdb_exception exception = *current_catcher->exception;
178
 
179
            if (current_catcher->mask & RETURN_MASK (exception.reason))
180
              {
181
                /* Exit normally if this catcher can handle this
182
                   exception.  The caller analyses the func return
183
                   values.  */
184
                catcher_pop ();
185
                return 0;
186
              }
187
            /* The caller didn't request that the event be caught,
188
               relay the event to the next containing
189
               catch_errors(). */
190
            catcher_pop ();
191
            throw_exception (exception);
192
          }
193
        default:
194
          internal_error (__FILE__, __LINE__, _("bad state"));
195
        }
196
    default:
197
      internal_error (__FILE__, __LINE__, _("bad switch"));
198
    }
199
}
200
 
201
int
202
exceptions_state_mc_action_iter (void)
203
{
204
  return exceptions_state_mc (CATCH_ITER);
205
}
206
 
207
int
208
exceptions_state_mc_action_iter_1 (void)
209
{
210
  return exceptions_state_mc (CATCH_ITER_1);
211
}
212
 
213
/* Return EXCEPTION to the nearest containing catch_errors().  */
214
 
215
void
216
throw_exception (struct gdb_exception exception)
217
{
218
  struct thread_info *tp = NULL;
219
 
220
  quit_flag = 0;
221
  immediate_quit = 0;
222
 
223
  if (!ptid_equal (inferior_ptid, null_ptid))
224
    tp = find_thread_ptid (inferior_ptid);
225
 
226
  /* Perhaps it would be cleaner to do this via the cleanup chain (not sure
227
     I can think of a reason why that is vital, though).  */
228
  if (tp != NULL)
229
    bpstat_clear_actions (tp->stop_bpstat);     /* Clear queued breakpoint commands */
230
 
231
  disable_current_display ();
232
  do_cleanups (ALL_CLEANUPS);
233
 
234
  /* Jump to the containing catch_errors() call, communicating REASON
235
     to that call via setjmp's return value.  Note that REASON can't
236
     be zero, by definition in defs.h. */
237
  exceptions_state_mc (CATCH_THROWING);
238
  *current_catcher->exception = exception;
239
  EXCEPTIONS_SIGLONGJMP (current_catcher->buf, exception.reason);
240
}
241
 
242
static char *last_message;
243
 
244
void
245
deprecated_throw_reason (enum return_reason reason)
246
{
247
  struct gdb_exception exception;
248
 
249
  memset (&exception, 0, sizeof exception);
250
 
251
  exception.reason = reason;
252
  switch (reason)
253
    {
254
    case RETURN_QUIT:
255
      break;
256
    case RETURN_ERROR:
257
      exception.error = GENERIC_ERROR;
258
      break;
259
    default:
260
      internal_error (__FILE__, __LINE__, _("bad switch"));
261
    }
262
 
263
  throw_exception (exception);
264
}
265
 
266
static void
267
print_flush (void)
268
{
269
  struct serial *gdb_stdout_serial;
270
 
271
  if (deprecated_error_begin_hook)
272
    deprecated_error_begin_hook ();
273
  target_terminal_ours ();
274
 
275
  /* We want all output to appear now, before we print the error.  We
276
     have 3 levels of buffering we have to flush (it's possible that
277
     some of these should be changed to flush the lower-level ones
278
     too):  */
279
 
280
  /* 1.  The _filtered buffer.  */
281
  wrap_here ("");
282
 
283
  /* 2.  The stdio buffer.  */
284
  gdb_flush (gdb_stdout);
285
  gdb_flush (gdb_stderr);
286
 
287
  /* 3.  The system-level buffer.  */
288
  gdb_stdout_serial = serial_fdopen (1);
289
  if (gdb_stdout_serial)
290
    {
291
      serial_drain_output (gdb_stdout_serial);
292
      serial_un_fdopen (gdb_stdout_serial);
293
    }
294
 
295
  annotate_error_begin ();
296
}
297
 
298
static void
299
print_exception (struct ui_file *file, struct gdb_exception e)
300
{
301
  /* KLUGE: cagney/2005-01-13: Write the string out one line at a time
302
     as that way the MI's behavior is preserved.  */
303
  const char *start;
304
  const char *end;
305
 
306
  for (start = e.message; start != NULL; start = end)
307
    {
308
      end = strchr (start, '\n');
309
      if (end == NULL)
310
        fputs_filtered (start, file);
311
      else
312
        {
313
          end++;
314
          ui_file_write (file, start, end - start);
315
        }
316
    }
317
  fprintf_filtered (file, "\n");
318
 
319
  /* Now append the annotation.  */
320
  switch (e.reason)
321
    {
322
    case RETURN_QUIT:
323
      annotate_quit ();
324
      break;
325
    case RETURN_ERROR:
326
      /* Assume that these are all errors.  */
327
      annotate_error ();
328
      break;
329
    default:
330
      internal_error (__FILE__, __LINE__, _("Bad switch."));
331
    }
332
}
333
 
334
void
335
exception_print (struct ui_file *file, struct gdb_exception e)
336
{
337
  if (e.reason < 0 && e.message != NULL)
338
    {
339
      print_flush ();
340
      print_exception (file, e);
341
    }
342
}
343
 
344
void
345
exception_fprintf (struct ui_file *file, struct gdb_exception e,
346
                   const char *prefix, ...)
347
{
348
  if (e.reason < 0 && e.message != NULL)
349
    {
350
      va_list args;
351
 
352
      print_flush ();
353
 
354
      /* Print the prefix.  */
355
      va_start (args, prefix);
356
      vfprintf_filtered (file, prefix, args);
357
      va_end (args);
358
 
359
      print_exception (file, e);
360
    }
361
}
362
 
363
static void
364
print_any_exception (struct ui_file *file, const char *prefix,
365
                     struct gdb_exception e)
366
{
367
  if (e.reason < 0 && e.message != NULL)
368
    {
369
      target_terminal_ours ();
370
      wrap_here ("");           /* Force out any buffered output */
371
      gdb_flush (gdb_stdout);
372
      annotate_error_begin ();
373
 
374
      /* Print the prefix.  */
375
      if (prefix != NULL && prefix[0] != '\0')
376
        fputs_filtered (prefix, file);
377
      print_exception (file, e);
378
    }
379
}
380
 
381
static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
382
throw_it (enum return_reason reason, enum errors error, const char *fmt,
383
          va_list ap)
384
{
385
  struct gdb_exception e;
386
  char *new_message;
387
 
388
  /* Save the message.  Create the new message before deleting the
389
     old, the new message may include the old message text.  */
390
  new_message = xstrvprintf (fmt, ap);
391
  xfree (last_message);
392
  last_message = new_message;
393
 
394
  /* Create the exception.  */
395
  e.reason = reason;
396
  e.error = error;
397
  e.message = last_message;
398
 
399
  /* Throw the exception.  */
400
  throw_exception (e);
401
}
402
 
403
void
404
throw_verror (enum errors error, const char *fmt, va_list ap)
405
{
406
  throw_it (RETURN_ERROR, error, fmt, ap);
407
}
408
 
409
void
410
throw_vfatal (const char *fmt, va_list ap)
411
{
412
  throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
413
}
414
 
415
void
416
throw_error (enum errors error, const char *fmt, ...)
417
{
418
  va_list args;
419
 
420
  va_start (args, fmt);
421
  throw_it (RETURN_ERROR, error, fmt, args);
422
  va_end (args);
423
}
424
 
425
/* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
426
   handler.  If an exception (enum return_reason) is thrown using
427
   throw_exception() than all cleanups installed since
428
   catch_exceptions() was entered are invoked, the (-ve) exception
429
   value is then returned by catch_exceptions.  If FUNC() returns
430
   normally (with a positive or zero return value) then that value is
431
   returned by catch_exceptions().  It is an internal_error() for
432
   FUNC() to return a negative value.
433
 
434
   See exceptions.h for further usage details.
435
 
436
   Must not be called with immediate_quit in effect (bad things might
437
   happen, say we got a signal in the middle of a memcpy to quit_return).
438
   This is an OK restriction; with very few exceptions immediate_quit can
439
   be replaced by judicious use of QUIT.  */
440
 
441
/* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with
442
   error() et.al. could maintain a set of flags that indicate the the
443
   current state of each of the longjmp buffers.  This would give the
444
   longjmp code the chance to detect a longjmp botch (before it gets
445
   to longjmperror()).  Prior to 1999-11-05 this wasn't possible as
446
   code also randomly used a SET_TOP_LEVEL macro that directly
447
   initialize the longjmp buffers. */
448
 
449
int
450
catch_exceptions (struct ui_out *uiout,
451
                  catch_exceptions_ftype *func,
452
                  void *func_args,
453
                  return_mask mask)
454
{
455
  return catch_exceptions_with_msg (uiout, func, func_args, NULL, mask);
456
}
457
 
458
struct gdb_exception
459
catch_exception (struct ui_out *uiout,
460
                 catch_exception_ftype *func,
461
                 void *func_args,
462
                 return_mask mask)
463
{
464
  volatile struct gdb_exception exception;
465
 
466
  TRY_CATCH (exception, mask)
467
    {
468
      (*func) (uiout, func_args);
469
    }
470
  return exception;
471
}
472
 
473
int
474
catch_exceptions_with_msg (struct ui_out *uiout,
475
                           catch_exceptions_ftype *func,
476
                           void *func_args,
477
                           char **gdberrmsg,
478
                           return_mask mask)
479
{
480
  volatile struct gdb_exception exception;
481
  volatile int val = 0;
482
 
483
  TRY_CATCH (exception, mask)
484
    {
485
      val = (*func) (uiout, func_args);
486
    }
487
  print_any_exception (gdb_stderr, NULL, exception);
488
  gdb_assert (val >= 0);
489
  gdb_assert (exception.reason <= 0);
490
  if (exception.reason < 0)
491
    {
492
      /* If caller wants a copy of the low-level error message, make
493
         one.  This is used in the case of a silent error whereby the
494
         caller may optionally want to issue the message.  */
495
      if (gdberrmsg != NULL)
496
        {
497
          if (exception.message != NULL)
498
            *gdberrmsg = xstrdup (exception.message);
499
          else
500
            *gdberrmsg = NULL;
501
        }
502
      return exception.reason;
503
    }
504
  return val;
505
}
506
 
507
/* This function is superseded by catch_exceptions().  */
508
 
509
int
510
catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
511
              return_mask mask)
512
{
513
  volatile int val = 0;
514
  volatile struct gdb_exception exception;
515
 
516
  TRY_CATCH (exception, mask)
517
    {
518
      val = func (func_args);
519
    }
520
  print_any_exception (gdb_stderr, errstring, exception);
521
  if (exception.reason != 0)
522
    return 0;
523
  return val;
524
}
525
 
526
int
527
catch_command_errors (catch_command_errors_ftype * command,
528
                      char *arg, int from_tty, return_mask mask)
529
{
530
  volatile struct gdb_exception e;
531
 
532
  TRY_CATCH (e, mask)
533
    {
534
      command (arg, from_tty);
535
    }
536
  print_any_exception (gdb_stderr, NULL, e);
537
  if (e.reason < 0)
538
    return 0;
539
  return 1;
540
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.