Ruby 4.1.0dev (2026-10-14 revision d037ba85ef1ff1b8a503f240e5ed083b644f1ec5)
error.c (d037ba85ef1ff1b8a503f240e5ed083b644f1ec5)
1/**********************************************************************
2
3 error.c -
4
5 $Author$
6 created at: Mon Aug 9 16:11:34 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "ruby/internal/config.h"
13
14#include <errno.h>
15#include <stdarg.h>
16#include <stdio.h>
17
18#ifdef HAVE_STDLIB_H
19# include <stdlib.h>
20#endif
21
22#ifdef HAVE_UNISTD_H
23# include <unistd.h>
24#endif
25
26#ifdef HAVE_SYS_WAIT_H
27# include <sys/wait.h>
28#endif
29
30#include "internal.h"
31#include "internal/class.h"
32#include "internal/error.h"
33#include "internal/eval.h"
34#include "internal/hash.h"
35#include "internal/io.h"
36#include "internal/load.h"
37#include "internal/object.h"
38#include "internal/process.h"
39#include "internal/string.h"
40#include "internal/symbol.h"
41#include "internal/thread.h"
42#include "internal/variable.h"
43#include "ruby/encoding.h"
44#include "ruby/st.h"
45#include "ruby/util.h"
46#include "internal/vm.h"
47#include "ruby_assert.h"
48#include "vm_core.h"
49#include "yjit.h"
50#include "zjit.h"
51
52#include "builtin.h"
53
59#ifndef EXIT_SUCCESS
60#define EXIT_SUCCESS 0
61#endif
62
63#ifndef WIFEXITED
64#define WIFEXITED(status) 1
65#endif
66
67#ifndef WEXITSTATUS
68#define WEXITSTATUS(status) (status)
69#endif
70
71VALUE rb_iseqw_local_variables(VALUE iseqval);
72VALUE rb_iseqw_new(const rb_iseq_t *);
73int rb_str_end_with_asciichar(VALUE str, int c);
74
75long rb_backtrace_length_limit = -1;
76VALUE rb_eEAGAIN;
77VALUE rb_eEWOULDBLOCK;
78VALUE rb_eEINPROGRESS;
79static VALUE rb_mWarning;
80static VALUE rb_cWarningBuffer;
81
82static ID id_warn;
83static ID id_category;
84static ID id_deprecated;
85static ID id_experimental;
86static ID id_performance;
87static ID id_strict_unused_block;
88static VALUE sym_category;
89static VALUE sym_highlight;
90static struct {
91 st_table *id2enum, *enum2id;
92} warning_categories;
93
94extern const char *rb_dynamic_description;
95
96static const char *
97rb_strerrno(int err)
98{
99#define defined_error(name, num) if (err == (num)) return (name);
100#define undefined_error(name)
101#include "known_errors.inc"
102#undef defined_error
103#undef undefined_error
104 return NULL;
105}
106
107static int
108err_position_0(char *buf, long len, const char *file, int line)
109{
110 if (!file) {
111 return 0;
112 }
113 else if (line == 0) {
114 return snprintf(buf, len, "%s: ", file);
115 }
116 else {
117 return snprintf(buf, len, "%s:%d: ", file, line);
118 }
119}
120
121RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 0)
122static VALUE
123err_vcatf(VALUE str, const char *pre, const char *file, int line,
124 const char *fmt, va_list args)
125{
126 if (file) {
127 rb_str_cat2(str, file);
128 if (line) rb_str_catf(str, ":%d", line);
129 rb_str_cat2(str, ": ");
130 }
131 if (pre) rb_str_cat2(str, pre);
132 rb_str_vcatf(str, fmt, args);
133 return str;
134}
135
136static VALUE syntax_error_with_path(VALUE, VALUE, VALUE*, rb_encoding*);
137
138VALUE
139rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
140 rb_encoding *enc, const char *fmt, va_list args)
141{
142 const char *fn = NIL_P(file) ? NULL : RSTRING_PTR(file);
143 if (!exc) {
144 VALUE mesg = rb_enc_str_new(0, 0, enc);
145 err_vcatf(mesg, NULL, fn, line, fmt, args);
146 rb_str_cat2(mesg, "\n");
147 rb_write_error_str(mesg);
148 }
149 else {
150 VALUE mesg;
151 exc = syntax_error_with_path(exc, file, &mesg, enc);
152 err_vcatf(mesg, NULL, fn, line, fmt, args);
153 }
154
155 return exc;
156}
157
158static unsigned int warning_disabled_categories = (
160 ~RB_WARN_CATEGORY_DEFAULT_BITS);
161
162static unsigned int
163rb_warning_category_mask(VALUE category)
164{
165 return 1U << rb_warning_category_from_name(category);
166}
167
169rb_warning_category_from_name(VALUE category)
170{
171 st_data_t cat_value;
172 ID cat_id;
173 Check_Type(category, T_SYMBOL);
174 if (!(cat_id = rb_check_id(&category)) ||
175 !st_lookup(warning_categories.id2enum, cat_id, &cat_value)) {
176 rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category);
177 }
178 return (rb_warning_category_t)cat_value;
179}
180
181static VALUE
182rb_warning_category_to_name(rb_warning_category_t category)
183{
184 st_data_t id;
185 if (!st_lookup(warning_categories.enum2id, category, &id)) {
186 rb_raise(rb_eArgError, "invalid category: %d", (int)category);
187 }
188 return id ? ID2SYM(id) : Qnil;
189}
190
191void
192rb_warning_category_update(unsigned int mask, unsigned int bits)
193{
194 warning_disabled_categories &= ~mask;
195 warning_disabled_categories |= mask & ~bits;
196}
197
198bool
199rb_warning_category_enabled_p(rb_warning_category_t category)
200{
201 return !(warning_disabled_categories & (1U << category));
202}
203
204/*
205 * call-seq:
206 * Warning[category] -> true or false
207 *
208 * Returns the flag to show the warning messages for +category+.
209 * Supported categories are:
210 *
211 * +:deprecated+ ::
212 * deprecation warnings
213 * * assignment of non-nil value to <code>$,</code> and <code>$;</code>
214 * * keyword arguments
215 * etc.
216 *
217 * +:experimental+ ::
218 * experimental features
219 *
220 * +:performance+ ::
221 * performance hints
222 * * Shape variation limit
223 */
224
225static VALUE
226rb_warning_s_aref(VALUE mod, VALUE category)
227{
228 rb_warning_category_t cat = rb_warning_category_from_name(category);
229 return RBOOL(rb_warning_category_enabled_p(cat));
230}
231
232/*
233 * call-seq:
234 * Warning[category] = flag -> flag
235 *
236 * Sets the warning flags for +category+.
237 * See Warning.[] for the categories.
238 */
239
240static VALUE
241rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag)
242{
243 unsigned int mask = rb_warning_category_mask(category);
244 unsigned int disabled = warning_disabled_categories;
245 if (!RTEST(flag))
246 disabled |= mask;
247 else
248 disabled &= ~mask;
249 warning_disabled_categories = disabled;
250 return flag;
251}
252
253/*
254 * call-seq:
255 * categories -> array
256 *
257 * Returns a list of the supported category symbols.
258 */
259
260static VALUE
261rb_warning_s_categories(VALUE mod)
262{
263 st_index_t num = warning_categories.id2enum->num_entries;
264 ID *ids = ALLOCA_N(ID, num);
265 num = st_keys(warning_categories.id2enum, ids, num);
266 VALUE ary = rb_ary_new_capa(num);
267 for (st_index_t i = 0; i < num; ++i) {
268 rb_ary_push(ary, ID2SYM(ids[i]));
269 }
270 return rb_ary_freeze(ary);
271}
272
273/*
274 * call-seq:
275 * warn(msg, category: nil) -> nil
276 *
277 * Writes warning message +msg+ to $stderr. This method is called by
278 * Ruby for all emitted warnings. A +category+ may be included with
279 * the warning.
280 *
281 * See the documentation of the Warning module for how to customize this.
282 */
283
284static VALUE
285rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
286{
287 VALUE str;
288 VALUE opt;
289 VALUE category = Qnil;
290
291 rb_scan_args(argc, argv, "1:", &str, &opt);
292 if (!NIL_P(opt)) rb_get_kwargs(opt, &id_category, 0, 1, &category);
293
294 Check_Type(str, T_STRING);
296 if (!NIL_P(category)) {
297 rb_warning_category_t cat = rb_warning_category_from_name(category);
298 if (!rb_warning_category_enabled_p(cat)) return Qnil;
299 }
300 rb_write_error_str(str);
301 return Qnil;
302}
303
304/*
305 * Document-module: Warning
306 *
307 * The Warning module contains a single method named #warn, and the
308 * module extends itself, making Warning.warn available.
309 * Warning.warn is called for all warnings issued by Ruby.
310 * By default, warnings are printed to $stderr.
311 *
312 * Changing the behavior of Warning.warn is useful to customize how warnings are
313 * handled by Ruby, for instance by filtering some warnings, and/or outputting
314 * warnings somewhere other than <tt>$stderr</tt>.
315 *
316 * If you want to change the behavior of Warning.warn you should use
317 * <tt>Warning.extend(MyNewModuleWithWarnMethod)</tt> and you can use +super+
318 * to get the default behavior of printing the warning to <tt>$stderr</tt>.
319 *
320 * Example:
321 * module MyWarningFilter
322 * def warn(message, category: nil, **kwargs)
323 * if /some warning I want to ignore/.match?(message)
324 * # ignore
325 * else
326 * super
327 * end
328 * end
329 * end
330 * Warning.extend MyWarningFilter
331 *
332 * You should never redefine Warning#warn (the instance method), as that will
333 * then no longer provide a way to use the default behavior.
334 *
335 * The warning[https://rubygems.org/gems/warning] gem provides convenient ways to customize Warning.warn.
336 */
337
338static VALUE
339rb_warning_warn(VALUE mod, VALUE str)
340{
341 return rb_funcallv(mod, id_warn, 1, &str);
342}
343
344
345static int
346rb_warning_warn_arity(void)
347{
348 const rb_method_entry_t *me = rb_method_entry(rb_singleton_class(rb_mWarning), id_warn);
349 return me ? rb_method_entry_arity(me) : 1;
350}
351
352static VALUE
353rb_warn_category(VALUE str, VALUE category)
354{
355 if (RUBY_DEBUG && !NIL_P(category)) {
356 rb_warning_category_from_name(category);
357 }
358
359 if (rb_warning_warn_arity() == 1) {
360 return rb_warning_warn(rb_mWarning, str);
361 }
362 else {
363 VALUE args[2];
364 args[0] = str;
365 args[1] = rb_hash_new_capa(1);
366 rb_hash_aset(args[1], sym_category, category);
367 return rb_funcallv_kw(rb_mWarning, id_warn, 2, args, RB_PASS_KEYWORDS);
368 }
369}
370
371static void
372rb_write_warning_str(VALUE str)
373{
374 rb_warning_warn(rb_mWarning, str);
375}
376
377RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 0)
378static VALUE
379warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args)
380{
381 VALUE str = rb_enc_str_new(0, 0, enc);
382
383 err_vcatf(str, "warning: ", file, line, fmt, args);
384 return rb_str_cat2(str, "\n");
385}
386
387#define with_warn_vsprintf(enc, file, line, fmt) \
388 VALUE str; \
389 va_list args; \
390 va_start(args, fmt); \
391 str = warn_vsprintf(enc, file, line, fmt, args); \
392 va_end(args);
393
394void
395rb_compile_warn(const char *file, int line, const char *fmt, ...)
396{
397 if (!NIL_P(ruby_verbose)) {
398 with_warn_vsprintf(NULL, file, line, fmt) {
399 rb_write_warning_str(str);
400 }
401 }
402}
403
404void
405rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...)
406{
407 if (!NIL_P(ruby_verbose)) {
408 with_warn_vsprintf(enc, file, line, fmt) {
409 rb_write_warning_str(str);
410 }
411 }
412}
413
414/* rb_compile_warning() reports only in verbose mode */
415void
416rb_compile_warning(const char *file, int line, const char *fmt, ...)
417{
418 if (RTEST(ruby_verbose)) {
419 with_warn_vsprintf(NULL, file, line, fmt) {
420 rb_write_warning_str(str);
421 }
422 }
423}
424
425/* rb_enc_compile_warning() reports only in verbose mode */
426void
427rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...)
428{
429 if (RTEST(ruby_verbose)) {
430 with_warn_vsprintf(enc, file, line, fmt) {
431 rb_write_warning_str(str);
432 }
433 }
434}
435
436void
437rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...)
438{
439 if (!NIL_P(ruby_verbose)) {
440 with_warn_vsprintf(NULL, file, line, fmt) {
441 rb_warn_category(str, rb_warning_category_to_name(category));
442 }
443 }
444}
445
446RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
447static VALUE
448warning_string(rb_encoding *enc, const char *fmt, va_list args)
449{
450 int line;
451 const char *file = rb_source_location_cstr(&line);
452 return warn_vsprintf(enc, file, line, fmt, args);
453}
454
455#define with_warning_string(mesg, enc, fmt) \
456 with_warning_string_from(mesg, enc, fmt, fmt)
457#define with_warning_string_from(mesg, enc, fmt, last_arg) \
458 VALUE mesg; \
459 va_list args; va_start(args, last_arg); \
460 mesg = warning_string(enc, fmt, args); \
461 va_end(args);
462
463void
464rb_warn(const char *fmt, ...)
465{
466 if (!NIL_P(ruby_verbose)) {
467 with_warning_string(mesg, 0, fmt) {
468 rb_write_warning_str(mesg);
469 }
470 }
471}
472
473void
474rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
475{
476 if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
477 with_warning_string(mesg, 0, fmt) {
478 rb_warn_category(mesg, rb_warning_category_to_name(category));
479 }
480 }
481}
482
483void
484rb_enc_warn(rb_encoding *enc, const char *fmt, ...)
485{
486 if (!NIL_P(ruby_verbose)) {
487 with_warning_string(mesg, enc, fmt) {
488 rb_write_warning_str(mesg);
489 }
490 }
491}
492
493/* rb_warning() reports only in verbose mode */
494void
495rb_warning(const char *fmt, ...)
496{
497 if (RTEST(ruby_verbose)) {
498 with_warning_string(mesg, 0, fmt) {
499 rb_write_warning_str(mesg);
500 }
501 }
502}
503
504/* rb_category_warning() reports only in verbose mode */
505void
506rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
507{
508 if (RTEST(ruby_verbose) && rb_warning_category_enabled_p(category)) {
509 with_warning_string(mesg, 0, fmt) {
510 rb_warn_category(mesg, rb_warning_category_to_name(category));
511 }
512 }
513}
514
515VALUE
516rb_warning_string(const char *fmt, ...)
517{
518 with_warning_string(mesg, 0, fmt) {
519 }
520 return mesg;
521}
522
523#if 0
524void
525rb_enc_warning(rb_encoding *enc, const char *fmt, ...)
526{
527 if (RTEST(ruby_verbose)) {
528 with_warning_string(mesg, enc, fmt) {
529 rb_write_warning_str(mesg);
530 }
531 }
532}
533#endif
534
535static bool
536deprecation_warning_enabled(void)
537{
538 if (NIL_P(ruby_verbose)) return false;
539 if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return false;
540 return true;
541}
542
543static void
544warn_deprecated(VALUE mesg, const char *removal, const char *suggest, VALUE category)
545{
546 rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
547 rb_str_cat_cstr(mesg, " is deprecated");
548 if (removal) {
549 rb_str_catf(mesg, " and will be removed in Ruby %s", removal);
550 }
551 if (suggest) rb_str_catf(mesg, "; use %s instead", suggest);
552 rb_str_cat_cstr(mesg, "\n");
553 rb_warn_category(mesg, category);
554}
555
556void
557rb_warn_deprecated(const char *fmt, const char *suggest, ...)
558{
559 if (!deprecation_warning_enabled()) return;
560
561 with_warning_string_from(mesg, 0, fmt, suggest) {
562 warn_deprecated(mesg, NULL, suggest, ID2SYM(id_deprecated));
563 }
564}
565
566void
567rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...)
568{
569 if (!deprecation_warning_enabled()) return;
570
571 with_warning_string_from(mesg, 0, fmt, suggest) {
572 warn_deprecated(mesg, removal, suggest, ID2SYM(id_deprecated));
573 }
574}
575
576void
577rb_warn_to_remove(const char *removal, const char *fmt, const char *suggest, ...)
578{
579 if (NIL_P(ruby_verbose)) return;
580
581 with_warning_string_from(mesg, 0, fmt, suggest) {
582 warn_deprecated(mesg, removal, suggest, Qnil);
583 }
584}
585
586void
587rb_warn_reserved_name(const char *coming, const char *fmt, ...)
588{
589 if (!deprecation_warning_enabled()) return;
590
591 with_warning_string_from(mesg, 0, fmt, fmt) {
592 rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
593 rb_str_catf(mesg, " is reserved for Ruby %s\n", coming);
594 rb_warn_category(mesg, ID2SYM(id_deprecated));
595 }
596}
597
598static inline int
599end_with_asciichar(VALUE str, int c)
600{
601 return RB_TYPE_P(str, T_STRING) &&
602 rb_str_end_with_asciichar(str, c);
603}
604
605/* :nodoc: */
606static VALUE
607warning_write(int argc, VALUE *argv, VALUE buf)
608{
609 while (argc-- > 0) {
610 rb_str_append(buf, *argv++);
611 }
612 return buf;
613}
614
615VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
616
617static VALUE
618rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category)
619{
620 VALUE location = Qnil;
621 int argc = RARRAY_LENINT(msgs);
622 const VALUE *argv = RARRAY_CONST_PTR(msgs);
623
624 if (!NIL_P(ruby_verbose) && argc > 0) {
625 VALUE str = argv[0];
626 if (!NIL_P(uplevel)) {
627 long lev = NUM2LONG(uplevel);
628 if (lev < 0) {
629 rb_raise(rb_eArgError, "negative level (%ld)", lev);
630 }
631 location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE);
632 if (!NIL_P(location)) {
633 location = rb_ary_entry(location, 0);
634 }
635 }
636 if (argc > 1 || !NIL_P(uplevel) || !end_with_asciichar(str, '\n')) {
637 VALUE path;
638 if (NIL_P(uplevel)) {
639 str = rb_str_tmp_new(0);
640 }
641 else if (NIL_P(location) ||
642 NIL_P(path = rb_funcall(location, rb_intern("path"), 0))) {
643 str = rb_str_new_cstr("warning: ");
644 }
645 else {
646 str = rb_sprintf("%s:%ld: warning: ",
647 rb_string_value_ptr(&path),
648 NUM2LONG(rb_funcall(location, rb_intern("lineno"), 0)));
649 }
650 RBASIC_SET_CLASS(str, rb_cWarningBuffer);
651 rb_io_puts(argc, argv, str);
652 RBASIC_SET_CLASS(str, rb_cString);
653 }
654
655 if (!NIL_P(category)) {
656 category = rb_to_symbol_type(category);
657 rb_warning_category_from_name(category);
658 }
659
660 if (exc == rb_mWarning) {
662 rb_write_error_str(str);
663 }
664 else {
665 rb_warn_category(str, category);
666 }
667 }
668 return Qnil;
669}
670
671#define MAX_BUG_REPORTERS 0x100
672
673static struct bug_reporters {
674 void (*func)(FILE *out, void *data);
675 void *data;
676} bug_reporters[MAX_BUG_REPORTERS];
677
678static int bug_reporters_size;
679
680int
681rb_bug_reporter_add(void (*func)(FILE *, void *), void *data)
682{
683 struct bug_reporters *reporter;
684 if (bug_reporters_size >= MAX_BUG_REPORTERS) {
685 return 0; /* failed to register */
686 }
687 reporter = &bug_reporters[bug_reporters_size++];
688 reporter->func = func;
689 reporter->data = data;
690
691 return 1;
692}
693
694/* returns true if x can not be used as file name */
695static bool
696path_sep_p(char x)
697{
698#if defined __CYGWIN__ || defined DOSISH
699# define PATH_SEP_ENCODING 1
700 // Assume that "/" is only the first byte in any encoding.
701 if (x == ':') return true; // drive letter or ADS
702 if (x == '\\') return true;
703#endif
704 return x == '/';
705}
706
708 const char *ptr;
709 size_t len;
710};
711
712static const char PATHSEP_REPLACE = '!';
713
714static char *
715append_pathname(char *p, const char *pe, VALUE str)
716{
717#ifdef PATH_SEP_ENCODING
718 rb_encoding *enc = rb_enc_get(str);
719#endif
720 const char *s = RSTRING_PTR(str);
721 const char *const se = s + RSTRING_LEN(str);
722 char c;
723
724 --pe; // for terminator
725
726 while (p < pe && s < se && (c = *s) != '\0') {
727 if (c == '.') {
728 if (s == se || !*s) break; // chomp "." basename
729 if (path_sep_p(s[1])) goto skipsep; // skip "./"
730 }
731 else if (path_sep_p(c)) {
732 // squeeze successive separators
733 *p++ = PATHSEP_REPLACE;
734 skipsep:
735 while (++s < se && path_sep_p(*s));
736 continue;
737 }
738 const char *const ss = s;
739 while (p < pe && s < se && *s && !path_sep_p(*s)) {
740#ifdef PATH_SEP_ENCODING
741 int n = rb_enc_mbclen(s, se, enc);
742#else
743 const int n = 1;
744#endif
745 p += n;
746 s += n;
747 }
748 if (s > ss) memcpy(p - (s - ss), ss, s - ss);
749 }
750
751 return p;
752}
753
754static char *
755append_basename(char *p, const char *pe, struct path_string *path, VALUE str)
756{
757 if (!path->ptr) {
758#ifdef PATH_SEP_ENCODING
759 rb_encoding *enc = rb_enc_get(str);
760#endif
761 const char *const b = RSTRING_PTR(str), *const e = RSTRING_END(str), *p = e;
762
763 while (p > b) {
764 if (path_sep_p(p[-1])) {
765#ifdef PATH_SEP_ENCODING
766 const char *t = rb_enc_prev_char(b, p, e, enc);
767 if (t == p-1) break;
768 p = t;
769#else
770 break;
771#endif
772 }
773 else {
774 --p;
775 }
776 }
777
778 path->ptr = p;
779 path->len = e - p;
780 }
781 size_t n = path->len;
782 if (p + n > pe) n = pe - p;
783 memcpy(p, path->ptr, n);
784 return p + n;
785}
786
787static void
788finish_report(FILE *out, rb_pid_t pid)
789{
790 if (out != stdout && out != stderr) fclose(out);
791#ifdef HAVE_WORKING_FORK
792 if (pid > 0) waitpid(pid, NULL, 0);
793#endif
794}
795
797 struct path_string exe, script;
798 rb_pid_t pid;
799 time_t time;
800};
801
802/*
803 * Open a bug report file to write. The `RUBY_CRASH_REPORT`
804 * environment variable can be set to define a template that is used
805 * to name bug report files. The template can contain % specifiers
806 * which are substituted by the following values when a bug report
807 * file is created:
808 *
809 * %% A single % character.
810 * %e The base name of the executable filename.
811 * %E Pathname of executable, with slashes ('/') replaced by
812 * exclamation marks ('!').
813 * %f Similar to %e with the main script filename.
814 * %F Similar to %E with the main script filename.
815 * %p PID of dumped process in decimal.
816 * %t Time of dump, expressed as seconds since the Epoch,
817 * 1970-01-01 00:00:00 +0000 (UTC).
818 * %NNN Octal char code, upto 3 digits.
819 */
820static char *
821expand_report_argument(const char **input_template, struct report_expansion *values,
822 char *buf, size_t size, bool word)
823{
824 char *p = buf;
825 char *end = buf + size;
826 const char *template = *input_template;
827 bool store = true;
828
829 if (p >= end-1 || !*template) return NULL;
830 do {
831 char c = *template++;
832 if (word && ISSPACE(c)) break;
833 if (!store) continue;
834 if (c == '%') {
835 size_t n;
836 switch (c = *template++) {
837 case 'e':
838 p = append_basename(p, end, &values->exe, rb_argv0);
839 continue;
840 case 'E':
841 p = append_pathname(p, end, rb_argv0);
842 continue;
843 case 'f':
844 p = append_basename(p, end, &values->script, GET_VM()->orig_progname);
845 continue;
846 case 'F':
847 p = append_pathname(p, end, GET_VM()->orig_progname);
848 continue;
849 case 'p':
850 if (!values->pid) values->pid = getpid();
851 snprintf(p, end-p, "%" PRI_PIDT_PREFIX "d", values->pid);
852 p += strlen(p);
853 continue;
854 case 't':
855 if (!values->time) values->time = time(NULL);
856 snprintf(p, end-p, "%" PRI_TIMET_PREFIX "d", values->time);
857 p += strlen(p);
858 continue;
859 default:
860 if (c >= '0' && c <= '7') {
861 c = (unsigned char)ruby_scan_oct(template-1, 3, &n);
862 template += n - 1;
863 if (!c) store = false;
864 }
865 break;
866 }
867 }
868 if (p < end-1) *p++ = c;
869 } while (*template);
870 *input_template = template;
871 *p = '\0';
872 return ++p;
873}
874
875FILE *ruby_popen_writer(char *const *argv, rb_pid_t *pid);
876
877static FILE *
878open_report_path(const char *template, char *buf, size_t size, rb_pid_t *pid)
879{
880 struct report_expansion values = {{0}};
881
882 if (!template) return NULL;
883 if (0) fprintf(stderr, "RUBY_CRASH_REPORT=%s\n", buf);
884 if (*template == '|') {
885 char *argv[16], *bufend = buf + size, *p;
886 int argc;
887 template++;
888 for (argc = 0; argc < numberof(argv) - 1; ++argc) {
889 while (*template && ISSPACE(*template)) template++;
890 p = expand_report_argument(&template, &values, buf, bufend-buf, true);
891 if (!p) break;
892 argv[argc] = buf;
893 buf = p;
894 }
895 argv[argc] = NULL;
896 if (!p) return ruby_popen_writer(argv, pid);
897 }
898 else if (*template) {
899 expand_report_argument(&template, &values, buf, size, false);
900 return fopen(buf, "w");
901 }
902 return NULL;
903}
904
905static const char *crash_report;
906
907/* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
908#define REPORT_BUG_BUFSIZ 256
909static FILE *
910bug_report_file(const char *file, int line, rb_pid_t *pid)
911{
912 char buf[REPORT_BUG_BUFSIZ];
913 const char *report = crash_report;
914 if (!report) report = getenv("RUBY_CRASH_REPORT");
915 FILE *out = open_report_path(report, buf, sizeof(buf), pid);
916 int len = err_position_0(buf, sizeof(buf), file, line);
917
918 if (out) {
919 /* Disable buffering so crash report output is not lost if
920 * rb_vm_bugreport() triggers a secondary crash (e.g. SIGSEGV
921 * while walking JIT frames). */
922 setvbuf(out, NULL, _IONBF, 0);
923 if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len) return out;
924 fclose(out);
925 }
926 if ((ssize_t)fwrite(buf, 1, len, stderr) == (ssize_t)len) {
927 return stderr;
928 }
929 if ((ssize_t)fwrite(buf, 1, len, stdout) == (ssize_t)len) {
930 return stdout;
931 }
932
933 return NULL;
934}
935
936FUNC_MINIMIZED(static void bug_important_message(FILE *out, const char *const msg, size_t len));
937
938static void
939bug_important_message(FILE *out, const char *const msg, size_t len)
940{
941 const char *const endmsg = msg + len;
942 const char *p = msg;
943
944 if (!len) return;
945 if (isatty(fileno(out))) {
946 static const char red[] = "\033[;31;1;7m";
947 static const char green[] = "\033[;32;7m";
948 static const char reset[] = "\033[m";
949 const char *e = strchr(p, '\n');
950 const int w = (int)(e - p);
951 do {
952 int i = (int)(e - p);
953 fputs(*p == ' ' ? green : red, out);
954 fwrite(p, 1, e - p, out);
955 for (; i < w; ++i) fputc(' ', out);
956 fputs(reset, out);
957 fputc('\n', out);
958 } while ((p = e + 1) < endmsg && (e = strchr(p, '\n')) != 0 && e > p + 1);
959 }
960 fwrite(p, 1, endmsg - p, out);
961}
962
963static void
964preface_dump(FILE *out)
965{
966#if defined __APPLE__
967 static const char msg[] = ""
968 "-- Crash Report log information "
969 "--------------------------------------------\n"
970 " See Crash Report log file in one of the following locations:\n"
971 " * ~/Library/Logs/DiagnosticReports\n"
972 " * /Library/Logs/DiagnosticReports\n"
973 " for more details.\n"
974 "Don't forget to include the above Crash Report log file in bug reports.\n"
975 "\n";
976 const size_t msglen = sizeof(msg) - 1;
977#else
978 const char *msg = NULL;
979 const size_t msglen = 0;
980#endif
981 bug_important_message(out, msg, msglen);
982}
983
984static void
985postscript_dump(FILE *out)
986{
987#if defined __APPLE__
988 static const char msg[] = ""
989 "[IMPORTANT]"
990 /*" ------------------------------------------------"*/
991 "\n""Don't forget to include the Crash Report log file under\n"
992 "DiagnosticReports directory in bug reports.\n"
993 /*"------------------------------------------------------------\n"*/
994 "\n";
995 const size_t msglen = sizeof(msg) - 1;
996#else
997 const char *msg = NULL;
998 const size_t msglen = 0;
999#endif
1000 bug_important_message(out, msg, msglen);
1001}
1002
1003RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
1004static void
1005bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
1006{
1007 char buf[REPORT_BUG_BUFSIZ];
1008
1009 fputs("[BUG] ", out);
1010 vsnprintf(buf, sizeof(buf), fmt, args);
1011 fputs(buf, out);
1012 snprintf(buf, sizeof(buf), "\n%s\n\n", rb_dynamic_description);
1013 fputs(buf, out);
1014 preface_dump(out);
1015}
1016
1017#define bug_report_begin(out, fmt) do { \
1018 va_list args; \
1019 va_start(args, fmt); \
1020 bug_report_begin_valist(out, fmt, args); \
1021 va_end(args); \
1022} while (0)
1023
1024static void
1025bug_report_end(FILE *out, rb_pid_t pid)
1026{
1027 /* call additional bug reporters */
1028 {
1029 int i;
1030 for (i=0; i<bug_reporters_size; i++) {
1031 struct bug_reporters *reporter = &bug_reporters[i];
1032 (*reporter->func)(out, reporter->data);
1033 }
1034 }
1035 postscript_dump(out);
1036 finish_report(out, pid);
1037}
1038
1039/* Only the first thread to get here writes a report. A second one -- another Ractor
1040 * failing the same assertion, say -- would interleave into it and leave both
1041 * unreadable [Bug #21146], so it waits for the writer to abort the process instead.
1042 * The writer is let through again, for the crash-while-reporting path. */
1043static const rb_execution_context_t *bug_reporter_ec;
1044static rb_atomic_t bug_reporter_claimed;
1045
1046static bool
1047bug_report_claim(void)
1048{
1049 const rb_execution_context_t *ec = rb_current_execution_context(false);
1050
1051 if (RUBY_ATOMIC_CAS(bug_reporter_claimed, 0, 1) == 0) {
1052 bug_reporter_ec = ec;
1053 return true;
1054 }
1055 if (ec != NULL && ec == bug_reporter_ec) {
1056 return true;
1057 }
1058
1059 /* Bounded, so a writer that hangs ends as a crash and not as a hang. */
1060 for (int i = 0; i < 100; i++) {
1061#ifdef _WIN32
1062 Sleep(100);
1063#else
1064 struct timespec ts = { 0, 100 * 1000 * 1000 };
1065 nanosleep(&ts, NULL);
1066#endif
1067 }
1068 return false;
1069}
1070
1071#define report_bug(file, line, fmt, ctx) do { \
1072 rb_pid_t pid = -1; \
1073 FILE *out = bug_report_claim() ? bug_report_file(file, line, &pid) : NULL; \
1074 if (out) { \
1075 bug_report_begin(out, fmt); \
1076 rb_vm_bugreport(ctx, out); \
1077 bug_report_end(out, pid); \
1078 } \
1079} while (0) \
1080
1081#define report_bug_valist(file, line, fmt, ctx, args) do { \
1082 rb_pid_t pid = -1; \
1083 FILE *out = bug_report_claim() ? bug_report_file(file, line, &pid) : NULL; \
1084 if (out) { \
1085 bug_report_begin_valist(out, fmt, args); \
1086 rb_vm_bugreport(ctx, out); \
1087 bug_report_end(out, pid); \
1088 } \
1089} while (0) \
1090
1091void
1092ruby_set_crash_report(const char *template)
1093{
1094 crash_report = template;
1095#if RUBY_DEBUG
1096 rb_pid_t pid = -1;
1097 char buf[REPORT_BUG_BUFSIZ];
1098 FILE *out = open_report_path(template, buf, sizeof(buf), &pid);
1099 if (out) {
1100 time_t t = time(NULL);
1101 fprintf(out, "ruby_test_bug_report: %s", ctime(&t));
1102 finish_report(out, pid);
1103 }
1104#endif
1105}
1106
1107NORETURN(static void die(void));
1108static void
1109die(void)
1110{
1111#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
1112 /* mingw32 declares in stdlib.h but does not provide. */
1113 _set_abort_behavior( 0, _CALL_REPORTFAULT);
1114#endif
1115
1116 /* Reset SIGABRT to default so that abort() does not trigger our custom
1117 * handler (sigabrt), which would re-open the crash report file with "w"
1118 * and truncate the report already written by rb_bug(). */
1119 signal(SIGABRT, SIG_DFL);
1120 abort();
1121}
1122
1123RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
1124static void
1125rb_bug_without_die_internal(const char *fmt, va_list args)
1126{
1127 const char *file = NULL;
1128 int line = 0;
1129
1130 if (rb_current_execution_context(false)) {
1131 file = rb_source_location_cstr(&line);
1132 }
1133
1134 report_bug_valist(file, line, fmt, NULL, args);
1135}
1136
1137RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
1138void
1139rb_bug_without_die(const char *fmt, ...)
1140{
1141 va_list args;
1142 va_start(args, fmt);
1143 rb_bug_without_die_internal(fmt, args);
1144 va_end(args);
1145}
1146
1147void
1148rb_bug(const char *fmt, ...)
1149{
1150 va_list args;
1151 va_start(args, fmt);
1152 rb_bug_without_die_internal(fmt, args);
1153 va_end(args);
1154 die();
1155}
1156
1157void
1158rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *ctx, const char *fmt, ...)
1159{
1160 const char *file = NULL;
1161 int line = 0;
1162
1163 if (rb_current_execution_context(false)) {
1164 file = rb_source_location_cstr(&line);
1165 }
1166
1167 report_bug(file, line, fmt, ctx);
1168
1169 if (default_sighandler) default_sighandler(sig);
1170
1172 die();
1173}
1174
1175
1176void
1177rb_bug_errno(const char *mesg, int errno_arg)
1178{
1179 if (errno_arg == 0)
1180 rb_bug("%s: errno == 0 (NOERROR)", mesg);
1181 else {
1182 const char *errno_str = rb_strerrno(errno_arg);
1183 if (errno_str)
1184 rb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
1185 else
1186 rb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
1187 }
1188}
1189
1190/*
1191 * this is safe to call inside signal handler and timer thread
1192 * (which isn't a Ruby Thread object)
1193 */
1194#define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
1195#define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
1196
1197void
1198rb_async_bug_errno(const char *mesg, int errno_arg)
1199{
1200 WRITE_CONST(2, "[ASYNC BUG] ");
1201 write_or_abort(2, mesg, strlen(mesg));
1202 WRITE_CONST(2, "\n");
1203
1204 if (errno_arg == 0) {
1205 WRITE_CONST(2, "errno == 0 (NOERROR)\n");
1206 }
1207 else {
1208 const char *errno_str = rb_strerrno(errno_arg);
1209
1210 if (!errno_str)
1211 errno_str = "undefined errno";
1212 write_or_abort(2, errno_str, strlen(errno_str));
1213 }
1214 WRITE_CONST(2, "\n\n");
1215 write_or_abort(2, rb_dynamic_description, strlen(rb_dynamic_description));
1216 abort();
1217}
1218
1219void
1220rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
1221{
1222 report_bug_valist(RSTRING_PTR(file), line, fmt, NULL, args);
1223}
1224
1225void
1226rb_assert_failure(const char *file, int line, const char *name, const char *expr)
1227{
1228 rb_assert_failure_detail(file, line, name, expr, NULL);
1229}
1230
1231void
1232rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr,
1233 const char *fmt, ...)
1234{
1235 rb_pid_t pid = -1;
1236 FILE *out = bug_report_claim() ? bug_report_file(file, line, &pid) : NULL;
1237 if (out) {
1238 fputs("Assertion Failed: ", out);
1239 if (name) fprintf(out, "%s:", name);
1240 fputs(expr, out);
1241
1242 if (fmt && *fmt) {
1243 va_list args;
1244 va_start(args, fmt);
1245 fputs(": ", out);
1246 vfprintf(out, fmt, args);
1247 va_end(args);
1248 }
1249 fprintf(out, "\n%s\n\n", rb_dynamic_description);
1250
1251 preface_dump(out);
1252 rb_vm_bugreport(NULL, out);
1253 bug_report_end(out, pid);
1254 }
1255
1256 die();
1257}
1258
1259static const char builtin_types[][10] = {
1260 "", /* 0x00, */
1261 "Object",
1262 "Class",
1263 "Module",
1264 "Float",
1265 "String",
1266 "Regexp",
1267 "Array",
1268 "Hash",
1269 "Struct",
1270 "Integer",
1271 "File",
1272 "Data", /* internal use: wrapped C pointers */
1273 "MatchData", /* data of $~ */
1274 "Complex",
1275 "Rational",
1276 "", /* 0x10 */
1277 "nil",
1278 "true",
1279 "false",
1280 "Symbol", /* :symbol */
1281 "Integer",
1282 "undef", /* internal use: #undef; should not happen */
1283 "", /* 0x17 */
1284 "", /* 0x18 */
1285 "", /* 0x19 */
1286 "<Memo>", /* internal use: general memo */
1287 "<Node>", /* internal use: syntax tree node */
1288 "<iClass>", /* internal use: mixed-in module holder */
1289};
1290
1291const char *
1292rb_builtin_type_name(int t)
1293{
1294 const char *name;
1295 if ((unsigned int)t >= numberof(builtin_types)) return 0;
1296 name = builtin_types[t];
1297 if (*name) return name;
1298 return 0;
1299}
1300
1301static VALUE
1302displaying_class_of(VALUE x)
1303{
1304 switch (x) {
1305 case Qfalse: return rb_fstring_cstr("false");
1306 case Qnil: return rb_fstring_cstr("nil");
1307 case Qtrue: return rb_fstring_cstr("true");
1308 default: return rb_obj_class(x);
1309 }
1310}
1311
1312static const char *
1313builtin_class_name(VALUE x)
1314{
1315 const char *etype;
1316
1317 if (NIL_P(x)) {
1318 etype = "nil";
1319 }
1320 else if (FIXNUM_P(x)) {
1321 etype = "Integer";
1322 }
1323 else if (SYMBOL_P(x)) {
1324 etype = "Symbol";
1325 }
1326 else if (RB_TYPE_P(x, T_TRUE)) {
1327 etype = "true";
1328 }
1329 else if (RB_TYPE_P(x, T_FALSE)) {
1330 etype = "false";
1331 }
1332 else {
1333 etype = NULL;
1334 }
1335 return etype;
1336}
1337
1338const char *
1339rb_builtin_class_name(VALUE x)
1340{
1341 const char *etype = builtin_class_name(x);
1342
1343 if (!etype) {
1344 etype = rb_obj_classname(x);
1345 }
1346 return etype;
1347}
1348
1349COLDFUNC NORETURN(static void unexpected_type(VALUE, int, int));
1350#define UNDEF_LEAKED "undef leaked to the Ruby space"
1351
1352void
1354{
1355 rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
1356 actual->wrap_struct_name, expected->wrap_struct_name);
1357}
1358
1359void
1360rb_unexpected_object_type(VALUE obj, const char *expected)
1361{
1362 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
1363 displaying_class_of(obj), expected);
1364}
1365
1366static void
1367unexpected_type(VALUE x, int xt, int t)
1368{
1369 const char *tname = rb_builtin_type_name(t);
1370 VALUE mesg, exc = rb_eFatal;
1371
1372 if (tname) {
1373 rb_unexpected_object_type(x, tname);
1374 }
1375 else if (xt > T_MASK && xt <= 0x3f) {
1376 mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
1377 " from extension library for ruby 1.8)", t, xt);
1378 }
1379 else {
1380 mesg = rb_sprintf("unknown type 0x%x (0x%x given)", t, xt);
1381 }
1382 rb_exc_raise(rb_exc_new_str(exc, mesg));
1383}
1384
1385void
1387{
1388 int xt;
1389
1390 if (RB_UNLIKELY(UNDEF_P(x))) {
1391 rb_bug(UNDEF_LEAKED);
1392 }
1393
1394 if (t == T_DATA) {
1395 /*
1396 * Typed data is not simple `T_DATA`, but in a sense an
1397 * extension of `struct RVALUE`, which are incompatible with
1398 * each other except when inherited.
1399 *
1400 * So it is not enough to just check `T_DATA`, it must be
1401 * identified by its `type` using `Check_TypedStruct` instead.
1402 */
1403 rb_unexpected_object_type(x, builtin_types[t]);
1404 }
1405 xt = TYPE(x);
1406 if (xt != t) {
1407 unexpected_type(x, xt, t);
1408 }
1409}
1410
1411void
1413{
1414 if (RB_UNLIKELY(UNDEF_P(x))) {
1415 rb_bug(UNDEF_LEAKED);
1416 }
1417
1418 unexpected_type(x, TYPE(x), t);
1419}
1420
1421#undef rb_typeddata_inherited_p
1422int
1423rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
1424{
1425 return rbimpl_typeddata_inherited_p_inline(child, parent);
1426}
1427
1428#undef rb_typeddata_is_kind_of
1429int
1430rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
1431{
1432 return rbimpl_typeddata_is_kind_of_inline(obj, data_type);
1433}
1434
1435#undef rb_typeddata_is_instance_of
1436int
1437rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type)
1438{
1439 return rb_typeddata_is_instance_of_inline(obj, data_type);
1440}
1441
1442void *
1444{
1445 return rbimpl_check_typeddata(obj, data_type);
1446}
1447
1448/* exception classes */
1472
1476
1479static VALUE rb_eNOERROR;
1480
1481ID ruby_static_id_cause;
1482#define id_cause ruby_static_id_cause
1483static ID id_message, id_detailed_message, id_backtrace;
1484static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path;
1485static ID id_receiver, id_recv, id_iseq, id_local_variables;
1486static ID id_private_call_p, id_top, id_bottom;
1487#define id_bt idBt
1488#define id_bt_locations idBt_locations
1489#define id_mesg idMesg
1490#define id_name idName
1491
1492#undef rb_exc_new_cstr
1493
1494VALUE
1495rb_exc_new(VALUE etype, const char *ptr, rb_len_t len)
1496{
1497 VALUE mesg = rb_str_new(ptr, len);
1498 return rb_class_new_instance(1, &mesg, etype);
1499}
1500
1501VALUE
1502rb_exc_new_cstr(VALUE etype, const char *s)
1503{
1504 return rb_exc_new(etype, s, strlen(s));
1505}
1506
1507VALUE
1509{
1510 rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
1511 StringValue(str);
1512 return rb_class_new_instance(1, &str, etype);
1513}
1514
1515static VALUE
1516exc_init(VALUE exc, VALUE mesg)
1517{
1518 rb_ivar_set(exc, id_mesg, mesg);
1519 rb_ivar_set(exc, id_bt, Qnil);
1520
1521 return exc;
1522}
1523
1524/*
1525 * call-seq:
1526 * Exception.new(message = nil) -> exception
1527 *
1528 * Returns a new exception object.
1529 *
1530 * The given +message+ should be
1531 * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects];
1532 * see method #message;
1533 * if not given, the message is the class name of the new instance
1534 * (which may be the name of a subclass):
1535 *
1536 * Examples:
1537 *
1538 * Exception.new # => #<Exception: Exception>
1539 * LoadError.new # => #<LoadError: LoadError> # Subclass of Exception.
1540 * Exception.new('Boom') # => #<Exception: Boom>
1541 *
1542 */
1543
1544static VALUE
1545exc_initialize(int argc, VALUE *argv, VALUE exc)
1546{
1547 VALUE arg;
1548
1549 arg = (!rb_check_arity(argc, 0, 1) ? Qnil : argv[0]);
1550 return exc_init(exc, arg);
1551}
1552
1553/*
1554 * Document-method: exception
1555 *
1556 * call-seq:
1557 * exception(message = nil) -> self or new_exception
1558 *
1559 * Returns an exception object of the same class as +self+;
1560 * useful for creating a similar exception, but with a different message.
1561 *
1562 * With +message+ +nil+, returns +self+:
1563 *
1564 * x0 = StandardError.new('Boom') # => #<StandardError: Boom>
1565 * x1 = x0.exception # => #<StandardError: Boom>
1566 * x0.equal?(x1) # => true
1567 *
1568 * With {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]
1569 * +message+ (even the same as the original message),
1570 * returns a new exception object whose class is the same as +self+,
1571 * and whose message is the given +message+:
1572 *
1573 * x1 = x0.exception('Boom') # => #<StandardError: Boom>
1574 * x0.equal?(x1) # => false
1575 *
1576 */
1577
1578static VALUE
1579exc_exception(int argc, VALUE *argv, VALUE self)
1580{
1581 VALUE exc;
1582
1583 argc = rb_check_arity(argc, 0, 1);
1584 if (argc == 0) return self;
1585 if (argc == 1 && self == argv[0]) return self;
1586 exc = rb_obj_clone(self);
1587 rb_ivar_set(exc, id_mesg, argv[0]);
1588 return exc;
1589}
1590
1591/*
1592 * call-seq:
1593 * to_s -> string
1594 *
1595 * Returns a string representation of +self+:
1596 *
1597 * x = RuntimeError.new('Boom')
1598 * x.to_s # => "Boom"
1599 * x = RuntimeError.new
1600 * x.to_s # => "RuntimeError"
1601 *
1602 */
1603
1604static VALUE
1605exc_to_s(VALUE exc)
1606{
1607 VALUE mesg = rb_attr_get(exc, idMesg);
1608
1609 if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
1610 return rb_String(mesg);
1611}
1612
1613/* FIXME: Include eval_error.c */
1614void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VALUE highlight, VALUE reverse);
1615
1616static VALUE
1617rb_get_message(VALUE exc)
1618{
1619 VALUE e = rb_check_funcall(exc, id_message, 0, 0);
1620 if (UNDEF_P(e)) return Qnil;
1621 if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
1622 return e;
1623}
1624
1625VALUE
1626rb_get_detailed_message(VALUE exc, VALUE opt)
1627{
1628 VALUE e;
1629 if (NIL_P(opt)) {
1630 e = rb_check_funcall(exc, id_detailed_message, 0, 0);
1631 }
1632 else {
1633 e = rb_check_funcall_kw(exc, id_detailed_message, 1, &opt, 1);
1634 }
1635 if (UNDEF_P(e)) return Qnil;
1636 if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
1637 return e;
1638}
1639
1640/*
1641 * call-seq:
1642 * Exception.to_tty? -> true or false
1643 *
1644 * Returns +true+ if exception messages will be sent to a terminal device.
1645 */
1646static VALUE
1647exc_s_to_tty_p(VALUE self)
1648{
1649 return RBOOL(rb_stderr_tty_p());
1650}
1651
1652static VALUE
1653check_highlight_keyword(VALUE opt, int auto_tty_detect)
1654{
1655 VALUE highlight = Qnil;
1656
1657 if (!NIL_P(opt)) {
1658 highlight = rb_hash_lookup(opt, sym_highlight);
1659
1660 switch (highlight) {
1661 default:
1662 rb_bool_expected(highlight, "highlight", TRUE);
1664 case Qtrue: case Qfalse: case Qnil: break;
1665 }
1666 }
1667
1668 if (NIL_P(highlight)) {
1669 highlight = RBOOL(auto_tty_detect && rb_stderr_tty_p());
1670 }
1671
1672 return highlight;
1673}
1674
1675static VALUE
1676check_order_keyword(VALUE opt)
1677{
1678 VALUE order = Qnil;
1679
1680 if (!NIL_P(opt)) {
1681 static VALUE kw_order;
1682 if (!kw_order) kw_order = ID2SYM(rb_intern_const("order"));
1683
1684 order = rb_hash_lookup(opt, kw_order);
1685
1686 if (order != Qnil) {
1687 ID id = rb_check_id(&order);
1688 if (id == id_bottom) order = Qtrue;
1689 else if (id == id_top) order = Qfalse;
1690 else {
1691 rb_raise(rb_eArgError, "expected :top or :bottom as "
1692 "order: %+"PRIsVALUE, order);
1693 }
1694 }
1695 }
1696
1697 if (NIL_P(order)) order = Qfalse;
1698
1699 return order;
1700}
1701
1702/*
1703 * call-seq:
1704 * full_message(highlight: true, order: :top) -> string
1705 *
1706 * Returns an enhanced message string:
1707 *
1708 * - Includes the exception class name.
1709 * - If the value of keyword +highlight+ is true (not +nil+ or +false+),
1710 * includes bolding ANSI codes (see below) to enhance the appearance of the message.
1711 * - Includes the {backtrace}[rdoc-ref:exceptions.md@Backtraces]:
1712 *
1713 * - If the value of keyword +order+ is +:top+ (the default),
1714 * lists the error message and the innermost backtrace entry first.
1715 * - If the value of keyword +order+ is +:bottom+,
1716 * lists the error message the innermost entry last.
1717 *
1718 * Example:
1719 *
1720 * def baz
1721 * begin
1722 * 1 / 0
1723 * rescue => x
1724 * pp x.message
1725 * pp x.full_message(highlight: false).split("\n")
1726 * pp x.full_message.split("\n")
1727 * end
1728 * end
1729 * def bar; baz; end
1730 * def foo; bar; end
1731 * foo
1732 *
1733 * Output:
1734 *
1735 * "divided by 0"
1736 * ["t.rb:3:in 'Integer#/': divided by 0 (ZeroDivisionError)",
1737 * "\tfrom t.rb:3:in 'Object#baz'",
1738 * "\tfrom t.rb:10:in 'Object#bar'",
1739 * "\tfrom t.rb:11:in 'Object#foo'",
1740 * "\tfrom t.rb:12:in '<main>'"]
1741 * ["t.rb:3:in 'Integer#/': \e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m",
1742 * "\tfrom t.rb:3:in 'Object#baz'",
1743 * "\tfrom t.rb:10:in 'Object#bar'",
1744 * "\tfrom t.rb:11:in 'Object#foo'",
1745 * "\tfrom t.rb:12:in '<main>'"]
1746 *
1747 * An overriding method should be careful with ANSI code enhancements;
1748 * see {Messages}[rdoc-ref:exceptions.md@Messages].
1749 */
1750
1751static VALUE
1752exc_full_message(int argc, VALUE *argv, VALUE exc)
1753{
1754 VALUE opt, str, emesg, errat;
1755 VALUE highlight, order;
1756
1757 rb_scan_args(argc, argv, "0:", &opt);
1758
1759 highlight = check_highlight_keyword(opt, 1);
1760 order = check_order_keyword(opt);
1761
1762 {
1763 if (NIL_P(opt)) opt = rb_hash_new_capa(1);
1764 rb_hash_aset(opt, sym_highlight, highlight);
1765 }
1766
1767 str = rb_str_new2("");
1768 errat = rb_get_backtrace(exc);
1769 emesg = rb_get_detailed_message(exc, opt);
1770
1771 rb_error_write(exc, emesg, errat, str, opt, highlight, order);
1772 return str;
1773}
1774
1775/*
1776 * call-seq:
1777 * message -> string
1778 *
1779 * Returns #to_s.
1780 *
1781 * See {Messages}[rdoc-ref:exceptions.md@Messages].
1782 */
1783
1784static VALUE
1785exc_message(VALUE exc)
1786{
1787 return rb_funcallv(exc, idTo_s, 0, 0);
1788}
1789
1790// Whether error_highlight, did_you_mean, and syntax_suggest have already
1791// been loaded (lazily on the first error, or eagerly via Process.warmup).
1792// Ractors run in parallel, so the load is claimed by an atomic exchange.
1793static rb_atomic_t decoration_gems_loaded = 0;
1794
1795static VALUE
1796load_decoration_gem(VALUE feature)
1797{
1798 // The C-level require bypasses Kernel#require monkeypatches;
1799 // displaying an error must not invoke or depend on them.
1800 return rb_require_string(feature);
1801}
1802
1803// Require error_highlight, did_you_mean, and syntax_suggest.
1804// rb_define_gem_modules registers an autoload entry for each enabled gem;
1805// disabled gems have no entry and are skipped.
1806static void
1807require_decoration_gems(void)
1808{
1809 // Loading must not disturb the caller's $!: it is called while
1810 // displaying an exception. rb_protect does not preserve errinfo, so
1811 // save and restore it around the requires, leaving $! untouched
1812 // whether or not a require raises.
1813 VALUE saved_errinfo = rb_errinfo();
1814 static const char *const gems[] = {"ErrorHighlight", "DidYouMean", "SyntaxSuggest"};
1815 for (size_t i = 0; i < numberof(gems); i++) {
1816 VALUE feature = rb_autoload_p(rb_cObject, rb_intern(gems[i]));
1817 if (NIL_P(feature)) continue;
1818 int state;
1819 rb_protect(load_decoration_gem, feature, &state);
1820 (void)state;
1821 }
1822 rb_set_errinfo(saved_errinfo);
1823}
1824
1825// Load the decoration gems on the first error display instead of at boot.
1826// In non-main Ractors rb_require_string delegates the require to the main
1827// Ractor, so this works from any Ractor.
1828// Returns whether the caller should re-dispatch to pick up the
1829// detailed_message decorators the gems prepend.
1830static bool
1831lazy_load_decoration_gems(VALUE exc)
1832{
1833 if (ATOMIC_EXCHANGE(decoration_gems_loaded, 1)) return false;
1834
1835 // When entered through super from a decorator already sitting above
1836 // this method, the caller decorates the result; re-dispatching would
1837 // decorate it twice.
1838 bool redispatch = rb_method_basic_definition_p(CLASS_OF(exc), id_detailed_message);
1839
1840 require_decoration_gems();
1841 return redispatch;
1842}
1843
1844// Load the decoration gems eagerly, e.g. from Process.warmup before a
1845// pre-forking server forks, so the prepended detailed_message decorators
1846// land in shared memory and do not bust method caches at runtime.
1847void
1848rb_eager_load_detailed_message_extension(void)
1849{
1850 if (ATOMIC_EXCHANGE(decoration_gems_loaded, 1)) return;
1851
1852 require_decoration_gems();
1853}
1854
1855/*
1856 * call-seq:
1857 * detailed_message(highlight: false, **kwargs) -> string
1858 *
1859 * Returns the message string with enhancements:
1860 *
1861 * - Includes the exception class name in the first line.
1862 * - If the value of keyword +highlight+ is +true+,
1863 * includes bolding and underlining ANSI codes (see below)
1864 * to enhance the appearance of the message.
1865 *
1866 * Examples:
1867 *
1868 * begin
1869 * 1 / 0
1870 * rescue => x
1871 * p x.message
1872 * p x.detailed_message # Class name added.
1873 * p x.detailed_message(highlight: true) # Class name, bolding, and underlining added.
1874 * end
1875 *
1876 * Output:
1877 *
1878 * "divided by 0"
1879 * "divided by 0 (ZeroDivisionError)"
1880 * "\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m"
1881 *
1882 * This method is overridden by some gems in the Ruby standard library to add information:
1883 *
1884 * - DidYouMean::Correctable#detailed_message.
1885 * - ErrorHighlight::CoreExt#detailed_message.
1886 * - SyntaxSuggest#detailed_message.
1887 *
1888 * An overriding method must be tolerant of passed keyword arguments,
1889 * which may include (but may not be limited to):
1890 *
1891 * - +:highlight+.
1892 * - +:did_you_mean+.
1893 * - +:error_highlight+.
1894 * - +:syntax_suggest+.
1895 *
1896 * An overriding method should also be careful with ANSI code enhancements;
1897 * see {Messages}[rdoc-ref:exceptions.md@Messages].
1898 */
1899
1900static VALUE
1901exc_detailed_message(int argc, VALUE *argv, VALUE exc)
1902{
1903 if (lazy_load_decoration_gems(exc)) {
1904 return rb_funcallv_kw(exc, id_detailed_message, argc, argv, RB_PASS_CALLED_KEYWORDS);
1905 }
1906
1907 VALUE opt;
1908
1909 rb_scan_args(argc, argv, "0:", &opt);
1910
1911 VALUE highlight = check_highlight_keyword(opt, 0);
1912
1913 extern VALUE rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight);
1914
1915 return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight));
1916}
1917
1918/*
1919 * call-seq:
1920 * inspect -> string
1921 *
1922 * Returns a string representation of +self+:
1923 *
1924 * x = RuntimeError.new('Boom')
1925 * x.inspect # => "#<RuntimeError: Boom>"
1926 * x = RuntimeError.new
1927 * x.inspect # => "#<RuntimeError: RuntimeError>"
1928 *
1929 */
1930
1931static VALUE
1932exc_inspect(VALUE exc)
1933{
1934 VALUE str, klass;
1935
1936 klass = CLASS_OF(exc);
1937 exc = rb_obj_as_string(exc);
1938 if (RSTRING_LEN(exc) == 0) {
1939 return rb_class_name(klass);
1940 }
1941
1942 str = rb_str_buf_new2("#<");
1943 klass = rb_class_name(klass);
1944 rb_str_buf_append(str, klass);
1945
1946 if (RTEST(rb_str_include(exc, rb_str_new2("\n")))) {
1947 rb_str_catf(str, ":%+"PRIsVALUE, exc);
1948 }
1949 else {
1950 rb_str_buf_cat(str, ": ", 2);
1951 rb_str_buf_append(str, exc);
1952 }
1953
1954 rb_str_buf_cat(str, ">", 1);
1955
1956 return str;
1957}
1958
1959/*
1960 * call-seq:
1961 * backtrace -> array or nil
1962 *
1963 * Returns the backtrace (the list of code locations that led to the exception),
1964 * as an array of strings.
1965 *
1966 * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
1967 *
1968 * def division(numerator, denominator)
1969 * numerator / denominator
1970 * end
1971 *
1972 * begin
1973 * division(1, 0)
1974 * rescue => ex
1975 * p ex.backtrace
1976 * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
1977 * loc = ex.backtrace.first
1978 * p loc.class
1979 * # String
1980 * end
1981 *
1982 * The value returned by this method might be adjusted when raising (see Kernel#raise),
1983 * or during intermediate handling by #set_backtrace.
1984 *
1985 * See also #backtrace_locations that provide the same value, as structured objects.
1986 * (Note though that two values might not be consistent with each other when
1987 * backtraces are manually adjusted.)
1988 *
1989 * see {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
1990 */
1991
1992static VALUE
1993exc_backtrace(VALUE exc)
1994{
1995 VALUE obj;
1996
1997 obj = rb_attr_get(exc, id_bt);
1998
1999 if (rb_backtrace_p(obj)) {
2000 obj = rb_backtrace_to_str_ary(obj);
2001 /* rb_ivar_set(exc, id_bt, obj); */
2002 }
2003
2004 return obj;
2005}
2006
2007static VALUE rb_check_backtrace(VALUE);
2008
2009VALUE
2010rb_get_backtrace(VALUE exc)
2011{
2012 ID mid = id_backtrace;
2013 VALUE info;
2014 if (rb_method_basic_definition_p(CLASS_OF(exc), id_backtrace)) {
2015 VALUE klass = rb_eException;
2016 rb_execution_context_t *ec = GET_EC();
2017 if (NIL_P(exc))
2018 return Qnil;
2019 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
2020 info = exc_backtrace(exc);
2021 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
2022 }
2023 else {
2024 info = rb_funcallv(exc, mid, 0, 0);
2025 }
2026 if (NIL_P(info)) return Qnil;
2027 return rb_check_backtrace(info);
2028}
2029
2030/*
2031 * call-seq:
2032 * backtrace_locations -> array or nil
2033 *
2034 * Returns the backtrace (the list of code locations that led to the exception),
2035 * as an array of Thread::Backtrace::Location instances.
2036 *
2037 * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
2038 *
2039 * def division(numerator, denominator)
2040 * numerator / denominator
2041 * end
2042 *
2043 * begin
2044 * division(1, 0)
2045 * rescue => ex
2046 * p ex.backtrace_locations
2047 * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
2048 * loc = ex.backtrace_locations.first
2049 * p loc.class
2050 * # Thread::Backtrace::Location
2051 * p loc.path
2052 * # "t.rb"
2053 * p loc.lineno
2054 * # 2
2055 * p loc.label
2056 * # "Integer#/"
2057 * end
2058 *
2059 * The value returned by this method might be adjusted when raising (see Kernel#raise),
2060 * or during intermediate handling by #set_backtrace.
2061 *
2062 * See also #backtrace that provide the same value as an array of strings.
2063 * (Note though that two values might not be consistent with each other when
2064 * backtraces are manually adjusted.)
2065 *
2066 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
2067 */
2068static VALUE
2069exc_backtrace_locations(VALUE exc)
2070{
2071 VALUE obj;
2072
2073 obj = rb_attr_get(exc, id_bt_locations);
2074 if (!NIL_P(obj)) {
2075 obj = rb_backtrace_to_location_ary(obj);
2076 }
2077 return obj;
2078}
2079
2080static VALUE
2081rb_check_backtrace(VALUE bt)
2082{
2083 rb_len_t i;
2084 static const char err[] = "backtrace must be an Array of String or an Array of Thread::Backtrace::Location";
2085
2086 if (!NIL_P(bt)) {
2087 if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
2088 if (rb_backtrace_p(bt)) return bt;
2089 if (!RB_TYPE_P(bt, T_ARRAY)) {
2090 rb_raise(rb_eTypeError, err);
2091 }
2092 for (i=0;i<RARRAY_LEN(bt);i++) {
2093 VALUE e = RARRAY_AREF(bt, i);
2094 if (!RB_TYPE_P(e, T_STRING)) {
2095 rb_raise(rb_eTypeError, err);
2096 }
2097 }
2098 }
2099 return bt;
2100}
2101
2102/*
2103 * call-seq:
2104 * set_backtrace(value) -> value
2105 *
2106 * Sets the backtrace value for +self+; returns the given +value+.
2107 *
2108 * The +value+ might be:
2109 *
2110 * - an array of Thread::Backtrace::Location;
2111 * - an array of String instances;
2112 * - a single String instance; or
2113 * - +nil+.
2114 *
2115 * Using array of Thread::Backtrace::Location is the most consistent
2116 * option: it sets both #backtrace and #backtrace_locations. It should be
2117 * preferred when possible. The suitable array of locations can be obtained
2118 * from Kernel#caller_locations, copied from another error, or just set to
2119 * the adjusted result of the current error's #backtrace_locations:
2120 *
2121 * require 'json'
2122 *
2123 * def parse_payload(text)
2124 * JSON.parse(text) # test.rb, line 4
2125 * rescue JSON::ParserError => ex
2126 * ex.set_backtrace(ex.backtrace_locations[2...])
2127 * raise
2128 * end
2129 *
2130 * parse_payload('{"wrong: "json"')
2131 * # test.rb:4:in 'Object#parse_payload': unexpected token at '{"wrong: "json"' (JSON::ParserError)
2132 * #
2133 * # An error points to the body of parse_payload method,
2134 * # hiding the parts of the backtrace related to the internals
2135 * # of the "json" library
2136 *
2137 * # The error has both #backtace and #backtrace_locations set
2138 * # consistently:
2139 * begin
2140 * parse_payload('{"wrong: "json"')
2141 * rescue => ex
2142 * p ex.backtrace
2143 * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
2144 * p ex.backtrace_locations
2145 * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
2146 * end
2147 *
2148 * When the desired stack of locations is not available and should
2149 * be constructed from scratch, an array of strings or a singular
2150 * string can be used. In this case, only #backtrace is affected:
2151 *
2152 * def parse_payload(text)
2153 * JSON.parse(text)
2154 * rescue JSON::ParserError => ex
2155 * ex.set_backtrace(["dsl.rb:34", "framework.rb:1"])
2156 * # The error have the new value in #backtrace:
2157 * p ex.backtrace
2158 * # ["dsl.rb:34", "framework.rb:1"]
2159 *
2160 * # but the original one in #backtrace_locations
2161 * p ex.backtrace_locations
2162 * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
2163 * end
2164 *
2165 * parse_payload('{"wrong: "json"')
2166 *
2167 * Calling #set_backtrace with +nil+ clears up #backtrace but doesn't affect
2168 * #backtrace_locations:
2169 *
2170 * def parse_payload(text)
2171 * JSON.parse(text)
2172 * rescue JSON::ParserError => ex
2173 * ex.set_backtrace(nil)
2174 * p ex.backtrace
2175 * # nil
2176 * p ex.backtrace_locations
2177 * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
2178 * end
2179 *
2180 * parse_payload('{"wrong: "json"')
2181 *
2182 * On reraising of such an exception, both #backtrace and #backtrace_locations
2183 * is set to the place of reraising:
2184 *
2185 * def parse_payload(text)
2186 * JSON.parse(text)
2187 * rescue JSON::ParserError => ex
2188 * ex.set_backtrace(nil)
2189 * raise # test.rb, line 7
2190 * end
2191 *
2192 * begin
2193 * parse_payload('{"wrong: "json"')
2194 * rescue => ex
2195 * p ex.backtrace
2196 * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
2197 * p ex.backtrace_locations
2198 * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
2199 * end
2200 *
2201 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
2202 */
2203
2204static VALUE
2205exc_set_backtrace(VALUE exc, VALUE bt)
2206{
2207 VALUE btobj = rb_location_ary_to_backtrace(bt);
2208 if (RTEST(btobj)) {
2209 rb_ivar_set(exc, id_bt, btobj);
2210 rb_ivar_set(exc, id_bt_locations, btobj);
2211 return bt;
2212 }
2213 else {
2214 return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
2215 }
2216}
2217
2218VALUE
2219rb_exc_set_backtrace(VALUE exc, VALUE bt)
2220{
2221 return exc_set_backtrace(exc, bt);
2222}
2223
2224/*
2225 * call-seq:
2226 * cause -> exception or nil
2227 *
2228 * Returns the previous value of global variable <tt>$!</tt>,
2229 * which may be +nil+
2230 * (see {Global Variables}[rdoc-ref:exceptions.md@Global+Variables]):
2231 *
2232 * begin
2233 * raise('Boom 0')
2234 * rescue => x0
2235 * puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}."
2236 * begin
2237 * raise('Boom 1')
2238 * rescue => x1
2239 * puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}."
2240 * begin
2241 * raise('Boom 2')
2242 * rescue => x2
2243 * puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}."
2244 * end
2245 * end
2246 * end
2247 *
2248 * Output:
2249 *
2250 * Exception: Boom 0; $!: Boom 0; cause: nil.
2251 * Exception: Boom 1; $!: Boom 1; cause: Boom 0.
2252 * Exception: Boom 2; $!: Boom 2; cause: Boom 1.
2253 *
2254 */
2255
2256static VALUE
2257exc_cause(VALUE exc)
2258{
2259 return rb_attr_get(exc, id_cause);
2260}
2261
2262static VALUE
2263try_convert_to_exception(VALUE obj)
2264{
2265 return rb_check_funcall(obj, idException, 0, 0);
2266}
2267
2268/*
2269 * call-seq:
2270 * self == other -> true or false
2271 *
2272 * Returns whether +other+ is the same class as +self+
2273 * and its #message and #backtrace are equal to those of +self+.
2274 *
2275 */
2276
2277static VALUE
2278exc_equal(VALUE exc, VALUE obj)
2279{
2280 VALUE mesg, backtrace;
2281
2282 if (exc == obj) return Qtrue;
2283
2284 if (rb_obj_class(exc) != rb_obj_class(obj)) {
2285 int state;
2286
2287 obj = rb_protect(try_convert_to_exception, obj, &state);
2288 if (state || UNDEF_P(obj)) {
2289 rb_set_errinfo(Qnil);
2290 return Qfalse;
2291 }
2292 if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
2293 mesg = rb_check_funcall(obj, id_message, 0, 0);
2294 if (UNDEF_P(mesg)) return Qfalse;
2295 backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
2296 if (UNDEF_P(backtrace)) return Qfalse;
2297 }
2298 else {
2299 mesg = rb_attr_get(obj, id_mesg);
2300 backtrace = exc_backtrace(obj);
2301 }
2302
2303 if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
2304 return Qfalse;
2305 return rb_equal(exc_backtrace(exc), backtrace);
2306}
2307
2308/*
2309 * call-seq:
2310 * SystemExit.new -> system_exit
2311 * SystemExit.new(status) -> system_exit
2312 * SystemExit.new(status, msg) -> system_exit
2313 * SystemExit.new(msg) -> system_exit
2314 *
2315 * Create a new +SystemExit+ exception with the given status and message.
2316 * Status is true, false, or an integer.
2317 * If status is not given, true is used.
2318 */
2319
2320static VALUE
2321exit_initialize(int argc, VALUE *argv, VALUE exc)
2322{
2323 VALUE status;
2324 if (argc > 0) {
2325 status = *argv;
2326
2327 switch (status) {
2328 case Qtrue:
2329 status = INT2FIX(EXIT_SUCCESS);
2330 ++argv;
2331 --argc;
2332 break;
2333 case Qfalse:
2334 status = INT2FIX(EXIT_FAILURE);
2335 ++argv;
2336 --argc;
2337 break;
2338 default:
2339 status = rb_check_to_int(status);
2340 if (NIL_P(status)) {
2341 status = INT2FIX(EXIT_SUCCESS);
2342 }
2343 else {
2344#if EXIT_SUCCESS != 0
2345 if (status == INT2FIX(0))
2346 status = INT2FIX(EXIT_SUCCESS);
2347#endif
2348 ++argv;
2349 --argc;
2350 }
2351 break;
2352 }
2353 }
2354 else {
2355 status = INT2FIX(EXIT_SUCCESS);
2356 }
2357 rb_call_super(argc, argv);
2358 rb_ivar_set(exc, id_status, status);
2359 return exc;
2360}
2361
2362
2363/*
2364 * call-seq:
2365 * system_exit.status -> integer
2366 *
2367 * Return the status value associated with this system exit.
2368 */
2369
2370static VALUE
2371exit_status(VALUE exc)
2372{
2373 return rb_attr_get(exc, id_status);
2374}
2375
2376
2377/*
2378 * call-seq:
2379 * system_exit.success? -> true or false
2380 *
2381 * Returns +true+ if exiting successful, +false+ if not.
2382 */
2383
2384static VALUE
2385exit_success_p(VALUE exc)
2386{
2387 VALUE status_val = rb_attr_get(exc, id_status);
2388 int status;
2389
2390 if (NIL_P(status_val))
2391 return Qtrue;
2392 status = NUM2INT(status_val);
2393 return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
2394}
2395
2396static VALUE
2397err_init_recv(VALUE exc, VALUE recv)
2398{
2399 if (!UNDEF_P(recv)) rb_ivar_set(exc, id_recv, recv);
2400 return exc;
2401}
2402
2403/*
2404 * call-seq:
2405 * FrozenError.new(msg=nil, receiver: nil) -> frozen_error
2406 *
2407 * Construct a new FrozenError exception. If given the <i>receiver</i>
2408 * parameter may subsequently be examined using the FrozenError#receiver
2409 * method.
2410 *
2411 * a = [].freeze
2412 * raise FrozenError.new("can't modify frozen array", receiver: a)
2413 */
2414
2415static VALUE
2416frozen_err_initialize(int argc, VALUE *argv, VALUE self)
2417{
2418 ID keywords[1];
2419 VALUE values[numberof(keywords)], options;
2420
2421 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
2422 keywords[0] = id_receiver;
2423 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2424 rb_call_super(argc, argv);
2425 err_init_recv(self, values[0]);
2426 return self;
2427}
2428
2429/*
2430 * Document-method: FrozenError#receiver
2431 * call-seq:
2432 * frozen_error.receiver -> object
2433 *
2434 * Return the receiver associated with this FrozenError exception.
2435 */
2436
2437#define frozen_err_receiver name_err_receiver
2438
2439void
2440rb_name_error(ID id, const char *fmt, ...)
2441{
2442 VALUE exc, argv[2];
2443 va_list args;
2444
2445 va_start(args, fmt);
2446 argv[0] = rb_vsprintf(fmt, args);
2447 va_end(args);
2448
2449 argv[1] = ID2SYM(id);
2450 exc = rb_class_new_instance(2, argv, rb_eNameError);
2451 rb_exc_raise(exc);
2452}
2453
2454void
2455rb_name_error_str(VALUE str, const char *fmt, ...)
2456{
2457 VALUE exc, argv[2];
2458 va_list args;
2459
2460 va_start(args, fmt);
2461 argv[0] = rb_vsprintf(fmt, args);
2462 va_end(args);
2463
2464 argv[1] = str;
2465 exc = rb_class_new_instance(2, argv, rb_eNameError);
2466 rb_exc_raise(exc);
2467}
2468
2469static VALUE
2470name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
2471{
2472 const rb_execution_context_t *ec = GET_EC();
2473 rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
2474 cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
2475 rb_ivar_set(exc, id_name, method);
2476 err_init_recv(exc, recv);
2477 if (cfp && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
2478 rb_ivar_set(exc, id_iseq, rb_iseqw_new(CFP_ISEQ(cfp)));
2479 }
2480 return exc;
2481}
2482
2483/*
2484 * call-seq:
2485 * NameError.new(msg=nil, name=nil, receiver: nil) -> name_error
2486 *
2487 * Construct a new NameError exception. If given the <i>name</i>
2488 * parameter may subsequently be examined using the NameError#name
2489 * method. <i>receiver</i> parameter allows to pass object in
2490 * context of which the error happened. Example:
2491 *
2492 * [1, 2, 3].method(:rject) # NameError with name "rject" and receiver: Array
2493 * [1, 2, 3].singleton_method(:rject) # NameError with name "rject" and receiver: [1, 2, 3]
2494 */
2495
2496static VALUE
2497name_err_initialize(int argc, VALUE *argv, VALUE self)
2498{
2499 ID keywords[1];
2500 VALUE values[numberof(keywords)], name, options;
2501
2502 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
2503 keywords[0] = id_receiver;
2504 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2505 name = (argc > 1) ? argv[--argc] : Qnil;
2506 rb_call_super(argc, argv);
2507 name_err_init_attr(self, values[0], name);
2508 return self;
2509}
2510
2511static VALUE rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method);
2512
2513static VALUE
2514name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method)
2515{
2516 exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
2517 return name_err_init_attr(exc, recv, method);
2518}
2519
2520VALUE
2521rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
2522{
2524 return name_err_init(exc, mesg, recv, method);
2525}
2526
2527/*
2528 * call-seq:
2529 * name_error.name -> string or nil
2530 *
2531 * Return the name associated with this NameError exception.
2532 */
2533
2534static VALUE
2535name_err_name(VALUE self)
2536{
2537 return rb_attr_get(self, id_name);
2538}
2539
2540/*
2541 * call-seq:
2542 * name_error.local_variables -> array
2543 *
2544 * Return a list of the local variable names defined where this
2545 * NameError exception was raised.
2546 *
2547 * Internal use only.
2548 */
2549
2550static VALUE
2551name_err_local_variables(VALUE self)
2552{
2553 VALUE vars = rb_attr_get(self, id_local_variables);
2554
2555 if (NIL_P(vars)) {
2556 VALUE iseqw = rb_attr_get(self, id_iseq);
2557 if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
2558 if (NIL_P(vars)) vars = rb_ary_new();
2559 rb_ivar_set(self, id_local_variables, vars);
2560 }
2561 return vars;
2562}
2563
2564static VALUE
2565nometh_err_init_attr(VALUE exc, VALUE args, int priv)
2566{
2567 rb_ivar_set(exc, id_args, args);
2568 rb_ivar_set(exc, id_private_call_p, RBOOL(priv));
2569 return exc;
2570}
2571
2572/*
2573 * call-seq:
2574 * NoMethodError.new(msg=nil, name=nil, args=nil, private=false, receiver: nil) -> no_method_error
2575 *
2576 * Construct a NoMethodError exception for a method of the given name
2577 * called with the given arguments. The name may be accessed using
2578 * the <code>#name</code> method on the resulting object, and the
2579 * arguments using the <code>#args</code> method.
2580 *
2581 * If <i>private</i> argument were passed, it designates method was
2582 * attempted to call in private context, and can be accessed with
2583 * <code>#private_call?</code> method.
2584 *
2585 * <i>receiver</i> argument stores an object whose method was called.
2586 */
2587
2588static VALUE
2589nometh_err_initialize(int argc, VALUE *argv, VALUE self)
2590{
2591 int priv;
2592 VALUE args, options;
2593 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
2594 priv = (argc > 3) && (--argc, RTEST(argv[argc]));
2595 args = (argc > 2) ? argv[--argc] : Qnil;
2596 if (!NIL_P(options)) argv[argc++] = options;
2598 return nometh_err_init_attr(self, args, priv);
2599}
2600
2601VALUE
2602rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
2603{
2605 name_err_init(exc, mesg, recv, method);
2606 return nometh_err_init_attr(exc, args, priv);
2607}
2608
2610 VALUE mesg;
2611 VALUE recv;
2612 VALUE name;
2614
2615static void
2616name_err_mesg_mark_and_move(void *p)
2617{
2619 rb_gc_mark_and_move(&ptr->mesg);
2620 rb_gc_mark_and_move(&ptr->recv);
2621 rb_gc_mark_and_move(&ptr->name);
2622}
2623
2624static const rb_data_type_t name_err_mesg_data_type = {
2625 "name_err_mesg",
2626 {
2627 name_err_mesg_mark_and_move,
2629 NULL, // No external memory to report,
2630 name_err_mesg_mark_and_move,
2631 },
2632 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
2633};
2634
2635/* :nodoc: */
2636static VALUE
2637rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE name)
2638{
2639 name_error_message_t *message;
2640 VALUE result = TypedData_Make_Struct(klass, name_error_message_t, &name_err_mesg_data_type, message);
2641 RB_OBJ_WRITE(result, &message->mesg, mesg);
2642 RB_OBJ_WRITE(result, &message->recv, recv);
2643 RB_OBJ_WRITE(result, &message->name, name);
2644 return result;
2645}
2646
2647/* :nodoc: */
2648static VALUE
2649rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
2650{
2651 return rb_name_err_mesg_init(rb_cNameErrorMesg, mesg, recv, method);
2652}
2653
2654/* :nodoc: */
2655static VALUE
2656name_err_mesg_alloc(VALUE klass)
2657{
2658 return rb_name_err_mesg_init(klass, Qnil, Qnil, Qnil);
2659}
2660
2661/* :nodoc: */
2662static VALUE
2663name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
2664{
2665 if (obj1 == obj2) return obj1;
2666 rb_obj_init_copy(obj1, obj2);
2667
2668 name_error_message_t *ptr1, *ptr2;
2669 TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
2670 TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
2671
2672 RB_OBJ_WRITE(obj1, &ptr1->mesg, ptr2->mesg);
2673 RB_OBJ_WRITE(obj1, &ptr1->recv, ptr2->recv);
2674 RB_OBJ_WRITE(obj1, &ptr1->name, ptr2->name);
2675 return obj1;
2676}
2677
2678/* :nodoc: */
2679static VALUE
2680name_err_mesg_equal(VALUE obj1, VALUE obj2)
2681{
2682 if (obj1 == obj2) return Qtrue;
2683
2684 if (rb_obj_class(obj2) != rb_cNameErrorMesg)
2685 return Qfalse;
2686
2687 name_error_message_t *ptr1, *ptr2;
2688 TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
2689 TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
2690
2691 if (!rb_equal(ptr1->mesg, ptr2->mesg)) return Qfalse;
2692 if (!rb_equal(ptr1->recv, ptr2->recv)) return Qfalse;
2693 if (!rb_equal(ptr1->name, ptr2->name)) return Qfalse;
2694 return Qtrue;
2695}
2696
2697/* :nodoc: */
2698static VALUE
2699name_err_mesg_receiver_name(VALUE obj)
2700{
2701 if (RB_SPECIAL_CONST_P(obj)) return Qundef;
2702 if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) {
2703 return rb_check_funcall(obj, rb_intern("name"), 0, 0);
2704 }
2705 return Qundef;
2706}
2707
2708/* :nodoc: */
2709static VALUE
2710name_err_mesg_to_str(VALUE obj)
2711{
2713 TypedData_Get_Struct(obj, name_error_message_t, &name_err_mesg_data_type, ptr);
2714
2715 VALUE mesg = ptr->mesg;
2716 if (NIL_P(mesg)) return Qnil;
2717 else {
2718 struct RString s_str = {RBASIC_INIT}, c_str = {RBASIC_INIT}, d_str = {RBASIC_INIT};
2719 VALUE c, s, d = 0, args[4], c2;
2720 int state = 0;
2721 rb_encoding *usascii = rb_usascii_encoding();
2722
2723#define rb_memsearch_lit(str, v) \
2724 rb_memsearch((str), rb_strlen_lit(str), RSTRING_PTR(v), RSTRING_LEN(v), rb_enc_get(v))
2725#define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
2726 c = s = FAKE_CSTR(&s_str, "");
2727 obj = ptr->recv;
2728 switch (obj) {
2729 case Qnil:
2730 c = d = FAKE_CSTR(&d_str, "nil");
2731 break;
2732 case Qtrue:
2733 c = d = FAKE_CSTR(&d_str, "true");
2734 break;
2735 case Qfalse:
2736 c = d = FAKE_CSTR(&d_str, "false");
2737 break;
2738 default:
2739 if (rb_memsearch_lit("%2$s", mesg) >= 0) {
2740 d = rb_protect(name_err_mesg_receiver_name, obj, &state);
2741 if (state || NIL_OR_UNDEF_P(d))
2742 d = rb_protect(rb_inspect, obj, &state);
2743 if (state) {
2744 rb_set_errinfo(Qnil);
2745 }
2746 d = rb_check_string_type(d);
2747 if (NIL_P(d)) {
2748 d = rb_any_to_s(obj);
2749 }
2750 }
2751
2752 if (!RB_SPECIAL_CONST_P(obj)) {
2753 switch (RB_BUILTIN_TYPE(obj)) {
2754 case T_MODULE:
2755 s = FAKE_CSTR(&s_str, "module ");
2756 c = obj;
2757 break;
2758 case T_CLASS:
2759 s = FAKE_CSTR(&s_str, "class ");
2760 c = obj;
2761 break;
2762 default:
2763 goto object;
2764 }
2765 }
2766 else {
2767 VALUE klass;
2768 object:
2769 klass = CLASS_OF(obj);
2770 if (RB_TYPE_P(klass, T_CLASS) && RCLASS_SINGLETON_P(klass)) {
2771 s = FAKE_CSTR(&s_str, "");
2772 if (obj == rb_vm_top_self()) {
2773 c = FAKE_CSTR(&c_str, "main");
2774 }
2775 else {
2776 c = rb_any_to_s(obj);
2777 }
2778 break;
2779 }
2780 else {
2781 s = FAKE_CSTR(&s_str, "an instance of ");
2782 c = rb_class_real(klass);
2783 }
2784 }
2785 c2 = rb_protect(name_err_mesg_receiver_name, c, &state);
2786 if (state || NIL_OR_UNDEF_P(c2))
2787 c2 = rb_protect(rb_inspect, c, &state);
2788 if (state) {
2789 rb_set_errinfo(Qnil);
2790 }
2791 c2 = rb_check_string_type(c2);
2792 if (NIL_P(c2)) {
2793 c2 = rb_any_to_s(c);
2794 }
2795 c = c2;
2796 break;
2797 }
2798 args[0] = rb_obj_as_string(ptr->name);
2799 args[1] = d;
2800 args[2] = s;
2801 args[3] = c;
2802 mesg = rb_str_format(4, args, mesg);
2803 }
2804 return mesg;
2805}
2806
2807/* :nodoc: */
2808static VALUE
2809name_err_mesg_dump(VALUE obj, VALUE limit)
2810{
2811 return name_err_mesg_to_str(obj);
2812}
2813
2814/* :nodoc: */
2815static VALUE
2816name_err_mesg_load(VALUE klass, VALUE str)
2817{
2818 return str;
2819}
2820
2821/*
2822 * call-seq:
2823 * name_error.receiver -> object
2824 *
2825 * Return the receiver associated with this NameError exception.
2826 */
2827
2828static VALUE
2829name_err_receiver(VALUE self)
2830{
2831 VALUE recv = rb_ivar_lookup(self, id_recv, Qundef);
2832 if (!UNDEF_P(recv)) return recv;
2833
2834 VALUE mesg = rb_attr_get(self, id_mesg);
2835 if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
2836 rb_raise(rb_eArgError, "no receiver is available");
2837 }
2838
2840 TypedData_Get_Struct(mesg, name_error_message_t, &name_err_mesg_data_type, ptr);
2841 return ptr->recv;
2842}
2843
2844/*
2845 * call-seq:
2846 * no_method_error.args -> obj
2847 *
2848 * Return the arguments passed in as the third parameter to
2849 * the constructor.
2850 */
2851
2852static VALUE
2853nometh_err_args(VALUE self)
2854{
2855 return rb_attr_get(self, id_args);
2856}
2857
2858/*
2859 * call-seq:
2860 * no_method_error.private_call? -> true or false
2861 *
2862 * Return true if the caused method was called as private.
2863 */
2864
2865static VALUE
2866nometh_err_private_call_p(VALUE self)
2867{
2868 return rb_attr_get(self, id_private_call_p);
2869}
2870
2871static const char *
2872type_err_cname(VALUE val)
2873{
2874 if (NIL_P(val)) {
2875 return "nil";
2876 }
2877 else if (val == Qtrue) {
2878 return "true";
2879 }
2880 else if (val == Qfalse) {
2881 return "false";
2882 }
2883 return NULL;
2884}
2885
2886NORETURN(static void type_err_raise(VALUE val, const char *tname, const char *msg));
2887static void
2888type_err_raise(VALUE val, const char *tname, const char *msg)
2889{
2890 const char *cname = type_err_cname(val);
2891 rb_encoding *enc = rb_utf8_encoding();
2892 if (cname) {
2893 rb_enc_raise(enc, rb_eTypeError, "%s %s into %s", msg, cname, tname);
2894 }
2895 rb_enc_raise(enc, rb_eTypeError, "%s %"PRIsVALUE" into %s", msg, rb_obj_class(val), tname);
2896}
2897
2898NORETURN(void rb_no_implicit_conversion(VALUE val, const char *tname));
2899void
2900rb_no_implicit_conversion(VALUE val, const char *tname)
2901{
2902 type_err_raise(val, tname, "no implicit conversion of");
2903}
2904
2905NORETURN(void rb_cant_convert(VALUE val, const char *tname));
2906void
2907rb_cant_convert(VALUE val, const char *tname)
2908{
2909 type_err_raise(val, tname, "can't convert");
2910}
2911
2912NORETURN(void rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret));
2913void
2914rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret)
2915{
2916 const char *cname = type_err_cname(val);
2917 rb_encoding *enc = rb_utf8_encoding();
2918 if (cname) {
2920 enc, rb_eTypeError, "can't convert %s into %s (%s#%s gives %s)",
2921 cname, tname, cname, method_name, type_err_cname(ret));
2922 }
2923 VALUE klass = rb_obj_class(val);
2924 const char *retname = type_err_cname(ret);
2925 if (!retname) {
2926 retname = rb_obj_classname(ret);
2927 }
2929 enc, rb_eTypeError, "can't convert %"PRIsVALUE" into %s (%"PRIsVALUE"#%s gives %s)",
2930 klass, tname, klass, method_name, retname);
2931}
2932
2933void
2934rb_invalid_str(const char *str, const char *type)
2935{
2936 VALUE s = rb_str_new2(str);
2937
2938 rb_raise(rb_eArgError, "invalid value for %s: %+"PRIsVALUE, type, s);
2939}
2940
2941/*
2942 * call-seq:
2943 * key_error.receiver -> object
2944 *
2945 * Return the receiver associated with this KeyError exception.
2946 */
2947
2948static VALUE
2949key_err_receiver(VALUE self)
2950{
2951 VALUE recv;
2952
2953 recv = rb_ivar_lookup(self, id_receiver, Qundef);
2954 if (!UNDEF_P(recv)) return recv;
2955 rb_raise(rb_eArgError, "no receiver is available");
2956}
2957
2958/*
2959 * call-seq:
2960 * key_error.key -> object
2961 *
2962 * Return the key caused this KeyError exception.
2963 */
2964
2965static VALUE
2966key_err_key(VALUE self)
2967{
2968 VALUE key;
2969
2970 key = rb_ivar_lookup(self, id_key, Qundef);
2971 if (!UNDEF_P(key)) return key;
2972 rb_raise(rb_eArgError, "no key is available");
2973}
2974
2975VALUE
2976rb_key_err_new(VALUE mesg, VALUE recv, VALUE key)
2977{
2979 rb_ivar_set(exc, id_mesg, mesg);
2980 rb_ivar_set(exc, id_bt, Qnil);
2981 rb_ivar_set(exc, id_key, key);
2982 rb_ivar_set(exc, id_receiver, recv);
2983 return exc;
2984}
2985
2986/*
2987 * call-seq:
2988 * KeyError.new(message=nil, receiver: nil, key: nil) -> key_error
2989 *
2990 * Construct a new +KeyError+ exception with the given message,
2991 * receiver and key.
2992 */
2993
2994static VALUE
2995key_err_initialize(int argc, VALUE *argv, VALUE self)
2996{
2997 VALUE options;
2998
2999 rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
3000
3001 if (!NIL_P(options)) {
3002 ID keywords[2];
3003 VALUE values[numberof(keywords)];
3004 int i;
3005 keywords[0] = id_receiver;
3006 keywords[1] = id_key;
3007 rb_get_kwargs(options, keywords, 0, numberof(values), values);
3008 for (i = 0; i < numberof(values); ++i) {
3009 if (!UNDEF_P(values[i])) {
3010 rb_ivar_set(self, keywords[i], values[i]);
3011 }
3012 }
3013 }
3014
3015 return self;
3016}
3017
3018/*
3019 * call-seq:
3020 * no_matching_pattern_key_error.matchee -> object
3021 *
3022 * Return the matchee associated with this NoMatchingPatternKeyError exception.
3023 */
3024
3025static VALUE
3026no_matching_pattern_key_err_matchee(VALUE self)
3027{
3028 VALUE matchee;
3029
3030 matchee = rb_ivar_lookup(self, id_matchee, Qundef);
3031 if (!UNDEF_P(matchee)) return matchee;
3032 rb_raise(rb_eArgError, "no matchee is available");
3033}
3034
3035/*
3036 * call-seq:
3037 * no_matching_pattern_key_error.key -> object
3038 *
3039 * Return the key caused this NoMatchingPatternKeyError exception.
3040 */
3041
3042static VALUE
3043no_matching_pattern_key_err_key(VALUE self)
3044{
3045 VALUE key;
3046
3047 key = rb_ivar_lookup(self, id_key, Qundef);
3048 if (!UNDEF_P(key)) return key;
3049 rb_raise(rb_eArgError, "no key is available");
3050}
3051
3052/*
3053 * call-seq:
3054 * NoMatchingPatternKeyError.new(message=nil, matchee: nil, key: nil) -> no_matching_pattern_key_error
3055 *
3056 * Construct a new +NoMatchingPatternKeyError+ exception with the given message,
3057 * matchee and key.
3058 */
3059
3060static VALUE
3061no_matching_pattern_key_err_initialize(int argc, VALUE *argv, VALUE self)
3062{
3063 VALUE options;
3064
3065 rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
3066
3067 if (!NIL_P(options)) {
3068 ID keywords[2];
3069 VALUE values[numberof(keywords)];
3070 int i;
3071 keywords[0] = id_matchee;
3072 keywords[1] = id_key;
3073 rb_get_kwargs(options, keywords, 0, numberof(values), values);
3074 for (i = 0; i < numberof(values); ++i) {
3075 if (!UNDEF_P(values[i])) {
3076 rb_ivar_set(self, keywords[i], values[i]);
3077 }
3078 }
3079 }
3080
3081 return self;
3082}
3083
3084
3085/*
3086 * call-seq:
3087 * SyntaxError.new([msg]) -> syntax_error
3088 *
3089 * Construct a SyntaxError exception.
3090 */
3091
3092static VALUE
3093syntax_error_initialize(int argc, VALUE *argv, VALUE self)
3094{
3095 VALUE mesg;
3096 if (argc == 0) {
3097 mesg = rb_fstring_lit("compile error");
3098 argc = 1;
3099 argv = &mesg;
3100 }
3101 return rb_call_super(argc, argv);
3102}
3103
3104static VALUE
3105syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
3106{
3107 if (NIL_P(exc)) {
3108 *mesg = rb_enc_str_new(0, 0, enc);
3109 exc = rb_class_new_instance(1, mesg, rb_eSyntaxError);
3110 rb_ivar_set(exc, id_i_path, path);
3111 }
3112 else {
3113 VALUE old_path = rb_attr_get(exc, id_i_path);
3114 if (old_path != path) {
3115 if (rb_str_equal(path, old_path)) {
3116 rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE" (%p->%p)",
3117 old_path, (void *)old_path, (void *)path);
3118 }
3119 else {
3120 rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE"(%s%s)->%+"PRIsVALUE"(%s)",
3121 old_path, rb_enc_name(rb_enc_get(old_path)),
3122 (FL_TEST(old_path, RSTRING_FSTR) ? ":FSTR" : ""),
3123 path, rb_enc_name(rb_enc_get(path)));
3124 }
3125 }
3126 VALUE s = *mesg = rb_attr_get(exc, idMesg);
3127 if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n')
3128 rb_str_cat_cstr(s, "\n");
3129 }
3130 return exc;
3131}
3132
3133/*
3134 * Document-module: Errno
3135 *
3136 * When an operating system encounters an error,
3137 * it typically reports the error as an integer error code:
3138 *
3139 * $ ls nosuch.txt
3140 * ls: cannot access 'nosuch.txt': No such file or directory
3141 * $ echo $? # Code for last error.
3142 * 2
3143 *
3144 * When the Ruby interpreter interacts with the operating system
3145 * and receives such an error code (e.g., +2+),
3146 * it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+):
3147 *
3148 * File.open('nosuch.txt')
3149 * # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT)
3150 *
3151 * Each such class is:
3152 *
3153 * - A nested class in this module, +Errno+.
3154 * - A subclass of class SystemCallError.
3155 * - Associated with an error code.
3156 *
3157 * Thus:
3158 *
3159 * Errno::ENOENT.superclass # => SystemCallError
3160 * Errno::ENOENT::Errno # => 2
3161 *
3162 * The names of nested classes are returned by method +Errno.constants+:
3163 *
3164 * Errno.constants.size # => 158
3165 * Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV]
3166 *
3167 * As seen above, the error code associated with each class
3168 * is available as the value of a constant;
3169 * the value for a particular class may vary among operating systems.
3170 * If the class is not needed for the particular operating system,
3171 * the value is zero:
3172 *
3173 * Errno::ENOENT::Errno # => 2
3174 * Errno::ENOTCAPABLE::Errno # => 0
3175 *
3176 * Each class in Errno can be created with optional messages:
3177 *
3178 * Errno::EPIPE.new # => #<Errno::EPIPE: Broken pipe>
3179 * Errno::EPIPE.new("foo") # => #<Errno::EPIPE: Broken pipe - foo>
3180 * Errno::EPIPE.new("foo", "here") # => #<Errno::EPIPE: Broken pipe @ here - foo>
3181 *
3182 * See SystemCallError.new.
3183 */
3184
3185static st_table *syserr_tbl;
3186
3187void
3188rb_free_warning(void)
3189{
3190 st_free_table(warning_categories.id2enum);
3191 st_free_table(warning_categories.enum2id);
3192 st_free_table(syserr_tbl);
3193}
3194
3195static VALUE
3196setup_syserr(int n, const char *name)
3197{
3198 VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
3199
3200 /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
3201 switch (n) {
3202 case EAGAIN:
3203 rb_eEAGAIN = error;
3204
3205#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3206 break;
3207 case EWOULDBLOCK:
3208#endif
3209
3210 rb_eEWOULDBLOCK = error;
3211 break;
3212 case EINPROGRESS:
3213 rb_eEINPROGRESS = error;
3214 break;
3215 }
3216
3217 rb_define_const(error, "Errno", INT2NUM(n));
3218 st_add_direct(syserr_tbl, n, (st_data_t)error);
3219 return error;
3220}
3221
3222static VALUE
3223set_syserr(int n, const char *name)
3224{
3225 st_data_t error;
3226
3227 if (!st_lookup(syserr_tbl, n, &error)) {
3228 return setup_syserr(n, name);
3229 }
3230 else {
3231 VALUE errclass = (VALUE)error;
3232 rb_define_const(rb_mErrno, name, errclass);
3233 return errclass;
3234 }
3235}
3236
3237static VALUE
3238get_syserr(int n)
3239{
3240 st_data_t error;
3241
3242 if (!st_lookup(syserr_tbl, n, &error)) {
3243 char name[DECIMAL_SIZE_OF(n) + sizeof("E-")];
3244
3245 snprintf(name, sizeof(name), "E%03d", n);
3246 return setup_syserr(n, name);
3247 }
3248 return (VALUE)error;
3249}
3250
3251/*
3252 * call-seq:
3253 * SystemCallError.new(msg, errno = nil, func = nil) -> system_call_error_subclass
3254 *
3255 * If _errno_ corresponds to a known system error code, constructs the
3256 * appropriate Errno class for that error, otherwise constructs a
3257 * generic SystemCallError object. The error number is subsequently
3258 * available via the #errno method.
3259 *
3260 * If only numeric object is given, it is treated as an Integer _errno_,
3261 * and _msg_ is omitted, otherwise the first argument _msg_ is used as
3262 * the additional error message.
3263 *
3264 * SystemCallError.new(Errno::EPIPE::Errno)
3265 * #=> #<Errno::EPIPE: Broken pipe>
3266 *
3267 * SystemCallError.new("foo")
3268 * #=> #<SystemCallError: unknown error - foo>
3269 *
3270 * SystemCallError.new("foo", Errno::EPIPE::Errno)
3271 * #=> #<Errno::EPIPE: Broken pipe - foo>
3272 *
3273 * If _func_ is not +nil+, it is appended to the message with "<tt> @ </tt>".
3274 *
3275 * SystemCallError.new("foo", Errno::EPIPE::Errno, "here")
3276 * #=> #<Errno::EPIPE: Broken pipe @ here - foo>
3277 *
3278 * A subclass of SystemCallError can also be instantiated via the
3279 * +new+ method of the subclass. See Errno.
3280 */
3281
3282static VALUE
3283syserr_initialize(int argc, VALUE *argv, VALUE self)
3284{
3285 const char *err;
3286 VALUE mesg, error, func, errmsg;
3287 VALUE klass = rb_obj_class(self);
3288
3289 if (klass == rb_eSystemCallError) {
3290 st_data_t data = (st_data_t)klass;
3291 rb_scan_args(argc, argv, "12", &mesg, &error, &func);
3292 if (argc == 1 && FIXNUM_P(mesg)) {
3293 error = mesg; mesg = Qnil;
3294 }
3295 if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
3296 klass = (VALUE)data;
3297 /* change class */
3298 if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
3299 rb_raise(rb_eTypeError, "invalid instance type");
3300 }
3301 RBASIC_SET_CLASS(self, klass);
3302 }
3303 }
3304 else {
3305 rb_scan_args(argc, argv, "02", &mesg, &func);
3306 error = rb_const_get(klass, id_Errno);
3307 }
3308 if (!NIL_P(error)) err = strerror(NUM2INT(error));
3309 else err = "unknown error";
3310
3311 errmsg = rb_enc_str_new_cstr(err, rb_locale_encoding());
3312 if (!NIL_P(mesg)) {
3313 VALUE str = StringValue(mesg);
3314
3315 if (!NIL_P(func)) rb_str_catf(errmsg, " @ %"PRIsVALUE, func);
3316 rb_str_catf(errmsg, " - %"PRIsVALUE, str);
3317 }
3318 mesg = errmsg;
3319
3320 rb_call_super(1, &mesg);
3321 rb_ivar_set(self, id_errno, error);
3322 return self;
3323}
3324
3325/*
3326 * call-seq:
3327 * system_call_error.errno -> integer
3328 *
3329 * Return this SystemCallError's error number.
3330 */
3331
3332static VALUE
3333syserr_errno(VALUE self)
3334{
3335 return rb_attr_get(self, id_errno);
3336}
3337
3338/*
3339 * call-seq:
3340 * system_call_error === other -> true or false
3341 *
3342 * Return +true+ if the receiver is a generic +SystemCallError+, or
3343 * if the error numbers +self+ and _other_ are the same.
3344 */
3345
3346static VALUE
3347syserr_eqq(VALUE self, VALUE exc)
3348{
3349 VALUE num, e;
3350
3352 if (!rb_respond_to(exc, id_errno)) return Qfalse;
3353 }
3354 else if (self == rb_eSystemCallError) return Qtrue;
3355
3356 num = rb_attr_get(exc, id_errno);
3357 if (NIL_P(num)) {
3358 num = rb_funcallv(exc, id_errno, 0, 0);
3359 }
3360 e = rb_const_get(self, id_Errno);
3361 return RBOOL(FIXNUM_P(num) ? num == e : rb_equal(num, e));
3362}
3363
3364
3365/*
3366 * Document-class: StandardError
3367 *
3368 * The most standard error types are subclasses of StandardError. A
3369 * rescue clause without an explicit Exception class will rescue all
3370 * StandardErrors (and only those).
3371 *
3372 * def foo
3373 * raise "Oups"
3374 * end
3375 * foo rescue "Hello" #=> "Hello"
3376 *
3377 * On the other hand:
3378 *
3379 * require 'does/not/exist' rescue "Hi"
3380 *
3381 * <em>raises the exception:</em>
3382 *
3383 * LoadError: no such file to load -- does/not/exist
3384 *
3385 */
3386
3387/*
3388 * Document-class: SystemExit
3389 *
3390 * Raised by +exit+ to initiate the termination of the script.
3391 */
3392
3393/*
3394 * Document-class: SignalException
3395 *
3396 * Raised when a signal is received.
3397 *
3398 * begin
3399 * Process.kill('HUP',Process.pid)
3400 * sleep # wait for receiver to handle signal sent by Process.kill
3401 * rescue SignalException => e
3402 * puts "received Exception #{e}"
3403 * end
3404 *
3405 * <em>produces:</em>
3406 *
3407 * received Exception SIGHUP
3408 */
3409
3410/*
3411 * Document-class: Interrupt
3412 *
3413 * Raised when the interrupt signal is received, typically because the
3414 * user has pressed Control-C (on most posix platforms). As such, it is a
3415 * subclass of +SignalException+.
3416 *
3417 * begin
3418 * puts "Press ctrl-C when you get bored"
3419 * loop {}
3420 * rescue Interrupt => e
3421 * puts "Note: You will typically use Signal.trap instead."
3422 * end
3423 *
3424 * <em>produces:</em>
3425 *
3426 * Press ctrl-C when you get bored
3427 *
3428 * <em>then waits until it is interrupted with Control-C and then prints:</em>
3429 *
3430 * Note: You will typically use Signal.trap instead.
3431 */
3432
3433/*
3434 * Document-class: TypeError
3435 *
3436 * Raised when encountering an object that is not of the expected type.
3437 *
3438 * [1, 2, 3].first("two")
3439 *
3440 * <em>raises the exception:</em>
3441 *
3442 * TypeError: no implicit conversion of String into Integer
3443 *
3444 */
3445
3446/*
3447 * Document-class: ArgumentError
3448 *
3449 * Raised when the arguments are wrong and there isn't a more specific
3450 * Exception class.
3451 *
3452 * Ex: passing the wrong number of arguments
3453 *
3454 * [1, 2, 3].first(4, 5)
3455 *
3456 * <em>raises the exception:</em>
3457 *
3458 * ArgumentError: wrong number of arguments (given 2, expected 1)
3459 *
3460 * Ex: passing an argument that is not acceptable:
3461 *
3462 * [1, 2, 3].first(-4)
3463 *
3464 * <em>raises the exception:</em>
3465 *
3466 * ArgumentError: negative array size
3467 */
3468
3469/*
3470 * Document-class: IndexError
3471 *
3472 * Raised when the given index is invalid.
3473 *
3474 * a = [:foo, :bar]
3475 * a.fetch(0) #=> :foo
3476 * a[4] #=> nil
3477 * a.fetch(4) #=> IndexError: index 4 outside of array bounds: -2...2
3478 *
3479 */
3480
3481/*
3482 * Document-class: KeyError
3483 *
3484 * Raised when the specified key is not found. It is a subclass of
3485 * IndexError.
3486 *
3487 * h = {"foo" => :bar}
3488 * h.fetch("foo") #=> :bar
3489 * h.fetch("baz") #=> KeyError: key not found: "baz"
3490 *
3491 */
3492
3493/*
3494 * Document-class: RangeError
3495 *
3496 * Raised when a given numerical value is out of range.
3497 *
3498 * [1, 2, 3].drop(1 << 100)
3499 *
3500 * <em>raises the exception:</em>
3501 *
3502 * RangeError: bignum too big to convert into `long'
3503 */
3504
3505/*
3506 * Document-class: ScriptError
3507 *
3508 * ScriptError is the superclass for errors raised when a script
3509 * can not be executed because of a +LoadError+,
3510 * +NotImplementedError+ or a +SyntaxError+. Note these type of
3511 * +ScriptErrors+ are not +StandardError+ and will not be
3512 * rescued unless it is specified explicitly (or its ancestor
3513 * +Exception+).
3514 */
3515
3516/*
3517 * Document-class: SyntaxError
3518 *
3519 * Raised when encountering Ruby code with an invalid syntax.
3520 *
3521 * eval("1+1=2")
3522 *
3523 * <em>raises the exception:</em>
3524 *
3525 * SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
3526 */
3527
3528/*
3529 * Document-class: LoadError
3530 *
3531 * Raised when a file required (a Ruby script, extension library, ...)
3532 * fails to load.
3533 *
3534 * require 'this/file/does/not/exist'
3535 *
3536 * <em>raises the exception:</em>
3537 *
3538 * LoadError: no such file to load -- this/file/does/not/exist
3539 */
3540
3541/*
3542 * Document-class: NotImplementedError
3543 *
3544 * Raised when a feature is not implemented on the current platform. For
3545 * example, methods depending on the +fsync+ or +fork+ system calls may
3546 * raise this exception if the underlying operating system or Ruby
3547 * runtime does not support them.
3548 *
3549 * Note that if +fork+ raises a +NotImplementedError+, then
3550 * <code>respond_to?(:fork)</code> returns +false+.
3551 */
3552
3553/*
3554 * Document-class: NameError
3555 *
3556 * Raised when a given name is invalid or undefined.
3557 *
3558 * puts foo
3559 *
3560 * <em>raises the exception:</em>
3561 *
3562 * NameError: undefined local variable or method `foo' for main:Object
3563 *
3564 * Since constant names must start with a capital:
3565 *
3566 * Integer.const_set :answer, 42
3567 *
3568 * <em>raises the exception:</em>
3569 *
3570 * NameError: wrong constant name answer
3571 */
3572
3573/*
3574 * Document-class: NoMethodError
3575 *
3576 * Raised when a method is called on a receiver which doesn't have it
3577 * defined and also fails to respond with +method_missing+.
3578 *
3579 * "hello".to_ary
3580 *
3581 * <em>raises the exception:</em>
3582 *
3583 * NoMethodError: undefined method `to_ary' for an instance of String
3584 */
3585
3586/*
3587 * Document-class: FrozenError
3588 *
3589 * Raised when there is an attempt to modify a frozen object.
3590 *
3591 * [1, 2, 3].freeze << 4
3592 *
3593 * <em>raises the exception:</em>
3594 *
3595 * FrozenError: can't modify frozen Array
3596 */
3597
3598/*
3599 * Document-class: RuntimeError
3600 *
3601 * A generic error class raised when an invalid operation is attempted.
3602 * Kernel#raise will raise a RuntimeError if no Exception class is
3603 * specified.
3604 *
3605 * raise "ouch"
3606 *
3607 * <em>raises the exception:</em>
3608 *
3609 * RuntimeError: ouch
3610 */
3611
3612/*
3613 * Document-class: SecurityError
3614 *
3615 * No longer used by internal code.
3616 */
3617
3618/*
3619 * Document-class: NoMemoryError
3620 *
3621 * Raised when memory allocation fails.
3622 */
3623
3624/*
3625 * Document-class: SystemCallError
3626 *
3627 * SystemCallError is the base class for all low-level
3628 * platform-dependent errors.
3629 *
3630 * The errors available on the current platform are subclasses of
3631 * SystemCallError and are defined in the Errno module.
3632 *
3633 * File.open("does/not/exist")
3634 *
3635 * <em>raises the exception:</em>
3636 *
3637 * Errno::ENOENT: No such file or directory - does/not/exist
3638 */
3639
3640/*
3641 * Document-class: EncodingError
3642 *
3643 * EncodingError is the base class for encoding errors.
3644 */
3645
3646/*
3647 * Document-class: Encoding::CompatibilityError
3648 *
3649 * Raised by Encoding and String methods when the source encoding is
3650 * incompatible with the target encoding.
3651 */
3652
3653/*
3654 * Document-class: NoMatchingPatternError
3655 *
3656 * Raised when matching pattern not found.
3657 */
3658
3659/*
3660 * Document-class: NoMatchingPatternKeyError
3661 *
3662 * Raised when matching key not found.
3663 */
3664
3665/*
3666 * Document-class: fatal
3667 *
3668 * +fatal+ is an Exception that is raised when Ruby has encountered a fatal
3669 * error and must exit.
3670 */
3671
3672/*
3673 * Document-class: NameError::message
3674 * :nodoc:
3675 */
3676
3677/*
3678 * Document-class: Exception
3679 *
3680 * Class +Exception+ and its subclasses are used to indicate that an error
3681 * or other problem has occurred,
3682 * and may need to be handled.
3683 * See {Exceptions}[rdoc-ref:exceptions.md].
3684 *
3685 * An +Exception+ object carries certain information:
3686 *
3687 * - The type (the exception's class),
3688 * commonly StandardError, RuntimeError, or a subclass of one or the other;
3689 * see {Built-In Exception Class Hierarchy}[rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy].
3690 * - An optional descriptive message;
3691 * see methods ::new, #message.
3692 * - Optional backtrace information;
3693 * see methods #backtrace, #backtrace_locations, #set_backtrace.
3694 * - An optional cause;
3695 * see method #cause.
3696 *
3697 * == Built-In \Exception Class Hierarchy
3698 *
3699 * The hierarchy of built-in subclasses of class +Exception+:
3700 *
3701 * * NoMemoryError
3702 * * ScriptError
3703 * * LoadError
3704 * * NotImplementedError
3705 * * SyntaxError
3706 * * SecurityError
3707 * * SignalException
3708 * * Interrupt
3709 * * StandardError
3710 * * ArgumentError
3711 * * UncaughtThrowError
3712 * * EncodingError
3713 * * FiberError
3714 * * IOError
3715 * * EOFError
3716 * * IndexError
3717 * * KeyError
3718 * * StopIteration
3719 * * ClosedQueueError
3720 * * LocalJumpError
3721 * * NameError
3722 * * NoMethodError
3723 * * RangeError
3724 * * FloatDomainError
3725 * * RegexpError
3726 * * RuntimeError
3727 * * FrozenError
3728 * * SystemCallError
3729 * * Errno (and its subclasses, representing system errors)
3730 * * ThreadError
3731 * * TypeError
3732 * * ZeroDivisionError
3733 * * SystemExit
3734 * * SystemStackError
3735 * * {fatal}[rdoc-ref:fatal]
3736 *
3737 */
3738
3739static VALUE
3740exception_alloc(VALUE klass)
3741{
3742 return rb_class_allocate_instance(klass);
3743}
3744
3745static VALUE
3746exception_dumper(VALUE exc)
3747{
3748 // TODO: Currently, the instance variables "bt" and "bt_locations"
3749 // refers to the same object (Array of String). But "bt_locations"
3750 // should have an Array of Thread::Backtrace::Locations.
3751
3752 return exc;
3753}
3754
3755static int
3756ivar_copy_i(ID key, VALUE val, st_data_t exc)
3757{
3758 rb_ivar_set((VALUE)exc, key, val);
3759 return ST_CONTINUE;
3760}
3761
3762void rb_exc_check_circular_cause(VALUE exc);
3763
3764static VALUE
3765exception_loader(VALUE exc, VALUE obj)
3766{
3767 // The loader function of rb_marshal_define_compat seems to be called for two events:
3768 // one is for fixup (r_fixup_compat), the other is for TYPE_USERDEF.
3769 // In the former case, the first argument is an instance of Exception (because
3770 // we pass rb_eException to rb_marshal_define_compat). In the latter case, the first
3771 // argument is a class object (see TYPE_USERDEF case in r_object0).
3772 // We want to copy all instance variables (but "bt_locations") from obj to exc.
3773 // But we do not want to do so in the second case, so the following branch is for that.
3774 if (RB_TYPE_P(exc, T_CLASS)) return obj; // maybe called from Marshal's TYPE_USERDEF
3775
3776 rb_ivar_foreach(obj, ivar_copy_i, exc);
3777
3778 rb_exc_check_circular_cause(exc);
3779
3780 if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) {
3781 rb_ivar_set(exc, id_bt_locations, Qnil);
3782 }
3783
3784 return exc;
3785}
3786
3787void
3788Init_Exception(void)
3789{
3790 rb_eException = rb_define_class("Exception", rb_cObject);
3791 rb_define_alloc_func(rb_eException, exception_alloc);
3792 rb_marshal_define_compat(rb_eException, rb_eException, exception_dumper, exception_loader);
3794 rb_define_singleton_method(rb_eException, "to_tty?", exc_s_to_tty_p, 0);
3795 rb_define_method(rb_eException, "exception", exc_exception, -1);
3796 rb_define_method(rb_eException, "initialize", exc_initialize, -1);
3797 rb_define_method(rb_eException, "==", exc_equal, 1);
3798 rb_define_method(rb_eException, "to_s", exc_to_s, 0);
3799 rb_define_method(rb_eException, "message", exc_message, 0);
3800 rb_define_method(rb_eException, "detailed_message", exc_detailed_message, -1);
3801 rb_define_method(rb_eException, "full_message", exc_full_message, -1);
3802 rb_define_method(rb_eException, "inspect", exc_inspect, 0);
3803 rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
3804 rb_define_method(rb_eException, "backtrace_locations", exc_backtrace_locations, 0);
3805 rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
3806 rb_define_method(rb_eException, "cause", exc_cause, 0);
3807
3808 rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
3809 rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
3810 rb_define_method(rb_eSystemExit, "status", exit_status, 0);
3811 rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
3812
3813 rb_eFatal = rb_define_class("fatal", rb_eException);
3814 rb_eSignal = rb_define_class("SignalException", rb_eException);
3815 rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal);
3816
3817 rb_eStandardError = rb_define_class("StandardError", rb_eException);
3818 rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
3819 rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
3820 rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
3821 rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
3822 rb_define_method(rb_eKeyError, "initialize", key_err_initialize, -1);
3823 rb_define_method(rb_eKeyError, "receiver", key_err_receiver, 0);
3824 rb_define_method(rb_eKeyError, "key", key_err_key, 0);
3825 rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
3826
3827 rb_eScriptError = rb_define_class("ScriptError", rb_eException);
3828 rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
3829 rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);
3830
3831 /* RDoc will use literal name value while parsing rb_attr,
3832 * and will render `idPath` as an attribute name without this trick */
3833 ID path = idPath;
3834
3835 /* the path that failed to parse */
3836 rb_attr(rb_eSyntaxError, path, TRUE, FALSE, FALSE);
3837
3838 rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
3839 /* the path that failed to load */
3840 rb_attr(rb_eLoadError, path, TRUE, FALSE, FALSE);
3841
3842 rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
3843
3844 rb_eNameError = rb_define_class("NameError", rb_eStandardError);
3845 rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
3846 rb_define_method(rb_eNameError, "name", name_err_name, 0);
3847 rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0);
3848 rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0);
3849 rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cObject);
3850 rb_define_alloc_func(rb_cNameErrorMesg, name_err_mesg_alloc);
3851 rb_define_method(rb_cNameErrorMesg, "initialize_copy", name_err_mesg_init_copy, 1);
3852 rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
3853 rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
3854 rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_dump, 1);
3855 rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
3856 rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
3857 rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
3858 rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
3859 rb_define_method(rb_eNoMethodError, "private_call?", nometh_err_private_call_p, 0);
3860
3861 rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
3862 rb_eFrozenError = rb_define_class("FrozenError", rb_eRuntimeError);
3863 rb_define_method(rb_eFrozenError, "initialize", frozen_err_initialize, -1);
3864 rb_define_method(rb_eFrozenError, "receiver", frozen_err_receiver, 0);
3865 rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
3866 rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
3867 rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
3868 rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
3869 rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eStandardError);
3870 rb_eNoMatchingPatternKeyError = rb_define_class("NoMatchingPatternKeyError", rb_eNoMatchingPatternError);
3871 rb_define_method(rb_eNoMatchingPatternKeyError, "initialize", no_matching_pattern_key_err_initialize, -1);
3872 rb_define_method(rb_eNoMatchingPatternKeyError, "matchee", no_matching_pattern_key_err_matchee, 0);
3873 rb_define_method(rb_eNoMatchingPatternKeyError, "key", no_matching_pattern_key_err_key, 0);
3874
3875 syserr_tbl = st_init_numtable();
3876 rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
3877 rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
3878 rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
3879 rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
3880
3881 rb_mErrno = rb_define_module("Errno");
3882
3883 rb_mWarning = rb_define_module("Warning");
3884 rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
3885 rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
3886 rb_define_singleton_method(rb_mWarning, "categories", rb_warning_s_categories, 0);
3887 rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
3888 rb_extend_object(rb_mWarning, rb_mWarning);
3889
3890 /* :nodoc: */
3891 rb_cWarningBuffer = rb_define_class_under(rb_mWarning, "buffer", rb_cString);
3892 rb_define_method(rb_cWarningBuffer, "write", warning_write, -1);
3893
3894 id_cause = rb_intern_const("cause");
3895 id_message = rb_intern_const("message");
3896 id_detailed_message = rb_intern_const("detailed_message");
3897 id_backtrace = rb_intern_const("backtrace");
3898 id_key = rb_intern_const("key");
3899 id_matchee = rb_intern_const("matchee");
3900 id_args = rb_intern_const("args");
3901 id_receiver = rb_intern_const("receiver");
3902 id_private_call_p = rb_intern_const("private_call?");
3903 id_local_variables = rb_intern_const("local_variables");
3904 id_Errno = rb_intern_const("Errno");
3905 id_errno = rb_intern_const("errno");
3906 id_i_path = rb_intern_const("@path");
3907 id_warn = rb_intern_const("warn");
3908 id_category = rb_intern_const("category");
3909 id_deprecated = rb_intern_const("deprecated");
3910 id_experimental = rb_intern_const("experimental");
3911 id_performance = rb_intern_const("performance");
3912 id_strict_unused_block = rb_intern_const("strict_unused_block");
3913 id_top = rb_intern_const("top");
3914 id_bottom = rb_intern_const("bottom");
3915 id_iseq = rb_make_internal_id();
3916 id_recv = rb_make_internal_id();
3917
3918 sym_category = ID2SYM(id_category);
3919 sym_highlight = ID2SYM(rb_intern_const("highlight"));
3920
3921 warning_categories.id2enum = rb_init_identtable();
3922 st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED);
3923 st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL);
3924 st_add_direct(warning_categories.id2enum, id_performance, RB_WARN_CATEGORY_PERFORMANCE);
3925 st_add_direct(warning_categories.id2enum, id_strict_unused_block, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK);
3926
3927 warning_categories.enum2id = rb_init_identtable();
3928 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_NONE, 0);
3929 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_DEPRECATED, id_deprecated);
3930 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_EXPERIMENTAL, id_experimental);
3931 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_PERFORMANCE, id_performance);
3932 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK, id_strict_unused_block);
3933}
3934
3935void
3936rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
3937{
3938 va_list args;
3939 VALUE mesg;
3940
3941 va_start(args, fmt);
3942 mesg = rb_enc_vsprintf(enc, fmt, args);
3943 va_end(args);
3944
3945 rb_exc_raise(rb_exc_new3(exc, mesg));
3946}
3947
3948void
3949rb_vraise(VALUE exc, const char *fmt, va_list ap)
3950{
3951 rb_exc_raise(rb_exc_new3(exc, rb_vsprintf(fmt, ap)));
3952}
3953
3954void
3955rb_raise(VALUE exc_class, const char *fmt, ...)
3956{
3957 va_list args;
3958 va_start(args, fmt);
3959 VALUE exc = rb_exc_new3(exc_class, rb_vsprintf(fmt, args));
3960 va_end(args);
3961 rb_exc_raise(exc);
3962}
3963
3964NORETURN(static void raise_loaderror(VALUE path, VALUE mesg));
3965
3966static void
3967raise_loaderror(VALUE path, VALUE mesg)
3968{
3969 VALUE err = rb_exc_new3(rb_eLoadError, mesg);
3970 rb_ivar_set(err, id_i_path, path);
3971 rb_exc_raise(err);
3972}
3973
3974void
3975rb_loaderror(const char *fmt, ...)
3976{
3977 va_list args;
3978 VALUE mesg;
3979
3980 va_start(args, fmt);
3981 mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
3982 va_end(args);
3983 raise_loaderror(Qnil, mesg);
3984}
3985
3986void
3987rb_loaderror_with_path(VALUE path, const char *fmt, ...)
3988{
3989 va_list args;
3990 VALUE mesg;
3991
3992 va_start(args, fmt);
3993 mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
3994 va_end(args);
3995 raise_loaderror(path, mesg);
3996}
3997
3998void
4000{
4001 rb_raise(rb_eNotImpError,
4002 "%"PRIsVALUE"() function is unimplemented on this machine",
4003 rb_id2str(rb_frame_this_func()));
4004}
4005
4006void
4007rb_fatal(const char *fmt, ...)
4008{
4009 va_list args;
4010 VALUE mesg;
4011
4012 if (! ruby_thread_has_gvl_p()) {
4013 /* The thread has no GVL. Object allocation impossible (cant run GC),
4014 * thus no message can be printed out. */
4015 fprintf(stderr, "[FATAL] rb_fatal() outside of GVL\n");
4016 rb_print_backtrace(stderr);
4017 die();
4018 }
4019
4020 va_start(args, fmt);
4021 mesg = rb_vsprintf(fmt, args);
4022 va_end(args);
4023
4025}
4026
4027static VALUE
4028make_errno_exc(const char *mesg)
4029{
4030 int n = errno;
4031
4032 errno = 0;
4033 if (n == 0) {
4034 rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
4035 }
4036 return rb_syserr_new(n, mesg);
4037}
4038
4039static VALUE
4040make_errno_exc_str(VALUE mesg)
4041{
4042 int n = errno;
4043
4044 errno = 0;
4045 if (!mesg) mesg = Qnil;
4046 if (n == 0) {
4047 const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
4048 rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
4049 }
4050 return rb_syserr_new_str(n, mesg);
4051}
4052
4053VALUE
4054rb_syserr_new(int n, const char *mesg)
4055{
4056 VALUE arg;
4057 arg = mesg ? rb_str_new2(mesg) : Qnil;
4058 return rb_syserr_new_str(n, arg);
4059}
4060
4061VALUE
4063{
4064 return rb_class_new_instance(1, &arg, get_syserr(n));
4065}
4066
4067void
4068rb_syserr_fail(int e, const char *mesg)
4069{
4070 rb_exc_raise(rb_syserr_new(e, mesg));
4071}
4072
4073void
4075{
4077}
4078
4079#undef rb_sys_fail
4080void
4081rb_sys_fail(const char *mesg)
4082{
4083 rb_exc_raise(make_errno_exc(mesg));
4084}
4085
4086#undef rb_sys_fail_str
4087void
4088rb_sys_fail_str(VALUE mesg)
4089{
4090 rb_exc_raise(make_errno_exc_str(mesg));
4091}
4092
4093#ifdef RUBY_FUNCTION_NAME_STRING
4094void
4095rb_sys_fail_path_in(const char *func_name, VALUE path)
4096{
4097 int n = errno;
4098
4099 errno = 0;
4100 rb_syserr_fail_path_in(func_name, n, path);
4101}
4102
4103void
4104rb_syserr_fail_path_in(const char *func_name, int n, VALUE path)
4105{
4106 rb_exc_raise(rb_syserr_new_path_in(func_name, n, path));
4107}
4108
4109VALUE
4110rb_syserr_new_path_in(const char *func_name, int n, VALUE path)
4111{
4112 VALUE args[2];
4113
4114 if (!path) path = Qnil;
4115 if (n == 0) {
4116 const char *s = !NIL_P(path) ? RSTRING_PTR(path) : "";
4117 if (!func_name) func_name = "(null)";
4118 rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
4119 func_name, s);
4120 }
4121 args[0] = path;
4122 args[1] = rb_str_new_cstr(func_name);
4123 return rb_class_new_instance(2, args, get_syserr(n));
4124}
4125#endif
4126
4127NORETURN(static void rb_mod_exc_raise(VALUE exc, VALUE mod));
4128
4129static void
4130rb_mod_exc_raise(VALUE exc, VALUE mod)
4131{
4132 rb_extend_object(exc, mod);
4133 rb_exc_raise(exc);
4134}
4135
4136void
4137rb_mod_sys_fail(VALUE mod, const char *mesg)
4138{
4139 VALUE exc = make_errno_exc(mesg);
4140 rb_mod_exc_raise(exc, mod);
4141}
4142
4143void
4145{
4146 VALUE exc = make_errno_exc_str(mesg);
4147 rb_mod_exc_raise(exc, mod);
4148}
4149
4150void
4151rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
4152{
4153 VALUE exc = rb_syserr_new(e, mesg);
4154 rb_mod_exc_raise(exc, mod);
4155}
4156
4157void
4159{
4160 VALUE exc = rb_syserr_new_str(e, mesg);
4161 rb_mod_exc_raise(exc, mod);
4162}
4163
4164static void
4165syserr_warning(VALUE mesg, int err)
4166{
4167 rb_str_set_len(mesg, RSTRING_LEN(mesg)-1);
4168 rb_str_catf(mesg, ": %s\n", strerror(err));
4169 rb_write_warning_str(mesg);
4170}
4171
4172#if 0
4173void
4174rb_sys_warn(const char *fmt, ...)
4175{
4176 if (!NIL_P(ruby_verbose)) {
4177 int errno_save = errno;
4178 with_warning_string(mesg, 0, fmt) {
4179 syserr_warning(mesg, errno_save);
4180 }
4181 errno = errno_save;
4182 }
4183}
4184
4185void
4186rb_syserr_warn(int err, const char *fmt, ...)
4187{
4188 if (!NIL_P(ruby_verbose)) {
4189 with_warning_string(mesg, 0, fmt) {
4190 syserr_warning(mesg, err);
4191 }
4192 }
4193}
4194
4195void
4196rb_sys_enc_warn(rb_encoding *enc, const char *fmt, ...)
4197{
4198 if (!NIL_P(ruby_verbose)) {
4199 int errno_save = errno;
4200 with_warning_string(mesg, enc, fmt) {
4201 syserr_warning(mesg, errno_save);
4202 }
4203 errno = errno_save;
4204 }
4205}
4206
4207void
4208rb_syserr_enc_warn(int err, rb_encoding *enc, const char *fmt, ...)
4209{
4210 if (!NIL_P(ruby_verbose)) {
4211 with_warning_string(mesg, enc, fmt) {
4212 syserr_warning(mesg, err);
4213 }
4214 }
4215}
4216#endif
4217
4218void
4219rb_sys_warning(const char *fmt, ...)
4220{
4221 if (RTEST(ruby_verbose)) {
4222 int errno_save = errno;
4223 with_warning_string(mesg, 0, fmt) {
4224 syserr_warning(mesg, errno_save);
4225 }
4226 errno = errno_save;
4227 }
4228}
4229
4230#if 0
4231void
4232rb_syserr_warning(int err, const char *fmt, ...)
4233{
4234 if (RTEST(ruby_verbose)) {
4235 with_warning_string(mesg, 0, fmt) {
4236 syserr_warning(mesg, err);
4237 }
4238 }
4239}
4240#endif
4241
4242void
4243rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...)
4244{
4245 if (RTEST(ruby_verbose)) {
4246 int errno_save = errno;
4247 with_warning_string(mesg, enc, fmt) {
4248 syserr_warning(mesg, errno_save);
4249 }
4250 errno = errno_save;
4251 }
4252}
4253
4254void
4255rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...)
4256{
4257 if (RTEST(ruby_verbose)) {
4258 with_warning_string(mesg, enc, fmt) {
4259 syserr_warning(mesg, err);
4260 }
4261 }
4262}
4263
4264void
4265rb_load_fail(VALUE path, const char *err)
4266{
4267 VALUE mesg = rb_str_buf_new_cstr(err);
4268 rb_str_cat2(mesg, " -- ");
4269 rb_str_append(mesg, path); /* should be ASCII compatible */
4270 raise_loaderror(path, mesg);
4271}
4272
4273void
4274rb_error_frozen(const char *what)
4275{
4276 rb_raise(rb_eFrozenError, "can't modify frozen %s", what);
4277}
4278
4279void
4280rb_frozen_error_raise(VALUE frozen_obj, const char *fmt, ...)
4281{
4282 va_list args;
4283 VALUE exc, mesg;
4284
4285 va_start(args, fmt);
4286 mesg = rb_vsprintf(fmt, args);
4287 va_end(args);
4288 exc = rb_exc_new3(rb_eFrozenError, mesg);
4289 rb_ivar_set(exc, id_recv, frozen_obj);
4290 rb_exc_raise(exc);
4291}
4292
4293static VALUE
4294inspect_frozen_obj(VALUE obj, VALUE mesg, int recur)
4295{
4296 if (recur) {
4297 rb_str_cat_cstr(mesg, " ...");
4298 }
4299 else {
4300 rb_str_append(mesg, rb_inspect(obj));
4301 }
4302 return mesg;
4303}
4304
4305static VALUE
4306get_created_info(VALUE obj, int *pline)
4307{
4308 VALUE info = rb_attr_get(obj, id_debug_created_info);
4309
4310 if (NIL_P(info)) return Qnil;
4311
4312 VALUE path = rb_ary_entry(info, 0);
4313 VALUE line = rb_ary_entry(info, 1);
4314 if (NIL_P(path)) return Qnil;
4315 *pline = NUM2INT(line);
4316 return StringValue(path);
4317}
4318
4319void
4321{
4322 rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
4323
4324 VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ",
4325 rb_obj_class(frozen_obj));
4327
4328 rb_ivar_set(exc, id_recv, frozen_obj);
4329 rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg);
4330
4331 int created_line;
4332 VALUE created_path = get_created_info(frozen_obj, &created_line);
4333 if (!NIL_P(created_path)) {
4334 rb_str_catf(mesg, ", created at %"PRIsVALUE":%d", created_path, created_line);
4335 }
4336 rb_exc_raise(exc);
4337}
4338
4339void
4340rb_warn_unchilled_literal(VALUE obj)
4341{
4343 if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
4344 int line;
4345 VALUE file = rb_source_location(&line);
4346 VALUE mesg = NIL_P(file) ? rb_str_new(0, 0) : rb_str_dup(file);
4347
4348 if (!NIL_P(file)) {
4349 if (line) rb_str_catf(mesg, ":%d", line);
4350 rb_str_cat2(mesg, ": ");
4351 }
4352 rb_str_cat2(mesg, "warning: literal string will be frozen in the future");
4353
4354 VALUE str = obj;
4355 if (STR_SHARED_P(str)) {
4356 str = RSTRING(obj)->as.heap.aux.shared;
4357 }
4358 VALUE created = get_created_info(str, &line);
4359 if (NIL_P(created)) {
4360 rb_str_cat2(mesg, " (run with --debug-frozen-string-literal for more information)\n");
4361 }
4362 else {
4363 rb_str_cat2(mesg, "\n");
4364 rb_str_append(mesg, created);
4365 if (line) rb_str_catf(mesg, ":%d", line);
4366 rb_str_cat2(mesg, ": info: the string was created here\n");
4367 }
4368 rb_warn_category(mesg, rb_warning_category_to_name(category));
4369 }
4370}
4371
4372#undef rb_check_frozen
4373void
4374rb_check_frozen(VALUE obj)
4375{
4377}
4378
4379void
4381{
4382 if (!FL_ABLE(obj)) return;
4383 rb_check_frozen(obj);
4384 if (!FL_ABLE(orig)) return;
4385}
4386
4387void
4388Init_syserr(void)
4389{
4390 rb_eNOERROR = setup_syserr(0, "NOERROR");
4391#if 0
4392 /* No error */
4393 rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR);
4394#endif
4395#define defined_error(name, num) set_syserr((num), (name));
4396#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR);
4397#include "known_errors.inc"
4398#undef defined_error
4399#undef undefined_error
4400}
4401
4402#include "warning.rbinc"
4403
#define RUBY_DEBUG
Define this macro when you want assertions.
Definition assert.h:88
#define RUBY_ATOMIC_CAS(var, oldval, newval)
Atomic compare-and-swap.
Definition atomic.h:165
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
Definition atomic.h:69
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
Identical to rb_enc_sprintf(), except it takes a va_list instead of variadic arguments.
Definition sprintf.c:1224
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
Definition event.h:43
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
Definition event.h:44
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition eval.c:1940
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
Definition class.c:3052
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:3385
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition class.c:3174
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition string.h:1700
#define TYPE(_)
Old name of rb_type.
Definition value_type.h:108
#define ISSPACE
Old name of rb_isspace.
Definition ctype.h:88
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define T_MASK
Old name of RUBY_T_MASK.
Definition value_type.h:68
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
#define rb_str_cat2
Old name of rb_str_cat_cstr.
Definition string.h:1708
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
Definition assume.h:28
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
Definition string.h:1704
#define T_DATA
Old name of RUBY_T_DATA.
Definition value_type.h:60
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
#define T_MODULE
Old name of RUBY_T_MODULE.
Definition value_type.h:70
#define T_TRUE
Old name of RUBY_T_TRUE.
Definition value_type.h:81
#define FL_ABLE
Old name of RB_FL_ABLE.
Definition fl_type.h:118
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:658
#define rb_exc_new3
Old name of rb_exc_new_str.
Definition error.h:38
#define T_FALSE
Old name of RUBY_T_FALSE.
Definition value_type.h:61
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
Definition int.h:44
#define INT2NUM
Old name of RB_INT2NUM.
Definition int.h:43
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition value_type.h:80
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:127
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
void rb_notimplement(void)
Definition error.c:3999
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Identical to rb_sys_fail(), except it takes additional module to extend the exception object before r...
Definition error.c:4137
rb_warning_category_t
Warning categories.
Definition error.h:43
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:474
void rb_category_warning(rb_warning_category_t category, const char *fmt,...)
Identical to rb_warning(), except it takes additional "category" parameter.
Definition error.c:506
void rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
Identical to rb_mod_sys_fail(), except it does not depend on C global variable errno.
Definition error.c:4151
VALUE rb_eNotImpError
NotImplementedError exception.
Definition error.c:1467
VALUE rb_eScriptError
ScriptError exception.
Definition error.c:1473
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition eval.c:678
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
Definition error.c:4068
VALUE rb_eKeyError
KeyError exception.
Definition error.c:1460
VALUE rb_cNameErrorMesg
NameError::Message class.
Definition error.c:1469
VALUE rb_eSystemExit
SystemExit exception.
Definition error.c:1450
void rb_name_error(ID id, const char *fmt,...)
Raises an instance of rb_eNameError.
Definition error.c:2440
void rb_sys_warning(const char *fmt,...)
Identical to rb_sys_fail(), except it does not raise an exception to render a warning instead.
Definition error.c:4219
void rb_check_copyable(VALUE obj, VALUE orig)
Ensures that the passed object can be initialize_copy relationship.
Definition error.c:4380
VALUE rb_eStandardError
StandardError exception.
Definition error.c:1454
VALUE rb_mErrno
Errno module.
Definition error.c:1478
VALUE rb_syserr_new_str(int n, VALUE arg)
Identical to rb_syserr_new(), except it takes the message in Ruby's String instead of C's.
Definition error.c:4062
void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's String instead of C's.
Definition error.c:4158
void rb_error_frozen(const char *what)
Identical to rb_frozen_error_raise(), except its raising exception has a message like "can't modify f...
Definition error.c:4274
VALUE rb_eFrozenError
FrozenError exception.
Definition error.c:1456
VALUE rb_eNoMemError
NoMemoryError exception.
Definition error.c:1468
VALUE rb_eRangeError
RangeError exception.
Definition error.c:1461
VALUE rb_eLoadError
LoadError exception.
Definition error.c:1475
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
Definition error.c:4074
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
Definition error.h:476
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1457
void rb_unexpected_object_type(VALUE obj, const char *expected)
Fails with the given object's type incompatibility to the type.
Definition error.c:1360
VALUE rb_eNoMatchingPatternError
NoMatchingPatternError exception.
Definition error.c:1470
void rb_name_error_str(VALUE str, const char *fmt,...)
Identical to rb_name_error(), except it takes a VALUE instead of ID.
Definition error.c:2455
void rb_frozen_error_raise(VALUE frozen_obj, const char *fmt,...)
Raises an instance of rb_eFrozenError.
Definition error.c:4280
VALUE rb_eEncCompatError
Encoding::CompatibilityError exception.
Definition error.c:1464
void rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt,...)
Identical to rb_compile_warn(), except it also accepts category.
Definition error.c:437
VALUE rb_eFatal
fatal exception.
Definition error.c:1453
void rb_invalid_str(const char *str, const char *type)
Honestly I don't understand the name, but it raises an instance of rb_eArgError.
Definition error.c:2934
VALUE rb_eInterrupt
Interrupt exception.
Definition error.c:1451
VALUE rb_eNameError
NameError exception.
Definition error.c:1462
VALUE rb_eNoMethodError
NoMethodError exception.
Definition error.c:1465
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
Definition eval.c:691
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1455
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead of returning false.
Definition error.c:1443
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:464
VALUE rb_eNoMatchingPatternKeyError
NoMatchingPatternKeyError exception.
Definition error.c:1471
void rb_error_frozen_object(VALUE frozen_obj)
Identical to rb_error_frozen(), except it takes arbitrary Ruby object instead of C's string.
Definition error.c:4320
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
Definition error.c:1508
VALUE rb_eArgError
ArgumentError exception.
Definition error.c:1458
void rb_bug_errno(const char *mesg, int errno_arg)
This is a wrapper of rb_bug() which automatically constructs appropriate message from the passed errn...
Definition error.c:1177
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
Identical to rb_raise(), except it additionally takes an encoding.
Definition error.c:3936
void rb_loaderror(const char *fmt,...)
Raises an instance of rb_eLoadError.
Definition error.c:3975
VALUE rb_eException
Mother of all exceptions.
Definition error.c:1449
VALUE rb_exc_new(VALUE etype, const char *ptr, rb_len_t len)
Creates an instance of the passed exception class.
Definition error.c:1495
VALUE rb_eIndexError
IndexError exception.
Definition error.c:1459
void rb_loaderror_with_path(VALUE path, const char *fmt,...)
Identical to rb_loaderror(), except it additionally takes which file is unable to load.
Definition error.c:3987
VALUE rb_eSyntaxError
SyntaxError exception.
Definition error.c:1474
VALUE rb_eEncodingError
EncodingError exception.
Definition error.c:1463
void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected)
Fails with the given object's type incompatibility to the type.
Definition error.c:1353
VALUE rb_syserr_new(int n, const char *mesg)
Creates an exception object that represents the given C errno.
Definition error.c:4054
VALUE rb_eSecurityError
SecurityError exception.
Definition error.c:1466
void rb_unexpected_type(VALUE x, int t)
Fails with the given object's type incompatibility to the type.
Definition error.c:1412
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Identical to rb_mod_sys_fail(), except it takes the message in Ruby's String instead of C's.
Definition error.c:4144
void rb_check_type(VALUE x, int t)
This was the old implementation of Check_Type(), but they diverged.
Definition error.c:1386
VALUE rb_eSystemCallError
SystemCallError exception.
Definition error.c:1477
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:495
VALUE rb_eSignal
SignalException exception.
Definition error.c:1452
@ RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
Warning is for checking unused block strictly.
Definition error.h:57
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition error.h:48
@ RB_WARN_CATEGORY_EXPERIMENTAL
Warning is for experimental features.
Definition error.h:51
@ RB_WARN_CATEGORY_PERFORMANCE
Warning is for performance issues (not enabled by -w).
Definition error.h:54
@ RB_WARN_CATEGORY_NONE
Category unspecified.
Definition error.h:45
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
Definition object.c:3347
VALUE rb_cObject
Object class.
Definition object.c:60
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
Definition object.c:658
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition object.c:2268
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition object.c:2309
VALUE rb_obj_init_copy(VALUE src, VALUE dst)
Default implementation of #initialize_copy, #initialize_dup and #initialize_clone.
Definition object.c:605
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:234
VALUE rb_cEncoding
Encoding class.
Definition encoding.c:60
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:669
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
Definition object.c:225
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:140
VALUE rb_obj_clone(VALUE obj)
Produces a shallow copy of the given object.
Definition object.c:501
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition object.c:906
VALUE rb_String(VALUE val)
This is the logic behind Kernel#String.
Definition object.c:3881
VALUE rb_cString
String class.
Definition string.c:85
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:492
Encoding relates APIs.
#define RBIMPL_ATTR_FORMAT(x, y, z)
Wraps (or simulates) __attribute__((format))
Definition format.h:33
VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new(), except it assumes the passed pointer is a pointer to a C string.
Definition string.c:1175
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1123
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
Definition vm_eval.c:1090
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition vm_eval.c:1081
VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
Identical to rb_call_super(), except you can specify how to handle the last element of the given arra...
Definition vm_eval.c:355
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition vm_eval.c:363
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_entry(VALUE ary, rb_len_t off)
Queries an element of an array.
VALUE rb_ary_new_capa(rb_len_t capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
static void rb_check_frozen_inline(VALUE obj)
Just another name of rb_check_frozen.
Definition error.h:253
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
VALUE rb_require_string(VALUE feature)
Finds and loads the given feature, if absent.
Definition load.c:1497
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Marshal format compatibility layer.
Definition marshal.c:139
void ruby_default_signal(int sig)
Pretends as if there was no custom signal handler.
Definition signal.c:411
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition string.c:3917
VALUE rb_str_tmp_new(rb_len_t len)
Allocates a "temporary" string.
Definition string.c:1797
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
Definition string.h:1523
#define rb_str_buf_cat
Just another name of rb_str_cat.
Definition string.h:1706
#define rb_exc_new_cstr(exc, str)
Identical to rb_exc_new(), except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1695
void rb_str_set_len(VALUE str, rb_len_t len)
Overwrites the length of the string.
Definition string.c:3504
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition string.c:2038
#define rb_str_buf_new_cstr(str)
Identical to rb_str_new_cstr, except done differently.
Definition string.h:1664
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
Definition string.c:3883
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
Definition string.c:4386
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition string.c:2866
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3051
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1681
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1539
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition string.c:1902
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
Definition variable.c:3462
VALUE rb_autoload_p(VALUE space, ID name)
Queries if an autoload is defined at a point.
Definition variable.c:3330
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition variable.c:2139
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
Definition variable.c:516
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:3696
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well... Let us hesitate from describing what a "basic definition" is.
Definition vm_method.c:3574
void rb_attr(VALUE klass, ID name, int need_reader, int need_writer, int honour_visibility)
This function resembles now-deprecated Module#attr.
Definition vm_method.c:2507
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition vm_eval.c:691
VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_check_funcall(), except you can specify how to handle the last element of the given a...
Definition vm_eval.c:685
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:285
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition symbol.c:1289
int len
Length of the buffer.
Definition io.h:8
#define DECIMAL_SIZE_OF(expr)
An approximation of decimal representation size.
Definition util.h:48
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
Definition sprintf.c:974
VALUE rb_vsprintf(const char *fmt, va_list ap)
Identical to rb_sprintf(), except it takes a va_list.
Definition sprintf.c:1251
#define ALLOCA_N(type, n)
Definition memory.h:292
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_ivar_foreach(VALUE q, int_type *w, VALUE e)
Iteration over each instance variable of the object.
#define PRI_PIDT_PREFIX
A rb_sprintf() format prefix to be used for a pid_t parameter.
Definition pid_t.h:38
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:50
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition rarray.h:280
#define RARRAY_AREF(a, i)
Definition rarray.h:402
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:51
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
Definition rstring.h:409
#define RSTRING(obj)
Convenient casting macro.
Definition rstring.h:41
char * rb_string_value_ptr(volatile VALUE *ptr)
Identical to rb_str_to_str(), except it returns the converted string's backend memory region.
Definition string.c:2898
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
Definition rtypeddata.h:81
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
Definition rtypeddata.h:773
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
Definition rtypeddata.h:604
VALUE rb_argv0
The value of $0 at process bootup.
Definition ruby.c:1918
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
Definition variable.c:531
#define errno
Ractor-aware version of errno.
Definition ruby.h:388
#define RB_PASS_KEYWORDS
Pass keywords, final argument must be a hash of keywords.
Definition scan_args.h:72
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition scan_args.h:78
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
Defines old _.
Ruby's String.
Definition rstring.h:196
char * ptr
Pointer to the contents of the string.
Definition rstring.h:222
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:242
const char * wrap_struct_name
Name of structs of this kind.
Definition rtypeddata.h:249
Definition method.h:55
Definition st.h:79
long rb_len_t
A signed integer type for lengths and indices of objects such as String and Array.
Definition value.h:131
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
Definition value_type.h:182
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:425
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376