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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [exceptions.c] - Blame information for rev 157

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

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

powered by: WebSVN 2.1.0

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