Coverage Report

Created: 2023-09-25 06:17

/src/mruby/src/error.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** error.c - Exception class
3
**
4
** See Copyright Notice in mruby.h
5
*/
6
7
#include <errno.h>
8
#include <stdlib.h>
9
#include <mruby.h>
10
#include <mruby/array.h>
11
#include <mruby/irep.h>
12
#include <mruby/proc.h>
13
#include <mruby/string.h>
14
#include <mruby/variable.h>
15
#include <mruby/error.h>
16
#include <mruby/class.h>
17
#include <mruby/throw.h>
18
#include <mruby/internal.h>
19
#include <mruby/presym.h>
20
21
void
22
mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg)
23
1.17k
{
24
1.17k
  if (!mrb_string_p(mesg)) {
25
0
    mesg = mrb_obj_as_string(mrb, mesg);
26
0
  }
27
1.17k
  exc->mesg = mrb_obj_ptr(mesg);
28
1.17k
  mrb_field_write_barrier_value(mrb, (struct RBasic*)exc, mesg);
29
1.17k
}
30
31
mrb_value
32
mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc)
33
0
{
34
0
  if (exc->mesg == NULL) return mrb_nil_value();
35
0
  return mrb_obj_value(exc->mesg);
36
0
}
37
38
MRB_API mrb_value
39
mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str)
40
1.16k
{
41
1.16k
  mrb_ensure_string_type(mrb, str);
42
43
1.16k
  struct RException *e = MRB_OBJ_ALLOC(mrb, MRB_TT_EXCEPTION, c);
44
1.16k
  mrb_value exc = mrb_obj_value(e);
45
1.16k
  mrb_exc_mesg_set(mrb, e, str);
46
1.16k
  return exc;
47
1.16k
}
48
49
MRB_API mrb_value
50
mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, mrb_int len)
51
0
{
52
0
  return mrb_exc_new_str(mrb, c, mrb_str_new(mrb, ptr, len));
53
0
}
54
55
/*
56
 * call-seq:
57
 *    Exception.new(msg = nil)   ->  exception
58
 *
59
 *  Construct a new Exception object, optionally passing in
60
 *  a message.
61
 */
62
63
static mrb_value
64
exc_initialize(mrb_state *mrb, mrb_value exc)
65
16
{
66
16
  mrb_value mesg;
67
68
16
  if (mrb_get_args(mrb, "|o", &mesg) == 1) {
69
16
    mrb_exc_mesg_set(mrb, mrb_exc_ptr(exc), mesg);
70
16
  }
71
16
  return exc;
72
16
}
73
74
/*
75
 *  Document-method: exception
76
 *
77
 *  call-seq:
78
 *     exc.exception(string)  ->  an_exception or exc
79
 *
80
 *  With no argument, or if the argument is the same as the receiver,
81
 *  return the receiver. Otherwise, create a new
82
 *  exception object of the same class as the receiver, but with a
83
 *  message equal to <code>string</code>.
84
 *
85
 */
86
87
static mrb_value
88
exc_exception(mrb_state *mrb, mrb_value self)
89
0
{
90
0
  mrb_value exc;
91
0
  mrb_value a;
92
0
  mrb_int argc;
93
94
0
  argc = mrb_get_args(mrb, "|o", &a);
95
0
  if (argc == 0) return self;
96
0
  if (mrb_obj_equal(mrb, self, a)) return self;
97
0
  exc = mrb_obj_clone(mrb, self);
98
0
  mrb_exc_mesg_set(mrb, mrb_exc_ptr(exc), a);
99
100
0
  return exc;
101
0
}
102
103
/*
104
 * call-seq:
105
 *   exception.to_s   ->  string
106
 *
107
 * Returns exception's message (or the name of the exception if
108
 * no message is set).
109
 */
110
111
static mrb_value
112
exc_to_s(mrb_state *mrb, mrb_value exc)
113
0
{
114
0
  mrb_value mesg = mrb_exc_mesg_get(mrb, mrb_exc_ptr(exc));
115
0
  struct RObject *p;
116
117
0
  if (!mrb_string_p(mesg)) {
118
0
    return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
119
0
  }
120
0
  p = mrb_obj_ptr(mesg);
121
0
  if (!p->c) {
122
0
    p->c = mrb->string_class;
123
0
  }
124
0
  return mesg;
125
0
}
126
127
/*
128
 * call-seq:
129
 *   exception.inspect   -> string
130
 *
131
 * Returns this exception's file name, line number,
132
 * message and class name.
133
 * If file name or line number is not set,
134
 * returns message and class name.
135
 */
