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