Ruby: error.c Source File

Ruby 3.3.5p100 (2024-09-03 revision ef084cc8f4958c1b6e4ead99136631bef6d8ddba)

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