136
137
mrb_value
138
mrb_exc_inspect(mrb_state *mrb, mrb_value exc)
139
0
{
140
0
  mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc)));
141
0
  mrb_value mesg = mrb_exc_mesg_get(mrb, mrb_exc_ptr(exc)); /* string or nil */
142
0
  return (mrb_nil_p(mesg)||RSTRING_LEN(mesg)==0) ? cname : mrb_format(mrb, "%v (%v)", mesg, cname);
143
0
}
144
145
void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc);
146
147
static void
148
set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
149
0
{
150
0
  if (!mrb_array_p(backtrace)) {
151
0
  type_err:
152
0
    mrb_raise(mrb, E_TYPE_ERROR, "backtrace must be Array of String");
153
0
  }
154
0
  else {
155
0
    const mrb_value *p = RARRAY_PTR(backtrace);
156
0
    const mrb_value *pend = p + RARRAY_LEN(backtrace);
157
158
0
    while (p < pend) {
159
0
      if (!mrb_string_p(*p)) goto type_err;
160
0
      p++;
161
0
    }
162
0
  }
163
0
  mrb_exc_ptr(exc)->backtrace = mrb_obj_ptr(backtrace);
164
0
  mrb_field_write_barrier_value(mrb, mrb_basic_ptr(exc), backtrace);
165
0
}
166
167
static mrb_value
168
exc_set_backtrace(mrb_state *mrb, mrb_value exc)
169
0
{
170
0
  mrb_value backtrace = mrb_get_arg1(mrb);
171
172
0
  set_backtrace(mrb, exc, backtrace);
173
0
  return backtrace;
174
0
}
175
176
void
177
mrb_exc_set(mrb_state *mrb, mrb_value exc)
178
148
{
179
148
  if (mrb_nil_p(exc)) {
180
0
    mrb->exc = 0;
181
0
  }
182
148
  else {
183
148
    mrb->exc = mrb_obj_ptr(exc);
184
148
    if (mrb->gc.arena_idx > 0 &&
185
148
        (struct RBasic*)mrb->exc == mrb->gc.arena[mrb->gc.arena_idx-1]) {
186
145
      mrb->gc.arena_idx--;
187
145
    }
188
148
    if (!mrb->gc.out_of_memory && !mrb_frozen_p(mrb->exc)) {
189
145
      mrb_keep_backtrace(mrb, exc);
190
145
    }
191
148
  }
192
148
}
193
194
static mrb_noreturn void
195
exc_throw(mrb_state *mrb, mrb_value exc)
196
137
{
197
137
  if (!mrb->jmp) {
198
0
    mrb_print_error(mrb);
199
0
    abort();
200
0
  }
201
137
  MRB_THROW(mrb->jmp);
202
0
}
203
204
MRB_API mrb_noreturn void
205
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
206
137
{
207
137
  if (mrb_break_p(exc)) {
208
0
    mrb->exc = mrb_obj_ptr(exc);
209
0
  }
210
137
  else {
211
137
    if (mrb_type(exc) != MRB_TT_EXCEPTION) {
212
0
      mrb_raise(mrb, E_TYPE_ERROR, "exception object expected");
213
0
    }
214
137
    mrb_exc_set(mrb, exc);
215
137
  }
216
137
  exc_throw(mrb, exc);
217
137
}
218
219
MRB_API mrb_noreturn void
220
mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg)
221
27
{
222
27
  mrb_exc_raise(mrb, mrb_exc_new_str(mrb, c, mrb_str_new_cstr(mrb, msg)));
223
27
}
224
225
/*
226
 * <code>vsprintf</code> like formatting.
227
 *
228
 * The syntax of a format sequence is as follows.
229
 *
230
 *   %[modifier]specifier
231
 *
232
 * The modifiers are:
233
 *
234
 *   ----------+------------------------------------------------------------
235
 *   Modifier  | Meaning
236
 *   ----------+------------------------------------------------------------
237
 *       !     | Convert to string by corresponding `inspect` instead of
238
 *             | corresponding `to_s`.
239
 *   ----------+------------------------------------------------------------
240
 *
241
 * The specifiers are:
242
 *
243
 *   ----------+----------------+--------------------------------------------
244
 *   Specifier | Argument Type  | Note
245
 *   ----------+----------------+--------------------------------------------
246
 *       c     | char           |
247
 *       d     | int            |
248
 *       f     | mrb_float      |
249
 *       i     | mrb_int        |
250
 *       l     | char*, size_t  | Arguments are string and length.
251
 *       n     | mrb_sym        |
252
 *       s     | char*          | Argument is NUL terminated string.
253
 *       t     | mrb_value      | Convert to type (class) of object.
254
 *      v,S    | mrb_value      |
255
 *       C     | struct RClass* |
256
 *       T     | mrb_value      | Convert to real type (class) of object.
257
 *       Y     | mrb_value      | Same as `!v` if argument is `true`, `false`
258
 *             |                | or `nil`, otherwise same as `T`.
259
 *       %     | -              | Convert to percent sign itself (no argument
260
 *             |                | taken).
261
 *   ----------+----------------+--------------------------------------------
262
 */
