1 /**********************************************************************
6 created at: Mon Aug 9 16:11:34 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
10 **********************************************************************/
12 #include "ruby/internal/config.h"
26 #ifdef HAVE_SYS_WAIT_H
27 # include <sys/wait.h>
31 # include <AvailabilityMacros.h>
35 #include "internal/class.h"
36 #include "internal/error.h"
37 #include "internal/eval.h"
38 #include "internal/hash.h"
39 #include "internal/io.h"
40 #include "internal/load.h"
41 #include "internal/object.h"
42 #include "internal/process.h"
43 #include "internal/string.h"
44 #include "internal/symbol.h"
45 #include "internal/thread.h"
46 #include "internal/variable.h"
47 #include "ruby/encoding.h"
49 #include "ruby/util.h"
50 #include "ruby_assert.h"
57 * \addtogroup exception
62 #define EXIT_SUCCESS 0
66 #define WIFEXITED(status) 1
70 #define WEXITSTATUS(status) (status)
73 VALUE
rb_iseqw_local_variables(VALUE iseqval
);
74 VALUE
rb_iseqw_new(const rb_iseq_t
*);
75 int rb_str_end_with_asciichar(VALUE str
, int c
);
77 long rb_backtrace_length_limit
= -1;
79 VALUE rb_eEWOULDBLOCK
;
80 VALUE rb_eEINPROGRESS
;
81 static VALUE rb_mWarning
;
82 static VALUE rb_cWarningBuffer
;
85 static ID id_category
;
86 static ID id_deprecated
;
87 static ID id_experimental
;
88 static ID id_performance
;
89 static ID id_strict_unused_block
;
90 static VALUE sym_category
;
91 static VALUE sym_highlight
;
93 st_table
*id2enum
, *enum2id
;
96 extern const char *rb_dynamic_description
;
101 #define defined_error(name, num) if (err == (num)) return (name);
102 #define undefined_error(name)
103 #include "known_errors.inc"
105 #undef undefined_error
110 err_position_0(char *buf
, long len
, const char *file
, int line
)
115 else if (line
== 0) {
116 return snprintf(buf
, len
, "%s: ", file
);
119 return snprintf(buf
, len
, "%s:%d: ", file
, line
);
123 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT
, 5, 0)
125 err_vcatf(VALUE str
, const char *pre
, const char *file
, int line
,
126 const char *fmt
, va_list args
)
129 rb_str_cat2(str
, file
);
130 if (line
) rb_str_catf(str
, ":%d", line
);
131 rb_str_cat2(str
, ": ");
133 if (pre
) rb_str_cat2(str
, pre
);
134 rb_str_vcatf(str
, fmt
, args
);
138 static VALUE
syntax_error_with_path(VALUE
, VALUE
, VALUE
*, rb_encoding
*);
141 rb_syntax_error_append(VALUE exc
, VALUE file
, int line
, int column
,
142 rb_encoding
*enc
, const char *fmt
, va_list args
)
144 const char *fn
= NIL_P(file
) ? NULL
: RSTRING_PTR(file
);
146 VALUE mesg
= rb_enc_str_new(0, 0, enc
);
147 err_vcatf(mesg
, NULL
, fn
, line
, fmt
, args
);
148 rb_str_cat2(mesg
, "\n");
149 rb_write_error_str(mesg
);
153 exc
= syntax_error_with_path(exc
, file
, &mesg
, enc
);
154 err_vcatf(mesg
, NULL
, fn
, line
, fmt
, args
);
160 static unsigned int warning_disabled_categories
= (
161 (1U << RB_WARN_CATEGORY_DEPRECATED
) |
162 ~RB_WARN_CATEGORY_DEFAULT_BITS
);
165 rb_warning_category_mask(VALUE category
)
167 return 1U << rb_warning_category_from_name(category
);
170 rb_warning_category_t
171 rb_warning_category_from_name(VALUE category
)
175 Check_Type(category
, T_SYMBOL
);
176 if (!(cat_id
= rb_check_id(&category
)) ||
177 !st_lookup(warning_categories
.id2enum
, cat_id
, &cat_value
)) {
178 rb_raise(rb_eArgError
, "unknown category: %"PRIsVALUE
, category
);
180 return (rb_warning_category_t
)cat_value
;
184 rb_warning_category_to_name(rb_warning_category_t category
)
187 if (!st_lookup(warning_categories
.enum2id
, category
, &id
)) {
188 rb_raise(rb_eArgError
, "invalid category: %d", (int)category
);
190 return id
? ID2SYM(id
) : Qnil
;
194 rb_warning_category_update(unsigned int mask
, unsigned int bits
)
196 warning_disabled_categories
&= ~mask
;
197 warning_disabled_categories
|= mask
& ~bits
;
201 rb_warning_category_enabled_p(rb_warning_category_t category
)
203 return !(warning_disabled_categories
& (1U << category
));
208 * Warning[category] -> true or false
210 * Returns the flag to show the warning messages for +category+.
211 * Supported categories are:
214 * deprecation warnings
215 * * assignment of non-nil value to <code>$,</code> and <code>$;</code>
216 * * keyword arguments
220 * experimental features
224 * * Shape variation limit
228 rb_warning_s_aref(VALUE mod
, VALUE category
)
230 rb_warning_category_t cat
= rb_warning_category_from_name(category
);
231 return RBOOL(rb_warning_category_enabled_p(cat
));
236 * Warning[category] = flag -> flag
238 * Sets the warning flags for +category+.
239 * See Warning.[] for the categories.
243 rb_warning_s_aset(VALUE mod
, VALUE category
, VALUE flag
)
245 unsigned int mask
= rb_warning_category_mask(category
);
246 unsigned int disabled
= warning_disabled_categories
;
251 warning_disabled_categories
= disabled
;
257 * categories -> array
259 * Returns a list of the supported category symbols.
263 rb_warning_s_categories(VALUE mod
)
265 st_index_t num
= warning_categories
.id2enum
->num_entries
;
266 ID
*ids
= ALLOCA_N(ID
, num
);
267 num
= st_keys(warning_categories
.id2enum
, ids
, num
);
268 VALUE ary
= rb_ary_new_capa(num
);
269 for (st_index_t i
= 0; i
< num
; ++i
) {
270 rb_ary_push(ary
, ID2SYM(ids
[i
]));
272 return rb_ary_freeze(ary
);
277 * warn(msg, category: nil) -> nil
279 * Writes warning message +msg+ to $stderr. This method is called by
280 * Ruby for all emitted warnings. A +category+ may be included with
283 * See the documentation of the Warning module for how to customize this.
287 rb_warning_s_warn(int argc
, VALUE
*argv
, VALUE mod
)
291 VALUE category
= Qnil
;
293 rb_scan_args(argc
, argv
, "1:", &str
, &opt
);
294 if (!NIL_P(opt
)) rb_get_kwargs(opt
, &id_category
, 0, 1, &category
);
296 Check_Type(str
, T_STRING
);
297 rb_must_asciicompat(str
);
298 if (!NIL_P(category
)) {
299 rb_warning_category_t cat
= rb_warning_category_from_name(category
);
300 if (!rb_warning_category_enabled_p(cat
)) return Qnil
;
302 rb_write_error_str(str
);
307 * Document-module: Warning
309 * The Warning module contains a single method named #warn, and the
310 * module extends itself, making Warning.warn available.
311 * Warning.warn is called for all warnings issued by Ruby.
312 * By default, warnings are printed to $stderr.
314 * Changing the behavior of Warning.warn is useful to customize how warnings are
315 * handled by Ruby, for instance by filtering some warnings, and/or outputting
316 * warnings somewhere other than <tt>$stderr</tt>.
318 * If you want to change the behavior of Warning.warn you should use
319 * <tt>Warning.extend(MyNewModuleWithWarnMethod)</tt> and you can use +super+
320 * to get the default behavior of printing the warning to <tt>$stderr</tt>.
323 * module MyWarningFilter
324 * def warn(message, category: nil, **kwargs)
325 * if /some warning I want to ignore/.match?(message)
332 * Warning.extend MyWarningFilter
334 * You should never redefine Warning#warn (the instance method), as that will
335 * then no longer provide a way to use the default behavior.
337 * The warning[https://rubygems.org/gems/warning] gem provides convenient ways to customize Warning.warn.
341 rb_warning_warn(VALUE mod
, VALUE str
)
343 return rb_funcallv(mod
, id_warn
, 1, &str
);
348 rb_warning_warn_arity(void)
350 const rb_method_entry_t
*me
= rb_method_entry(rb_singleton_class(rb_mWarning
), id_warn
);
351 return me
? rb_method_entry_arity(me
) : 1;
355 rb_warn_category(VALUE str
, VALUE category
)
357 if (RUBY_DEBUG
&& !NIL_P(category
)) {
358 rb_warning_category_from_name(category
);
361 if (rb_warning_warn_arity() == 1) {
362 return rb_warning_warn(rb_mWarning
, str
);
367 args
[1] = rb_hash_new();
368 rb_hash_aset(args
[1], sym_category
, category
);
369 return rb_funcallv_kw(rb_mWarning
, id_warn
, 2, args
, RB_PASS_KEYWORDS
);
374 rb_write_warning_str(VALUE str
)
376 rb_warning_warn(rb_mWarning
, str
);
379 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT
, 4, 0)
381 warn_vsprintf(rb_encoding
*enc
, const char *file
, int line
, const char *fmt
, va_list args
)
383 VALUE str
= rb_enc_str_new(0, 0, enc
);
385 err_vcatf(str
, "warning: ", file
, line
, fmt
, args
);
386 return rb_str_cat2(str
, "\n");
389 #define with_warn_vsprintf(enc, file, line, fmt) \
392 va_start(args, fmt); \
393 str = warn_vsprintf(enc, file, line, fmt, args); \
397 rb_compile_warn(const char *file
, int line
, const char *fmt
, ...)
399 if (!NIL_P(ruby_verbose
)) {
400 with_warn_vsprintf(NULL
, file
, line
, fmt
) {
401 rb_write_warning_str(str
);
407 rb_enc_compile_warn(rb_encoding
*enc
, const char *file
, int line
, const char *fmt
, ...)
409 if (!NIL_P(ruby_verbose
)) {
410 with_warn_vsprintf(enc
, file
, line
, fmt
) {
411 rb_write_warning_str(str
);
416 /* rb_compile_warning() reports only in verbose mode */
418 rb_compile_warning(const char *file
, int line
, const char *fmt
, ...)
420 if (RTEST(ruby_verbose
)) {
421 with_warn_vsprintf(NULL
, file
, line
, fmt
) {
422 rb_write_warning_str(str
);
427 /* rb_enc_compile_warning() reports only in verbose mode */
429 rb_enc_compile_warning(rb_encoding
*enc
, const char *file
, int line
, const char *fmt
, ...)
431 if (RTEST(ruby_verbose
)) {
432 with_warn_vsprintf(enc
, file
, line
, fmt
) {
433 rb_write_warning_str(str
);
439 rb_category_compile_warn(rb_warning_category_t category
, const char *file
, int line
, const char *fmt
, ...)
441 if (!NIL_P(ruby_verbose
)) {
442 with_warn_vsprintf(NULL
, file
, line
, fmt
) {
443 rb_warn_category(str
, rb_warning_category_to_name(category
));
448 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT
, 2, 0)
450 warning_string(rb_encoding
*enc
, const char *fmt
, va_list args
)
453 const char *file
= rb_source_location_cstr(&line
);
454 return warn_vsprintf(enc
, file
, line
, fmt
, args
);
457 #define with_warning_string(mesg, enc, fmt) \
458 with_warning_string_from(mesg, enc, fmt, fmt)
459 #define with_warning_string_from(mesg, enc, fmt, last_arg) \
461 va_list args; va_start(args, last_arg); \
462 mesg = warning_string(enc, fmt, args); \
466 rb_warn(const char *fmt
, ...)
468 if (!NIL_P(ruby_verbose
)) {
469 with_warning_string(mesg
, 0, fmt
) {
470 rb_write_warning_str(mesg
);
476 rb_category_warn(rb_warning_category_t category
, const char *fmt
, ...)
478 if (!NIL_P(ruby_verbose
) && rb_warning_category_enabled_p(category
)) {
479 with_warning_string(mesg
, 0, fmt
) {
480 rb_warn_category(mesg
, rb_warning_category_to_name(category
));
486 rb_enc_warn(rb_encoding
*enc
, const char *fmt
, ...)
488 if (!NIL_P(ruby_verbose
)) {
489 with_warning_string(mesg
, enc
, fmt
) {
490 rb_write_warning_str(mesg
);
495 /* rb_warning() reports only in verbose mode */
497 rb_warning(const char *fmt
, ...)
499 if (RTEST(ruby_verbose
)) {
500 with_warning_string(mesg
, 0, fmt
) {
501 rb_write_warning_str(mesg
);
506 /* rb_category_warning() reports only in verbose mode */
508 rb_category_warning(rb_warning_category_t category
, const char *fmt
, ...)
510 if (RTEST(ruby_verbose
) && rb_warning_category_enabled_p(category
)) {
511 with_warning_string(mesg
, 0, fmt
) {
512 rb_warn_category(mesg
, rb_warning_category_to_name(category
));
518 rb_warning_string(const char *fmt
, ...)
520 with_warning_string(mesg
, 0, fmt
) {
527 rb_enc_warning(rb_encoding
*enc
, const char *fmt
, ...)
529 if (RTEST(ruby_verbose
)) {
530 with_warning_string(mesg
, enc
, fmt
) {
531 rb_write_warning_str(mesg
);
538 deprecation_warning_enabled(void)
540 if (NIL_P(ruby_verbose
)) return false;
541 if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED
)) return false;
546 warn_deprecated(VALUE mesg
, const char *removal
, const char *suggest
)
548 rb_str_set_len(mesg
, RSTRING_LEN(mesg
) - 1);
549 rb_str_cat_cstr(mesg
, " is deprecated");
551 rb_str_catf(mesg
, " and will be removed in Ruby %s", removal
);
553 if (suggest
) rb_str_catf(mesg
, "; use %s instead", suggest
);
554 rb_str_cat_cstr(mesg
, "\n");
555 rb_warn_category(mesg
, ID2SYM(id_deprecated
));
559 rb_warn_deprecated(const char *fmt
, const char *suggest
, ...)
561 if (!deprecation_warning_enabled()) return;
563 with_warning_string_from(mesg
, 0, fmt
, suggest
) {
564 warn_deprecated(mesg
, NULL
, suggest
);
569 rb_warn_deprecated_to_remove(const char *removal
, const char *fmt
, const char *suggest
, ...)
571 if (!deprecation_warning_enabled()) return;
573 with_warning_string_from(mesg
, 0, fmt
, suggest
) {
574 warn_deprecated(mesg
, removal
, suggest
);
579 rb_warn_reserved_name(const char *coming
, const char *fmt
, ...)
581 if (!deprecation_warning_enabled()) return;
583 with_warning_string_from(mesg
, 0, fmt
, fmt
) {
584 rb_str_set_len(mesg
, RSTRING_LEN(mesg
) - 1);
585 rb_str_catf(mesg
, " is reserved for Ruby %s\n", coming
);
586 rb_warn_category(mesg
, ID2SYM(id_deprecated
));
591 end_with_asciichar(VALUE str
, int c
)
593 return RB_TYPE_P(str
, T_STRING
) &&
594 rb_str_end_with_asciichar(str
, c
);
599 warning_write(int argc
, VALUE
*argv
, VALUE buf
)
602 rb_str_append(buf
, *argv
++);
607 VALUE
rb_ec_backtrace_location_ary(const rb_execution_context_t
*ec
, long lev
, long n
, bool skip_internal
);
610 rb_warn_m(rb_execution_context_t
*ec
, VALUE exc
, VALUE msgs
, VALUE uplevel
, VALUE category
)
612 VALUE location
= Qnil
;
613 int argc
= RARRAY_LENINT(msgs
);
614 const VALUE
*argv
= RARRAY_CONST_PTR(msgs
);
616 if (!NIL_P(ruby_verbose
) && argc
> 0) {
618 if (!NIL_P(uplevel
)) {
619 long lev
= NUM2LONG(uplevel
);
621 rb_raise(rb_eArgError
, "negative level (%ld)", lev
);
623 location
= rb_ec_backtrace_location_ary(ec
, lev
+ 1, 1, TRUE
);
624 if (!NIL_P(location
)) {
625 location
= rb_ary_entry(location
, 0);
628 if (argc
> 1 || !NIL_P(uplevel
) || !end_with_asciichar(str
, '\n')) {
630 if (NIL_P(uplevel
)) {
631 str
= rb_str_tmp_new(0);
633 else if (NIL_P(location
) ||
634 NIL_P(path
= rb_funcall(location
, rb_intern("path"), 0))) {
635 str
= rb_str_new_cstr("warning: ");
638 str
= rb_sprintf("%s:%ld: warning: ",
639 rb_string_value_ptr(&path
),
640 NUM2LONG(rb_funcall(location
, rb_intern("lineno"), 0)));
642 RBASIC_SET_CLASS(str
, rb_cWarningBuffer
);
643 rb_io_puts(argc
, argv
, str
);
644 RBASIC_SET_CLASS(str
, rb_cString
);
647 if (!NIL_P(category
)) {
648 category
= rb_to_symbol_type(category
);
649 rb_warning_category_from_name(category
);
652 if (exc
== rb_mWarning
) {
653 rb_must_asciicompat(str
);
654 rb_write_error_str(str
);
657 rb_warn_category(str
, category
);
663 #define MAX_BUG_REPORTERS 0x100
665 static struct bug_reporters
{
666 void (*func
)(FILE *out
, void *data
);
668 } bug_reporters
[MAX_BUG_REPORTERS
];
670 static int bug_reporters_size
;
673 rb_bug_reporter_add(void (*func
)(FILE *, void *), void *data
)
675 struct bug_reporters
*reporter
;
676 if (bug_reporters_size
>= MAX_BUG_REPORTERS
) {
677 return 0; /* failed to register */
679 reporter
= &bug_reporters
[bug_reporters_size
++];
680 reporter
->func
= func
;
681 reporter
->data
= data
;
686 /* returns true if x can not be used as file name */
690 #if defined __CYGWIN__ || defined DOSISH
691 # define PATH_SEP_ENCODING 1
692 // Assume that "/" is only the first byte in any encoding.
693 if (x
== ':') return true; // drive letter or ADS
694 if (x
== '\\') return true;
704 static const char PATHSEP_REPLACE
= '!';
707 append_pathname(char *p
, const char *pe
, VALUE str
)
709 #ifdef PATH_SEP_ENCODING
710 rb_encoding
*enc
= rb_enc_get(str
);
712 const char *s
= RSTRING_PTR(str
);
713 const char *const se
= s
+ RSTRING_LEN(str
);
716 --pe
; // for terminator
718 while (p
< pe
&& s
< se
&& (c
= *s
) != '\0') {
720 if (s
== se
|| !*s
) break; // chomp "." basename
721 if (path_sep_p(s
[1])) goto skipsep
; // skip "./"
723 else if (path_sep_p(c
)) {
724 // squeeze successive separators
725 *p
++ = PATHSEP_REPLACE
;
727 while (++s
< se
&& path_sep_p(*s
));
730 const char *const ss
= s
;
731 while (p
< pe
&& s
< se
&& *s
&& !path_sep_p(*s
)) {
732 #ifdef PATH_SEP_ENCODING
733 int n
= rb_enc_mbclen(s
, se
, enc
);
740 if (s
> ss
) memcpy(p
- (s
- ss
), ss
, s
- ss
);
747 append_basename(char *p
, const char *pe
, struct path_string
*path
, VALUE str
)
750 #ifdef PATH_SEP_ENCODING
751 rb_encoding
*enc
= rb_enc_get(str
);
753 const char *const b
= RSTRING_PTR(str
), *const e
= RSTRING_END(str
), *p
= e
;
756 if (path_sep_p(p
[-1])) {
757 #ifdef PATH_SEP_ENCODING
758 const char *t
= rb_enc_prev_char(b
, p
, e
, enc
);
773 size_t n
= path
->len
;
774 if (p
+ n
> pe
) n
= pe
- p
;
775 memcpy(p
, path
->ptr
, n
);
780 finish_report(FILE *out
, rb_pid_t pid
)
782 if (out
!= stdout
&& out
!= stderr
) fclose(out
);
783 #ifdef HAVE_WORKING_FORK
784 if (pid
> 0) waitpid(pid
, NULL
, 0);
788 struct report_expansion
{
789 struct path_string exe
, script
;
795 * Open a bug report file to write. The `RUBY_CRASH_REPORT`
796 * environment variable can be set to define a template that is used
797 * to name bug report files. The template can contain % specifiers
798 * which are substituted by the following values when a bug report
801 * %% A single % character.
802 * %e The base name of the executable filename.
803 * %E Pathname of executable, with slashes ('/') replaced by
804 * exclamation marks ('!').
805 * %f Similar to %e with the main script filename.
806 * %F Similar to %E with the main script filename.
807 * %p PID of dumped process in decimal.
808 * %t Time of dump, expressed as seconds since the Epoch,
809 * 1970-01-01 00:00:00 +0000 (UTC).
810 * %NNN Octal char code, upto 3 digits.
813 expand_report_argument(const char **input_template
, struct report_expansion
*values
,
814 char *buf
, size_t size
, bool word
)
817 char *end
= buf
+ size
;
818 const char *template = *input_template
;
821 if (p
>= end
-1 || !*template) return NULL
;
823 char c
= *template++;
824 if (word
&& ISSPACE(c
)) break;
825 if (!store
) continue;
828 switch (c
= *template++) {
830 p
= append_basename(p
, end
, &values
->exe
, rb_argv0
);
833 p
= append_pathname(p
, end
, rb_argv0
);
836 p
= append_basename(p
, end
, &values
->script
, GET_VM()->orig_progname
);
839 p
= append_pathname(p
, end
, GET_VM()->orig_progname
);
842 if (!values
->pid
) values
->pid
= getpid();
843 snprintf(p
, end
-p
, "%" PRI_PIDT_PREFIX
"d", values
->pid
);
847 if (!values
->time
) values
->time
= time(NULL
);
848 snprintf(p
, end
-p
, "%" PRI_TIMET_PREFIX
"d", values
->time
);
852 if (c
>= '0' && c
<= '7') {
853 c
= (unsigned char)ruby_scan_oct(template-1, 3, &n
);
855 if (!c
) store
= false;
860 if (p
< end
-1) *p
++ = c
;
862 *input_template
= template;
867 FILE *ruby_popen_writer(char *const *argv
, rb_pid_t
*pid
);
870 open_report_path(const char *template, char *buf
, size_t size
, rb_pid_t
*pid
)
872 struct report_expansion values
= {{0}};
874 if (!template) return NULL
;
875 if (0) fprintf(stderr
, "RUBY_CRASH_REPORT=%s\n", buf
);
876 if (*template == '|') {
877 char *argv
[16], *bufend
= buf
+ size
, *p
;
880 for (argc
= 0; argc
< numberof(argv
) - 1; ++argc
) {
881 while (*template && ISSPACE(*template)) template++;
882 p
= expand_report_argument(&template, &values
, buf
, bufend
-buf
, true);
888 if (!p
) return ruby_popen_writer(argv
, pid
);
890 else if (*template) {
891 expand_report_argument(&template, &values
, buf
, size
, false);
892 return fopen(buf
, "w");
897 static const char *crash_report
;
899 /* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
900 #define REPORT_BUG_BUFSIZ 256
902 bug_report_file(const char *file
, int line
, rb_pid_t
*pid
)
904 char buf
[REPORT_BUG_BUFSIZ
];
905 const char *report
= crash_report
;
906 if (!report
) report
= getenv("RUBY_CRASH_REPORT");
907 FILE *out
= open_report_path(report
, buf
, sizeof(buf
), pid
);
908 int len
= err_position_0(buf
, sizeof(buf
), file
, line
);
911 if ((ssize_t
)fwrite(buf
, 1, len
, out
) == (ssize_t
)len
) return out
;
914 if ((ssize_t
)fwrite(buf
, 1, len
, stderr
) == (ssize_t
)len
) {
917 if ((ssize_t
)fwrite(buf
, 1, len
, stdout
) == (ssize_t
)len
) {
924 FUNC_MINIMIZED(static void bug_important_message(FILE *out
, const char *const msg
, size_t len
));
927 bug_important_message(FILE *out
, const char *const msg
, size_t len
)
929 const char *const endmsg
= msg
+ len
;
933 if (isatty(fileno(out
))) {
934 static const char red
[] = "\033[;31;1;7m";
935 static const char green
[] = "\033[;32;7m";
936 static const char reset
[] = "\033[m";
937 const char *e
= strchr(p
, '\n');
938 const int w
= (int)(e
- p
);
940 int i
= (int)(e
- p
);
941 fputs(*p
== ' ' ? green
: red
, out
);
942 fwrite(p
, 1, e
- p
, out
);
943 for (; i
< w
; ++i
) fputc(' ', out
);
946 } while ((p
= e
+ 1) < endmsg
&& (e
= strchr(p
, '\n')) != 0 && e
> p
+ 1);
948 fwrite(p
, 1, endmsg
- p
, out
);
951 #undef CRASH_REPORTER_MAY_BE_CREATED
952 #if defined(__APPLE__) && \
953 (!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 */
954 # define CRASH_REPORTER_MAY_BE_CREATED
957 preface_dump(FILE *out
)
959 #if defined __APPLE__
960 static const char msg
[] = ""
961 "-- Crash Report log information "
962 "--------------------------------------------\n"
963 " See Crash Report log file in one of the following locations:\n"
964 # ifdef CRASH_REPORTER_MAY_BE_CREATED
965 " * ~/Library/Logs/CrashReporter\n"
966 " * /Library/Logs/CrashReporter\n"
968 " * ~/Library/Logs/DiagnosticReports\n"
969 " * /Library/Logs/DiagnosticReports\n"
970 " for more details.\n"
971 "Don't forget to include the above Crash Report log file in bug reports.\n"
973 const size_t msglen
= sizeof(msg
) - 1;
975 const char *msg
= NULL
;
976 const size_t msglen
= 0;
978 bug_important_message(out
, msg
, msglen
);
982 postscript_dump(FILE *out
)
984 #if defined __APPLE__
985 static const char msg
[] = ""
987 /*" ------------------------------------------------"*/
988 "\n""Don't forget to include the Crash Report log file under\n"
989 # ifdef CRASH_REPORTER_MAY_BE_CREATED
992 "DiagnosticReports directory in bug reports.\n"
993 /*"------------------------------------------------------------\n"*/
995 const size_t msglen
= sizeof(msg
) - 1;
997 const char *msg
= NULL
;
998 const size_t msglen
= 0;
1000 bug_important_message(out
, msg
, msglen
);
1003 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT
, 2, 0)
1005 bug_report_begin_valist(FILE *out
, const char *fmt
, va_list args
)
1007 char buf
[REPORT_BUG_BUFSIZ
];
1009 fputs("[BUG] ", out
);
1010 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
1012 snprintf(buf
, sizeof(buf
), "\n%s\n\n", rb_dynamic_description
);
1017 #define bug_report_begin(out, fmt) do { \
1019 va_start(args, fmt); \
1020 bug_report_begin_valist(out, fmt, args); \
1025 bug_report_end(FILE *out
, rb_pid_t pid
)
1027 /* call additional bug reporters */
1030 for (i
=0; i
<bug_reporters_size
; i
++) {
1031 struct bug_reporters
*reporter
= &bug_reporters
[i
];
1032 (*reporter
->func
)(out
, reporter
->data
);
1035 postscript_dump(out
);
1036 finish_report(out
, pid
);
1039 #define report_bug(file, line, fmt, ctx) do { \
1040 rb_pid_t pid = -1; \
1041 FILE *out = bug_report_file(file, line, &pid); \
1043 bug_report_begin(out, fmt); \
1044 rb_vm_bugreport(ctx, out); \
1045 bug_report_end(out, pid); \
1049 #define report_bug_valist(file, line, fmt, ctx, args) do { \
1050 rb_pid_t pid = -1; \
1051 FILE *out = bug_report_file(file, line, &pid); \
1053 bug_report_begin_valist(out, fmt, args); \
1054 rb_vm_bugreport(ctx, out); \
1055 bug_report_end(out, pid); \
1060 ruby_set_crash_report(const char *template)
1062 crash_report
= template;
1065 char buf
[REPORT_BUG_BUFSIZ
];
1066 FILE *out
= open_report_path(template, buf
, sizeof(buf
), &pid
);
1068 time_t t
= time(NULL
);
1069 fprintf(out
, "ruby_test_bug_report: %s", ctime(&t
));
1070 finish_report(out
, pid
);
1075 NORETURN(static void die(void));
1079 #if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
1080 _set_abort_behavior( 0, _CALL_REPORTFAULT
);
1086 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT
, 1, 0)
1088 rb_bug_without_die_internal(const char *fmt
, va_list args
)
1090 const char *file
= NULL
;
1094 file
= rb_source_location_cstr(&line
);
1097 report_bug_valist(file
, line
, fmt
, NULL
, args
);
1100 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT
, 1, 0)
1102 rb_bug_without_die(const char *fmt
, ...)
1105 va_start(args
, fmt
);
1106 rb_bug_without_die_internal(fmt
, args
);
1111 rb_bug(const char *fmt
, ...)
1114 va_start(args
, fmt
);
1115 rb_bug_without_die_internal(fmt
, args
);
1121 rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler
, int sig
, const void *ctx
, const char *fmt
, ...)
1123 const char *file
= NULL
;
1127 file
= rb_source_location_cstr(&line
);
1130 report_bug(file
, line
, fmt
, ctx
);
1132 if (default_sighandler
) default_sighandler(sig
);
1134 ruby_default_signal(sig
);
1140 rb_bug_errno(const char *mesg
, int errno_arg
)
1143 rb_bug("%s: errno == 0 (NOERROR)", mesg
);
1145 const char *errno_str
= rb_strerrno(errno_arg
);
1147 rb_bug("%s: %s (%s)", mesg
, strerror(errno_arg
), errno_str
);
1149 rb_bug("%s: %s (%d)", mesg
, strerror(errno_arg
), errno_arg
);
1154 * this is safe to call inside signal handler and timer thread
1155 * (which isn't a Ruby Thread object)
1157 #define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
1158 #define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
1161 rb_async_bug_errno(const char *mesg
, int errno_arg
)
1163 WRITE_CONST(2, "[ASYNC BUG] ");
1164 write_or_abort(2, mesg
, strlen(mesg
));
1165 WRITE_CONST(2, "\n");
1167 if (errno_arg
== 0) {
1168 WRITE_CONST(2, "errno == 0 (NOERROR)\n");
1171 const char *errno_str
= rb_strerrno(errno_arg
);
1174 errno_str
= "undefined errno";
1175 write_or_abort(2, errno_str
, strlen(errno_str
));
1177 WRITE_CONST(2, "\n\n");
1178 write_or_abort(2, rb_dynamic_description
, strlen(rb_dynamic_description
));
1183 rb_report_bug_valist(VALUE file
, int line
, const char *fmt
, va_list args
)
1185 report_bug_valist(RSTRING_PTR(file
), line
, fmt
, NULL
, args
);
1189 rb_assert_failure(const char *file
, int line
, const char *name
, const char *expr
)
1191 rb_assert_failure_detail(file
, line
, name
, expr
, NULL
);
1195 rb_assert_failure_detail(const char *file
, int line
, const char *name
, const char *expr
,
1196 const char *fmt
, ...)
1199 FILE *out
= bug_report_file(file
, line
, &pid
);
1201 fputs("Assertion Failed: ", out
);
1202 if (name
) fprintf(out
, "%s:", name
);
1207 va_start(args
, fmt
);
1209 vfprintf(out
, fmt
, args
);
1212 fprintf(out
, "\n%s\n\n", rb_dynamic_description
);
1215 rb_vm_bugreport(NULL
, out
);
1216 bug_report_end(out
, pid
);
1222 static const char builtin_types
[][10] = {
1235 "Data", /* internal use: wrapped C pointers */
1236 "MatchData", /* data of $~ */
1243 "Symbol", /* :symbol */
1245 "undef", /* internal use: #undef; should not happen */
1249 "<Memo>", /* internal use: general memo */
1250 "<Node>", /* internal use: syntax tree node */
1251 "<iClass>", /* internal use: mixed-in module holder */
1255 rb_builtin_type_name(int t
)
1258 if ((unsigned int)t
>= numberof(builtin_types
)) return 0;
1259 name
= builtin_types
[t
];
1260 if (*name
) return name
;
1265 displaying_class_of(VALUE x
)
1268 case Qfalse
: return rb_fstring_cstr("false");
1269 case Qnil
: return rb_fstring_cstr("nil");
1270 case Qtrue
: return rb_fstring_cstr("true");
1271 default: return rb_obj_class(x
);
1276 builtin_class_name(VALUE x
)
1283 else if (FIXNUM_P(x
)) {
1286 else if (SYMBOL_P(x
)) {
1289 else if (RB_TYPE_P(x
, T_TRUE
)) {
1292 else if (RB_TYPE_P(x
, T_FALSE
)) {
1302 rb_builtin_class_name(VALUE x
)
1304 const char *etype
= builtin_class_name(x
);
1307 etype
= rb_obj_classname(x
);
1312 COLDFUNC
NORETURN(static void unexpected_type(VALUE
, int, int));
1313 #define UNDEF_LEAKED "undef leaked to the Ruby space"
1316 unexpected_type(VALUE x
, int xt
, int t
)
1318 const char *tname
= rb_builtin_type_name(t
);
1319 VALUE mesg
, exc
= rb_eFatal
;
1322 mesg
= rb_sprintf("wrong argument type %"PRIsVALUE
" (expected %s)",
1323 displaying_class_of(x
), tname
);
1324 exc
= rb_eTypeError
;
1326 else if (xt
> T_MASK
&& xt
<= 0x3f) {
1327 mesg
= rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
1328 " from extension library for ruby 1.8)", t
, xt
);
1331 mesg
= rb_sprintf("unknown type 0x%x (0x%x given)", t
, xt
);
1333 rb_exc_raise(rb_exc_new_str(exc
, mesg
));
1337 rb_check_type(VALUE x
, int t
)
1341 if (RB_UNLIKELY(UNDEF_P(x
))) {
1342 rb_bug(UNDEF_LEAKED
);
1346 if (xt
!= t
|| (xt
== T_DATA
&& rbimpl_rtypeddata_p(x
))) {
1348 * Typed data is not simple `T_DATA`, but in a sense an
1349 * extension of `struct RVALUE`, which are incompatible with
1350 * each other except when inherited.
1352 * So it is not enough to just check `T_DATA`, it must be
1353 * identified by its `type` using `Check_TypedStruct` instead.
1355 unexpected_type(x
, xt
, t
);
1360 rb_unexpected_type(VALUE x
, int t
)
1362 if (RB_UNLIKELY(UNDEF_P(x
))) {
1363 rb_bug(UNDEF_LEAKED
);
1366 unexpected_type(x
, TYPE(x
), t
);
1370 rb_typeddata_inherited_p(const rb_data_type_t
*child
, const rb_data_type_t
*parent
)
1373 if (child
== parent
) return 1;
1374 child
= child
->parent
;
1380 rb_typeddata_is_kind_of(VALUE obj
, const rb_data_type_t
*data_type
)
1382 if (!RB_TYPE_P(obj
, T_DATA
) ||
1383 !RTYPEDDATA_P(obj
) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj
), data_type
)) {
1389 #undef rb_typeddata_is_instance_of
1391 rb_typeddata_is_instance_of(VALUE obj
, const rb_data_type_t
*data_type
)
1393 return rb_typeddata_is_instance_of_inline(obj
, data_type
);
1397 rb_check_typeddata(VALUE obj
, const rb_data_type_t
*data_type
)
1401 if (!RB_TYPE_P(obj
, T_DATA
)) {
1402 actual
= displaying_class_of(obj
);
1404 else if (!RTYPEDDATA_P(obj
)) {
1405 actual
= displaying_class_of(obj
);
1407 else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj
), data_type
)) {
1408 const char *name
= RTYPEDDATA_TYPE(obj
)->wrap_struct_name
;
1409 actual
= rb_str_new_cstr(name
); /* or rb_fstring_cstr? not sure... */
1412 return RTYPEDDATA_GET_DATA(obj
);
1415 const char *expected
= data_type
->wrap_struct_name
;
1416 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (expected %s)",
1418 UNREACHABLE_RETURN(NULL
);
1421 /* exception classes */
1422 VALUE rb_eException
;
1423 VALUE rb_eSystemExit
;
1424 VALUE rb_eInterrupt
;
1427 VALUE rb_eStandardError
;
1428 VALUE rb_eRuntimeError
;
1429 VALUE rb_eFrozenError
;
1430 VALUE rb_eTypeError
;
1432 VALUE rb_eIndexError
;
1434 VALUE rb_eRangeError
;
1435 VALUE rb_eNameError
;
1436 VALUE rb_eEncodingError
;
1437 VALUE rb_eEncCompatError
;
1438 VALUE rb_eNoMethodError
;
1439 VALUE rb_eSecurityError
;
1440 VALUE rb_eNotImpError
;
1441 VALUE rb_eNoMemError
;
1442 VALUE rb_cNameErrorMesg
;
1443 VALUE rb_eNoMatchingPatternError
;
1444 VALUE rb_eNoMatchingPatternKeyError
;
1446 VALUE rb_eScriptError
;
1447 VALUE rb_eSyntaxError
;
1448 VALUE rb_eLoadError
;
1450 VALUE rb_eSystemCallError
;
1452 static VALUE rb_eNOERROR
;
1454 ID ruby_static_id_cause
;
1455 #define id_cause ruby_static_id_cause
1456 static ID id_message
, id_detailed_message
, id_backtrace
;
1457 static ID id_key
, id_matchee
, id_args
, id_Errno
, id_errno
, id_i_path
;
1458 static ID id_receiver
, id_recv
, id_iseq
, id_local_variables
;
1459 static ID id_private_call_p
, id_top
, id_bottom
;
1461 #define id_bt_locations idBt_locations
1462 #define id_mesg idMesg
1463 #define id_name idName
1465 #undef rb_exc_new_cstr
1468 rb_exc_new(VALUE etype
, const char *ptr
, long len
)
1470 VALUE mesg
= rb_str_new(ptr
, len
);
1471 return rb_class_new_instance(1, &mesg
, etype
);
1475 rb_exc_new_cstr(VALUE etype
, const char *s
)
1477 return rb_exc_new(etype
, s
, strlen(s
));
1481 rb_exc_new_str(VALUE etype
, VALUE str
)
1483 rb_yjit_lazy_push_frame(GET_EC()->cfp
->pc
);
1485 return rb_class_new_instance(1, &str
, etype
);
1489 exc_init(VALUE exc
, VALUE mesg
)
1491 rb_ivar_set(exc
, id_mesg
, mesg
);
1492 rb_ivar_set(exc
, id_bt
, Qnil
);
1499 * Exception.new(message = nil) -> exception
1501 * Returns a new exception object.
1503 * The given +message+ should be
1504 * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects];
1505 * see method #message;
1506 * if not given, the message is the class name of the new instance
1507 * (which may be the name of a subclass):
1511 * Exception.new # => #<Exception: Exception>
1512 * LoadError.new # => #<LoadError: LoadError> # Subclass of Exception.
1513 * Exception.new('Boom') # => #<Exception: Boom>
1518 exc_initialize(int argc
, VALUE
*argv
, VALUE exc
)
1522 arg
= (!rb_check_arity(argc
, 0, 1) ? Qnil
: argv
[0]);
1523 return exc_init(exc
, arg
);
1527 * Document-method: exception
1530 * exception(message = nil) -> self or new_exception
1532 * Returns an exception object of the same class as +self+;
1533 * useful for creating a similar exception, but with a different message.
1535 * With +message+ +nil+, returns +self+:
1537 * x0 = StandardError.new('Boom') # => #<StandardError: Boom>
1538 * x1 = x0.exception # => #<StandardError: Boom>
1539 * x0.__id__ == x1.__id__ # => true
1541 * With {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]
1542 * +message+ (even the same as the original message),
1543 * returns a new exception object whose class is the same as +self+,
1544 * and whose message is the given +message+:
1546 * x1 = x0.exception('Boom') # => #<StandardError: Boom>
1547 * x0..equal?(x1) # => false
1552 exc_exception(int argc
, VALUE
*argv
, VALUE self
)
1556 argc
= rb_check_arity(argc
, 0, 1);
1557 if (argc
== 0) return self
;
1558 if (argc
== 1 && self
== argv
[0]) return self
;
1559 exc
= rb_obj_clone(self
);
1560 rb_ivar_set(exc
, id_mesg
, argv
[0]);
1568 * Returns a string representation of +self+:
1570 * x = RuntimeError.new('Boom')
1571 * x.to_s # => "Boom"
1572 * x = RuntimeError.new
1573 * x.to_s # => "RuntimeError"
1580 VALUE mesg
= rb_attr_get(exc
, idMesg
);
1582 if (NIL_P(mesg
)) return rb_class_name(CLASS_OF(exc
));
1583 return rb_String(mesg
);
1586 /* FIXME: Include eval_error.c */
1587 void rb_error_write(VALUE errinfo
, VALUE emesg
, VALUE errat
, VALUE str
, VALUE opt
, VALUE highlight
, VALUE reverse
);
1590 rb_get_message(VALUE exc
)
1592 VALUE e
= rb_check_funcall(exc
, id_message
, 0, 0);
1593 if (UNDEF_P(e
)) return Qnil
;
1594 if (!RB_TYPE_P(e
, T_STRING
)) e
= rb_check_string_type(e
);
1599 rb_get_detailed_message(VALUE exc
, VALUE opt
)
1603 e
= rb_check_funcall(exc
, id_detailed_message
, 0, 0);
1606 e
= rb_check_funcall_kw(exc
, id_detailed_message
, 1, &opt
, 1);
1608 if (UNDEF_P(e
)) return Qnil
;
1609 if (!RB_TYPE_P(e
, T_STRING
)) e
= rb_check_string_type(e
);
1615 * Exception.to_tty? -> true or false
1617 * Returns +true+ if exception messages will be sent to a terminal device.
1620 exc_s_to_tty_p(VALUE self
)
1622 return RBOOL(rb_stderr_tty_p());
1626 check_highlight_keyword(VALUE opt
, int auto_tty_detect
)
1628 VALUE highlight
= Qnil
;
1631 highlight
= rb_hash_lookup(opt
, sym_highlight
);
1633 switch (highlight
) {
1635 rb_bool_expected(highlight
, "highlight", TRUE
);
1637 case Qtrue
: case Qfalse
: case Qnil
: break;
1641 if (NIL_P(highlight
)) {
1642 highlight
= RBOOL(auto_tty_detect
&& rb_stderr_tty_p());
1649 check_order_keyword(VALUE opt
)
1654 static VALUE kw_order
;
1655 if (!kw_order
) kw_order
= ID2SYM(rb_intern_const("order"));
1657 order
= rb_hash_lookup(opt
, kw_order
);
1659 if (order
!= Qnil
) {
1660 ID id
= rb_check_id(&order
);
1661 if (id
== id_bottom
) order
= Qtrue
;
1662 else if (id
== id_top
) order
= Qfalse
;
1664 rb_raise(rb_eArgError
, "expected :top or :bottom as "
1665 "order: %+"PRIsVALUE
, order
);
1670 if (NIL_P(order
)) order
= Qfalse
;
1677 * full_message(highlight: true, order: :top) -> string
1679 * Returns an enhanced message string:
1681 * - Includes the exception class name.
1682 * - If the value of keyword +highlight+ is true (not +nil+ or +false+),
1683 * includes bolding ANSI codes (see below) to enhance the appearance of the message.
1684 * - Includes the {backtrace}[rdoc-ref:exceptions.md@Backtraces]:
1686 * - If the value of keyword +order+ is +:top+ (the default),
1687 * lists the error message and the innermost backtrace entry first.
1688 * - If the value of keyword +order+ is +:bottom+,
1689 * lists the error message the the innermost entry last.
1698 * pp x.full_message(highlight: false).split("\n")
1699 * pp x.full_message.split("\n")
1709 * ["t.rb:3:in 'Integer#/': divided by 0 (ZeroDivisionError)",
1710 * "\tfrom t.rb:3:in 'Object#baz'",
1711 * "\tfrom t.rb:10:in 'Object#bar'",
1712 * "\tfrom t.rb:11:in 'Object#foo'",
1713 * "\tfrom t.rb:12:in '<main>'"]
1714 * ["t.rb:3:in 'Integer#/': \e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m",
1715 * "\tfrom t.rb:3:in 'Object#baz'",
1716 * "\tfrom t.rb:10:in 'Object#bar'",
1717 * "\tfrom t.rb:11:in 'Object#foo'",
1718 * "\tfrom t.rb:12:in '<main>'"]
1720 * An overriding method should be careful with ANSI code enhancements;
1721 * see {Messages}[rdoc-ref:exceptions.md@Messages].
1725 exc_full_message(int argc
, VALUE
*argv
, VALUE exc
)
1727 VALUE opt
, str
, emesg
, errat
;
1728 VALUE highlight
, order
;
1730 rb_scan_args(argc
, argv
, "0:", &opt
);
1732 highlight
= check_highlight_keyword(opt
, 1);
1733 order
= check_order_keyword(opt
);
1736 if (NIL_P(opt
)) opt
= rb_hash_new();
1737 rb_hash_aset(opt
, sym_highlight
, highlight
);
1740 str
= rb_str_new2("");
1741 errat
= rb_get_backtrace(exc
);
1742 emesg
= rb_get_detailed_message(exc
, opt
);
1744 rb_error_write(exc
, emesg
, errat
, str
, opt
, highlight
, order
);
1754 * See {Messages}[rdoc-ref:exceptions.md@Messages].
1758 exc_message(VALUE exc
)
1760 return rb_funcallv(exc
, idTo_s
, 0, 0);
1765 * detailed_message(highlight: false, **kwargs) -> string
1767 * Returns the message string with enhancements:
1769 * - Includes the exception class name in the first line.
1770 * - If the value of keyword +highlight+ is +true+,
1771 * includes bolding and underlining ANSI codes (see below)
1772 * to enhance the appearance of the message.
1780 * p x.detailed_message # Class name added.
1781 * p x.detailed_message(highlight: true) # Class name, bolding, and underlining added.
1787 * "divided by 0 (ZeroDivisionError)"
1788 * "\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m"
1790 * This method is overridden by some gems in the Ruby standard library to add information:
1792 * - DidYouMean::Correctable#detailed_message.
1793 * - ErrorHighlight::CoreExt#detailed_message.
1794 * - SyntaxSuggest#detailed_message.
1796 * An overriding method must be tolerant of passed keyword arguments,
1797 * which may include (but may not be limited to):
1800 * - +:did_you_mean+.
1801 * - +:error_highlight+.
1802 * - +:syntax_suggest+.
1804 * An overriding method should also be careful with ANSI code enhancements;
1805 * see {Messages}[rdoc-ref:exceptions.md@Messages].
1809 exc_detailed_message(int argc
, VALUE
*argv
, VALUE exc
)
1813 rb_scan_args(argc
, argv
, "0:", &opt
);
1815 VALUE highlight
= check_highlight_keyword(opt
, 0);
1817 extern VALUE
rb_decorate_message(const VALUE eclass
, VALUE emesg
, int highlight
);
1819 return rb_decorate_message(CLASS_OF(exc
), rb_get_message(exc
), RTEST(highlight
));
1826 * Returns a string representation of +self+:
1828 * x = RuntimeError.new('Boom')
1829 * x.inspect # => "#<RuntimeError: Boom>"
1830 * x = RuntimeError.new
1831 * x.inspect # => "#<RuntimeError: RuntimeError>"
1836 exc_inspect(VALUE exc
)
1840 klass
= CLASS_OF(exc
);
1841 exc
= rb_obj_as_string(exc
);
1842 if (RSTRING_LEN(exc
) == 0) {
1843 return rb_class_name(klass
);
1846 str
= rb_str_buf_new2("#<");
1847 klass
= rb_class_name(klass
);
1848 rb_str_buf_append(str
, klass
);
1850 if (RTEST(rb_str_include(exc
, rb_str_new2("\n")))) {
1851 rb_str_catf(str
, ":%+"PRIsVALUE
, exc
);
1854 rb_str_buf_cat(str
, ": ", 2);
1855 rb_str_buf_append(str
, exc
);
1858 rb_str_buf_cat(str
, ">", 1);
1865 * backtrace -> array or nil
1867 * Returns the backtrace (the list of code locations that led to the exception),
1868 * as an array of strings.
1870 * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
1872 * def division(numerator, denominator)
1873 * numerator / denominator
1880 * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
1881 * loc = ex.backtrace.first
1886 * The value returned by this method migth be adjusted when raising (see Kernel#raise),
1887 * or during intermediate handling by #set_backtrace.
1889 * See also #backtrace_locations that provide the same value, as structured objects.
1890 * (Note though that two values might not be consistent with each other when
1891 * backtraces are manually adjusted.)
1893 * see {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
1897 exc_backtrace(VALUE exc
)
1901 obj
= rb_attr_get(exc
, id_bt
);
1903 if (rb_backtrace_p(obj
)) {
1904 obj
= rb_backtrace_to_str_ary(obj
);
1905 /* rb_ivar_set(exc, id_bt, obj); */
1911 static VALUE
rb_check_backtrace(VALUE
);
1914 rb_get_backtrace(VALUE exc
)
1916 ID mid
= id_backtrace
;
1918 if (rb_method_basic_definition_p(CLASS_OF(exc
), id_backtrace
)) {
1919 VALUE klass
= rb_eException
;
1920 rb_execution_context_t
*ec
= GET_EC();
1923 EXEC_EVENT_HOOK(ec
, RUBY_EVENT_C_CALL
, exc
, mid
, mid
, klass
, Qundef
);
1924 info
= exc_backtrace(exc
);
1925 EXEC_EVENT_HOOK(ec
, RUBY_EVENT_C_RETURN
, exc
, mid
, mid
, klass
, info
);
1928 info
= rb_funcallv(exc
, mid
, 0, 0);
1930 if (NIL_P(info
)) return Qnil
;
1931 return rb_check_backtrace(info
);
1936 * backtrace_locations -> array or nil
1938 * Returns the backtrace (the list of code locations that led to the exception),
1939 * as an array of Thread::Backtrace::Location instances.
1941 * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
1943 * def division(numerator, denominator)
1944 * numerator / denominator
1950 * p ex.backtrace_locations
1951 * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
1952 * loc = ex.backtrace_locations.first
1954 * # Thread::Backtrace::Location
1963 * The value returned by this method might be adjusted when raising (see Kernel#raise),
1964 * or during intermediate handling by #set_backtrace.
1966 * See also #backtrace that provide the same value as an array of strings.
1967 * (Note though that two values might not be consistent with each other when
1968 * backtraces are manually adjusted.)
1970 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
1973 exc_backtrace_locations(VALUE exc
)
1977 obj
= rb_attr_get(exc
, id_bt_locations
);
1979 obj
= rb_backtrace_to_location_ary(obj
);
1985 rb_check_backtrace(VALUE bt
)
1988 static const char err
[] = "backtrace must be an Array of String or an Array of Thread::Backtrace::Location";
1991 if (RB_TYPE_P(bt
, T_STRING
)) return rb_ary_new3(1, bt
);
1992 if (rb_backtrace_p(bt
)) return bt
;
1993 if (!RB_TYPE_P(bt
, T_ARRAY
)) {
1994 rb_raise(rb_eTypeError
, err
);
1996 for (i
=0;i
<RARRAY_LEN(bt
);i
++) {
1997 VALUE e
= RARRAY_AREF(bt
, i
);
1998 if (!RB_TYPE_P(e
, T_STRING
)) {
1999 rb_raise(rb_eTypeError
, err
);
2008 * set_backtrace(value) -> value
2010 * Sets the backtrace value for +self+; returns the given +value+.
2012 * The +value+ might be:
2014 * - an array of Thread::Backtrace::Location;
2015 * - an array of String instances;
2016 * - a single String instance; or
2019 * Using array of Thread::Backtrace::Location is the most consistent
2020 * option: it sets both #backtrace and #backtrace_locations. It should be
2021 * preferred when possible. The suitable array of locations can be obtained
2022 * from Kernel#caller_locations, copied from another error, or just set to
2023 * the adjusted result of the current error's #backtrace_locations:
2027 * def parse_payload(text)
2028 * JSON.parse(text) # test.rb, line 4
2029 * rescue JSON::ParserError => ex
2030 * ex.set_backtrace(ex.backtrace_locations[2...])
2034 * parse_payload('{"wrong: "json"')
2035 * # test.rb:4:in 'Object#parse_payload': unexpected token at '{"wrong: "json"' (JSON::ParserError)
2037 * # An error points to the body of parse_payload method,
2038 * # hiding the parts of the backtrace related to the internals
2039 * # of the "json" library
2041 * # The error has both #backtace and #backtrace_locations set
2044 * parse_payload('{"wrong: "json"')
2047 * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
2048 * p ex.backtrace_locations
2049 * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
2052 * When the desired stack of locations is not available and should
2053 * be constructed from scratch, an array of strings or a singular
2054 * string can be used. In this case, only #backtrace is affected:
2056 * def parse_payload(text)
2058 * rescue JSON::ParserError => ex
2059 * ex.set_backtrace(["dsl.rb:34", "framework.rb:1"])
2060 * # The error have the new value in #backtrace:
2062 * # ["dsl.rb:34", "framework.rb:1"]
2064 * # but the original one in #backtrace_locations
2065 * p ex.backtrace_locations
2066 * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
2069 * parse_payload('{"wrong: "json"')
2071 * Calling #set_backtrace with +nil+ clears up #backtrace but doesn't affect
2072 * #backtrace_locations:
2074 * def parse_payload(text)
2076 * rescue JSON::ParserError => ex
2077 * ex.set_backtrace(nil)
2080 * p ex.backtrace_locations
2081 * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
2084 * parse_payload('{"wrong: "json"')
2086 * On reraising of such an exception, both #backtrace and #backtrace_locations
2087 * is set to the place of reraising:
2089 * def parse_payload(text)
2091 * rescue JSON::ParserError => ex
2092 * ex.set_backtrace(nil)
2093 * raise # test.rb, line 7
2097 * parse_payload('{"wrong: "json"')
2100 * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
2101 * p ex.backtrace_locations
2102 * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
2105 * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
2109 exc_set_backtrace(VALUE exc
, VALUE bt
)
2111 VALUE btobj
= rb_location_ary_to_backtrace(bt
);
2113 rb_ivar_set(exc
, id_bt
, btobj
);
2114 rb_ivar_set(exc
, id_bt_locations
, btobj
);
2118 return rb_ivar_set(exc
, id_bt
, rb_check_backtrace(bt
));
2123 rb_exc_set_backtrace(VALUE exc
, VALUE bt
)
2125 return exc_set_backtrace(exc
, bt
);
2130 * cause -> exception or nil
2132 * Returns the previous value of global variable <tt>$!</tt>,
2133 * which may be +nil+
2134 * (see {Global Variables}[rdoc-ref:exceptions.md@Global+Variables]):
2139 * puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}."
2143 * puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}."
2147 * puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}."
2154 * Exception: Boom 0; $!: Boom 0; cause: nil.
2155 * Exception: Boom 1; $!: Boom 1; cause: Boom 0.
2156 * Exception: Boom 2; $!: Boom 2; cause: Boom 1.
2161 exc_cause(VALUE exc
)
2163 return rb_attr_get(exc
, id_cause
);
2167 try_convert_to_exception(VALUE obj
)
2169 return rb_check_funcall(obj
, idException
, 0, 0);
2174 * self == object -> true or false
2176 * Returns whether +object+ is the same class as +self+
2177 * and its #message and #backtrace are equal to those of +self+.
2182 exc_equal(VALUE exc
, VALUE obj
)
2184 VALUE mesg
, backtrace
;
2186 if (exc
== obj
) return Qtrue
;
2188 if (rb_obj_class(exc
) != rb_obj_class(obj
)) {
2191 obj
= rb_protect(try_convert_to_exception
, obj
, &state
);
2192 if (state
|| UNDEF_P(obj
)) {
2193 rb_set_errinfo(Qnil
);
2196 if (rb_obj_class(exc
) != rb_obj_class(obj
)) return Qfalse
;
2197 mesg
= rb_check_funcall(obj
, id_message
, 0, 0);
2198 if (UNDEF_P(mesg
)) return Qfalse
;
2199 backtrace
= rb_check_funcall(obj
, id_backtrace
, 0, 0);
2200 if (UNDEF_P(backtrace
)) return Qfalse
;
2203 mesg
= rb_attr_get(obj
, id_mesg
);
2204 backtrace
= exc_backtrace(obj
);
2207 if (!rb_equal(rb_attr_get(exc
, id_mesg
), mesg
))
2209 return rb_equal(exc_backtrace(exc
), backtrace
);
2214 * SystemExit.new -> system_exit
2215 * SystemExit.new(status) -> system_exit
2216 * SystemExit.new(status, msg) -> system_exit
2217 * SystemExit.new(msg) -> system_exit
2219 * Create a new +SystemExit+ exception with the given status and message.
2220 * Status is true, false, or an integer.
2221 * If status is not given, true is used.
2225 exit_initialize(int argc
, VALUE
*argv
, VALUE exc
)
2233 status
= INT2FIX(EXIT_SUCCESS
);
2238 status
= INT2FIX(EXIT_FAILURE
);
2243 status
= rb_check_to_int(status
);
2244 if (NIL_P(status
)) {
2245 status
= INT2FIX(EXIT_SUCCESS
);
2248 #if EXIT_SUCCESS != 0
2249 if (status
== INT2FIX(0))
2250 status
= INT2FIX(EXIT_SUCCESS
);
2259 status
= INT2FIX(EXIT_SUCCESS
);
2261 rb_call_super(argc
, argv
);
2262 rb_ivar_set(exc
, id_status
, status
);
2269 * system_exit.status -> integer
2271 * Return the status value associated with this system exit.
2275 exit_status(VALUE exc
)
2277 return rb_attr_get(exc
, id_status
);
2283 * system_exit.success? -> true or false
2285 * Returns +true+ if exiting successful, +false+ if not.
2289 exit_success_p(VALUE exc
)
2291 VALUE status_val
= rb_attr_get(exc
, id_status
);
2294 if (NIL_P(status_val
))
2296 status
= NUM2INT(status_val
);
2297 return RBOOL(WIFEXITED(status
) && WEXITSTATUS(status
) == EXIT_SUCCESS
);
2301 err_init_recv(VALUE exc
, VALUE recv
)
2303 if (!UNDEF_P(recv
)) rb_ivar_set(exc
, id_recv
, recv
);
2309 * FrozenError.new(msg=nil, receiver: nil) -> frozen_error
2311 * Construct a new FrozenError exception. If given the <i>receiver</i>
2312 * parameter may subsequently be examined using the FrozenError#receiver
2316 * raise FrozenError.new("can't modify frozen array", receiver: a)
2320 frozen_err_initialize(int argc
, VALUE
*argv
, VALUE self
)
2323 VALUE values
[numberof(keywords
)], options
;
2325 argc
= rb_scan_args(argc
, argv
, "*:", NULL
, &options
);
2326 keywords
[0] = id_receiver
;
2327 rb_get_kwargs(options
, keywords
, 0, numberof(values
), values
);
2328 rb_call_super(argc
, argv
);
2329 err_init_recv(self
, values
[0]);
2334 * Document-method: FrozenError#receiver
2336 * frozen_error.receiver -> object
2338 * Return the receiver associated with this FrozenError exception.
2341 #define frozen_err_receiver name_err_receiver
2344 rb_name_error(ID id
, const char *fmt
, ...)
2349 va_start(args
, fmt
);
2350 argv
[0] = rb_vsprintf(fmt
, args
);
2353 argv
[1] = ID2SYM(id
);
2354 exc
= rb_class_new_instance(2, argv
, rb_eNameError
);
2359 rb_name_error_str(VALUE str
, const char *fmt
, ...)
2364 va_start(args
, fmt
);
2365 argv
[0] = rb_vsprintf(fmt
, args
);
2369 exc
= rb_class_new_instance(2, argv
, rb_eNameError
);
2374 name_err_init_attr(VALUE exc
, VALUE recv
, VALUE method
)
2376 const rb_execution_context_t
*ec
= GET_EC();
2377 rb_control_frame_t
*cfp
= RUBY_VM_PREVIOUS_CONTROL_FRAME(ec
->cfp
);
2378 cfp
= rb_vm_get_ruby_level_next_cfp(ec
, cfp
);
2379 rb_ivar_set(exc
, id_name
, method
);
2380 err_init_recv(exc
, recv
);
2381 if (cfp
&& VM_FRAME_TYPE(cfp
) != VM_FRAME_MAGIC_DUMMY
) {
2382 rb_ivar_set(exc
, id_iseq
, rb_iseqw_new(cfp
->iseq
));
2389 * NameError.new(msg=nil, name=nil, receiver: nil) -> name_error
2391 * Construct a new NameError exception. If given the <i>name</i>
2392 * parameter may subsequently be examined using the NameError#name
2393 * method. <i>receiver</i> parameter allows to pass object in
2394 * context of which the error happened. Example:
2396 * [1, 2, 3].method(:rject) # NameError with name "rject" and receiver: Array
2397 * [1, 2, 3].singleton_method(:rject) # NameError with name "rject" and receiver: [1, 2, 3]
2401 name_err_initialize(int argc
, VALUE
*argv
, VALUE self
)
2404 VALUE values
[numberof(keywords
)], name
, options
;
2406 argc
= rb_scan_args(argc
, argv
, "*:", NULL
, &options
);
2407 keywords
[0] = id_receiver
;
2408 rb_get_kwargs(options
, keywords
, 0, numberof(values
), values
);
2409 name
= (argc
> 1) ? argv
[--argc
] : Qnil
;
2410 rb_call_super(argc
, argv
);
2411 name_err_init_attr(self
, values
[0], name
);
2415 static VALUE
rb_name_err_mesg_new(VALUE mesg
, VALUE recv
, VALUE method
);
2418 name_err_init(VALUE exc
, VALUE mesg
, VALUE recv
, VALUE method
)
2420 exc_init(exc
, rb_name_err_mesg_new(mesg
, recv
, method
));
2421 return name_err_init_attr(exc
, recv
, method
);
2425 rb_name_err_new(VALUE mesg
, VALUE recv
, VALUE method
)
2427 VALUE exc
= rb_obj_alloc(rb_eNameError
);
2428 return name_err_init(exc
, mesg
, recv
, method
);
2433 * name_error.name -> string or nil
2435 * Return the name associated with this NameError exception.
2439 name_err_name(VALUE self
)
2441 return rb_attr_get(self
, id_name
);
2446 * name_error.local_variables -> array
2448 * Return a list of the local variable names defined where this
2449 * NameError exception was raised.
2451 * Internal use only.
2455 name_err_local_variables(VALUE self
)
2457 VALUE vars
= rb_attr_get(self
, id_local_variables
);
2460 VALUE iseqw
= rb_attr_get(self
, id_iseq
);
2461 if (!NIL_P(iseqw
)) vars
= rb_iseqw_local_variables(iseqw
);
2462 if (NIL_P(vars
)) vars
= rb_ary_new();
2463 rb_ivar_set(self
, id_local_variables
, vars
);
2469 nometh_err_init_attr(VALUE exc
, VALUE args
, int priv
)
2471 rb_ivar_set(exc
, id_args
, args
);
2472 rb_ivar_set(exc
, id_private_call_p
, RBOOL(priv
));
2478 * NoMethodError.new(msg=nil, name=nil, args=nil, private=false, receiver: nil) -> no_method_error
2480 * Construct a NoMethodError exception for a method of the given name
2481 * called with the given arguments. The name may be accessed using
2482 * the <code>#name</code> method on the resulting object, and the
2483 * arguments using the <code>#args</code> method.
2485 * If <i>private</i> argument were passed, it designates method was
2486 * attempted to call in private context, and can be accessed with
2487 * <code>#private_call?</code> method.
2489 * <i>receiver</i> argument stores an object whose method was called.
2493 nometh_err_initialize(int argc
, VALUE
*argv
, VALUE self
)
2496 VALUE args
, options
;
2497 argc
= rb_scan_args(argc
, argv
, "*:", NULL
, &options
);
2498 priv
= (argc
> 3) && (--argc
, RTEST(argv
[argc
]));
2499 args
= (argc
> 2) ? argv
[--argc
] : Qnil
;
2500 if (!NIL_P(options
)) argv
[argc
++] = options
;
2501 rb_call_super_kw(argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
2502 return nometh_err_init_attr(self
, args
, priv
);
2506 rb_nomethod_err_new(VALUE mesg
, VALUE recv
, VALUE method
, VALUE args
, int priv
)
2508 VALUE exc
= rb_obj_alloc(rb_eNoMethodError
);
2509 name_err_init(exc
, mesg
, recv
, method
);
2510 return nometh_err_init_attr(exc
, args
, priv
);
2513 typedef struct name_error_message_struct
{
2517 } name_error_message_t
;
2520 name_err_mesg_mark(void *p
)
2522 name_error_message_t
*ptr
= (name_error_message_t
*)p
;
2523 rb_gc_mark_movable(ptr
->mesg
);
2524 rb_gc_mark_movable(ptr
->recv
);
2525 rb_gc_mark_movable(ptr
->name
);
2529 name_err_mesg_update(void *p
)
2531 name_error_message_t
*ptr
= (name_error_message_t
*)p
;
2532 ptr
->mesg
= rb_gc_location(ptr
->mesg
);
2533 ptr
->recv
= rb_gc_location(ptr
->recv
);
2534 ptr
->name
= rb_gc_location(ptr
->name
);
2537 static const rb_data_type_t name_err_mesg_data_type
= {
2541 RUBY_TYPED_DEFAULT_FREE
,
2542 NULL
, // No external memory to report,
2543 name_err_mesg_update
,
2545 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
| RUBY_TYPED_WB_PROTECTED
| RUBY_TYPED_EMBEDDABLE
2550 rb_name_err_mesg_init(VALUE klass
, VALUE mesg
, VALUE recv
, VALUE name
)
2552 name_error_message_t
*message
;
2553 VALUE result
= TypedData_Make_Struct(klass
, name_error_message_t
, &name_err_mesg_data_type
, message
);
2554 RB_OBJ_WRITE(result
, &message
->mesg
, mesg
);
2555 RB_OBJ_WRITE(result
, &message
->recv
, recv
);
2556 RB_OBJ_WRITE(result
, &message
->name
, name
);
2562 rb_name_err_mesg_new(VALUE mesg
, VALUE recv
, VALUE method
)
2564 return rb_name_err_mesg_init(rb_cNameErrorMesg
, mesg
, recv
, method
);
2569 name_err_mesg_alloc(VALUE klass
)
2571 return rb_name_err_mesg_init(klass
, Qnil
, Qnil
, Qnil
);
2576 name_err_mesg_init_copy(VALUE obj1
, VALUE obj2
)
2578 if (obj1
== obj2
) return obj1
;
2579 rb_obj_init_copy(obj1
, obj2
);
2581 name_error_message_t
*ptr1
, *ptr2
;
2582 TypedData_Get_Struct(obj1
, name_error_message_t
, &name_err_mesg_data_type
, ptr1
);
2583 TypedData_Get_Struct(obj2
, name_error_message_t
, &name_err_mesg_data_type
, ptr2
);
2585 RB_OBJ_WRITE(obj1
, &ptr1
->mesg
, ptr2
->mesg
);
2586 RB_OBJ_WRITE(obj1
, &ptr1
->recv
, ptr2
->recv
);
2587 RB_OBJ_WRITE(obj1
, &ptr1
->name
, ptr2
->name
);
2593 name_err_mesg_equal(VALUE obj1
, VALUE obj2
)
2595 if (obj1
== obj2
) return Qtrue
;
2597 if (rb_obj_class(obj2
) != rb_cNameErrorMesg
)
2600 name_error_message_t
*ptr1
, *ptr2
;
2601 TypedData_Get_Struct(obj1
, name_error_message_t
, &name_err_mesg_data_type
, ptr1
);
2602 TypedData_Get_Struct(obj2
, name_error_message_t
, &name_err_mesg_data_type
, ptr2
);
2604 if (!rb_equal(ptr1
->mesg
, ptr2
->mesg
)) return Qfalse
;
2605 if (!rb_equal(ptr1
->recv
, ptr2
->recv
)) return Qfalse
;
2606 if (!rb_equal(ptr1
->name
, ptr2
->name
)) return Qfalse
;
2612 name_err_mesg_receiver_name(VALUE obj
)
2614 if (RB_SPECIAL_CONST_P(obj
)) return Qundef
;
2615 if (RB_BUILTIN_TYPE(obj
) == T_MODULE
|| RB_BUILTIN_TYPE(obj
) == T_CLASS
) {
2616 return rb_check_funcall(obj
, rb_intern("name"), 0, 0);
2623 name_err_mesg_to_str(VALUE obj
)
2625 name_error_message_t
*ptr
;
2626 TypedData_Get_Struct(obj
, name_error_message_t
, &name_err_mesg_data_type
, ptr
);
2628 VALUE mesg
= ptr
->mesg
;
2629 if (NIL_P(mesg
)) return Qnil
;
2631 struct RString s_str
, c_str
, d_str
;
2632 VALUE c
, s
, d
= 0, args
[4], c2
;
2634 rb_encoding
*usascii
= rb_usascii_encoding();
2636 #define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
2637 c
= s
= FAKE_CSTR(&s_str
, "");
2641 c
= d
= FAKE_CSTR(&d_str
, "nil");
2644 c
= d
= FAKE_CSTR(&d_str
, "true");
2647 c
= d
= FAKE_CSTR(&d_str
, "false");
2650 if (strstr(RSTRING_PTR(mesg
), "%2$s")) {
2651 d
= rb_protect(name_err_mesg_receiver_name
, obj
, &state
);
2652 if (state
|| NIL_OR_UNDEF_P(d
))
2653 d
= rb_protect(rb_inspect
, obj
, &state
);
2655 rb_set_errinfo(Qnil
);
2657 d
= rb_check_string_type(d
);
2659 d
= rb_any_to_s(obj
);
2663 if (!RB_SPECIAL_CONST_P(obj
)) {
2664 switch (RB_BUILTIN_TYPE(obj
)) {
2666 s
= FAKE_CSTR(&s_str
, "module ");
2670 s
= FAKE_CSTR(&s_str
, "class ");
2680 klass
= CLASS_OF(obj
);
2681 if (RB_TYPE_P(klass
, T_CLASS
) && RCLASS_SINGLETON_P(klass
)) {
2682 s
= FAKE_CSTR(&s_str
, "");
2683 if (obj
== rb_vm_top_self()) {
2684 c
= FAKE_CSTR(&c_str
, "main");
2687 c
= rb_any_to_s(obj
);
2692 s
= FAKE_CSTR(&s_str
, "an instance of ");
2693 c
= rb_class_real(klass
);
2696 c2
= rb_protect(name_err_mesg_receiver_name
, c
, &state
);
2697 if (state
|| NIL_OR_UNDEF_P(c2
))
2698 c2
= rb_protect(rb_inspect
, c
, &state
);
2700 rb_set_errinfo(Qnil
);
2702 c2
= rb_check_string_type(c2
);
2704 c2
= rb_any_to_s(c
);
2709 args
[0] = rb_obj_as_string(ptr
->name
);
2713 mesg
= rb_str_format(4, args
, mesg
);
2720 name_err_mesg_dump(VALUE obj
, VALUE limit
)
2722 return name_err_mesg_to_str(obj
);
2727 name_err_mesg_load(VALUE klass
, VALUE str
)
2734 * name_error.receiver -> object
2736 * Return the receiver associated with this NameError exception.
2740 name_err_receiver(VALUE self
)
2742 VALUE recv
= rb_ivar_lookup(self
, id_recv
, Qundef
);
2743 if (!UNDEF_P(recv
)) return recv
;
2745 VALUE mesg
= rb_attr_get(self
, id_mesg
);
2746 if (!rb_typeddata_is_kind_of(mesg
, &name_err_mesg_data_type
)) {
2747 rb_raise(rb_eArgError
, "no receiver is available");
2750 name_error_message_t
*ptr
;
2751 TypedData_Get_Struct(mesg
, name_error_message_t
, &name_err_mesg_data_type
, ptr
);
2757 * no_method_error.args -> obj
2759 * Return the arguments passed in as the third parameter to
2764 nometh_err_args(VALUE self
)
2766 return rb_attr_get(self
, id_args
);
2771 * no_method_error.private_call? -> true or false
2773 * Return true if the caused method was called as private.
2777 nometh_err_private_call_p(VALUE self
)
2779 return rb_attr_get(self
, id_private_call_p
);
2783 rb_invalid_str(const char *str
, const char *type
)
2785 VALUE s
= rb_str_new2(str
);
2787 rb_raise(rb_eArgError
, "invalid value for %s: %+"PRIsVALUE
, type
, s
);
2792 * key_error.receiver -> object
2794 * Return the receiver associated with this KeyError exception.
2798 key_err_receiver(VALUE self
)
2802 recv
= rb_ivar_lookup(self
, id_receiver
, Qundef
);
2803 if (!UNDEF_P(recv
)) return recv
;
2804 rb_raise(rb_eArgError
, "no receiver is available");
2809 * key_error.key -> object
2811 * Return the key caused this KeyError exception.
2815 key_err_key(VALUE self
)
2819 key
= rb_ivar_lookup(self
, id_key
, Qundef
);
2820 if (!UNDEF_P(key
)) return key
;
2821 rb_raise(rb_eArgError
, "no key is available");
2825 rb_key_err_new(VALUE mesg
, VALUE recv
, VALUE key
)
2827 VALUE exc
= rb_obj_alloc(rb_eKeyError
);
2828 rb_ivar_set(exc
, id_mesg
, mesg
);
2829 rb_ivar_set(exc
, id_bt
, Qnil
);
2830 rb_ivar_set(exc
, id_key
, key
);
2831 rb_ivar_set(exc
, id_receiver
, recv
);
2837 * KeyError.new(message=nil, receiver: nil, key: nil) -> key_error
2839 * Construct a new +KeyError+ exception with the given message,
2844 key_err_initialize(int argc
, VALUE
*argv
, VALUE self
)
2848 rb_call_super(rb_scan_args(argc
, argv
, "01:", NULL
, &options
), argv
);
2850 if (!NIL_P(options
)) {
2852 VALUE values
[numberof(keywords
)];
2854 keywords
[0] = id_receiver
;
2855 keywords
[1] = id_key
;
2856 rb_get_kwargs(options
, keywords
, 0, numberof(values
), values
);
2857 for (i
= 0; i
< numberof(values
); ++i
) {
2858 if (!UNDEF_P(values
[i
])) {
2859 rb_ivar_set(self
, keywords
[i
], values
[i
]);
2869 * no_matching_pattern_key_error.matchee -> object
2871 * Return the matchee associated with this NoMatchingPatternKeyError exception.
2875 no_matching_pattern_key_err_matchee(VALUE self
)
2879 matchee
= rb_ivar_lookup(self
, id_matchee
, Qundef
);
2880 if (!UNDEF_P(matchee
)) return matchee
;
2881 rb_raise(rb_eArgError
, "no matchee is available");
2886 * no_matching_pattern_key_error.key -> object
2888 * Return the key caused this NoMatchingPatternKeyError exception.
2892 no_matching_pattern_key_err_key(VALUE self
)
2896 key
= rb_ivar_lookup(self
, id_key
, Qundef
);
2897 if (!UNDEF_P(key
)) return key
;
2898 rb_raise(rb_eArgError
, "no key is available");
2903 * NoMatchingPatternKeyError.new(message=nil, matchee: nil, key: nil) -> no_matching_pattern_key_error
2905 * Construct a new +NoMatchingPatternKeyError+ exception with the given message,
2910 no_matching_pattern_key_err_initialize(int argc
, VALUE
*argv
, VALUE self
)
2914 rb_call_super(rb_scan_args(argc
, argv
, "01:", NULL
, &options
), argv
);
2916 if (!NIL_P(options
)) {
2918 VALUE values
[numberof(keywords
)];
2920 keywords
[0] = id_matchee
;
2921 keywords
[1] = id_key
;
2922 rb_get_kwargs(options
, keywords
, 0, numberof(values
), values
);
2923 for (i
= 0; i
< numberof(values
); ++i
) {
2924 if (!UNDEF_P(values
[i
])) {
2925 rb_ivar_set(self
, keywords
[i
], values
[i
]);
2936 * SyntaxError.new([msg]) -> syntax_error
2938 * Construct a SyntaxError exception.
2942 syntax_error_initialize(int argc
, VALUE
*argv
, VALUE self
)
2946 mesg
= rb_fstring_lit("compile error");
2950 return rb_call_super(argc
, argv
);
2954 syntax_error_with_path(VALUE exc
, VALUE path
, VALUE
*mesg
, rb_encoding
*enc
)
2957 *mesg
= rb_enc_str_new(0, 0, enc
);
2958 exc
= rb_class_new_instance(1, mesg
, rb_eSyntaxError
);
2959 rb_ivar_set(exc
, id_i_path
, path
);
2962 VALUE old_path
= rb_attr_get(exc
, id_i_path
);
2963 if (old_path
!= path
) {
2964 if (rb_str_equal(path
, old_path
)) {
2965 rb_raise(rb_eArgError
, "SyntaxError#path changed: %+"PRIsVALUE
" (%p->%p)",
2966 old_path
, (void *)old_path
, (void *)path
);
2969 rb_raise(rb_eArgError
, "SyntaxError#path changed: %+"PRIsVALUE
"(%s%s)->%+"PRIsVALUE
"(%s)",
2970 old_path
, rb_enc_name(rb_enc_get(old_path
)),
2971 (FL_TEST(old_path
, RSTRING_FSTR
) ? ":FSTR" : ""),
2972 path
, rb_enc_name(rb_enc_get(path
)));
2975 VALUE s
= *mesg
= rb_attr_get(exc
, idMesg
);
2976 if (RSTRING_LEN(s
) > 0 && *(RSTRING_END(s
)-1) != '\n')
2977 rb_str_cat_cstr(s
, "\n");
2983 * Document-module: Errno
2985 * When an operating system encounters an error,
2986 * it typically reports the error as an integer error code:
2989 * ls: cannot access 'nosuch.txt': No such file or directory
2990 * $ echo $? # Code for last error.
2993 * When the Ruby interpreter interacts with the operating system
2994 * and receives such an error code (e.g., +2+),
2995 * it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+):
2997 * File.open('nosuch.txt')
2998 * # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT)
3000 * Each such class is:
3002 * - A nested class in this module, +Errno+.
3003 * - A subclass of class SystemCallError.
3004 * - Associated with an error code.
3008 * Errno::ENOENT.superclass # => SystemCallError
3009 * Errno::ENOENT::Errno # => 2
3011 * The names of nested classes are returned by method +Errno.constants+:
3013 * Errno.constants.size # => 158
3014 * Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV]
3016 * As seen above, the error code associated with each class
3017 * is available as the value of a constant;
3018 * the value for a particular class may vary among operating systems.
3019 * If the class is not needed for the particular operating system,
3020 * the value is zero:
3022 * Errno::ENOENT::Errno # => 2
3023 * Errno::ENOTCAPABLE::Errno # => 0
3025 * Each class in Errno can be created with optional messages:
3027 * Errno::EPIPE.new # => #<Errno::EPIPE: Broken pipe>
3028 * Errno::EPIPE.new("foo") # => #<Errno::EPIPE: Broken pipe - foo>
3029 * Errno::EPIPE.new("foo", "here") # => #<Errno::EPIPE: Broken pipe @ here - foo>
3031 * See SystemCallError.new.
3034 static st_table
*syserr_tbl
;
3037 rb_free_warning(void)
3039 st_free_table(warning_categories
.id2enum
);
3040 st_free_table(warning_categories
.enum2id
);
3041 st_free_table(syserr_tbl
);
3045 setup_syserr(int n
, const char *name
)
3047 VALUE error
= rb_define_class_under(rb_mErrno
, name
, rb_eSystemCallError
);
3049 /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
3054 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3059 rb_eEWOULDBLOCK
= error
;
3062 rb_eEINPROGRESS
= error
;
3066 rb_define_const(error
, "Errno", INT2NUM(n
));
3067 st_add_direct(syserr_tbl
, n
, (st_data_t
)error
);
3072 set_syserr(int n
, const char *name
)
3076 if (!st_lookup(syserr_tbl
, n
, &error
)) {
3077 return setup_syserr(n
, name
);
3080 VALUE errclass
= (VALUE
)error
;
3081 rb_define_const(rb_mErrno
, name
, errclass
);
3091 if (!st_lookup(syserr_tbl
, n
, &error
)) {
3092 char name
[DECIMAL_SIZE_OF(n
) + sizeof("E-")];
3094 snprintf(name
, sizeof(name
), "E%03d", n
);
3095 return setup_syserr(n
, name
);
3097 return (VALUE
)error
;
3102 * SystemCallError.new(msg, errno = nil, func = nil) -> system_call_error_subclass
3104 * If _errno_ corresponds to a known system error code, constructs the
3105 * appropriate Errno class for that error, otherwise constructs a
3106 * generic SystemCallError object. The error number is subsequently
3107 * available via the #errno method.
3109 * If only numeric object is given, it is treated as an Integer _errno_,
3110 * and _msg_ is omitted, otherwise the first argument _msg_ is used as
3111 * the additional error message.
3113 * SystemCallError.new(Errno::EPIPE::Errno)
3114 * #=> #<Errno::EPIPE: Broken pipe>
3116 * SystemCallError.new("foo")
3117 * #=> #<SystemCallError: unknown error - foo>
3119 * SystemCallError.new("foo", Errno::EPIPE::Errno)
3120 * #=> #<Errno::EPIPE: Broken pipe - foo>
3122 * If _func_ is not +nil+, it is appended to the message with "<tt> @ </tt>".
3124 * SystemCallError.new("foo", Errno::EPIPE::Errno, "here")
3125 * #=> #<Errno::EPIPE: Broken pipe @ here - foo>
3127 * A subclass of SystemCallError can also be instantiated via the
3128 * +new+ method of the subclass. See Errno.
3132 syserr_initialize(int argc
, VALUE
*argv
, VALUE self
)
3135 VALUE mesg
, error
, func
, errmsg
;
3136 VALUE klass
= rb_obj_class(self
);
3138 if (klass
== rb_eSystemCallError
) {
3139 st_data_t data
= (st_data_t
)klass
;
3140 rb_scan_args(argc
, argv
, "12", &mesg
, &error
, &func
);
3141 if (argc
== 1 && FIXNUM_P(mesg
)) {
3142 error
= mesg
; mesg
= Qnil
;
3144 if (!NIL_P(error
) && st_lookup(syserr_tbl
, NUM2LONG(error
), &data
)) {
3145 klass
= (VALUE
)data
;
3147 if (!RB_TYPE_P(self
, T_OBJECT
)) { /* insurance to avoid type crash */
3148 rb_raise(rb_eTypeError
, "invalid instance type");
3150 RBASIC_SET_CLASS(self
, klass
);
3154 rb_scan_args(argc
, argv
, "02", &mesg
, &func
);
3155 error
= rb_const_get(klass
, id_Errno
);
3157 if (!NIL_P(error
)) err
= strerror(NUM2INT(error
));
3158 else err
= "unknown error";
3160 errmsg
= rb_enc_str_new_cstr(err
, rb_locale_encoding());
3162 VALUE str
= StringValue(mesg
);
3164 if (!NIL_P(func
)) rb_str_catf(errmsg
, " @ %"PRIsVALUE
, func
);
3165 rb_str_catf(errmsg
, " - %"PRIsVALUE
, str
);
3169 rb_call_super(1, &mesg
);
3170 rb_ivar_set(self
, id_errno
, error
);
3176 * system_call_error.errno -> integer
3178 * Return this SystemCallError's error number.
3182 syserr_errno(VALUE self
)
3184 return rb_attr_get(self
, id_errno
);
3189 * system_call_error === other -> true or false
3191 * Return +true+ if the receiver is a generic +SystemCallError+, or
3192 * if the error numbers +self+ and _other_ are the same.
3196 syserr_eqq(VALUE self
, VALUE exc
)
3200 if (!rb_obj_is_kind_of(exc
, rb_eSystemCallError
)) {
3201 if (!rb_respond_to(exc
, id_errno
)) return Qfalse
;
3203 else if (self
== rb_eSystemCallError
) return Qtrue
;
3205 num
= rb_attr_get(exc
, id_errno
);
3207 num
= rb_funcallv(exc
, id_errno
, 0, 0);
3209 e
= rb_const_get(self
, id_Errno
);
3210 return RBOOL(FIXNUM_P(num
) ? num
== e
: rb_equal(num
, e
));
3215 * Document-class: StandardError
3217 * The most standard error types are subclasses of StandardError. A
3218 * rescue clause without an explicit Exception class will rescue all
3219 * StandardErrors (and only those).
3224 * foo rescue "Hello" #=> "Hello"
3226 * On the other hand:
3228 * require 'does/not/exist' rescue "Hi"
3230 * <em>raises the exception:</em>
3232 * LoadError: no such file to load -- does/not/exist
3237 * Document-class: SystemExit
3239 * Raised by +exit+ to initiate the termination of the script.
3243 * Document-class: SignalException
3245 * Raised when a signal is received.
3248 * Process.kill('HUP',Process.pid)
3249 * sleep # wait for receiver to handle signal sent by Process.kill
3250 * rescue SignalException => e
3251 * puts "received Exception #{e}"
3254 * <em>produces:</em>
3256 * received Exception SIGHUP
3260 * Document-class: Interrupt
3262 * Raised when the interrupt signal is received, typically because the
3263 * user has pressed Control-C (on most posix platforms). As such, it is a
3264 * subclass of +SignalException+.
3267 * puts "Press ctrl-C when you get bored"
3269 * rescue Interrupt => e
3270 * puts "Note: You will typically use Signal.trap instead."
3273 * <em>produces:</em>
3275 * Press ctrl-C when you get bored
3277 * <em>then waits until it is interrupted with Control-C and then prints:</em>
3279 * Note: You will typically use Signal.trap instead.
3283 * Document-class: TypeError
3285 * Raised when encountering an object that is not of the expected type.
3287 * [1, 2, 3].first("two")
3289 * <em>raises the exception:</em>
3291 * TypeError: no implicit conversion of String into Integer
3296 * Document-class: ArgumentError
3298 * Raised when the arguments are wrong and there isn't a more specific
3301 * Ex: passing the wrong number of arguments
3303 * [1, 2, 3].first(4, 5)
3305 * <em>raises the exception:</em>
3307 * ArgumentError: wrong number of arguments (given 2, expected 1)
3309 * Ex: passing an argument that is not acceptable:
3311 * [1, 2, 3].first(-4)
3313 * <em>raises the exception:</em>
3315 * ArgumentError: negative array size
3319 * Document-class: IndexError
3321 * Raised when the given index is invalid.
3324 * a.fetch(0) #=> :foo
3326 * a.fetch(4) #=> IndexError: index 4 outside of array bounds: -2...2
3331 * Document-class: KeyError
3333 * Raised when the specified key is not found. It is a subclass of
3336 * h = {"foo" => :bar}
3337 * h.fetch("foo") #=> :bar
3338 * h.fetch("baz") #=> KeyError: key not found: "baz"
3343 * Document-class: RangeError
3345 * Raised when a given numerical value is out of range.
3347 * [1, 2, 3].drop(1 << 100)
3349 * <em>raises the exception:</em>
3351 * RangeError: bignum too big to convert into `long'
3355 * Document-class: ScriptError
3357 * ScriptError is the superclass for errors raised when a script
3358 * can not be executed because of a +LoadError+,
3359 * +NotImplementedError+ or a +SyntaxError+. Note these type of
3360 * +ScriptErrors+ are not +StandardError+ and will not be
3361 * rescued unless it is specified explicitly (or its ancestor
3366 * Document-class: SyntaxError
3368 * Raised when encountering Ruby code with an invalid syntax.
3372 * <em>raises the exception:</em>
3374 * SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
3378 * Document-class: LoadError
3380 * Raised when a file required (a Ruby script, extension library, ...)
3383 * require 'this/file/does/not/exist'
3385 * <em>raises the exception:</em>
3387 * LoadError: no such file to load -- this/file/does/not/exist
3391 * Document-class: NotImplementedError
3393 * Raised when a feature is not implemented on the current platform. For
3394 * example, methods depending on the +fsync+ or +fork+ system calls may
3395 * raise this exception if the underlying operating system or Ruby
3396 * runtime does not support them.
3398 * Note that if +fork+ raises a +NotImplementedError+, then
3399 * <code>respond_to?(:fork)</code> returns +false+.
3403 * Document-class: NameError
3405 * Raised when a given name is invalid or undefined.
3409 * <em>raises the exception:</em>
3411 * NameError: undefined local variable or method `foo' for main:Object
3413 * Since constant names must start with a capital:
3415 * Integer.const_set :answer, 42
3417 * <em>raises the exception:</em>
3419 * NameError: wrong constant name answer
3423 * Document-class: NoMethodError
3425 * Raised when a method is called on a receiver which doesn't have it
3426 * defined and also fails to respond with +method_missing+.
3430 * <em>raises the exception:</em>
3432 * NoMethodError: undefined method `to_ary' for an instance of String
3436 * Document-class: FrozenError
3438 * Raised when there is an attempt to modify a frozen object.
3440 * [1, 2, 3].freeze << 4
3442 * <em>raises the exception:</em>
3444 * FrozenError: can't modify frozen Array
3448 * Document-class: RuntimeError
3450 * A generic error class raised when an invalid operation is attempted.
3451 * Kernel#raise will raise a RuntimeError if no Exception class is
3456 * <em>raises the exception:</em>
3458 * RuntimeError: ouch
3462 * Document-class: SecurityError
3464 * No longer used by internal code.
3468 * Document-class: NoMemoryError
3470 * Raised when memory allocation fails.
3474 * Document-class: SystemCallError
3476 * SystemCallError is the base class for all low-level
3477 * platform-dependent errors.
3479 * The errors available on the current platform are subclasses of
3480 * SystemCallError and are defined in the Errno module.
3482 * File.open("does/not/exist")
3484 * <em>raises the exception:</em>
3486 * Errno::ENOENT: No such file or directory - does/not/exist
3490 * Document-class: EncodingError
3492 * EncodingError is the base class for encoding errors.
3496 * Document-class: Encoding::CompatibilityError
3498 * Raised by Encoding and String methods when the source encoding is
3499 * incompatible with the target encoding.
3503 * Document-class: fatal
3505 * +fatal+ is an Exception that is raised when Ruby has encountered a fatal
3506 * error and must exit.
3510 * Document-class: NameError::message
3515 * Document-class: Exception
3517 * Class +Exception+ and its subclasses are used to indicate that an error
3518 * or other problem has occurred,
3519 * and may need to be handled.
3520 * See {Exceptions}[rdoc-ref:exceptions.md].
3522 * An +Exception+ object carries certain information:
3524 * - The type (the exception's class),
3525 * commonly StandardError, RuntimeError, or a subclass of one or the other;
3526 * see {Built-In Exception Class Hierarchy}[rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy].
3527 * - An optional descriptive message;
3528 * see methods ::new, #message.
3529 * - Optional backtrace information;
3530 * see methods #backtrace, #backtrace_locations, #set_backtrace.
3531 * - An optional cause;
3532 * see method #cause.
3534 * == Built-In \Exception Class Hierarchy
3536 * The hierarchy of built-in subclasses of class +Exception+:
3541 * * NotImplementedError
3548 * * UncaughtThrowError
3556 * * ClosedQueueError
3561 * * FloatDomainError
3566 * * Errno (and its subclasses, representing system errors)
3569 * * ZeroDivisionError
3571 * * SystemStackError
3572 * * {fatal}[rdoc-ref:fatal]
3577 exception_alloc(VALUE klass
)
3579 return rb_class_allocate_instance(klass
);
3583 exception_dumper(VALUE exc
)
3585 // TODO: Currently, the instance variables "bt" and "bt_locations"
3586 // refers to the same object (Array of String). But "bt_locations"
3587 // should have an Array of Thread::Backtrace::Locations.
3593 ivar_copy_i(ID key
, VALUE val
, st_data_t exc
)
3595 rb_ivar_set((VALUE
)exc
, key
, val
);
3599 void rb_exc_check_circular_cause(VALUE exc
);
3602 exception_loader(VALUE exc
, VALUE obj
)
3604 // The loader function of rb_marshal_define_compat seems to be called for two events:
3605 // one is for fixup (r_fixup_compat), the other is for TYPE_USERDEF.
3606 // In the former case, the first argument is an instance of Exception (because
3607 // we pass rb_eException to rb_marshal_define_compat). In the latter case, the first
3608 // argument is a class object (see TYPE_USERDEF case in r_object0).
3609 // We want to copy all instance variables (but "bt_locations") from obj to exc.
3610 // But we do not want to do so in the second case, so the following branch is for that.
3611 if (RB_TYPE_P(exc
, T_CLASS
)) return obj
; // maybe called from Marshal's TYPE_USERDEF
3613 rb_ivar_foreach(obj
, ivar_copy_i
, exc
);
3615 rb_exc_check_circular_cause(exc
);
3617 if (rb_attr_get(exc
, id_bt
) == rb_attr_get(exc
, id_bt_locations
)) {
3618 rb_ivar_set(exc
, id_bt_locations
, Qnil
);
3625 Init_Exception(void)
3627 rb_eException
= rb_define_class("Exception", rb_cObject
);
3628 rb_define_alloc_func(rb_eException
, exception_alloc
);
3629 rb_marshal_define_compat(rb_eException
, rb_eException
, exception_dumper
, exception_loader
);
3630 rb_define_singleton_method(rb_eException
, "exception", rb_class_new_instance
, -1);
3631 rb_define_singleton_method(rb_eException
, "to_tty?", exc_s_to_tty_p
, 0);
3632 rb_define_method(rb_eException
, "exception", exc_exception
, -1);
3633 rb_define_method(rb_eException
, "initialize", exc_initialize
, -1);
3634 rb_define_method(rb_eException
, "==", exc_equal
, 1);
3635 rb_define_method(rb_eException
, "to_s", exc_to_s
, 0);
3636 rb_define_method(rb_eException
, "message", exc_message
, 0);
3637 rb_define_method(rb_eException
, "detailed_message", exc_detailed_message
, -1);
3638 rb_define_method(rb_eException
, "full_message", exc_full_message
, -1);
3639 rb_define_method(rb_eException
, "inspect", exc_inspect
, 0);
3640 rb_define_method(rb_eException
, "backtrace", exc_backtrace
, 0);
3641 rb_define_method(rb_eException
, "backtrace_locations", exc_backtrace_locations
, 0);
3642 rb_define_method(rb_eException
, "set_backtrace", exc_set_backtrace
, 1);
3643 rb_define_method(rb_eException
, "cause", exc_cause
, 0);
3645 rb_eSystemExit
= rb_define_class("SystemExit", rb_eException
);
3646 rb_define_method(rb_eSystemExit
, "initialize", exit_initialize
, -1);
3647 rb_define_method(rb_eSystemExit
, "status", exit_status
, 0);
3648 rb_define_method(rb_eSystemExit
, "success?", exit_success_p
, 0);
3650 rb_eFatal
= rb_define_class("fatal", rb_eException
);
3651 rb_eSignal
= rb_define_class("SignalException", rb_eException
);
3652 rb_eInterrupt
= rb_define_class("Interrupt", rb_eSignal
);
3654 rb_eStandardError
= rb_define_class("StandardError", rb_eException
);
3655 rb_eTypeError
= rb_define_class("TypeError", rb_eStandardError
);
3656 rb_eArgError
= rb_define_class("ArgumentError", rb_eStandardError
);
3657 rb_eIndexError
= rb_define_class("IndexError", rb_eStandardError
);
3658 rb_eKeyError
= rb_define_class("KeyError", rb_eIndexError
);
3659 rb_define_method(rb_eKeyError
, "initialize", key_err_initialize
, -1);
3660 rb_define_method(rb_eKeyError
, "receiver", key_err_receiver
, 0);
3661 rb_define_method(rb_eKeyError
, "key", key_err_key
, 0);
3662 rb_eRangeError
= rb_define_class("RangeError", rb_eStandardError
);
3664 rb_eScriptError
= rb_define_class("ScriptError", rb_eException
);
3665 rb_eSyntaxError
= rb_define_class("SyntaxError", rb_eScriptError
);
3666 rb_define_method(rb_eSyntaxError
, "initialize", syntax_error_initialize
, -1);
3668 /* RDoc will use literal name value while parsing rb_attr,
3669 * and will render `idPath` as an attribute name without this trick */
3672 /* the path that failed to parse */
3673 rb_attr(rb_eSyntaxError
, path
, TRUE
, FALSE
, FALSE
);
3675 rb_eLoadError
= rb_define_class("LoadError", rb_eScriptError
);
3676 /* the path that failed to load */
3677 rb_attr(rb_eLoadError
, path
, TRUE
, FALSE
, FALSE
);
3679 rb_eNotImpError
= rb_define_class("NotImplementedError", rb_eScriptError
);
3681 rb_eNameError
= rb_define_class("NameError", rb_eStandardError
);
3682 rb_define_method(rb_eNameError
, "initialize", name_err_initialize
, -1);
3683 rb_define_method(rb_eNameError
, "name", name_err_name
, 0);
3684 rb_define_method(rb_eNameError
, "receiver", name_err_receiver
, 0);
3685 rb_define_method(rb_eNameError
, "local_variables", name_err_local_variables
, 0);
3686 rb_cNameErrorMesg
= rb_define_class_under(rb_eNameError
, "message", rb_cObject
);
3687 rb_define_alloc_func(rb_cNameErrorMesg
, name_err_mesg_alloc
);
3688 rb_define_method(rb_cNameErrorMesg
, "initialize_copy", name_err_mesg_init_copy
, 1);
3689 rb_define_method(rb_cNameErrorMesg
, "==", name_err_mesg_equal
, 1);
3690 rb_define_method(rb_cNameErrorMesg
, "to_str", name_err_mesg_to_str
, 0);
3691 rb_define_method(rb_cNameErrorMesg
, "_dump", name_err_mesg_dump
, 1);
3692 rb_define_singleton_method(rb_cNameErrorMesg
, "_load", name_err_mesg_load
, 1);
3693 rb_eNoMethodError
= rb_define_class("NoMethodError", rb_eNameError
);
3694 rb_define_method(rb_eNoMethodError
, "initialize", nometh_err_initialize
, -1);
3695 rb_define_method(rb_eNoMethodError
, "args", nometh_err_args
, 0);
3696 rb_define_method(rb_eNoMethodError
, "private_call?", nometh_err_private_call_p
, 0);
3698 rb_eRuntimeError
= rb_define_class("RuntimeError", rb_eStandardError
);
3699 rb_eFrozenError
= rb_define_class("FrozenError", rb_eRuntimeError
);
3700 rb_define_method(rb_eFrozenError
, "initialize", frozen_err_initialize
, -1);
3701 rb_define_method(rb_eFrozenError
, "receiver", frozen_err_receiver
, 0);
3702 rb_eSecurityError
= rb_define_class("SecurityError", rb_eException
);
3703 rb_eNoMemError
= rb_define_class("NoMemoryError", rb_eException
);
3704 rb_eEncodingError
= rb_define_class("EncodingError", rb_eStandardError
);
3705 rb_eEncCompatError
= rb_define_class_under(rb_cEncoding
, "CompatibilityError", rb_eEncodingError
);
3706 rb_eNoMatchingPatternError
= rb_define_class("NoMatchingPatternError", rb_eStandardError
);
3707 rb_eNoMatchingPatternKeyError
= rb_define_class("NoMatchingPatternKeyError", rb_eNoMatchingPatternError
);
3708 rb_define_method(rb_eNoMatchingPatternKeyError
, "initialize", no_matching_pattern_key_err_initialize
, -1);
3709 rb_define_method(rb_eNoMatchingPatternKeyError
, "matchee", no_matching_pattern_key_err_matchee
, 0);
3710 rb_define_method(rb_eNoMatchingPatternKeyError
, "key", no_matching_pattern_key_err_key
, 0);
3712 syserr_tbl
= st_init_numtable();
3713 rb_eSystemCallError
= rb_define_class("SystemCallError", rb_eStandardError
);
3714 rb_define_method(rb_eSystemCallError
, "initialize", syserr_initialize
, -1);
3715 rb_define_method(rb_eSystemCallError
, "errno", syserr_errno
, 0);
3716 rb_define_singleton_method(rb_eSystemCallError
, "===", syserr_eqq
, 1);
3718 rb_mErrno
= rb_define_module("Errno");
3720 rb_mWarning
= rb_define_module("Warning");
3721 rb_define_singleton_method(rb_mWarning
, "[]", rb_warning_s_aref
, 1);
3722 rb_define_singleton_method(rb_mWarning
, "[]=", rb_warning_s_aset
, 2);
3723 rb_define_singleton_method(rb_mWarning
, "categories", rb_warning_s_categories
, 0);
3724 rb_define_method(rb_mWarning
, "warn", rb_warning_s_warn
, -1);
3725 rb_extend_object(rb_mWarning
, rb_mWarning
);
3728 rb_cWarningBuffer
= rb_define_class_under(rb_mWarning
, "buffer", rb_cString
);
3729 rb_define_method(rb_cWarningBuffer
, "write", warning_write
, -1);
3731 id_cause
= rb_intern_const("cause");
3732 id_message
= rb_intern_const("message");
3733 id_detailed_message
= rb_intern_const("detailed_message");
3734 id_backtrace
= rb_intern_const("backtrace");
3735 id_key
= rb_intern_const("key");
3736 id_matchee
= rb_intern_const("matchee");
3737 id_args
= rb_intern_const("args");
3738 id_receiver
= rb_intern_const("receiver");
3739 id_private_call_p
= rb_intern_const("private_call?");
3740 id_local_variables
= rb_intern_const("local_variables");
3741 id_Errno
= rb_intern_const("Errno");
3742 id_errno
= rb_intern_const("errno");
3743 id_i_path
= rb_intern_const("@path");
3744 id_warn
= rb_intern_const("warn");
3745 id_category
= rb_intern_const("category");
3746 id_deprecated
= rb_intern_const("deprecated");
3747 id_experimental
= rb_intern_const("experimental");
3748 id_performance
= rb_intern_const("performance");
3749 id_strict_unused_block
= rb_intern_const("strict_unused_block");
3750 id_top
= rb_intern_const("top");
3751 id_bottom
= rb_intern_const("bottom");
3752 id_iseq
= rb_make_internal_id();
3753 id_recv
= rb_make_internal_id();
3755 sym_category
= ID2SYM(id_category
);
3756 sym_highlight
= ID2SYM(rb_intern_const("highlight"));
3758 warning_categories
.id2enum
= rb_init_identtable();
3759 st_add_direct(warning_categories
.id2enum
, id_deprecated
, RB_WARN_CATEGORY_DEPRECATED
);
3760 st_add_direct(warning_categories
.id2enum
, id_experimental
, RB_WARN_CATEGORY_EXPERIMENTAL
);
3761 st_add_direct(warning_categories
.id2enum
, id_performance
, RB_WARN_CATEGORY_PERFORMANCE
);
3762 st_add_direct(warning_categories
.id2enum
, id_strict_unused_block
, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
);
3764 warning_categories
.enum2id
= rb_init_identtable();
3765 st_add_direct(warning_categories
.enum2id
, RB_WARN_CATEGORY_NONE
, 0);
3766 st_add_direct(warning_categories
.enum2id
, RB_WARN_CATEGORY_DEPRECATED
, id_deprecated
);
3767 st_add_direct(warning_categories
.enum2id
, RB_WARN_CATEGORY_EXPERIMENTAL
, id_experimental
);
3768 st_add_direct(warning_categories
.enum2id
, RB_WARN_CATEGORY_PERFORMANCE
, id_performance
);
3769 st_add_direct(warning_categories
.enum2id
, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
, id_strict_unused_block
);
3773 rb_enc_raise(rb_encoding
*enc
, VALUE exc
, const char *fmt
, ...)
3778 va_start(args
, fmt
);
3779 mesg
= rb_enc_vsprintf(enc
, fmt
, args
);
3782 rb_exc_raise(rb_exc_new3(exc
, mesg
));
3786 rb_vraise(VALUE exc
, const char *fmt
, va_list ap
)
3788 rb_exc_raise(rb_exc_new3(exc
, rb_vsprintf(fmt
, ap
)));
3792 rb_raise(VALUE exc_class
, const char *fmt
, ...)
3795 va_start(args
, fmt
);
3796 VALUE exc
= rb_exc_new3(exc_class
, rb_vsprintf(fmt
, args
));
3801 NORETURN(static void raise_loaderror(VALUE path
, VALUE mesg
));
3804 raise_loaderror(VALUE path
, VALUE mesg
)
3806 VALUE err
= rb_exc_new3(rb_eLoadError
, mesg
);
3807 rb_ivar_set(err
, id_i_path
, path
);
3812 rb_loaderror(const char *fmt
, ...)
3817 va_start(args
, fmt
);
3818 mesg
= rb_enc_vsprintf(rb_locale_encoding(), fmt
, args
);
3820 raise_loaderror(Qnil
, mesg
);
3824 rb_loaderror_with_path(VALUE path
, const char *fmt
, ...)
3829 va_start(args
, fmt
);
3830 mesg
= rb_enc_vsprintf(rb_locale_encoding(), fmt
, args
);
3832 raise_loaderror(path
, mesg
);
3836 rb_notimplement(void)
3838 rb_raise(rb_eNotImpError
,
3839 "%"PRIsVALUE
"() function is unimplemented on this machine",
3840 rb_id2str(rb_frame_this_func()));
3844 rb_fatal(const char *fmt
, ...)
3849 if (! ruby_thread_has_gvl_p()) {
3850 /* The thread has no GVL. Object allocation impossible (cant run GC),
3851 * thus no message can be printed out. */
3852 fprintf(stderr
, "[FATAL] rb_fatal() outside of GVL\n");
3853 rb_print_backtrace(stderr
);
3857 va_start(args
, fmt
);
3858 mesg
= rb_vsprintf(fmt
, args
);
3861 rb_exc_fatal(rb_exc_new3(rb_eFatal
, mesg
));
3865 make_errno_exc(const char *mesg
)
3871 rb_bug("rb_sys_fail(%s) - errno == 0", mesg
? mesg
: "");
3873 return rb_syserr_new(n
, mesg
);
3877 make_errno_exc_str(VALUE mesg
)
3882 if (!mesg
) mesg
= Qnil
;
3884 const char *s
= !NIL_P(mesg
) ? RSTRING_PTR(mesg
) : "";
3885 rb_bug("rb_sys_fail_str(%s) - errno == 0", s
);
3887 return rb_syserr_new_str(n
, mesg
);
3891 rb_syserr_new(int n
, const char *mesg
)
3894 arg
= mesg
? rb_str_new2(mesg
) : Qnil
;
3895 return rb_syserr_new_str(n
, arg
);
3899 rb_syserr_new_str(int n
, VALUE arg
)
3901 return rb_class_new_instance(1, &arg
, get_syserr(n
));
3905 rb_syserr_fail(int e
, const char *mesg
)
3907 rb_exc_raise(rb_syserr_new(e
, mesg
));
3911 rb_syserr_fail_str(int e
, VALUE mesg
)
3913 rb_exc_raise(rb_syserr_new_str(e
, mesg
));
3918 rb_sys_fail(const char *mesg
)
3920 rb_exc_raise(make_errno_exc(mesg
));
3923 #undef rb_sys_fail_str
3925 rb_sys_fail_str(VALUE mesg
)
3927 rb_exc_raise(make_errno_exc_str(mesg
));
3930 #ifdef RUBY_FUNCTION_NAME_STRING
3932 rb_sys_fail_path_in(const char *func_name
, VALUE path
)
3937 rb_syserr_fail_path_in(func_name
, n
, path
);
3941 rb_syserr_fail_path_in(const char *func_name
, int n
, VALUE path
)
3943 rb_exc_raise(rb_syserr_new_path_in(func_name
, n
, path
));
3947 rb_syserr_new_path_in(const char *func_name
, int n
, VALUE path
)
3951 if (!path
) path
= Qnil
;
3953 const char *s
= !NIL_P(path
) ? RSTRING_PTR(path
) : "";
3954 if (!func_name
) func_name
= "(null)";
3955 rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
3959 args
[1] = rb_str_new_cstr(func_name
);
3960 return rb_class_new_instance(2, args
, get_syserr(n
));
3964 NORETURN(static void rb_mod_exc_raise(VALUE exc
, VALUE mod
));
3967 rb_mod_exc_raise(VALUE exc
, VALUE mod
)
3969 rb_extend_object(exc
, mod
);
3974 rb_mod_sys_fail(VALUE mod
, const char *mesg
)
3976 VALUE exc
= make_errno_exc(mesg
);
3977 rb_mod_exc_raise(exc
, mod
);
3981 rb_mod_sys_fail_str(VALUE mod
, VALUE mesg
)
3983 VALUE exc
= make_errno_exc_str(mesg
);
3984 rb_mod_exc_raise(exc
, mod
);
3988 rb_mod_syserr_fail(VALUE mod
, int e
, const char *mesg
)
3990 VALUE exc
= rb_syserr_new(e
, mesg
);
3991 rb_mod_exc_raise(exc
, mod
);
3995 rb_mod_syserr_fail_str(VALUE mod
, int e
, VALUE mesg
)
3997 VALUE exc
= rb_syserr_new_str(e
, mesg
);
3998 rb_mod_exc_raise(exc
, mod
);
4002 syserr_warning(VALUE mesg
, int err
)
4004 rb_str_set_len(mesg
, RSTRING_LEN(mesg
)-1);
4005 rb_str_catf(mesg
, ": %s\n", strerror(err
));
4006 rb_write_warning_str(mesg
);
4011 rb_sys_warn(const char *fmt
, ...)
4013 if (!NIL_P(ruby_verbose
)) {
4014 int errno_save
= errno
;
4015 with_warning_string(mesg
, 0, fmt
) {
4016 syserr_warning(mesg
, errno_save
);
4023 rb_syserr_warn(int err
, const char *fmt
, ...)
4025 if (!NIL_P(ruby_verbose
)) {
4026 with_warning_string(mesg
, 0, fmt
) {
4027 syserr_warning(mesg
, err
);
4033 rb_sys_enc_warn(rb_encoding
*enc
, const char *fmt
, ...)
4035 if (!NIL_P(ruby_verbose
)) {
4036 int errno_save
= errno
;
4037 with_warning_string(mesg
, enc
, fmt
) {
4038 syserr_warning(mesg
, errno_save
);
4045 rb_syserr_enc_warn(int err
, rb_encoding
*enc
, const char *fmt
, ...)
4047 if (!NIL_P(ruby_verbose
)) {
4048 with_warning_string(mesg
, enc
, fmt
) {
4049 syserr_warning(mesg
, err
);
4056 rb_sys_warning(const char *fmt
, ...)
4058 if (RTEST(ruby_verbose
)) {
4059 int errno_save
= errno
;
4060 with_warning_string(mesg
, 0, fmt
) {
4061 syserr_warning(mesg
, errno_save
);
4069 rb_syserr_warning(int err
, const char *fmt
, ...)
4071 if (RTEST(ruby_verbose
)) {
4072 with_warning_string(mesg
, 0, fmt
) {
4073 syserr_warning(mesg
, err
);
4080 rb_sys_enc_warning(rb_encoding
*enc
, const char *fmt
, ...)
4082 if (RTEST(ruby_verbose
)) {
4083 int errno_save
= errno
;
4084 with_warning_string(mesg
, enc
, fmt
) {
4085 syserr_warning(mesg
, errno_save
);
4092 rb_syserr_enc_warning(int err
, rb_encoding
*enc
, const char *fmt
, ...)
4094 if (RTEST(ruby_verbose
)) {
4095 with_warning_string(mesg
, enc
, fmt
) {
4096 syserr_warning(mesg
, err
);
4102 rb_load_fail(VALUE path
, const char *err
)
4104 VALUE mesg
= rb_str_buf_new_cstr(err
);
4105 rb_str_cat2(mesg
, " -- ");
4106 rb_str_append(mesg
, path
); /* should be ASCII compatible */
4107 raise_loaderror(path
, mesg
);
4111 rb_error_frozen(const char *what
)
4113 rb_raise(rb_eFrozenError
, "can't modify frozen %s", what
);
4117 rb_frozen_error_raise(VALUE frozen_obj
, const char *fmt
, ...)
4122 va_start(args
, fmt
);
4123 mesg
= rb_vsprintf(fmt
, args
);
4125 exc
= rb_exc_new3(rb_eFrozenError
, mesg
);
4126 rb_ivar_set(exc
, id_recv
, frozen_obj
);
4131 inspect_frozen_obj(VALUE obj
, VALUE mesg
, int recur
)
4134 rb_str_cat_cstr(mesg
, " ...");
4137 rb_str_append(mesg
, rb_inspect(obj
));
4143 get_created_info(VALUE obj
, int *pline
)
4145 VALUE info
= rb_attr_get(obj
, id_debug_created_info
);
4147 if (NIL_P(info
)) return Qnil
;
4149 VALUE path
= rb_ary_entry(info
, 0);
4150 VALUE line
= rb_ary_entry(info
, 1);
4151 if (NIL_P(path
)) return Qnil
;
4152 *pline
= NUM2INT(line
);
4153 return StringValue(path
);
4157 rb_error_frozen_object(VALUE frozen_obj
)
4159 rb_yjit_lazy_push_frame(GET_EC()->cfp
->pc
);
4161 VALUE mesg
= rb_sprintf("can't modify frozen %"PRIsVALUE
": ",
4162 CLASS_OF(frozen_obj
));
4163 VALUE exc
= rb_exc_new_str(rb_eFrozenError
, mesg
);
4165 rb_ivar_set(exc
, id_recv
, frozen_obj
);
4166 rb_exec_recursive(inspect_frozen_obj
, frozen_obj
, mesg
);
4169 VALUE created_path
= get_created_info(frozen_obj
, &created_line
);
4170 if (!NIL_P(created_path
)) {
4171 rb_str_catf(mesg
, ", created at %"PRIsVALUE
":%d", created_path
, created_line
);
4177 rb_warn_unchilled_literal(VALUE obj
)
4179 rb_warning_category_t category
= RB_WARN_CATEGORY_DEPRECATED
;
4180 if (!NIL_P(ruby_verbose
) && rb_warning_category_enabled_p(category
)) {
4182 VALUE file
= rb_source_location(&line
);
4183 VALUE mesg
= NIL_P(file
) ? rb_str_new(0, 0) : rb_str_dup(file
);
4186 if (line
) rb_str_catf(mesg
, ":%d", line
);
4187 rb_str_cat2(mesg
, ": ");
4189 rb_str_cat2(mesg
, "warning: literal string will be frozen in the future");
4192 if (STR_SHARED_P(str
)) {
4193 str
= RSTRING(obj
)->as
.heap
.aux
.shared
;
4195 VALUE created
= get_created_info(str
, &line
);
4196 if (NIL_P(created
)) {
4197 rb_str_cat2(mesg
, " (run with --debug-frozen-string-literal for more information)\n");
4200 rb_str_cat2(mesg
, "\n");
4201 rb_str_append(mesg
, created
);
4202 if (line
) rb_str_catf(mesg
, ":%d", line
);
4203 rb_str_cat2(mesg
, ": info: the string was created here\n");
4205 rb_warn_category(mesg
, rb_warning_category_to_name(category
));
4210 rb_warn_unchilled_symbol_to_s(VALUE obj
)
4213 RB_WARN_CATEGORY_DEPRECATED
,
4214 "string returned by :%s.to_s will be frozen in the future", RSTRING_PTR(obj
)
4218 #undef rb_check_frozen
4220 rb_check_frozen(VALUE obj
)
4222 rb_check_frozen_inline(obj
);
4226 rb_check_copyable(VALUE obj
, VALUE orig
)
4228 if (!FL_ABLE(obj
)) return;
4229 rb_check_frozen(obj
);
4230 if (!FL_ABLE(orig
)) return;
4236 rb_eNOERROR
= setup_syserr(0, "NOERROR");
4239 rb_define_const(rb_mErrno
, "NOERROR", rb_eNOERROR
);
4241 #define defined_error(name, num) set_syserr((num), (name));
4242 #define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR);
4243 #include "known_errors.inc"
4244 #undef defined_error
4245 #undef undefined_error
4248 #include "warning.rbinc"