Ruby 4.1.0dev (2026-11-09 revision 05e951b61434561a845b0888e5c61ac1735498f7)
error.c (05e951b61434561a845b0888e5c61ac1735498f7)
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
1790static VALUE
1791load_decoration_gem(VALUE name)
1792{
1793 // Fire the autoload, which waits for a concurrent load to complete.
1794 return rb_autoload_load(rb_cObject, (ID)name);
1795}
1796
1797// Require error_highlight, did_you_mean, and syntax_suggest.
1798// rb_define_gem_modules registers an autoload entry for each enabled gem.
1799static void
1800require_decoration_gems(void)
1801{
1802 // Loading must not disturb the caller's $!: it is called while
1803 // displaying an exception. rb_protect does not preserve errinfo, so
1804 // save and restore it around the requires, leaving $! untouched
1805 // whether or not a require raises.
1806 VALUE saved_errinfo = rb_errinfo();
1807 static const char *const gems[] = {"ErrorHighlight", "DidYouMean", "SyntaxSuggest"};
1808 for (size_t i = 0; i < numberof(gems); i++) {
1809 int state;
1810 rb_protect(load_decoration_gem, (VALUE)rb_intern(gems[i]), &state);
1811 (void)state;
1812 }
1813 rb_set_errinfo(saved_errinfo);
1814}
1815
1816// Load the decoration gems on the first error display instead of at boot.
1817// In non-main Ractors rb_autoload_load delegates the load to the main
1818// Ractor, so this works from any Ractor.
1819// Returns whether the caller should re-dispatch to pick up the
1820// detailed_message decorators the gems prepend.
1821static bool
1822lazy_load_decoration_gems(VALUE exc)
1823{
1824 // Re-dispatch only if the load has just prepended a decorator.
1825 bool before = rb_method_basic_definition_p(CLASS_OF(exc), id_detailed_message);
1826 require_decoration_gems();
1827 bool after = rb_method_basic_definition_p(CLASS_OF(exc), id_detailed_message);
1828 return before && !after;
1829}
1830
1831// Load the decoration gems eagerly, e.g. from Process.warmup before a
1832// pre-forking server forks, so the prepended detailed_message decorators
1833// land in shared memory and do not bust method caches at runtime.
1834void
1835rb_eager_load_detailed_message_extension(void)
1836{
1837 require_decoration_gems();
1838}
1839
1840/*
1841 * call-seq:
1842 * detailed_message(highlight: false, **kwargs) -> string
1843 *
1844 * Returns the message string with enhancements:
1845 *
1846 * - Includes the exception class name in the first line.
1847 * - If the value of keyword +highlight+ is +true+,
1848 * includes bolding and underlining ANSI codes (see below)
1849 * to enhance the appearance of the message.
1850 *
1851 * Examples:
1852 *
1853 * begin
1854 * 1 / 0
1855 * rescue => x
1856 * p x.message
1857 * p x.detailed_message # Class name added.
1858 * p x.detailed_message(highlight: true) # Class name, bolding, and underlining added.
1859 * end
1860 *
1861 * Output:
1862 *
1863 * "divided by 0"
1864 * "divided by 0 (ZeroDivisionError)"
1865 * "\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m"
1866 *
1867 * This method is overridden by some gems in the Ruby standard library to add information:
1868 *
1869 * - DidYouMean::Correctable#detailed_message.
1870 * - ErrorHighlight::CoreExt#detailed_message.
1871 * - SyntaxSuggest#detailed_message.
1872 *
1873 * An overriding method must be tolerant of passed keyword arguments,
1874 * which may include (but may not be limited to):
1875 *
1876 * - +:highlight+.
1877 * - +:did_you_mean+.
1878 * - +:error_highlight+.
1879 * - +:syntax_suggest+.
1880 *
1881 * An overriding method should also be careful with ANSI code enhancements;
1882 * see {Messages}[rdoc-ref:exceptions.md@Messages].
1883 */
1884
1885static VALUE
1886exc_detailed_message(int argc, VALUE *argv, VALUE exc)
1887{
1888 if (lazy_load_decoration_gems(exc)) {
1889 return rb_funcallv_kw(exc, id_detailed_message, argc, argv, RB_PASS_CALLED_KEYWORDS);
1890 }
1891
1892 VALUE opt;
1893
1894 rb_scan_args(argc, argv, "0:", &opt);
1895
1896 VALUE highlight = check_highlight_keyword(opt, 0);
1897
1898 extern VALUE rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight);
1899
1900 return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight));
1901}
1902
1903/*
1904 * call-seq:
1905 * inspect -> string
1906 *
1907 * Returns a string representation of +self+:
1908 *
1909 * x = RuntimeError.new('Boom')
1910 * x.inspect # => "#<RuntimeError: Boom>"
1911 * x = RuntimeError.new
1912 * x.inspect # => "#<RuntimeError: RuntimeError>"
1913 *
1914 */
1915
1916static VALUE
1917exc_inspect(VALUE exc)
1918{
1919 VALUE str, klass;
1920
1921 klass = CLASS_OF(exc);
1922 exc = rb_obj_as_string(exc);
1923 if (RSTRING_LEN(exc) == 0) {
1924 return rb_class_name(klass);
1925 }
1926
1927 str = rb_str_buf_new2("#<");
1928 klass = rb_class_name(klass);
1929 rb_str_buf_append(str, klass);
1930
1931 if (RTEST(rb_str_include(exc, rb_str_new2("\n")))) {
1932 rb_str_catf(str, ":%+"PRIsVALUE, exc);
1933 }
1934 else {
1935 rb_str_buf_cat(str, ": ", 2);
1936 rb_str_buf_append(str, exc);
1937 }
1938
1939 rb_str_buf_cat(str, ">", 1);
1940
1941 return str;
1942}
1943
1944/*
1945 * call-seq:
1946 * backtrace -> array or nil
1947 *
1948 * Returns the backtrace (the list of code locations that led to the exception),
1949 * as an array of strings.
1950 *
1951 * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
1952 *
1953 * def division(numerator, denominator)
1954 * numerator / denominator
1955 * end
1956 *
1957 * begin
1958 * division(1, 0)
1959 * rescue => ex
1960 * p ex.backtrace
1961 * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
1962 * loc = ex.backtrace.first
1963 * p loc.class
1964 * # String
1965 * end
1966 *
1967 * The value returned by this method might be adjusted when raising (see Kernel#raise),
1968 * or during intermediate handling by #set_backtrace.
1969 *
1970 * See also #backtrace_locations that provide the same value, as structured objects.
1971 * (Note though that two values might not be consistent with each other when
1972 * backtraces are manually adjusted.)
1973 *
1974 * see {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
1975 */
1976
1977static VALUE
1978exc_backtrace(VALUE exc)
1979{
1980 VALUE obj;
1981
1982 obj = rb_attr_get(exc, id_bt);
1983
1984 if (rb_backtrace_p(obj)) {
1985 obj = rb_backtrace_to_str_ary(obj);
1986 /* rb_ivar_set(exc, id_bt, obj); */
1987 }
1988
1989 return obj;
1990}
1991
1992static VALUE rb_check_backtrace(VALUE);
1993
1994VALUE
1995rb_get_backtrace(VALUE exc)
1996{
1997 ID mid = id_backtrace;
1998 VALUE info;
1999 if (rb_method_basic_definition_p(CLASS_OF(exc), id_backtrace)) {
2000 VALUE klass = rb_eException;
2001 rb_execution_context_t *ec = GET_EC();
2002 if (NIL_P(exc))
2003 return Qnil;
2004 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
2005 info = exc_backtrace(exc);
2006 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
2007 }
2008 else {
2009 info = rb_funcallv(exc, mid, 0, 0);
2010 }
2011 if (NIL_P(info)) return Qnil;
2012 return rb_check_backtrace(info);
2013}
2014
2015/*
2016 * call-seq:
2017 * backtrace_locations -> array or nil
2018 *
2019 * Returns the backtrace (the list of code locations that led to the exception),
2020 * as an array of Thread::Backtrace::Location instances.
2021 *
2022 * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
2023 *
2024 * def division(numerator, denominator)
2025 * numerator / denominator
2026 * end
2027 *
2028 * begin
2029 * division(1, 0)
2030 * rescue => ex
2031 * p ex.backtrace_locations
2032 * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
2033 * loc = ex.backtrace_locations.first
2034 * p loc.class
2035 * # Thread::Backtrace::Location
2036 * p loc.path
2037 * # "t.rb"
2038 * p loc.lineno
2039 * # 2
2040 * p loc.label
2041 * # "Integer#/"
2042 * end
2043 *
2044 * The value returned by this method might be adjusted when raising (see Kernel#raise),
2045 * or during intermediate handling by #set_backtrace.
2046 *
2047 * See also #backtrace that provide the same value as an array of strings.
2048 * (Note though that two values might not be consistent with each other when
2049 * backtraces are manually adjusted.)
2050 *
2051 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
2052 */
2053static VALUE
2054exc_backtrace_locations(VALUE exc)
2055{
2056 VALUE obj;
2057
2058 obj = rb_attr_get(exc, id_bt_locations);
2059 if (!NIL_P(obj)) {
2060 obj = rb_backtrace_to_location_ary(obj);
2061 }
2062 return obj;
2063}
2064
2065static VALUE
2066rb_check_backtrace(VALUE bt)
2067{
2068 rb_len_t i;
2069 static const char err[] = "backtrace must be an Array of String or an Array of Thread::Backtrace::Location";
2070
2071 if (!NIL_P(bt)) {
2072 if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
2073 if (rb_backtrace_p(bt)) return bt;
2074 if (!RB_TYPE_P(bt, T_ARRAY)) {
2075 rb_raise(rb_eTypeError, err);
2076 }
2077 for (i=0;i<RARRAY_LEN(bt);i++) {
2078 VALUE e = RARRAY_AREF(bt, i);
2079 if (!RB_TYPE_P(e, T_STRING)) {
2080 rb_raise(rb_eTypeError, err);
2081 }
2082 }
2083 }
2084 return bt;
2085}
2086
2087/*
2088 * call-seq:
2089 * set_backtrace(value) -> value
2090 *
2091 * Sets the backtrace value for +self+; returns the given +value+.
2092 *
2093 * The +value+ might be:
2094 *
2095 * - an array of Thread::Backtrace::Location;
2096 * - an array of String instances;
2097 * - a single String instance; or
2098 * - +nil+.
2099 *
2100 * Using array of Thread::Backtrace::Location is the most consistent
2101 * option: it sets both #backtrace and #backtrace_locations. It should be
2102 * preferred when possible. The suitable array of locations can be obtained
2103 * from Kernel#caller_locations, copied from another error, or just set to
2104 * the adjusted result of the current error's #backtrace_locations:
2105 *
2106 * require 'json'
2107 *
2108 * def parse_payload(text)
2109 * JSON.parse(text) # test.rb, line 4
2110 * rescue JSON::ParserError => ex
2111 * ex.set_backtrace(ex.backtrace_locations[2...])
2112 * raise
2113 * end
2114 *
2115 * parse_payload('{"wrong: "json"')
2116 * # test.rb:4:in 'Object#parse_payload': unexpected token at '{"wrong: "json"' (JSON::ParserError)
2117 * #
2118 * # An error points to the body of parse_payload method,
2119 * # hiding the parts of the backtrace related to the internals
2120 * # of the "json" library
2121 *
2122 * # The error has both #backtace and #backtrace_locations set
2123 * # consistently:
2124 * begin
2125 * parse_payload('{"wrong: "json"')
2126 * rescue => ex
2127 * p ex.backtrace
2128 * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
2129 * p ex.backtrace_locations
2130 * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
2131 * end
2132 *
2133 * When the desired stack of locations is not available and should
2134 * be constructed from scratch, an array of strings or a singular
2135 * string can be used. In this case, only #backtrace is affected:
2136 *
2137 * def parse_payload(text)
2138 * JSON.parse(text)
2139 * rescue JSON::ParserError => ex
2140 * ex.set_backtrace(["dsl.rb:34", "framework.rb:1"])
2141 * # The error have the new value in #backtrace:
2142 * p ex.backtrace
2143 * # ["dsl.rb:34", "framework.rb:1"]
2144 *
2145 * # but the original one in #backtrace_locations
2146 * p ex.backtrace_locations
2147 * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
2148 * end
2149 *
2150 * parse_payload('{"wrong: "json"')
2151 *
2152 * Calling #set_backtrace with +nil+ clears up #backtrace but doesn't affect
2153 * #backtrace_locations:
2154 *
2155 * def parse_payload(text)
2156 * JSON.parse(text)
2157 * rescue JSON::ParserError => ex
2158 * ex.set_backtrace(nil)
2159 * p ex.backtrace
2160 * # nil
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 * On reraising of such an exception, both #backtrace and #backtrace_locations
2168 * is set to the place of reraising:
2169 *
2170 * def parse_payload(text)
2171 * JSON.parse(text)
2172 * rescue JSON::ParserError => ex
2173 * ex.set_backtrace(nil)
2174 * raise # test.rb, line 7
2175 * end
2176 *
2177 * begin
2178 * parse_payload('{"wrong: "json"')
2179 * rescue => ex
2180 * p ex.backtrace
2181 * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
2182 * p ex.backtrace_locations
2183 * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
2184 * end
2185 *
2186 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
2187 */
2188
2189static VALUE
2190exc_set_backtrace(VALUE exc, VALUE bt)
2191{
2192 VALUE btobj = rb_location_ary_to_backtrace(bt);
2193 if (RTEST(btobj)) {
2194 rb_ivar_set(exc, id_bt, btobj);
2195 rb_ivar_set(exc, id_bt_locations, btobj);
2196 return bt;
2197 }
2198 else {
2199 return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
2200 }
2201}
2202
2203VALUE
2204rb_exc_set_backtrace(VALUE exc, VALUE bt)
2205{
2206 return exc_set_backtrace(exc, bt);
2207}
2208
2209/*
2210 * call-seq:
2211 * cause -> exception or nil
2212 *
2213 * Returns the previous value of global variable <tt>$!</tt>,
2214 * which may be +nil+
2215 * (see {Global Variables}[rdoc-ref:exceptions.md@Global+Variables]):
2216 *
2217 * begin
2218 * raise('Boom 0')
2219 * rescue => x0
2220 * puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}."
2221 * begin
2222 * raise('Boom 1')
2223 * rescue => x1
2224 * puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}."
2225 * begin
2226 * raise('Boom 2')
2227 * rescue => x2
2228 * puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}."
2229 * end
2230 * end
2231 * end
2232 *
2233 * Output:
2234 *
2235 * Exception: Boom 0; $!: Boom 0; cause: nil.
2236 * Exception: Boom 1; $!: Boom 1; cause: Boom 0.
2237 * Exception: Boom 2; $!: Boom 2; cause: Boom 1.
2238 *
2239 */
2240
2241static VALUE
2242exc_cause(VALUE exc)
2243{
2244 return rb_attr_get(exc, id_cause);
2245}
2246
2247static VALUE
2248try_convert_to_exception(VALUE obj)
2249{
2250 return rb_check_funcall(obj, idException, 0, 0);
2251}
2252
2253/*
2254 * call-seq:
2255 * self == other -> true or false
2256 *
2257 * Returns whether +other+ is the same class as +self+
2258 * and its #message and #backtrace are equal to those of +self+.
2259 *
2260 */
2261
2262static VALUE
2263exc_equal(VALUE exc, VALUE obj)
2264{
2265 VALUE mesg, backtrace;
2266
2267 if (exc == obj) return Qtrue;
2268
2269 if (rb_obj_class(exc) != rb_obj_class(obj)) {
2270 int state;
2271
2272 obj = rb_protect(try_convert_to_exception, obj, &state);
2273 if (state || UNDEF_P(obj)) {
2274 rb_set_errinfo(Qnil);
2275 return Qfalse;
2276 }
2277 if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
2278 mesg = rb_check_funcall(obj, id_message, 0, 0);
2279 if (UNDEF_P(mesg)) return Qfalse;
2280 backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
2281 if (UNDEF_P(backtrace)) return Qfalse;
2282 }
2283 else {
2284 mesg = rb_attr_get(obj, id_mesg);
2285 backtrace = exc_backtrace(obj);
2286 }
2287
2288 if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
2289 return Qfalse;
2290 return rb_equal(exc_backtrace(exc), backtrace);
2291}
2292
2293/*
2294 * call-seq:
2295 * SystemExit.new -> system_exit
2296 * SystemExit.new(status) -> system_exit
2297 * SystemExit.new(status, msg) -> system_exit
2298 * SystemExit.new(msg) -> system_exit
2299 *
2300 * Create a new +SystemExit+ exception with the given status and message.
2301 * Status is true, false, or an integer.
2302 * If status is not given, true is used.
2303 */
2304
2305static VALUE
2306exit_initialize(int argc, VALUE *argv, VALUE exc)
2307{
2308 VALUE status;
2309 if (argc > 0) {
2310 status = *argv;
2311
2312 switch (status) {
2313 case Qtrue:
2314 status = INT2FIX(EXIT_SUCCESS);
2315 ++argv;
2316 --argc;
2317 break;
2318 case Qfalse:
2319 status = INT2FIX(EXIT_FAILURE);
2320 ++argv;
2321 --argc;
2322 break;
2323 default:
2324 status = rb_check_to_int(status);
2325 if (NIL_P(status)) {
2326 status = INT2FIX(EXIT_SUCCESS);
2327 }
2328 else {
2329#if EXIT_SUCCESS != 0
2330 if (status == INT2FIX(0))
2331 status = INT2FIX(EXIT_SUCCESS);
2332#endif
2333 ++argv;
2334 --argc;
2335 }
2336 break;
2337 }
2338 }
2339 else {
2340 status = INT2FIX(EXIT_SUCCESS);
2341 }
2342 rb_call_super(argc, argv);
2343 rb_ivar_set(exc, id_status, status);
2344 return exc;
2345}
2346
2347
2348/*
2349 * call-seq:
2350 * system_exit.status -> integer
2351 *
2352 * Return the status value associated with this system exit.
2353 */
2354
2355static VALUE
2356exit_status(VALUE exc)
2357{
2358 return rb_attr_get(exc, id_status);
2359}
2360
2361
2362/*
2363 * call-seq:
2364 * system_exit.success? -> true or false
2365 *
2366 * Returns +true+ if exiting successful, +false+ if not.
2367 */
2368
2369static VALUE
2370exit_success_p(VALUE exc)
2371{
2372 VALUE status_val = rb_attr_get(exc, id_status);
2373 int status;
2374
2375 if (NIL_P(status_val))
2376 return Qtrue;
2377 status = NUM2INT(status_val);
2378 return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
2379}
2380
2381static VALUE
2382err_init_recv(VALUE exc, VALUE recv)
2383{
2384 if (!UNDEF_P(recv)) rb_ivar_set(exc, id_recv, recv);
2385 return exc;
2386}
2387
2388/*
2389 * call-seq:
2390 * FrozenError.new(msg=nil, receiver: nil) -> frozen_error
2391 *
2392 * Construct a new FrozenError exception. If given the <i>receiver</i>
2393 * parameter may subsequently be examined using the FrozenError#receiver
2394 * method.
2395 *
2396 * a = [].freeze
2397 * raise FrozenError.new("can't modify frozen array", receiver: a)
2398 */
2399
2400static VALUE
2401frozen_err_initialize(int argc, VALUE *argv, VALUE self)
2402{
2403 ID keywords[1];
2404 VALUE values[numberof(keywords)], options;
2405
2406 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
2407 keywords[0] = id_receiver;
2408 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2409 rb_call_super(argc, argv);
2410 err_init_recv(self, values[0]);
2411 return self;
2412}
2413
2414/*
2415 * Document-method: FrozenError#receiver
2416 * call-seq:
2417 * frozen_error.receiver -> object
2418 *
2419 * Return the receiver associated with this FrozenError exception.
2420 */
2421
2422#define frozen_err_receiver name_err_receiver
2423
2424void
2425rb_name_error(ID id, const char *fmt, ...)
2426{
2427 VALUE exc, argv[2];
2428 va_list args;
2429
2430 va_start(args, fmt);
2431 argv[0] = rb_vsprintf(fmt, args);
2432 va_end(args);
2433
2434 argv[1] = ID2SYM(id);
2435 exc = rb_class_new_instance(2, argv, rb_eNameError);
2436 rb_exc_raise(exc);
2437}
2438
2439void
2440rb_name_error_str(VALUE str, 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] = str;
2450 exc = rb_class_new_instance(2, argv, rb_eNameError);
2451 rb_exc_raise(exc);
2452}
2453
2454static VALUE
2455name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
2456{
2457 const rb_execution_context_t *ec = GET_EC();
2458 rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
2459 cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
2460 rb_ivar_set(exc, id_name, method);
2461 err_init_recv(exc, recv);
2462 if (cfp && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
2463 rb_ivar_set(exc, id_iseq, rb_iseqw_new(CFP_ISEQ(cfp)));
2464 }
2465 return exc;
2466}
2467
2468/*
2469 * call-seq:
2470 * NameError.new(msg=nil, name=nil, receiver: nil) -> name_error
2471 *
2472 * Construct a new NameError exception. If given the <i>name</i>
2473 * parameter may subsequently be examined using the NameError#name
2474 * method. <i>receiver</i> parameter allows to pass object in
2475 * context of which the error happened. Example:
2476 *
2477 * [1, 2, 3].method(:rject) # NameError with name "rject" and receiver: Array
2478 * [1, 2, 3].singleton_method(:rject) # NameError with name "rject" and receiver: [1, 2, 3]
2479 */
2480
2481static VALUE
2482name_err_initialize(int argc, VALUE *argv, VALUE self)
2483{
2484 ID keywords[1];
2485 VALUE values[numberof(keywords)], name, options;
2486
2487 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
2488 keywords[0] = id_receiver;
2489 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2490 name = (argc > 1) ? argv[--argc] : Qnil;
2491 rb_call_super(argc, argv);
2492 name_err_init_attr(self, values[0], name);
2493 return self;
2494}
2495
2496static VALUE rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method);
2497
2498static VALUE
2499name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method)
2500{
2501 exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
2502 return name_err_init_attr(exc, recv, method);
2503}
2504
2505VALUE
2506rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
2507{
2509 return name_err_init(exc, mesg, recv, method);
2510}
2511
2512/*
2513 * call-seq:
2514 * name_error.name -> string or nil
2515 *
2516 * Return the name associated with this NameError exception.
2517 */
2518
2519static VALUE
2520name_err_name(VALUE self)
2521{
2522 return rb_attr_get(self, id_name);
2523}
2524
2525/*
2526 * call-seq:
2527 * name_error.local_variables -> array
2528 *
2529 * Return a list of the local variable names defined where this
2530 * NameError exception was raised.
2531 *
2532 * Internal use only.
2533 */
2534
2535static VALUE
2536name_err_local_variables(VALUE self)
2537{
2538 VALUE vars = rb_attr_get(self, id_local_variables);
2539
2540 if (NIL_P(vars)) {
2541 VALUE iseqw = rb_attr_get(self, id_iseq);
2542 if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
2543 if (NIL_P(vars)) vars = rb_ary_new();
2544 rb_ivar_set(self, id_local_variables, vars);
2545 }
2546 return vars;
2547}
2548
2549static VALUE
2550nometh_err_init_attr(VALUE exc, VALUE args, int priv)
2551{
2552 rb_ivar_set(exc, id_args, args);
2553 rb_ivar_set(exc, id_private_call_p, RBOOL(priv));
2554 return exc;
2555}
2556
2557/*
2558 * call-seq:
2559 * NoMethodError.new(msg=nil, name=nil, args=nil, private=false, receiver: nil) -> no_method_error
2560 *
2561 * Construct a NoMethodError exception for a method of the given name
2562 * called with the given arguments. The name may be accessed using
2563 * the <code>#name</code> method on the resulting object, and the
2564 * arguments using the <code>#args</code> method.
2565 *
2566 * If <i>private</i> argument were passed, it designates method was
2567 * attempted to call in private context, and can be accessed with
2568 * <code>#private_call?</code> method.
2569 *
2570 * <i>receiver</i> argument stores an object whose method was called.
2571 */
2572
2573static VALUE
2574nometh_err_initialize(int argc, VALUE *argv, VALUE self)
2575{
2576 int priv;
2577 VALUE args, options;
2578 argc = rb_scan_args(argc, argv, "*:", NULL, &options);
2579 priv = (argc > 3) && (--argc, RTEST(argv[argc]));
2580 args = (argc > 2) ? argv[--argc] : Qnil;
2581 if (!NIL_P(options)) argv[argc++] = options;
2583 return nometh_err_init_attr(self, args, priv);
2584}
2585
2586VALUE
2587rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
2588{
2590 name_err_init(exc, mesg, recv, method);
2591 return nometh_err_init_attr(exc, args, priv);
2592}
2593
2595 VALUE mesg;
2596 VALUE recv;
2597 VALUE name;
2599
2600static void
2601name_err_mesg_mark_and_move(void *p)
2602{
2604 rb_gc_mark_and_move(&ptr->mesg);
2605 rb_gc_mark_and_move(&ptr->recv);
2606 rb_gc_mark_and_move(&ptr->name);
2607}
2608
2609static const rb_data_type_t name_err_mesg_data_type = {
2610 "name_err_mesg",
2611 {
2612 name_err_mesg_mark_and_move,
2614 NULL, // No external memory to report,
2615 name_err_mesg_mark_and_move,
2616 },
2617 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
2618};
2619
2620/* :nodoc: */
2621static VALUE
2622rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE name)
2623{
2624 name_error_message_t *message;
2625 VALUE result = TypedData_Make_Struct(klass, name_error_message_t, &name_err_mesg_data_type, message);
2626 RB_OBJ_WRITE(result, &message->mesg, mesg);
2627 RB_OBJ_WRITE(result, &message->recv, recv);
2628 RB_OBJ_WRITE(result, &message->name, name);
2629 return result;
2630}
2631
2632/* :nodoc: */
2633static VALUE
2634rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
2635{
2636 return rb_name_err_mesg_init(rb_cNameErrorMesg, mesg, recv, method);
2637}
2638
2639/* :nodoc: */
2640static VALUE
2641name_err_mesg_alloc(VALUE klass)
2642{
2643 return rb_name_err_mesg_init(klass, Qnil, Qnil, Qnil);
2644}
2645
2646/* :nodoc: */
2647static VALUE
2648name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
2649{
2650 if (obj1 == obj2) return obj1;
2651 rb_obj_init_copy(obj1, obj2);
2652
2653 name_error_message_t *ptr1, *ptr2;
2654 TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
2655 TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
2656
2657 RB_OBJ_WRITE(obj1, &ptr1->mesg, ptr2->mesg);
2658 RB_OBJ_WRITE(obj1, &ptr1->recv, ptr2->recv);
2659 RB_OBJ_WRITE(obj1, &ptr1->name, ptr2->name);
2660 return obj1;
2661}
2662
2663/* :nodoc: */
2664static VALUE
2665name_err_mesg_equal(VALUE obj1, VALUE obj2)
2666{
2667 if (obj1 == obj2) return Qtrue;
2668
2669 if (rb_obj_class(obj2) != rb_cNameErrorMesg)
2670 return Qfalse;
2671
2672 name_error_message_t *ptr1, *ptr2;
2673 TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
2674 TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
2675
2676 if (!rb_equal(ptr1->mesg, ptr2->mesg)) return Qfalse;
2677 if (!rb_equal(ptr1->recv, ptr2->recv)) return Qfalse;
2678 if (!rb_equal(ptr1->name, ptr2->name)) return Qfalse;
2679 return Qtrue;
2680}
2681
2682/* :nodoc: */
2683static VALUE
2684name_err_mesg_receiver_name(VALUE obj)
2685{
2686 if (RB_SPECIAL_CONST_P(obj)) return Qundef;
2687 if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) {
2688 return rb_check_funcall(obj, rb_intern("name"), 0, 0);
2689 }
2690 return Qundef;
2691}
2692
2693/* :nodoc: */
2694static VALUE
2695name_err_mesg_to_str(VALUE obj)
2696{
2698 TypedData_Get_Struct(obj, name_error_message_t, &name_err_mesg_data_type, ptr);
2699
2700 VALUE mesg = ptr->mesg;
2701 if (NIL_P(mesg)) return Qnil;
2702 else {
2703 struct RString s_str = {RBASIC_INIT}, c_str = {RBASIC_INIT}, d_str = {RBASIC_INIT};
2704 VALUE c, s, d = 0, args[4], c2;
2705 int state = 0;
2706 rb_encoding *usascii = rb_usascii_encoding();
2707
2708#define rb_memsearch_lit(str, v) \
2709 rb_memsearch((str), rb_strlen_lit(str), RSTRING_PTR(v), RSTRING_LEN(v), rb_enc_get(v))
2710#define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
2711 c = s = FAKE_CSTR(&s_str, "");
2712 obj = ptr->recv;
2713 switch (obj) {
2714 case Qnil:
2715 c = d = FAKE_CSTR(&d_str, "nil");
2716 break;
2717 case Qtrue:
2718 c = d = FAKE_CSTR(&d_str, "true");
2719 break;
2720 case Qfalse:
2721 c = d = FAKE_CSTR(&d_str, "false");
2722 break;
2723 default:
2724 if (rb_memsearch_lit("%2$s", mesg) >= 0) {
2725 d = rb_protect(name_err_mesg_receiver_name, obj, &state);
2726 if (state || NIL_OR_UNDEF_P(d))
2727 d = rb_protect(rb_inspect, obj, &state);
2728 if (state) {
2729 rb_set_errinfo(Qnil);
2730 }
2731 d = rb_check_string_type(d);
2732 if (NIL_P(d)) {
2733 d = rb_any_to_s(obj);
2734 }
2735 }
2736
2737 if (!RB_SPECIAL_CONST_P(obj)) {
2738 switch (RB_BUILTIN_TYPE(obj)) {
2739 case T_MODULE:
2740 s = FAKE_CSTR(&s_str, "module ");
2741 c = obj;
2742 break;
2743 case T_CLASS:
2744 s = FAKE_CSTR(&s_str, "class ");
2745 c = obj;
2746 break;
2747 default:
2748 goto object;
2749 }
2750 }
2751 else {
2752 VALUE klass;
2753 object:
2754 klass = CLASS_OF(obj);
2755 if (RB_TYPE_P(klass, T_CLASS) && RCLASS_SINGLETON_P(klass)) {
2756 s = FAKE_CSTR(&s_str, "");
2757 if (obj == rb_vm_top_self()) {
2758 c = FAKE_CSTR(&c_str, "main");
2759 }
2760 else {
2761 c = rb_any_to_s(obj);
2762 }
2763 break;
2764 }
2765 else {
2766 s = FAKE_CSTR(&s_str, "an instance of ");
2767 c = rb_class_real(klass);
2768 }
2769 }
2770 c2 = rb_protect(name_err_mesg_receiver_name, c, &state);
2771 if (state || NIL_OR_UNDEF_P(c2))
2772 c2 = rb_protect(rb_inspect, c, &state);
2773 if (state) {
2774 rb_set_errinfo(Qnil);
2775 }
2776 c2 = rb_check_string_type(c2);
2777 if (NIL_P(c2)) {
2778 c2 = rb_any_to_s(c);
2779 }
2780 c = c2;
2781 break;
2782 }
2783 args[0] = rb_obj_as_string(ptr->name);
2784 args[1] = d;
2785 args[2] = s;
2786 args[3] = c;
2787 mesg = rb_str_format(4, args, mesg);
2788 }
2789 return mesg;
2790}
2791
2792/* :nodoc: */
2793static VALUE
2794name_err_mesg_dump(VALUE obj, VALUE limit)
2795{
2796 return name_err_mesg_to_str(obj);
2797}
2798
2799/* :nodoc: */
2800static VALUE
2801name_err_mesg_load(VALUE klass, VALUE str)
2802{
2803 return str;
2804}
2805
2806/*
2807 * call-seq:
2808 * name_error.receiver -> object
2809 *
2810 * Return the receiver associated with this NameError exception.
2811 */
2812
2813static VALUE
2814name_err_receiver(VALUE self)
2815{
2816 VALUE recv = rb_ivar_lookup(self, id_recv, Qundef);
2817 if (!UNDEF_P(recv)) return recv;
2818
2819 VALUE mesg = rb_attr_get(self, id_mesg);
2820 if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
2821 rb_raise(rb_eArgError, "no receiver is available");
2822 }
2823
2825 TypedData_Get_Struct(mesg, name_error_message_t, &name_err_mesg_data_type, ptr);
2826 return ptr->recv;
2827}
2828
2829/*
2830 * call-seq:
2831 * no_method_error.args -> obj
2832 *
2833 * Return the arguments passed in as the third parameter to
2834 * the constructor.
2835 */
2836
2837static VALUE
2838nometh_err_args(VALUE self)
2839{
2840 return rb_attr_get(self, id_args);
2841}
2842
2843/*
2844 * call-seq:
2845 * no_method_error.private_call? -> true or false
2846 *
2847 * Return true if the caused method was called as private.
2848 */
2849
2850static VALUE
2851nometh_err_private_call_p(VALUE self)
2852{
2853 return rb_attr_get(self, id_private_call_p);
2854}
2855
2856static const char *
2857type_err_cname(VALUE val)
2858{
2859 if (NIL_P(val)) {
2860 return "nil";
2861 }
2862 else if (val == Qtrue) {
2863 return "true";
2864 }
2865 else if (val == Qfalse) {
2866 return "false";
2867 }
2868 return NULL;
2869}
2870
2871NORETURN(static void type_err_raise(VALUE val, const char *tname, const char *msg));
2872static void
2873type_err_raise(VALUE val, const char *tname, const char *msg)
2874{
2875 const char *cname = type_err_cname(val);
2876 rb_encoding *enc = rb_utf8_encoding();
2877 if (cname) {
2878 rb_enc_raise(enc, rb_eTypeError, "%s %s into %s", msg, cname, tname);
2879 }
2880 rb_enc_raise(enc, rb_eTypeError, "%s %"PRIsVALUE" into %s", msg, rb_obj_class(val), tname);
2881}
2882
2883NORETURN(void rb_no_implicit_conversion(VALUE val, const char *tname));
2884void
2885rb_no_implicit_conversion(VALUE val, const char *tname)
2886{
2887 type_err_raise(val, tname, "no implicit conversion of");
2888}
2889
2890NORETURN(void rb_cant_convert(VALUE val, const char *tname));
2891void
2892rb_cant_convert(VALUE val, const char *tname)
2893{
2894 type_err_raise(val, tname, "can't convert");
2895}
2896
2897NORETURN(void rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret));
2898void
2899rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret)
2900{
2901 const char *cname = type_err_cname(val);
2902 rb_encoding *enc = rb_utf8_encoding();
2903 if (cname) {
2905 enc, rb_eTypeError, "can't convert %s into %s (%s#%s gives %s)",
2906 cname, tname, cname, method_name, type_err_cname(ret));
2907 }
2908 VALUE klass = rb_obj_class(val);
2909 const char *retname = type_err_cname(ret);
2910 if (!retname) {
2911 retname = rb_obj_classname(ret);
2912 }
2914 enc, rb_eTypeError, "can't convert %"PRIsVALUE" into %s (%"PRIsVALUE"#%s gives %s)",
2915 klass, tname, klass, method_name, retname);
2916}
2917
2918void
2919rb_invalid_str(const char *str, const char *type)
2920{
2921 VALUE s = rb_str_new2(str);
2922
2923 rb_raise(rb_eArgError, "invalid value for %s: %+"PRIsVALUE, type, s);
2924}
2925
2926/*
2927 * call-seq:
2928 * key_error.receiver -> object
2929 *
2930 * Return the receiver associated with this KeyError exception.
2931 */
2932
2933static VALUE
2934key_err_receiver(VALUE self)
2935{
2936 VALUE recv;
2937
2938 recv = rb_ivar_lookup(self, id_receiver, Qundef);
2939 if (!UNDEF_P(recv)) return recv;
2940 rb_raise(rb_eArgError, "no receiver is available");
2941}
2942
2943/*
2944 * call-seq:
2945 * key_error.key -> object
2946 *
2947 * Return the key caused this KeyError exception.
2948 */
2949
2950static VALUE
2951key_err_key(VALUE self)
2952{
2953 VALUE key;
2954
2955 key = rb_ivar_lookup(self, id_key, Qundef);
2956 if (!UNDEF_P(key)) return key;
2957 rb_raise(rb_eArgError, "no key is available");
2958}
2959
2960VALUE
2961rb_key_err_new(VALUE mesg, VALUE recv, VALUE key)
2962{
2964 rb_ivar_set(exc, id_mesg, mesg);
2965 rb_ivar_set(exc, id_bt, Qnil);
2966 rb_ivar_set(exc, id_key, key);
2967 rb_ivar_set(exc, id_receiver, recv);
2968 return exc;
2969}
2970
2971/*
2972 * call-seq:
2973 * KeyError.new(message=nil, receiver: nil, key: nil) -> key_error
2974 *
2975 * Construct a new +KeyError+ exception with the given message,
2976 * receiver and key.
2977 */
2978
2979static VALUE
2980key_err_initialize(int argc, VALUE *argv, VALUE self)
2981{
2982 VALUE options;
2983
2984 rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
2985
2986 if (!NIL_P(options)) {
2987 ID keywords[2];
2988 VALUE values[numberof(keywords)];
2989 int i;
2990 keywords[0] = id_receiver;
2991 keywords[1] = id_key;
2992 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2993 for (i = 0; i < numberof(values); ++i) {
2994 if (!UNDEF_P(values[i])) {
2995 rb_ivar_set(self, keywords[i], values[i]);
2996 }
2997 }
2998 }
2999
3000 return self;
3001}
3002
3003/*
3004 * call-seq:
3005 * no_matching_pattern_key_error.matchee -> object
3006 *
3007 * Return the matchee associated with this NoMatchingPatternKeyError exception.
3008 */
3009
3010static VALUE
3011no_matching_pattern_key_err_matchee(VALUE self)
3012{
3013 VALUE matchee;
3014
3015 matchee = rb_ivar_lookup(self, id_matchee, Qundef);
3016 if (!UNDEF_P(matchee)) return matchee;
3017 rb_raise(rb_eArgError, "no matchee is available");
3018}
3019
3020/*
3021 * call-seq:
3022 * no_matching_pattern_key_error.key -> object
3023 *
3024 * Return the key caused this NoMatchingPatternKeyError exception.
3025 */
3026
3027static VALUE
3028no_matching_pattern_key_err_key(VALUE self)
3029{
3030 VALUE key;
3031
3032 key = rb_ivar_lookup(self, id_key, Qundef);
3033 if (!UNDEF_P(key)) return key;
3034 rb_raise(rb_eArgError, "no key is available");
3035}
3036
3037/*
3038 * call-seq:
3039 * NoMatchingPatternKeyError.new(message=nil, matchee: nil, key: nil) -> no_matching_pattern_key_error
3040 *
3041 * Construct a new +NoMatchingPatternKeyError+ exception with the given message,
3042 * matchee and key.
3043 */
3044
3045static VALUE
3046no_matching_pattern_key_err_initialize(int argc, VALUE *argv, VALUE self)
3047{
3048 VALUE options;
3049
3050 rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
3051
3052 if (!NIL_P(options)) {
3053 ID keywords[2];
3054 VALUE values[numberof(keywords)];
3055 int i;
3056 keywords[0] = id_matchee;
3057 keywords[1] = id_key;
3058 rb_get_kwargs(options, keywords, 0, numberof(values), values);
3059 for (i = 0; i < numberof(values); ++i) {
3060 if (!UNDEF_P(values[i])) {
3061 rb_ivar_set(self, keywords[i], values[i]);
3062 }
3063 }
3064 }
3065
3066 return self;
3067}
3068
3069
3070/*
3071 * call-seq:
3072 * SyntaxError.new([msg]) -> syntax_error
3073 *
3074 * Construct a SyntaxError exception.
3075 */
3076
3077static VALUE
3078syntax_error_initialize(int argc, VALUE *argv, VALUE self)
3079{
3080 VALUE mesg;
3081 if (argc == 0) {
3082 mesg = rb_fstring_lit("compile error");
3083 argc = 1;
3084 argv = &mesg;
3085 }
3086 return rb_call_super(argc, argv);
3087}
3088
3089static VALUE
3090syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
3091{
3092 if (NIL_P(exc)) {
3093 *mesg = rb_enc_str_new(0, 0, enc);
3094 exc = rb_class_new_instance(1, mesg, rb_eSyntaxError);
3095 rb_ivar_set(exc, id_i_path, path);
3096 }
3097 else {
3098 VALUE old_path = rb_attr_get(exc, id_i_path);
3099 if (old_path != path) {
3100 if (rb_str_equal(path, old_path)) {
3101 rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE" (%p->%p)",
3102 old_path, (void *)old_path, (void *)path);
3103 }
3104 else {
3105 rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE"(%s%s)->%+"PRIsVALUE"(%s)",
3106 old_path, rb_enc_name(rb_enc_get(old_path)),
3107 (FL_TEST(old_path, RSTRING_FSTR) ? ":FSTR" : ""),
3108 path, rb_enc_name(rb_enc_get(path)));
3109 }
3110 }
3111 VALUE s = *mesg = rb_attr_get(exc, idMesg);
3112 if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n')
3113 rb_str_cat_cstr(s, "\n");
3114 }
3115 return exc;
3116}
3117
3118/*
3119 * Document-module: Errno
3120 *
3121 * When an operating system encounters an error,
3122 * it typically reports the error as an integer error code:
3123 *
3124 * $ ls nosuch.txt
3125 * ls: cannot access 'nosuch.txt': No such file or directory
3126 * $ echo $? # Code for last error.
3127 * 2
3128 *
3129 * When the Ruby interpreter interacts with the operating system
3130 * and receives such an error code (e.g., +2+),
3131 * it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+):
3132 *
3133 * File.open('nosuch.txt')
3134 * # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT)
3135 *
3136 * Each such class is:
3137 *
3138 * - A nested class in this module, +Errno+.
3139 * - A subclass of class SystemCallError.
3140 * - Associated with an error code.
3141 *
3142 * Thus:
3143 *
3144 * Errno::ENOENT.superclass # => SystemCallError
3145 * Errno::ENOENT::Errno # => 2
3146 *
3147 * The names of nested classes are returned by method +Errno.constants+:
3148 *
3149 * Errno.constants.size # => 158
3150 * Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV]
3151 *
3152 * As seen above, the error code associated with each class
3153 * is available as the value of a constant;
3154 * the value for a particular class may vary among operating systems.
3155 * If the class is not needed for the particular operating system,
3156 * the value is zero:
3157 *
3158 * Errno::ENOENT::Errno # => 2
3159 * Errno::ENOTCAPABLE::Errno # => 0
3160 *
3161 * Each class in Errno can be created with optional messages:
3162 *
3163 * Errno::EPIPE.new # => #<Errno::EPIPE: Broken pipe>
3164 * Errno::EPIPE.new("foo") # => #<Errno::EPIPE: Broken pipe - foo>
3165 * Errno::EPIPE.new("foo", "here") # => #<Errno::EPIPE: Broken pipe @ here - foo>
3166 *
3167 * See SystemCallError.new.
3168 */
3169
3170static st_table *syserr_tbl;
3171
3172void
3173rb_free_warning(void)
3174{
3175 st_free_table(warning_categories.id2enum);
3176 st_free_table(warning_categories.enum2id);
3177 st_free_table(syserr_tbl);
3178}
3179
3180static VALUE
3181setup_syserr(int n, const char *name)
3182{
3183 VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
3184
3185 /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
3186 switch (n) {
3187 case EAGAIN:
3188 rb_eEAGAIN = error;
3189
3190#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3191 break;
3192 case EWOULDBLOCK:
3193#endif
3194
3195 rb_eEWOULDBLOCK = error;
3196 break;
3197 case EINPROGRESS:
3198 rb_eEINPROGRESS = error;
3199 break;
3200 }
3201
3202 rb_define_const(error, "Errno", INT2NUM(n));
3203 st_add_direct(syserr_tbl, n, (st_data_t)error);
3204 return error;
3205}
3206
3207static VALUE
3208set_syserr(int n, const char *name)
3209{
3210 st_data_t error;
3211
3212 if (!st_lookup(syserr_tbl, n, &error)) {
3213 return setup_syserr(n, name);
3214 }
3215 else {
3216 VALUE errclass = (VALUE)error;
3217 rb_define_const(rb_mErrno, name, errclass);
3218 return errclass;
3219 }
3220}
3221
3222static VALUE
3223get_syserr(int n)
3224{
3225 st_data_t error;
3226
3227 if (!st_lookup(syserr_tbl, n, &error)) {
3228 char name[DECIMAL_SIZE_OF(n) + sizeof("E-")];
3229
3230 snprintf(name, sizeof(name), "E%03d", n);
3231 return setup_syserr(n, name);
3232 }
3233 return (VALUE)error;
3234}
3235
3236/*
3237 * call-seq:
3238 * SystemCallError.new(msg, errno = nil, func = nil) -> system_call_error_subclass
3239 *
3240 * If _errno_ corresponds to a known system error code, constructs the
3241 * appropriate Errno class for that error, otherwise constructs a
3242 * generic SystemCallError object. The error number is subsequently
3243 * available via the #errno method.
3244 *
3245 * If only numeric object is given, it is treated as an Integer _errno_,
3246 * and _msg_ is omitted, otherwise the first argument _msg_ is used as
3247 * the additional error message.
3248 *
3249 * SystemCallError.new(Errno::EPIPE::Errno)
3250 * #=> #<Errno::EPIPE: Broken pipe>
3251 *
3252 * SystemCallError.new("foo")
3253 * #=> #<SystemCallError: unknown error - foo>
3254 *
3255 * SystemCallError.new("foo", Errno::EPIPE::Errno)
3256 * #=> #<Errno::EPIPE: Broken pipe - foo>
3257 *
3258 * If _func_ is not +nil+, it is appended to the message with "<tt> @ </tt>".
3259 *
3260 * SystemCallError.new("foo", Errno::EPIPE::Errno, "here")
3261 * #=> #<Errno::EPIPE: Broken pipe @ here - foo>
3262 *
3263 * A subclass of SystemCallError can also be instantiated via the
3264 * +new+ method of the subclass. See Errno.
3265 */
3266
3267static VALUE
3268syserr_initialize(int argc, VALUE *argv, VALUE self)
3269{
3270 const char *err;
3271 VALUE mesg, error, func, errmsg;
3272 VALUE klass = rb_obj_class(self);
3273
3274 if (klass == rb_eSystemCallError) {
3275 st_data_t data = (st_data_t)klass;
3276 rb_scan_args(argc, argv, "12", &mesg, &error, &func);
3277 if (argc == 1 && FIXNUM_P(mesg)) {
3278 error = mesg; mesg = Qnil;
3279 }
3280 if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
3281 klass = (VALUE)data;
3282 /* change class */
3283 if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
3284 rb_raise(rb_eTypeError, "invalid instance type");
3285 }
3286 RBASIC_SET_CLASS(self, klass);
3287 }
3288 }
3289 else {
3290 rb_scan_args(argc, argv, "02", &mesg, &func);
3291 error = rb_const_get(klass, id_Errno);
3292 }
3293 if (!NIL_P(error)) err = strerror(NUM2INT(error));
3294 else err = "unknown error";
3295
3296 errmsg = rb_enc_str_new_cstr(err, rb_locale_encoding());
3297 if (!NIL_P(mesg)) {
3298 VALUE str = StringValue(mesg);
3299
3300 if (!NIL_P(func)) rb_str_catf(errmsg, " @ %"PRIsVALUE, func);
3301 rb_str_catf(errmsg, " - %"PRIsVALUE, str);
3302 }
3303 mesg = errmsg;
3304
3305 rb_call_super(1, &mesg);
3306 rb_ivar_set(self, id_errno, error);
3307 return self;
3308}
3309
3310/*
3311 * call-seq:
3312 * system_call_error.errno -> integer
3313 *
3314 * Return this SystemCallError's error number.
3315 */
3316
3317static VALUE
3318syserr_errno(VALUE self)
3319{
3320 return rb_attr_get(self, id_errno);
3321}
3322
3323/*
3324 * call-seq:
3325 * system_call_error === other -> true or false
3326 *
3327 * Return +true+ if the receiver is a generic +SystemCallError+, or
3328 * if the error numbers +self+ and _other_ are the same.
3329 */
3330
3331static VALUE
3332syserr_eqq(VALUE self, VALUE exc)
3333{
3334 VALUE num, e;
3335
3337 if (!rb_respond_to(exc, id_errno)) return Qfalse;
3338 }
3339 else if (self == rb_eSystemCallError) return Qtrue;
3340
3341 num = rb_attr_get(exc, id_errno);
3342 if (NIL_P(num)) {
3343 num = rb_funcallv(exc, id_errno, 0, 0);
3344 }
3345 e = rb_const_get(self, id_Errno);
3346 return RBOOL(FIXNUM_P(num) ? num == e : rb_equal(num, e));
3347}
3348
3349
3350/*
3351 * Document-class: StandardError
3352 *
3353 * The most standard error types are subclasses of StandardError. A
3354 * rescue clause without an explicit Exception class will rescue all
3355 * StandardErrors (and only those).
3356 *
3357 * def foo
3358 * raise "Oups"
3359 * end
3360 * foo rescue "Hello" #=> "Hello"
3361 *
3362 * On the other hand:
3363 *
3364 * require 'does/not/exist' rescue "Hi"
3365 *
3366 * <em>raises the exception:</em>
3367 *
3368 * LoadError: no such file to load -- does/not/exist
3369 *
3370 */
3371
3372/*
3373 * Document-class: SystemExit
3374 *
3375 * Raised by +exit+ to initiate the termination of the script.
3376 */
3377
3378/*
3379 * Document-class: SignalException
3380 *
3381 * Raised when a signal is received.
3382 *
3383 * begin
3384 * Process.kill('HUP',Process.pid)
3385 * sleep # wait for receiver to handle signal sent by Process.kill
3386 * rescue SignalException => e
3387 * puts "received Exception #{e}"
3388 * end
3389 *
3390 * <em>produces:</em>
3391 *
3392 * received Exception SIGHUP
3393 */
3394
3395/*
3396 * Document-class: Interrupt
3397 *
3398 * Raised when the interrupt signal is received, typically because the
3399 * user has pressed Control-C (on most posix platforms). As such, it is a
3400 * subclass of +SignalException+.
3401 *
3402 * begin
3403 * puts "Press ctrl-C when you get bored"
3404 * loop {}
3405 * rescue Interrupt => e
3406 * puts "Note: You will typically use Signal.trap instead."
3407 * end
3408 *
3409 * <em>produces:</em>
3410 *
3411 * Press ctrl-C when you get bored
3412 *
3413 * <em>then waits until it is interrupted with Control-C and then prints:</em>
3414 *
3415 * Note: You will typically use Signal.trap instead.
3416 */
3417
3418/*
3419 * Document-class: TypeError
3420 *
3421 * Raised when encountering an object that is not of the expected type.
3422 *
3423 * [1, 2, 3].first("two")
3424 *
3425 * <em>raises the exception:</em>
3426 *
3427 * TypeError: no implicit conversion of String into Integer
3428 *
3429 */
3430
3431/*
3432 * Document-class: ArgumentError
3433 *
3434 * Raised when the arguments are wrong and there isn't a more specific
3435 * Exception class.
3436 *
3437 * Ex: passing the wrong number of arguments
3438 *
3439 * [1, 2, 3].first(4, 5)
3440 *
3441 * <em>raises the exception:</em>
3442 *
3443 * ArgumentError: wrong number of arguments (given 2, expected 1)
3444 *
3445 * Ex: passing an argument that is not acceptable:
3446 *
3447 * [1, 2, 3].first(-4)
3448 *
3449 * <em>raises the exception:</em>
3450 *
3451 * ArgumentError: negative array size
3452 */
3453
3454/*
3455 * Document-class: IndexError
3456 *
3457 * Raised when the given index is invalid.
3458 *
3459 * a = [:foo, :bar]
3460 * a.fetch(0) #=> :foo
3461 * a[4] #=> nil
3462 * a.fetch(4) #=> IndexError: index 4 outside of array bounds: -2...2
3463 *
3464 */
3465
3466/*
3467 * Document-class: KeyError
3468 *
3469 * Raised when the specified key is not found. It is a subclass of
3470 * IndexError.
3471 *
3472 * h = {"foo" => :bar}
3473 * h.fetch("foo") #=> :bar
3474 * h.fetch("baz") #=> KeyError: key not found: "baz"
3475 *
3476 */
3477
3478/*
3479 * Document-class: RangeError
3480 *
3481 * Raised when a given numerical value is out of range.
3482 *
3483 * [1, 2, 3].drop(1 << 100)
3484 *
3485 * <em>raises the exception:</em>
3486 *
3487 * RangeError: bignum too big to convert into `long'
3488 */
3489
3490/*
3491 * Document-class: ScriptError
3492 *
3493 * ScriptError is the superclass for errors raised when a script
3494 * can not be executed because of a +LoadError+,
3495 * +NotImplementedError+ or a +SyntaxError+. Note these type of
3496 * +ScriptErrors+ are not +StandardError+ and will not be
3497 * rescued unless it is specified explicitly (or its ancestor
3498 * +Exception+).
3499 */
3500
3501/*
3502 * Document-class: SyntaxError
3503 *
3504 * Raised when encountering Ruby code with an invalid syntax.
3505 *
3506 * eval("1+1=2")
3507 *
3508 * <em>raises the exception:</em>
3509 *
3510 * SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
3511 */
3512
3513/*
3514 * Document-class: LoadError
3515 *
3516 * Raised when a file required (a Ruby script, extension library, ...)
3517 * fails to load.
3518 *
3519 * require 'this/file/does/not/exist'
3520 *
3521 * <em>raises the exception:</em>
3522 *
3523 * LoadError: no such file to load -- this/file/does/not/exist
3524 */
3525
3526/*
3527 * Document-class: NotImplementedError
3528 *
3529 * Raised when a feature is not implemented on the current platform. For
3530 * example, methods depending on the +fsync+ or +fork+ system calls may
3531 * raise this exception if the underlying operating system or Ruby
3532 * runtime does not support them.
3533 *
3534 * Note that if +fork+ raises a +NotImplementedError+, then
3535 * <code>respond_to?(:fork)</code> returns +false+.
3536 */
3537
3538/*
3539 * Document-class: NameError
3540 *
3541 * Raised when a given name is invalid or undefined.
3542 *
3543 * puts foo
3544 *
3545 * <em>raises the exception:</em>
3546 *
3547 * NameError: undefined local variable or method `foo' for main:Object
3548 *
3549 * Since constant names must start with a capital:
3550 *
3551 * Integer.const_set :answer, 42
3552 *
3553 * <em>raises the exception:</em>
3554 *
3555 * NameError: wrong constant name answer
3556 */
3557
3558/*
3559 * Document-class: NoMethodError
3560 *
3561 * Raised when a method is called on a receiver which doesn't have it
3562 * defined and also fails to respond with +method_missing+.
3563 *
3564 * "hello".to_ary
3565 *
3566 * <em>raises the exception:</em>
3567 *
3568 * NoMethodError: undefined method `to_ary' for an instance of String
3569 */
3570
3571/*
3572 * Document-class: FrozenError
3573 *
3574 * Raised when there is an attempt to modify a frozen object.
3575 *
3576 * [1, 2, 3].freeze << 4
3577 *
3578 * <em>raises the exception:</em>
3579 *
3580 * FrozenError: can't modify frozen Array
3581 */
3582
3583/*
3584 * Document-class: RuntimeError
3585 *
3586 * A generic error class raised when an invalid operation is attempted.
3587 * Kernel#raise will raise a RuntimeError if no Exception class is
3588 * specified.
3589 *
3590 * raise "ouch"
3591 *
3592 * <em>raises the exception:</em>
3593 *
3594 * RuntimeError: ouch
3595 */
3596
3597/*
3598 * Document-class: SecurityError
3599 *
3600 * No longer used by internal code.
3601 */
3602
3603/*
3604 * Document-class: NoMemoryError
3605 *
3606 * Raised when memory allocation fails.
3607 */
3608
3609/*
3610 * Document-class: SystemCallError
3611 *
3612 * SystemCallError is the base class for all low-level
3613 * platform-dependent errors.
3614 *
3615 * The errors available on the current platform are subclasses of
3616 * SystemCallError and are defined in the Errno module.
3617 *
3618 * File.open("does/not/exist")
3619 *
3620 * <em>raises the exception:</em>
3621 *
3622 * Errno::ENOENT: No such file or directory - does/not/exist
3623 */
3624
3625/*
3626 * Document-class: EncodingError
3627 *
3628 * EncodingError is the base class for encoding errors.
3629 */
3630
3631/*
3632 * Document-class: Encoding::CompatibilityError
3633 *
3634 * Raised by Encoding and String methods when the source encoding is
3635 * incompatible with the target encoding.
3636 */
3637
3638/*
3639 * Document-class: NoMatchingPatternError
3640 *
3641 * Raised when matching pattern not found.
3642 */
3643
3644/*
3645 * Document-class: NoMatchingPatternKeyError
3646 *
3647 * Raised when matching key not found.
3648 */
3649
3650/*
3651 * Document-class: fatal
3652 *
3653 * +fatal+ is an Exception that is raised when Ruby has encountered a fatal
3654 * error and must exit.
3655 */
3656
3657/*
3658 * Document-class: NameError::message
3659 * :nodoc:
3660 */
3661
3662/*
3663 * Document-class: Exception
3664 *
3665 * Class +Exception+ and its subclasses are used to indicate that an error
3666 * or other problem has occurred,
3667 * and may need to be handled.
3668 * See {Exceptions}[rdoc-ref:exceptions.md].
3669 *
3670 * An +Exception+ object carries certain information:
3671 *
3672 * - The type (the exception's class),
3673 * commonly StandardError, RuntimeError, or a subclass of one or the other;
3674 * see {Built-In Exception Class Hierarchy}[rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy].
3675 * - An optional descriptive message;
3676 * see methods ::new, #message.
3677 * - Optional backtrace information;
3678 * see methods #backtrace, #backtrace_locations, #set_backtrace.
3679 * - An optional cause;
3680 * see method #cause.
3681 *
3682 * == Built-In \Exception Class Hierarchy
3683 *
3684 * The hierarchy of built-in subclasses of class +Exception+:
3685 *
3686 * * NoMemoryError
3687 * * ScriptError
3688 * * LoadError
3689 * * NotImplementedError
3690 * * SyntaxError
3691 * * SecurityError
3692 * * SignalException
3693 * * Interrupt
3694 * * StandardError
3695 * * ArgumentError
3696 * * UncaughtThrowError
3697 * * EncodingError
3698 * * FiberError
3699 * * IOError
3700 * * EOFError
3701 * * IndexError
3702 * * KeyError
3703 * * StopIteration
3704 * * ClosedQueueError
3705 * * LocalJumpError
3706 * * NameError
3707 * * NoMethodError
3708 * * RangeError
3709 * * FloatDomainError
3710 * * RegexpError
3711 * * RuntimeError
3712 * * FrozenError
3713 * * SystemCallError
3714 * * Errno (and its subclasses, representing system errors)
3715 * * ThreadError
3716 * * TypeError
3717 * * ZeroDivisionError
3718 * * SystemExit
3719 * * SystemStackError
3720 * * {fatal}[rdoc-ref:fatal]
3721 *
3722 */
3723
3724static VALUE
3725exception_alloc(VALUE klass)
3726{
3727 return rb_class_allocate_instance(klass);
3728}
3729
3730static VALUE
3731exception_dumper(VALUE exc)
3732{
3733 // TODO: Currently, the instance variables "bt" and "bt_locations"
3734 // refers to the same object (Array of String). But "bt_locations"
3735 // should have an Array of Thread::Backtrace::Locations.
3736
3737 return exc;
3738}
3739
3740static int
3741ivar_copy_i(ID key, VALUE val, st_data_t exc)
3742{
3743 rb_ivar_set((VALUE)exc, key, val);
3744 return ST_CONTINUE;
3745}
3746
3747void rb_exc_check_circular_cause(VALUE exc);
3748
3749static VALUE
3750exception_loader(VALUE exc, VALUE obj)
3751{
3752 // The loader function of rb_marshal_define_compat seems to be called for two events:
3753 // one is for fixup (r_fixup_compat), the other is for TYPE_USERDEF.
3754 // In the former case, the first argument is an instance of Exception (because
3755 // we pass rb_eException to rb_marshal_define_compat). In the latter case, the first
3756 // argument is a class object (see TYPE_USERDEF case in r_object0).
3757 // We want to copy all instance variables (but "bt_locations") from obj to exc.
3758 // But we do not want to do so in the second case, so the following branch is for that.
3759 if (RB_TYPE_P(exc, T_CLASS)) return obj; // maybe called from Marshal's TYPE_USERDEF
3760
3761 rb_ivar_foreach(obj, ivar_copy_i, exc);
3762
3763 rb_exc_check_circular_cause(exc);
3764
3765 if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) {
3766 rb_ivar_set(exc, id_bt_locations, Qnil);
3767 }
3768
3769 return exc;
3770}
3771
3772void
3773Init_Exception(void)
3774{
3775 rb_eException = rb_define_class("Exception", rb_cObject);
3776 rb_define_alloc_func(rb_eException, exception_alloc);
3777 rb_marshal_define_compat(rb_eException, rb_eException, exception_dumper, exception_loader);
3779 rb_define_singleton_method(rb_eException, "to_tty?", exc_s_to_tty_p, 0);
3780 rb_define_method(rb_eException, "exception", exc_exception, -1);
3781 rb_define_method(rb_eException, "initialize", exc_initialize, -1);
3782 rb_define_method(rb_eException, "==", exc_equal, 1);
3783 rb_define_method(rb_eException, "to_s", exc_to_s, 0);
3784 rb_define_method(rb_eException, "message", exc_message, 0);
3785 rb_define_method(rb_eException, "detailed_message", exc_detailed_message, -1);
3786 rb_define_method(rb_eException, "full_message", exc_full_message, -1);
3787 rb_define_method(rb_eException, "inspect", exc_inspect, 0);
3788 rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
3789 rb_define_method(rb_eException, "backtrace_locations", exc_backtrace_locations, 0);
3790 rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
3791 rb_define_method(rb_eException, "cause", exc_cause, 0);
3792
3793 rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
3794 rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
3795 rb_define_method(rb_eSystemExit, "status", exit_status, 0);
3796 rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
3797
3798 rb_eFatal = rb_define_class("fatal", rb_eException);
3799 rb_eSignal = rb_define_class("SignalException", rb_eException);
3800 rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal);
3801
3802 rb_eStandardError = rb_define_class("StandardError", rb_eException);
3803 rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
3804 rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
3805 rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
3806 rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
3807 rb_define_method(rb_eKeyError, "initialize", key_err_initialize, -1);
3808 rb_define_method(rb_eKeyError, "receiver", key_err_receiver, 0);
3809 rb_define_method(rb_eKeyError, "key", key_err_key, 0);
3810 rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
3811
3812 rb_eScriptError = rb_define_class("ScriptError", rb_eException);
3813 rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
3814 rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);
3815
3816 /* RDoc will use literal name value while parsing rb_attr,
3817 * and will render `idPath` as an attribute name without this trick */
3818 ID path = idPath;
3819
3820 /* the path that failed to parse */
3821 rb_attr(rb_eSyntaxError, path, TRUE, FALSE, FALSE);
3822
3823 rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
3824 /* the path that failed to load */
3825 rb_attr(rb_eLoadError, path, TRUE, FALSE, FALSE);
3826
3827 rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
3828
3829 rb_eNameError = rb_define_class("NameError", rb_eStandardError);
3830 rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
3831 rb_define_method(rb_eNameError, "name", name_err_name, 0);
3832 rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0);
3833 rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0);
3834 rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cObject);
3835 rb_define_alloc_func(rb_cNameErrorMesg, name_err_mesg_alloc);
3836 rb_define_method(rb_cNameErrorMesg, "initialize_copy", name_err_mesg_init_copy, 1);
3837 rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
3838 rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
3839 rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_dump, 1);
3840 rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
3841 rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
3842 rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
3843 rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
3844 rb_define_method(rb_eNoMethodError, "private_call?", nometh_err_private_call_p, 0);
3845
3846 rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
3847 rb_eFrozenError = rb_define_class("FrozenError", rb_eRuntimeError);
3848 rb_define_method(rb_eFrozenError, "initialize", frozen_err_initialize, -1);
3849 rb_define_method(rb_eFrozenError, "receiver", frozen_err_receiver, 0);
3850 rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
3851 rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
3852 rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
3853 rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
3854 rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eStandardError);
3855 rb_eNoMatchingPatternKeyError = rb_define_class("NoMatchingPatternKeyError", rb_eNoMatchingPatternError);
3856 rb_define_method(rb_eNoMatchingPatternKeyError, "initialize", no_matching_pattern_key_err_initialize, -1);
3857 rb_define_method(rb_eNoMatchingPatternKeyError, "matchee", no_matching_pattern_key_err_matchee, 0);
3858 rb_define_method(rb_eNoMatchingPatternKeyError, "key", no_matching_pattern_key_err_key, 0);
3859
3860 syserr_tbl = st_init_numtable();
3861 rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
3862 rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
3863 rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
3864 rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
3865
3866 rb_mErrno = rb_define_module("Errno");
3867
3868 rb_mWarning = rb_define_module("Warning");
3869 rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
3870 rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
3871 rb_define_singleton_method(rb_mWarning, "categories", rb_warning_s_categories, 0);
3872 rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
3873 rb_extend_object(rb_mWarning, rb_mWarning);
3874
3875 /* :nodoc: */
3876 rb_cWarningBuffer = rb_define_class_under(rb_mWarning, "buffer", rb_cString);
3877 rb_define_method(rb_cWarningBuffer, "write", warning_write, -1);
3878
3879 id_cause = rb_intern_const("cause");
3880 id_message = rb_intern_const("message");
3881 id_detailed_message = rb_intern_const("detailed_message");
3882 id_backtrace = rb_intern_const("backtrace");
3883 id_key = rb_intern_const("key");
3884 id_matchee = rb_intern_const("matchee");
3885 id_args = rb_intern_const("args");
3886 id_receiver = rb_intern_const("receiver");
3887 id_private_call_p = rb_intern_const("private_call?");
3888 id_local_variables = rb_intern_const("local_variables");
3889 id_Errno = rb_intern_const("Errno");
3890 id_errno = rb_intern_const("errno");
3891 id_i_path = rb_intern_const("@path");
3892 id_warn = rb_intern_const("warn");
3893 id_category = rb_intern_const("category");
3894 id_deprecated = rb_intern_const("deprecated");
3895 id_experimental = rb_intern_const("experimental");
3896 id_performance = rb_intern_const("performance");
3897 id_strict_unused_block = rb_intern_const("strict_unused_block");
3898 id_top = rb_intern_const("top");
3899 id_bottom = rb_intern_const("bottom");
3900 id_iseq = rb_make_internal_id();
3901 id_recv = rb_make_internal_id();
3902
3903 sym_category = ID2SYM(id_category);
3904 sym_highlight = ID2SYM(rb_intern_const("highlight"));
3905
3906 warning_categories.id2enum = rb_init_identtable();
3907 st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED);
3908 st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL);
3909 st_add_direct(warning_categories.id2enum, id_performance, RB_WARN_CATEGORY_PERFORMANCE);
3910 st_add_direct(warning_categories.id2enum, id_strict_unused_block, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK);
3911
3912 warning_categories.enum2id = rb_init_identtable();
3913 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_NONE, 0);
3914 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_DEPRECATED, id_deprecated);
3915 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_EXPERIMENTAL, id_experimental);
3916 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_PERFORMANCE, id_performance);
3917 st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK, id_strict_unused_block);
3918}
3919
3920void
3921rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
3922{
3923 va_list args;
3924 VALUE mesg;
3925
3926 va_start(args, fmt);
3927 mesg = rb_enc_vsprintf(enc, fmt, args);
3928 va_end(args);
3929
3930 rb_exc_raise(rb_exc_new3(exc, mesg));
3931}
3932
3933void
3934rb_vraise(VALUE exc, const char *fmt, va_list ap)
3935{
3936 rb_exc_raise(rb_exc_new3(exc, rb_vsprintf(fmt, ap)));
3937}
3938
3939void
3940rb_raise(VALUE exc_class, const char *fmt, ...)
3941{
3942 va_list args;
3943 va_start(args, fmt);
3944 VALUE exc = rb_exc_new3(exc_class, rb_vsprintf(fmt, args));
3945 va_end(args);
3946 rb_exc_raise(exc);
3947}
3948
3949NORETURN(static void raise_loaderror(VALUE path, VALUE mesg));
3950
3951static void
3952raise_loaderror(VALUE path, VALUE mesg)
3953{
3954 VALUE err = rb_exc_new3(rb_eLoadError, mesg);
3955 rb_ivar_set(err, id_i_path, path);
3956 rb_exc_raise(err);
3957}
3958
3959void
3960rb_loaderror(const char *fmt, ...)
3961{
3962 va_list args;
3963 VALUE mesg;
3964
3965 va_start(args, fmt);
3966 mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
3967 va_end(args);
3968 raise_loaderror(Qnil, mesg);
3969}
3970
3971void
3972rb_loaderror_with_path(VALUE path, const char *fmt, ...)
3973{
3974 va_list args;
3975 VALUE mesg;
3976
3977 va_start(args, fmt);
3978 mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
3979 va_end(args);
3980 raise_loaderror(path, mesg);
3981}
3982
3983void
3985{
3986 rb_raise(rb_eNotImpError,
3987 "%"PRIsVALUE"() function is unimplemented on this machine",
3988 rb_id2str(rb_frame_this_func()));
3989}
3990
3991void
3992rb_fatal(const char *fmt, ...)
3993{
3994 va_list args;
3995 VALUE mesg;
3996
3997 if (! ruby_thread_has_gvl_p()) {
3998 /* The thread has no GVL. Object allocation impossible (cant run GC),
3999 * thus no message can be printed out. */
4000 fprintf(stderr, "[FATAL] rb_fatal() outside of GVL\n");
4001 rb_print_backtrace(stderr);
4002 die();
4003 }
4004
4005 va_start(args, fmt);
4006 mesg = rb_vsprintf(fmt, args);
4007 va_end(args);
4008
4010}
4011
4012static VALUE
4013make_errno_exc(const char *mesg)
4014{
4015 int n = errno;
4016
4017 errno = 0;
4018 if (n == 0) {
4019 rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
4020 }
4021 return rb_syserr_new(n, mesg);
4022}
4023
4024static VALUE
4025make_errno_exc_str(VALUE mesg)
4026{
4027 int n = errno;
4028
4029 errno = 0;
4030 if (!mesg) mesg = Qnil;
4031 if (n == 0) {
4032 const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
4033 rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
4034 }
4035 return rb_syserr_new_str(n, mesg);
4036}
4037
4038VALUE
4039rb_syserr_new(int n, const char *mesg)
4040{
4041 VALUE arg;
4042 arg = mesg ? rb_str_new2(mesg) : Qnil;
4043 return rb_syserr_new_str(n, arg);
4044}
4045
4046VALUE
4048{
4049 return rb_class_new_instance(1, &arg, get_syserr(n));
4050}
4051
4052void
4053rb_syserr_fail(int e, const char *mesg)
4054{
4055 rb_exc_raise(rb_syserr_new(e, mesg));
4056}
4057
4058void
4060{
4062}
4063
4064#undef rb_sys_fail
4065void
4066rb_sys_fail(const char *mesg)
4067{
4068 rb_exc_raise(make_errno_exc(mesg));
4069}
4070
4071#undef rb_sys_fail_str
4072void
4073rb_sys_fail_str(VALUE mesg)
4074{
4075 rb_exc_raise(make_errno_exc_str(mesg));
4076}
4077
4078#ifdef RUBY_FUNCTION_NAME_STRING
4079void
4080rb_sys_fail_path_in(const char *func_name, VALUE path)
4081{
4082 int n = errno;
4083
4084 errno = 0;
4085 rb_syserr_fail_path_in(func_name, n, path);
4086}
4087
4088void
4089rb_syserr_fail_path_in(const char *func_name, int n, VALUE path)
4090{
4091 rb_exc_raise(rb_syserr_new_path_in(func_name, n, path));
4092}
4093
4094VALUE
4095rb_syserr_new_path_in(const char *func_name, int n, VALUE path)
4096{
4097 VALUE args[2];
4098
4099 if (!path) path = Qnil;
4100 if (n == 0) {
4101 const char *s = !NIL_P(path) ? RSTRING_PTR(path) : "";
4102 if (!func_name) func_name = "(null)";
4103 rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
4104 func_name, s);
4105 }
4106 args[0] = path;
4107 args[1] = rb_str_new_cstr(func_name);
4108 return rb_class_new_instance(2, args, get_syserr(n));
4109}
4110#endif
4111
4112NORETURN(static void rb_mod_exc_raise(VALUE exc, VALUE mod));
4113
4114static void
4115rb_mod_exc_raise(VALUE exc, VALUE mod)
4116{
4117 rb_extend_object(exc, mod);
4118 rb_exc_raise(exc);
4119}
4120
4121void
4122rb_mod_sys_fail(VALUE mod, const char *mesg)
4123{
4124 VALUE exc = make_errno_exc(mesg);
4125 rb_mod_exc_raise(exc, mod);
4126}
4127
4128void
4130{
4131 VALUE exc = make_errno_exc_str(mesg);
4132 rb_mod_exc_raise(exc, mod);
4133}
4134
4135void
4136rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
4137{
4138 VALUE exc = rb_syserr_new(e, mesg);
4139 rb_mod_exc_raise(exc, mod);
4140}
4141
4142void
4144{
4145 VALUE exc = rb_syserr_new_str(e, mesg);
4146 rb_mod_exc_raise(exc, mod);
4147}
4148
4149static void
4150syserr_warning(VALUE mesg, int err)
4151{
4152 rb_str_set_len(mesg, RSTRING_LEN(mesg)-1);
4153 rb_str_catf(mesg, ": %s\n", strerror(err));
4154 rb_write_warning_str(mesg);
4155}
4156
4157#if 0
4158void
4159rb_sys_warn(const char *fmt, ...)
4160{
4161 if (!NIL_P(ruby_verbose)) {
4162 int errno_save = errno;
4163 with_warning_string(mesg, 0, fmt) {
4164 syserr_warning(mesg, errno_save);
4165 }
4166 errno = errno_save;
4167 }
4168}
4169
4170void
4171rb_syserr_warn(int err, const char *fmt, ...)
4172{
4173 if (!NIL_P(ruby_verbose)) {
4174 with_warning_string(mesg, 0, fmt) {
4175 syserr_warning(mesg, err);
4176 }
4177 }
4178}
4179
4180void
4181rb_sys_enc_warn(rb_encoding *enc, const char *fmt, ...)
4182{
4183 if (!NIL_P(ruby_verbose)) {
4184 int errno_save = errno;
4185 with_warning_string(mesg, enc, fmt) {
4186 syserr_warning(mesg, errno_save);
4187 }
4188 errno = errno_save;
4189 }
4190}
4191
4192void
4193rb_syserr_enc_warn(int err, rb_encoding *enc, const char *fmt, ...)
4194{
4195 if (!NIL_P(ruby_verbose)) {
4196 with_warning_string(mesg, enc, fmt) {
4197 syserr_warning(mesg, err);
4198 }
4199 }
4200}
4201#endif
4202
4203void
4204rb_sys_warning(const char *fmt, ...)
4205{
4206 if (RTEST(ruby_verbose)) {
4207 int errno_save = errno;
4208 with_warning_string(mesg, 0, fmt) {
4209 syserr_warning(mesg, errno_save);
4210 }
4211 errno = errno_save;
4212 }
4213}
4214
4215#if 0
4216void
4217rb_syserr_warning(int err, const char *fmt, ...)
4218{
4219 if (RTEST(ruby_verbose)) {
4220 with_warning_string(mesg, 0, fmt) {
4221 syserr_warning(mesg, err);
4222 }
4223 }
4224}
4225#endif
4226
4227void
4228rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...)
4229{
4230 if (RTEST(ruby_verbose)) {
4231 int errno_save = errno;
4232 with_warning_string(mesg, enc, fmt) {
4233 syserr_warning(mesg, errno_save);
4234 }
4235 errno = errno_save;
4236 }
4237}
4238
4239void
4240rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...)
4241{
4242 if (RTEST(ruby_verbose)) {
4243 with_warning_string(mesg, enc, fmt) {
4244 syserr_warning(mesg, err);
4245 }
4246 }
4247}
4248
4249void
4250rb_load_fail(VALUE path, const char *err)
4251{
4252 VALUE mesg = rb_str_buf_new_cstr(err);
4253 rb_str_cat2(mesg, " -- ");
4254 rb_str_append(mesg, path); /* should be ASCII compatible */
4255 raise_loaderror(path, mesg);
4256}
4257
4258void
4259rb_error_frozen(const char *what)
4260{
4261 rb_raise(rb_eFrozenError, "can't modify frozen %s", what);
4262}
4263
4264void
4265rb_frozen_error_raise(VALUE frozen_obj, const char *fmt, ...)
4266{
4267 va_list args;
4268 VALUE exc, mesg;
4269
4270 va_start(args, fmt);
4271 mesg = rb_vsprintf(fmt, args);
4272 va_end(args);
4273 exc = rb_exc_new3(rb_eFrozenError, mesg);
4274 rb_ivar_set(exc, id_recv, frozen_obj);
4275 rb_exc_raise(exc);
4276}
4277
4278static VALUE
4279inspect_frozen_obj(VALUE obj, VALUE mesg, int recur)
4280{
4281 if (recur) {
4282 rb_str_cat_cstr(mesg, " ...");
4283 }
4284 else {
4285 rb_str_append(mesg, rb_inspect(obj));
4286 }
4287 return mesg;
4288}
4289
4290static VALUE
4291get_created_info(VALUE obj, int *pline)
4292{
4293 VALUE info = rb_attr_get(obj, id_debug_created_info);
4294
4295 if (NIL_P(info)) return Qnil;
4296
4297 VALUE path = rb_ary_entry(info, 0);
4298 VALUE line = rb_ary_entry(info, 1);
4299 if (NIL_P(path)) return Qnil;
4300 *pline = NUM2INT(line);
4301 return StringValue(path);
4302}
4303
4304void
4306{
4307 rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
4308
4309 VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ",
4310 rb_obj_class(frozen_obj));
4312
4313 rb_ivar_set(exc, id_recv, frozen_obj);
4314 rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg);
4315
4316 int created_line;
4317 VALUE created_path = get_created_info(frozen_obj, &created_line);
4318 if (!NIL_P(created_path)) {
4319 rb_str_catf(mesg, ", created at %"PRIsVALUE":%d", created_path, created_line);
4320 }
4321 rb_exc_raise(exc);
4322}
4323
4324void
4325rb_warn_unchilled_literal(VALUE obj)
4326{
4328 if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
4329 int line;
4330 VALUE file = rb_source_location(&line);
4331 VALUE mesg = NIL_P(file) ? rb_str_new(0, 0) : rb_str_dup(file);
4332
4333 if (!NIL_P(file)) {
4334 if (line) rb_str_catf(mesg, ":%d", line);
4335 rb_str_cat2(mesg, ": ");
4336 }
4337 rb_str_cat2(mesg, "warning: literal string will be frozen in the future");
4338
4339 VALUE str = obj;
4340 if (STR_SHARED_P(str)) {
4341 str = RSTRING(obj)->as.heap.aux.shared;
4342 }
4343 VALUE created = get_created_info(str, &line);
4344 if (NIL_P(created)) {
4345 rb_str_cat2(mesg, " (run with --debug-frozen-string-literal for more information)\n");
4346 }
4347 else {
4348 rb_str_cat2(mesg, "\n");
4349 rb_str_append(mesg, created);
4350 if (line) rb_str_catf(mesg, ":%d", line);
4351 rb_str_cat2(mesg, ": info: the string was created here\n");
4352 }
4353 rb_warn_category(mesg, rb_warning_category_to_name(category));
4354 }
4355}
4356
4357#undef rb_check_frozen
4358void
4359rb_check_frozen(VALUE obj)
4360{
4362}
4363
4364void
4366{
4367 if (!FL_ABLE(obj)) return;
4368 rb_check_frozen(obj);
4369 if (!FL_ABLE(orig)) return;
4370}
4371
4372void
4373Init_syserr(void)
4374{
4375 rb_eNOERROR = setup_syserr(0, "NOERROR");
4376#if 0
4377 /* No error */
4378 rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR);
4379#endif
4380#define defined_error(name, num) set_syserr((num), (name));
4381#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR);
4382#include "known_errors.inc"
4383#undef defined_error
4384#undef undefined_error
4385}
4386
4387#include "warning.rbinc"
4388
#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:1235
#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:3017
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:3350
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition class.c:3139
#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:3984
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:4122
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:4136
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:4053
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:2425
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:4204
void rb_check_copyable(VALUE obj, VALUE orig)
Ensures that the passed object can be initialize_copy relationship.
Definition error.c:4365
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:4047
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:4143
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:4259
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:4059
#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:2440
void rb_frozen_error_raise(VALUE frozen_obj, const char *fmt,...)
Raises an instance of rb_eFrozenError.
Definition error.c:4265
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:2919
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:4305
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:3921
void rb_loaderror(const char *fmt,...)
Raises an instance of rb_eLoadError.
Definition error.c:3960
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:3972
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:4039
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:4129
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:3343
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:654
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition object.c:2264
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition object.c:2305
VALUE rb_obj_init_copy(VALUE src, VALUE dst)
Default implementation of #initialize_copy, #initialize_dup and #initialize_clone.
Definition object.c:601
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:230
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:665
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
Definition object.c:221
VALUE rb_obj_clone(VALUE obj)
Produces a shallow copy of the given object.
Definition object.c:497
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:902
VALUE rb_String(VALUE val)
This is the logic behind Kernel#String.
Definition object.c:3877
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
#define RUBY_DEBUG
Define this macro when you want assertions.
Definition assert.h:88
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:1184
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1148
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:1115
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:1106
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:357
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition vm_eval.c:365
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
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:4002
VALUE rb_str_tmp_new(rb_len_t len)
Allocates a "temporary" string.
Definition string.c:1806
#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:3586
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition string.c:2047
#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:3968
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
Definition string.c:4499
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition string.c:2948
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3133
#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:1911
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:3515
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:2157
VALUE rb_autoload_load(VALUE space, ID name)
Kicks the autoload procedure as if it was "touched".
Definition variable.c:3345
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:3737
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:3615
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:2548
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:716
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:710
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:1295
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
unsigned long ruby_scan_oct(const char *str, size_t len, size_t *consumed)
Interprets the passed string as an octal unsigned integer.
Definition util.c:39
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
Definition sprintf.c:985
VALUE rb_vsprintf(const char *fmt, va_list ap)
Identical to rb_sprintf(), except it takes a va_list.
Definition sprintf.c:1262
#define ALLOCA_N(type, n)
Definition memory.h:295
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)
References an object in an array.
Definition rarray.h:421
#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:2980
#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:1919
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:142
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