263
MRB_API mrb_value
264
mrb_vformat(mrb_state *mrb, const char *format, va_list ap)
265
102
{
266
102
  const char *chars, *p = format, *b = format, *e;
267
102
  char ch;
268
102
  size_t len;
269
102
  mrb_int i;
270
102
  struct RClass *cls;
271
102
  mrb_bool inspect = FALSE;
272
102
  mrb_value result = mrb_str_new_capa(mrb, 128), obj, str;
273
102
  int ai = mrb_gc_arena_save(mrb);
274
275
2.98k
  while (*p) {
276
2.88k
    const char c = *p++;
277
2.88k
    e = p;
278
2.88k
    if (c == '%') {
279
125
      if (*p == '!') {
280
0
        inspect = TRUE;
281
0
        p++;
282
0
      }
283
125
      if (!*p) break;
284
125
      switch (*p) {
285
0
        case 'c':
286
0
          ch = (char)va_arg(ap, int);
287
0
          chars = &ch;
288
0
          len = 1;
289
0
          goto L_cat;
290
28
        case 'd': case 'i':
291
#if MRB_INT_MAX < INT_MAX
292
          i = (mrb_int)va_arg(ap, int);
293
#else
294
28
          i = *p == 'd' ? (mrb_int)va_arg(ap, int) : va_arg(ap, mrb_int);
295
28
#endif
296
28
          obj = mrb_int_value(mrb, i);
297
28
          goto L_cat_obj;
298
0
#ifndef MRB_NO_FLOAT
299
0
        case 'f':
300
0
          obj = mrb_float_value(mrb, (mrb_float)va_arg(ap, double));
301
0
          goto L_cat_obj;
302
0
#endif
303
0
        case 'l':
304
0
          chars = va_arg(ap, char*);
305
0
          len = va_arg(ap, size_t);
306
5
        L_cat:
307
5
          if (inspect) {
308
0
            obj = mrb_str_new(mrb, chars, len);
309
0
            goto L_cat_obj;
310
0
          }
311
125
        L_cat_plain:
312
125
          mrb_str_cat(mrb, result, b,  e - b - 1);
313
125
          mrb_str_cat(mrb, result, chars, len);
314
125
          b = ++p;
315
125
          mrb_gc_arena_restore(mrb, ai);
316
125
          break;
317
37
        case 'n':
318
#if UINT32_MAX < INT_MAX
319
          obj = mrb_symbol_value((mrb_sym)va_arg(ap, int));
320
#else
321
37
          obj = mrb_symbol_value(va_arg(ap, mrb_sym));
322
37
#endif
323
37
          goto L_cat_obj;
324
5
        case 's':
325
5
          chars = va_arg(ap, char*);
326
5
          len = strlen(chars);
327
5
          goto L_cat;
328
18
        case 't':
329
18
          cls = mrb_class(mrb, va_arg(ap, mrb_value));
330
18
          goto L_cat_class;
331
0
        case 'v': case 'S':
332
0
          obj = va_arg(ap, mrb_value);
333
120
        L_cat_obj:
334
120
          str = (inspect ? mrb_inspect : mrb_obj_as_string)(mrb, obj);
335
120
          if (mrb_type(str) != MRB_TT_STRING) {
336
0
            chars = "void (no string conversion)";
337
0
            len = strlen(chars);
338
0
          }
339
120
          else {
340
120
            chars = RSTRING_PTR(str);
341
120
            len = RSTRING_LEN(str);
342
120
          }
343
120
          goto L_cat_plain;
344
0
        case 'C':
345
0
          cls = va_arg(ap, struct RClass*);
346
18
        L_cat_class:
347
18
          obj = mrb_obj_value(cls);
348
18
          goto L_cat_obj;
349
0
        case 'T':
350
0
          obj = va_arg(ap, mrb_value);
351
0
        L_cat_real_class_of:
352
0
          cls = mrb_obj_class(mrb, obj);
353
0
          goto L_cat_class;
354
37
        case 'Y':
355
37
          obj = va_arg(ap, mrb_value);
356
37
          if (!mrb_test(obj) || mrb_true_p(obj)) {
357
37
            inspect = TRUE;
358
37
            goto L_cat_obj;
359
37
          }
360
0
          else {
361
0
            goto L_cat_real_class_of;
362
0
          }
363
0
        case '%':
364
0
        L_cat_current:
365
0
          chars = p;
366
0
          len = 1;
367
0
          goto L_cat_plain;
368
0
        default:
369
0
          mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - %%%c", *p);
370
125
      }
371
125
    }
372
2.75k
    else if (c == '\\') {
373
0
      if (!*p) break;
374
0
      goto L_cat_current;
375
376
0
    }
377
2.88k
  }
378
379
102
  mrb_str_cat(mrb, result, b, p - b);
380
102
  return result;
381
102
}
382
383
MRB_API mrb_value
384
mrb_format(mrb_state *mrb, const char *format, ...)
385
11
{
386
11
  va_list ap;
387
11
  mrb_value str;
388
389
11
  va_start(ap, format);
390
11
  str = mrb_vformat(mrb, format, ap);
391
11
  va_end(ap);
392
393
11
  return str;
394
11
}
395
396
static mrb_value
397
error_va(mrb_state *mrb, struct RClass *c, const char *fmt, va_list ap)
398
91
{
399
91
  mrb_value mesg = mrb_vformat(mrb, fmt, ap);
400
91
  return mrb_exc_new_str(mrb, c, mesg);
401
91
}
402
403
MRB_API mrb_noreturn void
404
mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...)
405
54
{
406
54
  va_list ap;
407
54
  mrb_value exc;
408
409
54
  va_start(ap, fmt);
410
54
  exc = error_va(mrb, c, fmt, ap);
411
54
  va_end(ap);
412
413
54
  mrb_exc_raise(mrb, exc);
414
54
}
415
416
MRB_API mrb_noreturn void
417
mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
418
0
{
419
0
  va_list ap;
420
0
  mrb_value exc;
421
422
0
  va_start(ap, fmt);
423
0
  exc = error_va(mrb, E_NAME_ERROR, fmt, ap);
424
0
  va_end(ap);
425
0
  mrb_iv_set(mrb, exc, MRB_IVSYM(name), mrb_symbol_value(id));
426
0
  mrb_exc_raise(mrb, exc);
427
0
}
428
429
MRB_API void
430
mrb_warn(mrb_state *mrb, const char *fmt, ...)
431
0
{
432
0
#ifndef MRB_NO_STDIO
433
0
  va_list ap;
434
0
  mrb_value str;
435
436
0
  va_start(ap, fmt);
437
0
  str = mrb_vformat(mrb, fmt, ap);
438
0
  fputs("warning: ", stderr);
439
0
  fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr);
440
0
  putc('\n', stderr);
441
0
  va_end(ap);
442
0
#endif
443
0
}
444
445
MRB_API mrb_noreturn void
446
mrb_bug(mrb_state *mrb, const char *mesg)
447
0
{
448
0
#ifndef MRB_NO_STDIO
449
0
  fputs("bug: ", stderr);
450
0
  fputs(mesg, stderr);
451
0
  fputs("\n", stderr);
452
0
#endif
453
0
  exit(EXIT_FAILURE);
454
0
}
455
456
mrb_value
457
mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg)
458
16
{
459
16
  mrb_int n = 1;
460
461
16
  if (mrb_nil_p(mesg)) {
462
0
    n = 0;
463
0
  }
464
16
  if (mrb_class_p(exc)) {
465
16
    exc = mrb_funcall_argv(mrb, exc, MRB_SYM(new), n, &mesg);
466
16
  }
467
0
  else if (mrb_exception_p(exc)) {
468
0
    if (n > 0) {
469
0
      exc = mrb_obj_clone(mrb, exc);
470
0
      mrb_exc_mesg_set(mrb, mrb_exc_ptr(exc), mesg);
471
0
    }
472
0
  }
473
0
  else {
474
0
    mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
475
0
  }
476
16
  if (mrb_type(exc) != MRB_TT_EXCEPTION) {
477
0
    mrb_raise(mrb, E_EXCEPTION, "exception object expected");
478
0
  }
479
16
  return exc;
480
16
}
481
482
MRB_API mrb_noreturn void
483
mrb_sys_fail(mrb_state *mrb, const char *mesg)
484
0
{
485
0
  struct RClass *sce;
486
0
  mrb_int no;
487
488
0
  no = (mrb_int)errno;
489
0
  if (mrb_class_defined_id(mrb, MRB_SYM(SystemCallError))) {
490
0
    sce = mrb_class_get_id(mrb, MRB_SYM(SystemCallError));
491
0
    if (mesg != NULL) {
492
0
      mrb_funcall_id(mrb, mrb_obj_value(sce), MRB_SYM(_sys_fail), 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg));
493
0
    }
494
0
    else {
495
0
      mrb_funcall_id(mrb, mrb_obj_value(sce), MRB_SYM(_sys_fail), 1, mrb_fixnum_value(no));
496
0
    }
497
0
  }
498
499
0
  mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
500
0
}
501
502
MRB_API mrb_noreturn void
503
mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...)
504
37
{
505
37
  va_list ap;
506
37
  mrb_value exc;
507
508
37
  va_start(ap, fmt);
509
37
  exc = error_va(mrb, E_NOMETHOD_ERROR, fmt, ap);
510
37
  va_end(ap);
511
37
  mrb_iv_set(mrb, exc, MRB_IVSYM(name), mrb_symbol_value(id));
512
37
  mrb_iv_set(mrb, exc, MRB_IVSYM(args), args);
513
37
  mrb_exc_raise(mrb, exc);
514
37
}
515
516
static mrb_noreturn void
517
frozen_error(mrb_state *mrb, mrb_value v)
518
0
{
519
0
  mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %T", v);
520
0
}
521
522
MRB_API mrb_noreturn void
523
mrb_frozen_error(mrb_state *mrb, void *frozen_obj)
524
0
{
525
0
  frozen_error(mrb, mrb_obj_value(frozen_obj));
526
0
}
527
528
MRB_API void
529
mrb_check_frozen(mrb_state *mrb, void *o)
530
1.46M
{
531
1.46M
  if (mrb_frozen_p((struct RBasic*)o)) {
532
0
    mrb_frozen_error(mrb, o);
533
0
  }
534
1.46M
}
535
536
MRB_API void
537
mrb_check_frozen_value(mrb_state *mrb, mrb_value v)
538
0
{
539
0
  if (mrb_immediate_p(v) || mrb_frozen_p(mrb_basic_ptr(v))) {
540
0
    frozen_error(mrb, v);
541
0
  }
542
0
}
543
544
MRB_API mrb_noreturn void
545
mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max)
546
3
{
547
3
#define FMT(exp) "wrong number of arguments (given %i, expected " exp ")"
548
3
  if (min == max)
549
3
    mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d"), argc, min);
550
0
  else if (max < 0)
551
0
    mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d+"), argc, min);
552
0
  else
553
0
    mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d..%d"), argc, min, max);
554
3
#undef FMT
555
3
}
556
557
void mrb_core_init_printabort(void);
558
559
int
560
mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state*, void*), void *opaque)
561
952
{
562
952
  struct mrb_jmpbuf *prev_jmp = mrb->jmp;
563
952
  struct mrb_jmpbuf c_jmp;
564
952
  int err = 1;
565
566
952
  MRB_TRY(&c_jmp) {
567
952
    mrb->jmp = &c_jmp;
568
952
    body(mrb, opaque);
569
952
    err = 0;
570
952
  } MRB_CATCH(&c_jmp) {
571
0
    if (mrb->exc) {
572
0
      mrb_print_error(mrb);
573
0
      mrb->exc = NULL;
574
0
    }
575
0
    else {
576
0
      mrb_core_init_printabort();
577
0
    }
578
0
  } MRB_END_EXC(&c_jmp);
579
580
952
  mrb->jmp = prev_jmp;
581
582
952
  return err;
583
952
}
584
585
mrb_noreturn void
586
mrb_core_init_abort(mrb_state *mrb)
587
0
{
588
0
  mrb->exc = NULL;
589
0
  exc_throw(mrb, mrb_nil_value());
590
0
}
591
592
void
593
mrb_protect_atexit(mrb_state *mrb)
594
476
{
595
476
  if (mrb->atexit_stack_len > 0) {
596
476
    struct mrb_jmpbuf *prev_jmp = mrb->jmp;
597
476
    struct mrb_jmpbuf c_jmp;
598
952
    for (int i = mrb->atexit_stack_len; i > 0; --i) {
599
476
      MRB_TRY(&c_jmp) {
600
476
        mrb->jmp = &c_jmp;
601
476
        mrb->atexit_stack[i - 1](mrb);
602
476
        mrb->jmp = prev_jmp;
603
476
      } MRB_CATCH(&c_jmp) {
604
        /* ignore atexit errors */
605
0
      } MRB_END_EXC(&c_jmp);
606
476
    }
607
476
#ifndef MRB_FIXED_STATE_ATEXIT_STACK
608
476
    mrb_free(mrb, mrb->atexit_stack);
609
476
#endif
610
476
    mrb->jmp = prev_jmp;
611
476
  }
612
476
}
613
614
mrb_noreturn void
615
mrb_raise_nomemory(mrb_state *mrb)
616
3
{
617
3
  if (mrb->nomem_err) {
618
3
    mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
619
3
  }
620
0
  else {
621
0
    mrb_core_init_abort(mrb);
622
0
  }
623
3
}
624
625
MRB_API void
626
mrb_print_error(mrb_state *mrb)
627
0
{
628
0
#ifndef MRB_NO_STDIO
629
0
  if (mrb->jmp == NULL) {
630
0
    struct mrb_jmpbuf c_jmp;
631
0
    MRB_TRY(&c_jmp) {
632
0
      mrb->jmp = &c_jmp;
633
0
      mrb_print_backtrace(mrb);
634
0
    } MRB_CATCH(&c_jmp) {
635
      /* ignore exception during print_backtrace() */
636
0
    } MRB_END_EXC(&c_jmp);
637
0
    mrb->jmp = NULL;
638
0
  }
639
0
  else {
640
0
    mrb_print_backtrace(mrb);
641
0
  }
642
0
#endif
643
0
}
644
645
/* clear error status in the mrb_state structure */
646
MRB_API void
647
mrb_clear_error(mrb_state *mrb)
648
0
{
649
0
  mrb->exc = NULL;
650
0
}
651
652
/* returns TRUE if error in the previous call; internally calls mrb_clear_error() */
653
MRB_API mrb_bool
654
mrb_check_error(mrb_state *mrb)
655
0
{
656
0
  if (mrb->exc) {
657
0
    mrb_clear_error(mrb);
658
0
    return TRUE;
659
0
  }
660
0
  return FALSE;
661
0
}
662
663
void
664
mrb_init_exception(mrb_state *mrb)
665
476
{
666
476
  struct RClass *exception, *script_error, *stack_error, *nomem_error;
667
668
476
  mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
669
476
  MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION);
670
476
  mrb_define_class_method(mrb, exception, "exception", mrb_instance_new,  MRB_ARGS_OPT(1));
671
476
  mrb_define_method(mrb, exception, "exception",       exc_exception,     MRB_ARGS_OPT(1));
672
476
  mrb_define_method(mrb, exception, "initialize",      exc_initialize,    MRB_ARGS_OPT(1));
673
476
  mrb_define_method(mrb, exception, "to_s",            exc_to_s,          MRB_ARGS_NONE());
674
476
  mrb_define_method(mrb, exception, "inspect",         mrb_exc_inspect,   MRB_ARGS_NONE());
675
476
  mrb_define_method(mrb, exception, "backtrace",       mrb_exc_backtrace, MRB_ARGS_NONE());
676
476
  mrb_define_method(mrb, exception, "set_backtrace",   exc_set_backtrace, MRB_ARGS_REQ(1));
677
678
476
  mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
679
476
  mrb_define_class(mrb, "RuntimeError", E_STANDARD_ERROR);          /* 15.2.28 */
680
476
  script_error = mrb_define_class(mrb, "ScriptError", exception);                /* 15.2.37 */
681
476
  mrb_define_class(mrb, "SyntaxError", script_error);                                        /* 15.2.38 */
682
476
  stack_error = mrb_define_class(mrb, "SystemStackError", exception);
683
476
  mrb->stack_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, stack_error, "stack level too deep"));
684
685
476
  nomem_error = mrb_define_class(mrb, "NoMemoryError", exception);
686
476
  mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, nomem_error, "Out of memory"));
687
#ifdef MRB_GC_FIXED_ARENA
688
  mrb->arena_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, nomem_error, "arena overflow error"));
689
#endif
690
476
}