1 /**********************************************************************
2 
3   error.c -
4 
5   $Author: nobu $
6   created at: Mon Aug  9 16:11:34 JST 1993
7 
8   Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "ruby/encoding.h"
13 #include "ruby/st.h"
14 #include "internal.h"
15 #include "ruby_assert.h"
16 #include "vm_core.h"
17 
18 #include <stdio.h>
19 #include <stdarg.h>
20 #ifdef HAVE_STDLIB_H
21 #include <stdlib.h>
22 #endif
23 #include <errno.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 
28 #if defined __APPLE__
29 # include <AvailabilityMacros.h>
30 #endif
31 
32 /*!
33  * \defgroup exception Exception handlings
34  * \{
35  */
36 
37 #ifndef EXIT_SUCCESS
38 #define EXIT_SUCCESS 0
39 #endif
40 
41 #ifndef WIFEXITED
42 #define WIFEXITED(status) 1
43 #endif
44 
45 #ifndef WEXITSTATUS
46 #define WEXITSTATUS(status) (status)
47 #endif
48 
49 VALUE rb_iseqw_local_variables(VALUE iseqval);
50 VALUE rb_iseqw_new(const rb_iseq_t *);
51 int rb_str_end_with_asciichar(VALUE str, int c);
52 
53 VALUE rb_eEAGAIN;
54 VALUE rb_eEWOULDBLOCK;
55 VALUE rb_eEINPROGRESS;
56 static VALUE rb_mWarning;
57 static VALUE rb_cWarningBuffer;
58 
59 static ID id_warn;
60 
61 extern const char ruby_description[];
62 
63 static const char REPORTBUG_MSG[] =
64 	"[NOTE]\n" \
65 	"You may have encountered a bug in the Ruby interpreter" \
66 	" or extension libraries.\n" \
67 	"Bug reports are welcome.\n" \
68 	""
69 	"For details: https://www.ruby-lang.org/bugreport.html\n\n" \
70     ;
71 
72 static const char *
rb_strerrno(int err)73 rb_strerrno(int err)
74 {
75 #define defined_error(name, num) if (err == (num)) return (name);
76 #define undefined_error(name)
77 #include "known_errors.inc"
78 #undef defined_error
79 #undef undefined_error
80     return NULL;
81 }
82 
83 static int
err_position_0(char * buf,long len,const char * file,int line)84 err_position_0(char *buf, long len, const char *file, int line)
85 {
86     if (!file) {
87 	return 0;
88     }
89     else if (line == 0) {
90 	return snprintf(buf, len, "%s: ", file);
91     }
92     else {
93 	return snprintf(buf, len, "%s:%d: ", file, line);
94     }
95 }
96 
97 static VALUE
err_vcatf(VALUE str,const char * pre,const char * file,int line,const char * fmt,va_list args)98 err_vcatf(VALUE str, const char *pre, const char *file, int line,
99 	  const char *fmt, va_list args)
100 {
101     if (file) {
102 	rb_str_cat2(str, file);
103 	if (line) rb_str_catf(str, ":%d", line);
104 	rb_str_cat2(str, ": ");
105     }
106     if (pre) rb_str_cat2(str, pre);
107     rb_str_vcatf(str, fmt, args);
108     return str;
109 }
110 
111 VALUE
rb_syntax_error_append(VALUE exc,VALUE file,int line,int column,rb_encoding * enc,const char * fmt,va_list args)112 rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
113 		       rb_encoding *enc, const char *fmt, va_list args)
114 {
115     const char *fn = NIL_P(file) ? NULL : RSTRING_PTR(file);
116     if (!exc) {
117 	VALUE mesg = rb_enc_str_new(0, 0, enc);
118 	err_vcatf(mesg, NULL, fn, line, fmt, args);
119 	rb_str_cat2(mesg, "\n");
120 	rb_write_error_str(mesg);
121     }
122     else {
123 	VALUE mesg;
124 	if (NIL_P(exc)) {
125 	    mesg = rb_enc_str_new(0, 0, enc);
126 	    exc = rb_class_new_instance(1, &mesg, rb_eSyntaxError);
127 	}
128 	else {
129 	    mesg = rb_attr_get(exc, idMesg);
130 	    if (RSTRING_LEN(mesg) > 0 && *(RSTRING_END(mesg)-1) != '\n')
131 		rb_str_cat_cstr(mesg, "\n");
132 	}
133 	err_vcatf(mesg, NULL, fn, line, fmt, args);
134     }
135 
136     return exc;
137 }
138 
139 void
ruby_deprecated_internal_feature(const char * func)140 ruby_deprecated_internal_feature(const char *func)
141 {
142     rb_print_backtrace();
143     rb_fatal("%s is only for internal use and deprecated; do not use", func);
144 }
145 
146 /*
147  * call-seq:
148  *    warn(msg)  -> nil
149  *
150  * Writes warning message +msg+ to $stderr. This method is called by
151  * Ruby for all emitted warnings.
152  */
153 
154 static VALUE
rb_warning_s_warn(VALUE mod,VALUE str)155 rb_warning_s_warn(VALUE mod, VALUE str)
156 {
157     Check_Type(str, T_STRING);
158     rb_must_asciicompat(str);
159     rb_write_error_str(str);
160     return Qnil;
161 }
162 
163 /*
164  *  Document-module: Warning
165  *
166  *  The Warning module contains a single method named #warn, and the
167  *  module extends itself, making <code>Warning.warn</code> available.
168  *  Warning.warn is called for all warnings issued by Ruby.
169  *  By default, warnings are printed to $stderr.
170  *
171  *  By overriding Warning.warn, you can change how warnings are
172  *  handled by Ruby, either filtering some warnings, and/or outputting
173  *  warnings somewhere other than $stderr.  When Warning.warn is
174  *  overridden, super can be called to get the default behavior of
175  *  printing the warning to $stderr.
176  */
177 
178 VALUE
rb_warning_warn(VALUE mod,VALUE str)179 rb_warning_warn(VALUE mod, VALUE str)
180 {
181     return rb_funcallv(mod, id_warn, 1, &str);
182 }
183 
184 static void
rb_write_warning_str(VALUE str)185 rb_write_warning_str(VALUE str)
186 {
187     rb_warning_warn(rb_mWarning, str);
188 }
189 
190 static VALUE
warn_vsprintf(rb_encoding * enc,const char * file,int line,const char * fmt,va_list args)191 warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args)
192 {
193     VALUE str = rb_enc_str_new(0, 0, enc);
194 
195     err_vcatf(str, "warning: ", file, line, fmt, args);
196     return rb_str_cat2(str, "\n");
197 }
198 
199 void
rb_compile_warn(const char * file,int line,const char * fmt,...)200 rb_compile_warn(const char *file, int line, const char *fmt, ...)
201 {
202     VALUE str;
203     va_list args;
204 
205     if (NIL_P(ruby_verbose)) return;
206 
207     va_start(args, fmt);
208     str = warn_vsprintf(NULL, file, line, fmt, args);
209     va_end(args);
210     rb_write_warning_str(str);
211 }
212 
213 /* rb_compile_warning() reports only in verbose mode */
214 void
rb_compile_warning(const char * file,int line,const char * fmt,...)215 rb_compile_warning(const char *file, int line, const char *fmt, ...)
216 {
217     VALUE str;
218     va_list args;
219 
220     if (!RTEST(ruby_verbose)) return;
221 
222     va_start(args, fmt);
223     str = warn_vsprintf(NULL, file, line, fmt, args);
224     va_end(args);
225     rb_write_warning_str(str);
226 }
227 
228 static VALUE
warning_string(rb_encoding * enc,const char * fmt,va_list args)229 warning_string(rb_encoding *enc, const char *fmt, va_list args)
230 {
231     int line;
232     const char *file = rb_source_location_cstr(&line);
233     return warn_vsprintf(enc, file, line, fmt, args);
234 }
235 
236 #define with_warning_string(mesg, enc, fmt) \
237     VALUE mesg; \
238     va_list args; va_start(args, fmt); \
239     mesg = warning_string(enc, fmt, args); \
240     va_end(args);
241 
242 void
rb_warn(const char * fmt,...)243 rb_warn(const char *fmt, ...)
244 {
245     if (!NIL_P(ruby_verbose)) {
246 	with_warning_string(mesg, 0, fmt) {
247 	    rb_write_warning_str(mesg);
248 	}
249     }
250 }
251 
252 void
rb_enc_warn(rb_encoding * enc,const char * fmt,...)253 rb_enc_warn(rb_encoding *enc, const char *fmt, ...)
254 {
255     if (!NIL_P(ruby_verbose)) {
256 	with_warning_string(mesg, enc, fmt) {
257 	    rb_write_warning_str(mesg);
258 	}
259     }
260 }
261 
262 /* rb_warning() reports only in verbose mode */
263 void
rb_warning(const char * fmt,...)264 rb_warning(const char *fmt, ...)
265 {
266     if (RTEST(ruby_verbose)) {
267 	with_warning_string(mesg, 0, fmt) {
268 	    rb_write_warning_str(mesg);
269 	}
270     }
271 }
272 
273 VALUE
rb_warning_string(const char * fmt,...)274 rb_warning_string(const char *fmt, ...)
275 {
276     with_warning_string(mesg, 0, fmt) {
277     }
278     return mesg;
279 }
280 
281 #if 0
282 void
283 rb_enc_warning(rb_encoding *enc, const char *fmt, ...)
284 {
285     if (RTEST(ruby_verbose)) {
286 	with_warning_string(mesg, enc, fmt) {
287 	    rb_write_warning_str(mesg);
288 	}
289     }
290 }
291 #endif
292 
293 static inline int
end_with_asciichar(VALUE str,int c)294 end_with_asciichar(VALUE str, int c)
295 {
296     return RB_TYPE_P(str, T_STRING) &&
297 	rb_str_end_with_asciichar(str, c);
298 }
299 
300 /* :nodoc: */
301 static VALUE
warning_write(int argc,VALUE * argv,VALUE buf)302 warning_write(int argc, VALUE *argv, VALUE buf)
303 {
304     while (argc-- > 0) {
305 	rb_str_append(buf, *argv++);
306     }
307     return buf;
308 }
309 
310 /*
311  * call-seq:
312  *    warn(msg, ...)   -> nil
313  *
314  * If warnings have been disabled (for example with the
315  * <code>-W0</code> flag), does nothing.  Otherwise,
316  * converts each of the messages to strings, appends a newline
317  * character to the string if the string does not end in a newline,
318  * and calls <code>Warning.warn</code> with the string.
319  *
320  *    warn("warning 1", "warning 2")
321  *
322  *  <em>produces:</em>
323  *
324  *    warning 1
325  *    warning 2
326  *
327  * If the <code>uplevel</code> keyword argument is given, the string will
328  * be prepended with information for the given caller frame in
329  * the same format used by the <code>rb_warn</code> C function.
330  *
331  *    # In baz.rb
332  *    def foo
333  *      warn("invalid call to foo", uplevel: 1)
334  *    end
335  *
336  *    def bar
337  *      foo
338  *    end
339  *
340  *    bar
341  *
342  *  <em>produces:</em>
343  *
344  *    baz.rb:6: warning: invalid call to foo
345  */
346 
347 static VALUE
rb_warn_m(int argc,VALUE * argv,VALUE exc)348 rb_warn_m(int argc, VALUE *argv, VALUE exc)
349 {
350     VALUE opts, location = Qnil;
351 
352     if (!NIL_P(ruby_verbose) && argc > 0 &&
353 	    (argc = rb_scan_args(argc, argv, "*:", NULL, &opts)) > 0) {
354 	VALUE str = argv[0], uplevel = Qnil;
355 	if (!NIL_P(opts)) {
356 	    static ID kwds[1];
357 	    if (!kwds[0]) {
358 		CONST_ID(kwds[0], "uplevel");
359 	    }
360 	    rb_get_kwargs(opts, kwds, 0, 1, &uplevel);
361 	    if (uplevel == Qundef) {
362 		uplevel = Qnil;
363 	    }
364 	    else if (!NIL_P(uplevel)) {
365 		VALUE args[2];
366 		long lev = NUM2LONG(uplevel);
367 		if (lev < 0) {
368 		    rb_raise(rb_eArgError, "negative level (%ld)", lev);
369 		}
370 		args[0] = LONG2NUM(lev + 1);
371 		args[1] = INT2FIX(1);
372 		location = rb_vm_thread_backtrace_locations(2, args, GET_THREAD()->self);
373 		if (!NIL_P(location)) {
374 		    location = rb_ary_entry(location, 0);
375 		}
376 	    }
377 	}
378 	if (argc > 1 || !NIL_P(uplevel) || !end_with_asciichar(str, '\n')) {
379 	    VALUE path;
380 	    if (NIL_P(uplevel)) {
381 		str = rb_str_tmp_new(0);
382 	    }
383 	    else if (NIL_P(location) ||
384 		     NIL_P(path = rb_funcall(location, rb_intern("path"), 0))) {
385 		str = rb_str_new_cstr("warning: ");
386 	    }
387 	    else {
388 		str = rb_sprintf("%s:%ld: warning: ",
389 		    rb_string_value_ptr(&path),
390 		    NUM2LONG(rb_funcall(location, rb_intern("lineno"), 0)));
391 	    }
392 	    RBASIC_SET_CLASS(str, rb_cWarningBuffer);
393 	    rb_io_puts(argc, argv, str);
394 	    RBASIC_SET_CLASS(str, rb_cString);
395 	}
396 	if (exc == rb_mWarning) {
397 	    rb_must_asciicompat(str);
398 	    rb_write_error_str(str);
399 	}
400 	else {
401 	    rb_write_warning_str(str);
402 	}
403     }
404     return Qnil;
405 }
406 
407 #define MAX_BUG_REPORTERS 0x100
408 
409 static struct bug_reporters {
410     void (*func)(FILE *out, void *data);
411     void *data;
412 } bug_reporters[MAX_BUG_REPORTERS];
413 
414 static int bug_reporters_size;
415 
416 int
rb_bug_reporter_add(void (* func)(FILE *,void *),void * data)417 rb_bug_reporter_add(void (*func)(FILE *, void *), void *data)
418 {
419     struct bug_reporters *reporter;
420     if (bug_reporters_size >= MAX_BUG_REPORTERS) {
421 	return 0; /* failed to register */
422     }
423     reporter = &bug_reporters[bug_reporters_size++];
424     reporter->func = func;
425     reporter->data = data;
426 
427     return 1;
428 }
429 
430 /* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
431 #define REPORT_BUG_BUFSIZ 256
432 static FILE *
bug_report_file(const char * file,int line)433 bug_report_file(const char *file, int line)
434 {
435     char buf[REPORT_BUG_BUFSIZ];
436     FILE *out = stderr;
437     int len = err_position_0(buf, sizeof(buf), file, line);
438 
439     if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len ||
440 	(ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) {
441 	return out;
442     }
443     return NULL;
444 }
445 
446 FUNC_MINIMIZED(static void bug_important_message(FILE *out, const char *const msg, size_t len));
447 
448 static void
bug_important_message(FILE * out,const char * const msg,size_t len)449 bug_important_message(FILE *out, const char *const msg, size_t len)
450 {
451     const char *const endmsg = msg + len;
452     const char *p = msg;
453 
454     if (!len) return;
455     if (isatty(fileno(out))) {
456 	static const char red[] = "\033[;31;1;7m";
457 	static const char green[] = "\033[;32;7m";
458 	static const char reset[] = "\033[m";
459 	const char *e = strchr(p, '\n');
460 	const int w = (int)(e - p);
461 	do {
462 	    int i = (int)(e - p);
463 	    fputs(*p == ' ' ? green : red, out);
464 	    fwrite(p, 1, e - p, out);
465 	    for (; i < w; ++i) fputc(' ', out);
466 	    fputs(reset, out);
467 	    fputc('\n', out);
468 	} while ((p = e + 1) < endmsg && (e = strchr(p, '\n')) != 0 && e > p + 1);
469     }
470     fwrite(p, 1, endmsg - p, out);
471 }
472 
473 static void
preface_dump(FILE * out)474 preface_dump(FILE *out)
475 {
476 #if defined __APPLE__
477     static const char msg[] = ""
478 	"-- Crash Report log information "
479 	"--------------------------------------------\n"
480 	"   See Crash Report log file under the one of following:\n"
481 # if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
482 	"     * ~/Library/Logs/CrashReporter\n"
483 	"     * /Library/Logs/CrashReporter\n"
484 # endif
485 	"     * ~/Library/Logs/DiagnosticReports\n"
486 	"     * /Library/Logs/DiagnosticReports\n"
487 	"   for more details.\n"
488 	"Don't forget to include the above Crash Report log file in bug reports.\n"
489 	"\n";
490     const size_t msglen = sizeof(msg) - 1;
491 #else
492     const char *msg = NULL;
493     const size_t msglen = 0;
494 #endif
495     bug_important_message(out, msg, msglen);
496 }
497 
498 static void
postscript_dump(FILE * out)499 postscript_dump(FILE *out)
500 {
501 #if defined __APPLE__
502     static const char msg[] = ""
503 	"[IMPORTANT]"
504 	/*" ------------------------------------------------"*/
505 	"\n""Don't forget to include the Crash Report log file under\n"
506 # if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
507 	"CrashReporter or "
508 # endif
509 	"DiagnosticReports directory in bug reports.\n"
510 	/*"------------------------------------------------------------\n"*/
511 	"\n";
512     const size_t msglen = sizeof(msg) - 1;
513 #else
514     const char *msg = NULL;
515     const size_t msglen = 0;
516 #endif
517     bug_important_message(out, msg, msglen);
518 }
519 
520 static void
bug_report_begin_valist(FILE * out,const char * fmt,va_list args)521 bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
522 {
523     char buf[REPORT_BUG_BUFSIZ];
524 
525     fputs("[BUG] ", out);
526     vsnprintf(buf, sizeof(buf), fmt, args);
527     fputs(buf, out);
528     snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description);
529     fputs(buf, out);
530     preface_dump(out);
531 }
532 
533 #define bug_report_begin(out, fmt) do { \
534     va_list args; \
535     va_start(args, fmt); \
536     bug_report_begin_valist(out, fmt, args); \
537     va_end(args); \
538 } while (0)
539 
540 static void
bug_report_end(FILE * out)541 bug_report_end(FILE *out)
542 {
543     /* call additional bug reporters */
544     {
545 	int i;
546 	for (i=0; i<bug_reporters_size; i++) {
547 	    struct bug_reporters *reporter = &bug_reporters[i];
548 	    (*reporter->func)(out, reporter->data);
549 	}
550     }
551     fputs(REPORTBUG_MSG, out);
552     postscript_dump(out);
553 }
554 
555 #define report_bug(file, line, fmt, ctx) do { \
556     FILE *out = bug_report_file(file, line); \
557     if (out) { \
558 	bug_report_begin(out, fmt); \
559 	rb_vm_bugreport(ctx); \
560 	bug_report_end(out); \
561     } \
562 } while (0) \
563 
564 #define report_bug_valist(file, line, fmt, ctx, args) do { \
565     FILE *out = bug_report_file(file, line); \
566     if (out) { \
567 	bug_report_begin_valist(out, fmt, args); \
568 	rb_vm_bugreport(ctx); \
569 	bug_report_end(out); \
570     } \
571 } while (0) \
572 
573 NORETURN(static void die(void));
574 static void
die(void)575 die(void)
576 {
577 #if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
578     _set_abort_behavior( 0, _CALL_REPORTFAULT);
579 #endif
580 
581     abort();
582 }
583 
584 void
rb_bug(const char * fmt,...)585 rb_bug(const char *fmt, ...)
586 {
587     const char *file = NULL;
588     int line = 0;
589 
590     if (GET_EC()) {
591 	file = rb_source_location_cstr(&line);
592     }
593 
594     report_bug(file, line, fmt, NULL);
595 
596     die();
597 }
598 
599 void
rb_bug_context(const void * ctx,const char * fmt,...)600 rb_bug_context(const void *ctx, const char *fmt, ...)
601 {
602     const char *file = NULL;
603     int line = 0;
604 
605     if (GET_EC()) {
606 	file = rb_source_location_cstr(&line);
607     }
608 
609     report_bug(file, line, fmt, ctx);
610 
611     die();
612 }
613 
614 
615 void
rb_bug_errno(const char * mesg,int errno_arg)616 rb_bug_errno(const char *mesg, int errno_arg)
617 {
618     if (errno_arg == 0)
619         rb_bug("%s: errno == 0 (NOERROR)", mesg);
620     else {
621         const char *errno_str = rb_strerrno(errno_arg);
622         if (errno_str)
623             rb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
624         else
625             rb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
626     }
627 }
628 
629 /*
630  * this is safe to call inside signal handler and timer thread
631  * (which isn't a Ruby Thread object)
632  */
633 #define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
634 #define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
635 
636 void
rb_async_bug_errno(const char * mesg,int errno_arg)637 rb_async_bug_errno(const char *mesg, int errno_arg)
638 {
639     WRITE_CONST(2, "[ASYNC BUG] ");
640     write_or_abort(2, mesg, strlen(mesg));
641     WRITE_CONST(2, "\n");
642 
643     if (errno_arg == 0) {
644 	WRITE_CONST(2, "errno == 0 (NOERROR)\n");
645     }
646     else {
647 	const char *errno_str = rb_strerrno(errno_arg);
648 
649 	if (!errno_str)
650 	    errno_str = "undefined errno";
651 	write_or_abort(2, errno_str, strlen(errno_str));
652     }
653     WRITE_CONST(2, "\n\n");
654     write_or_abort(2, ruby_description, strlen(ruby_description));
655     WRITE_CONST(2, "\n\n");
656     WRITE_CONST(2, REPORTBUG_MSG);
657     abort();
658 }
659 
660 void
rb_report_bug_valist(VALUE file,int line,const char * fmt,va_list args)661 rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
662 {
663     report_bug_valist(RSTRING_PTR(file), line, fmt, NULL, args);
664 }
665 
666 MJIT_FUNC_EXPORTED void
rb_assert_failure(const char * file,int line,const char * name,const char * expr)667 rb_assert_failure(const char *file, int line, const char *name, const char *expr)
668 {
669     FILE *out = stderr;
670     fprintf(out, "Assertion Failed: %s:%d:", file, line);
671     if (name) fprintf(out, "%s:", name);
672     fprintf(out, "%s\n%s\n\n", expr, ruby_description);
673     preface_dump(out);
674     rb_vm_bugreport(NULL);
675     bug_report_end(out);
676     die();
677 }
678 
679 static const char builtin_types[][10] = {
680     "", 			/* 0x00, */
681     "Object",
682     "Class",
683     "Module",
684     "Float",
685     "String",
686     "Regexp",
687     "Array",
688     "Hash",
689     "Struct",
690     "Bignum",
691     "File",
692     "Data",			/* internal use: wrapped C pointers */
693     "MatchData",		/* data of $~ */
694     "Complex",
695     "Rational",
696     "",				/* 0x10 */
697     "nil",
698     "true",
699     "false",
700     "Symbol",			/* :symbol */
701     "Fixnum",
702     "undef",			/* internal use: #undef; should not happen */
703     "",				/* 0x17 */
704     "",				/* 0x18 */
705     "",				/* 0x19 */
706     "Memo",			/* internal use: general memo */
707     "Node",			/* internal use: syntax tree node */
708     "iClass",			/* internal use: mixed-in module holder */
709 };
710 
711 const char *
rb_builtin_type_name(int t)712 rb_builtin_type_name(int t)
713 {
714     const char *name;
715     if ((unsigned int)t >= numberof(builtin_types)) return 0;
716     name = builtin_types[t];
717     if (*name) return name;
718     return 0;
719 }
720 
721 static const char *
builtin_class_name(VALUE x)722 builtin_class_name(VALUE x)
723 {
724     const char *etype;
725 
726     if (NIL_P(x)) {
727 	etype = "nil";
728     }
729     else if (FIXNUM_P(x)) {
730 	etype = "Integer";
731     }
732     else if (SYMBOL_P(x)) {
733 	etype = "Symbol";
734     }
735     else if (RB_TYPE_P(x, T_TRUE)) {
736 	etype = "true";
737     }
738     else if (RB_TYPE_P(x, T_FALSE)) {
739 	etype = "false";
740     }
741     else {
742 	etype = NULL;
743     }
744     return etype;
745 }
746 
747 const char *
rb_builtin_class_name(VALUE x)748 rb_builtin_class_name(VALUE x)
749 {
750     const char *etype = builtin_class_name(x);
751 
752     if (!etype) {
753 	etype = rb_obj_classname(x);
754     }
755     return etype;
756 }
757 
758 NORETURN(static void unexpected_type(VALUE, int, int));
759 #define UNDEF_LEAKED "undef leaked to the Ruby space"
760 
761 static void
unexpected_type(VALUE x,int xt,int t)762 unexpected_type(VALUE x, int xt, int t)
763 {
764     const char *tname = rb_builtin_type_name(t);
765     VALUE mesg, exc = rb_eFatal;
766 
767     if (tname) {
768 	const char *cname = builtin_class_name(x);
769 	if (cname)
770 	    mesg = rb_sprintf("wrong argument type %s (expected %s)",
771 			      cname, tname);
772 	else
773 	    mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
774 			      rb_obj_class(x), tname);
775 	exc = rb_eTypeError;
776     }
777     else if (xt > T_MASK && xt <= 0x3f) {
778 	mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
779 			  " from extension library for ruby 1.8)", t, xt);
780     }
781     else {
782 	mesg = rb_sprintf("unknown type 0x%x (0x%x given)", t, xt);
783     }
784     rb_exc_raise(rb_exc_new_str(exc, mesg));
785 }
786 
787 void
rb_check_type(VALUE x,int t)788 rb_check_type(VALUE x, int t)
789 {
790     int xt;
791 
792     if (x == Qundef) {
793 	rb_bug(UNDEF_LEAKED);
794     }
795 
796     xt = TYPE(x);
797     if (xt != t || (xt == T_DATA && RTYPEDDATA_P(x))) {
798 	unexpected_type(x, xt, t);
799     }
800 }
801 
802 void
rb_unexpected_type(VALUE x,int t)803 rb_unexpected_type(VALUE x, int t)
804 {
805     if (x == Qundef) {
806 	rb_bug(UNDEF_LEAKED);
807     }
808 
809     unexpected_type(x, TYPE(x), t);
810 }
811 
812 int
rb_typeddata_inherited_p(const rb_data_type_t * child,const rb_data_type_t * parent)813 rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
814 {
815     while (child) {
816 	if (child == parent) return 1;
817 	child = child->parent;
818     }
819     return 0;
820 }
821 
822 int
rb_typeddata_is_kind_of(VALUE obj,const rb_data_type_t * data_type)823 rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
824 {
825     if (!RB_TYPE_P(obj, T_DATA) ||
826 	!RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
827 	return 0;
828     }
829     return 1;
830 }
831 
832 #undef rb_typeddata_is_instance_of
833 int
rb_typeddata_is_instance_of(VALUE obj,const rb_data_type_t * data_type)834 rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type)
835 {
836     return rb_typeddata_is_instance_of_inline(obj, data_type);
837 }
838 
839 void *
rb_check_typeddata(VALUE obj,const rb_data_type_t * data_type)840 rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
841 {
842     const char *etype;
843 
844     if (!RB_TYPE_P(obj, T_DATA)) {
845       wrong_type:
846 	etype = builtin_class_name(obj);
847 	if (!etype)
848 	    rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
849 		     rb_obj_class(obj), data_type->wrap_struct_name);
850       wrong_datatype:
851 	rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
852 		 etype, data_type->wrap_struct_name);
853     }
854     if (!RTYPEDDATA_P(obj)) {
855 	goto wrong_type;
856     }
857     else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
858 	etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
859 	goto wrong_datatype;
860     }
861     return DATA_PTR(obj);
862 }
863 
864 /* exception classes */
865 VALUE rb_eException;
866 VALUE rb_eSystemExit;
867 VALUE rb_eInterrupt;
868 VALUE rb_eSignal;
869 VALUE rb_eFatal;
870 VALUE rb_eStandardError;
871 VALUE rb_eRuntimeError;
872 VALUE rb_eFrozenError;
873 VALUE rb_eTypeError;
874 VALUE rb_eArgError;
875 VALUE rb_eIndexError;
876 VALUE rb_eKeyError;
877 VALUE rb_eRangeError;
878 VALUE rb_eNameError;
879 VALUE rb_eEncodingError;
880 VALUE rb_eEncCompatError;
881 VALUE rb_eNoMethodError;
882 VALUE rb_eSecurityError;
883 VALUE rb_eNotImpError;
884 VALUE rb_eNoMemError;
885 VALUE rb_cNameErrorMesg;
886 
887 VALUE rb_eScriptError;
888 VALUE rb_eSyntaxError;
889 VALUE rb_eLoadError;
890 
891 VALUE rb_eSystemCallError;
892 VALUE rb_mErrno;
893 static VALUE rb_eNOERROR;
894 
895 ID ruby_static_id_cause;
896 #define id_cause ruby_static_id_cause
897 static ID id_message, id_backtrace;
898 static ID id_name, id_key, id_args, id_Errno, id_errno, id_i_path;
899 static ID id_receiver, id_recv, id_iseq, id_local_variables;
900 static ID id_private_call_p, id_top, id_bottom;
901 #define id_bt idBt
902 #define id_bt_locations idBt_locations
903 #define id_mesg idMesg
904 
905 #undef rb_exc_new_cstr
906 
907 VALUE
rb_exc_new(VALUE etype,const char * ptr,long len)908 rb_exc_new(VALUE etype, const char *ptr, long len)
909 {
910     VALUE mesg = rb_str_new(ptr, len);
911     return rb_class_new_instance(1, &mesg, etype);
912 }
913 
914 VALUE
rb_exc_new_cstr(VALUE etype,const char * s)915 rb_exc_new_cstr(VALUE etype, const char *s)
916 {
917     return rb_exc_new(etype, s, strlen(s));
918 }
919 
920 VALUE
rb_exc_new_str(VALUE etype,VALUE str)921 rb_exc_new_str(VALUE etype, VALUE str)
922 {
923     StringValue(str);
924     return rb_class_new_instance(1, &str, etype);
925 }
926 
927 static VALUE
exc_init(VALUE exc,VALUE mesg)928 exc_init(VALUE exc, VALUE mesg)
929 {
930     rb_ivar_set(exc, id_mesg, mesg);
931     rb_ivar_set(exc, id_bt, Qnil);
932 
933     return exc;
934 }
935 
936 /*
937  * call-seq:
938  *    Exception.new(msg = nil)   ->  exception
939  *
940  *  Construct a new Exception object, optionally passing in
941  *  a message.
942  */
943 
944 static VALUE
exc_initialize(int argc,VALUE * argv,VALUE exc)945 exc_initialize(int argc, VALUE *argv, VALUE exc)
946 {
947     VALUE arg;
948 
949     arg = (!rb_check_arity(argc, 0, 1) ? Qnil : argv[0]);
950     return exc_init(exc, arg);
951 }
952 
953 /*
954  *  Document-method: exception
955  *
956  *  call-seq:
957  *     exc.exception(string)  ->  an_exception or exc
958  *
959  *  With no argument, or if the argument is the same as the receiver,
960  *  return the receiver. Otherwise, create a new
961  *  exception object of the same class as the receiver, but with a
962  *  message equal to <code>string.to_str</code>.
963  *
964  */
965 
966 static VALUE
exc_exception(int argc,VALUE * argv,VALUE self)967 exc_exception(int argc, VALUE *argv, VALUE self)
968 {
969     VALUE exc;
970 
971     if (argc == 0) return self;
972     if (argc == 1 && self == argv[0]) return self;
973     exc = rb_obj_clone(self);
974     exc_initialize(argc, argv, exc);
975 
976     return exc;
977 }
978 
979 /*
980  * call-seq:
981  *   exception.to_s   ->  string
982  *
983  * Returns exception's message (or the name of the exception if
984  * no message is set).
985  */
986 
987 static VALUE
exc_to_s(VALUE exc)988 exc_to_s(VALUE exc)
989 {
990     VALUE mesg = rb_attr_get(exc, idMesg);
991 
992     if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
993     return rb_String(mesg);
994 }
995 
996 /* FIXME: Include eval_error.c */
997 void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse);
998 
999 VALUE
rb_get_message(VALUE exc)1000 rb_get_message(VALUE exc)
1001 {
1002     VALUE e = rb_check_funcall(exc, id_message, 0, 0);
1003     if (e == Qundef) return Qnil;
1004     if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
1005     return e;
1006 }
1007 
1008 /*
1009  * call-seq:
1010  *    Exception.to_tty?   ->  true or false
1011  *
1012  * Returns +true+ if exception messages will be sent to a tty.
1013  */
1014 static VALUE
exc_s_to_tty_p(VALUE self)1015 exc_s_to_tty_p(VALUE self)
1016 {
1017     return rb_stderr_tty_p() ? Qtrue : Qfalse;
1018 }
1019 
1020 /*
1021  * call-seq:
1022  *   exception.full_message(highlight: bool, order: [:top or :bottom]) ->  string
1023  *
1024  * Returns formatted string of _exception_.
1025  * The returned string is formatted using the same format that Ruby uses
1026  * when printing an uncaught exceptions to stderr.
1027  *
1028  * If _highlight_ is +true+ the default error handler will send the
1029  * messages to a tty.
1030  *
1031  * _order_ must be either of +:top+ or +:bottom+, and places the error
1032  * message and the innermost backtrace come at the top or the bottom.
1033  *
1034  * The default values of these options depend on <code>$stderr</code>
1035  * and its +tty?+ at the timing of a call.
1036  */
1037 
1038 static VALUE
exc_full_message(int argc,VALUE * argv,VALUE exc)1039 exc_full_message(int argc, VALUE *argv, VALUE exc)
1040 {
1041     VALUE opt, str, emesg, errat;
1042     enum {kw_highlight, kw_order, kw_max_};
1043     static ID kw[kw_max_];
1044     VALUE args[kw_max_] = {Qnil, Qnil};
1045 
1046     rb_scan_args(argc, argv, "0:", &opt);
1047     if (!NIL_P(opt)) {
1048 	if (!kw[0]) {
1049 #define INIT_KW(n) kw[kw_##n] = rb_intern_const(#n)
1050 	    INIT_KW(highlight);
1051 	    INIT_KW(order);
1052 #undef INIT_KW
1053 	}
1054 	rb_get_kwargs(opt, kw, 0, kw_max_, args);
1055 	switch (args[kw_highlight]) {
1056 	  default:
1057 	    rb_raise(rb_eArgError, "expected true or false as "
1058 		     "highlight: %+"PRIsVALUE, args[kw_highlight]);
1059 	  case Qundef: args[kw_highlight] = Qnil; break;
1060 	  case Qtrue: case Qfalse: case Qnil: break;
1061 	}
1062 	if (args[kw_order] == Qundef) {
1063 	    args[kw_order] = Qnil;
1064 	}
1065 	else {
1066 	    ID id = rb_check_id(&args[kw_order]);
1067 	    if (id == id_bottom) args[kw_order] = Qtrue;
1068 	    else if (id == id_top) args[kw_order] = Qfalse;
1069 	    else {
1070 		rb_raise(rb_eArgError, "expected :top or :bottom as "
1071 			 "order: %+"PRIsVALUE, args[kw_order]);
1072 	    }
1073 	}
1074     }
1075     str = rb_str_new2("");
1076     errat = rb_get_backtrace(exc);
1077     emesg = rb_get_message(exc);
1078 
1079     rb_error_write(exc, emesg, errat, str, args[kw_highlight], args[kw_order]);
1080     return str;
1081 }
1082 
1083 /*
1084  * call-seq:
1085  *   exception.message   ->  string
1086  *
1087  * Returns the result of invoking <code>exception.to_s</code>.
1088  * Normally this returns the exception's message or name.
1089  */
1090 
1091 static VALUE
exc_message(VALUE exc)1092 exc_message(VALUE exc)
1093 {
1094     return rb_funcallv(exc, idTo_s, 0, 0);
1095 }
1096 
1097 /*
1098  * call-seq:
1099  *   exception.inspect   -> string
1100  *
1101  * Return this exception's class name and message.
1102  */
1103 
1104 static VALUE
exc_inspect(VALUE exc)1105 exc_inspect(VALUE exc)
1106 {
1107     VALUE str, klass;
1108 
1109     klass = CLASS_OF(exc);
1110     exc = rb_obj_as_string(exc);
1111     if (RSTRING_LEN(exc) == 0) {
1112 	return rb_str_dup(rb_class_name(klass));
1113     }
1114 
1115     str = rb_str_buf_new2("#<");
1116     klass = rb_class_name(klass);
1117     rb_str_buf_append(str, klass);
1118     rb_str_buf_cat(str, ": ", 2);
1119     rb_str_buf_append(str, exc);
1120     rb_str_buf_cat(str, ">", 1);
1121 
1122     return str;
1123 }
1124 
1125 /*
1126  *  call-seq:
1127  *     exception.backtrace    -> array
1128  *
1129  *  Returns any backtrace associated with the exception. The backtrace
1130  *  is an array of strings, each containing either ``filename:lineNo: in
1131  *  `method''' or ``filename:lineNo.''
1132  *
1133  *     def a
1134  *       raise "boom"
1135  *     end
1136  *
1137  *     def b
1138  *       a()
1139  *     end
1140  *
1141  *     begin
1142  *       b()
1143  *     rescue => detail
1144  *       print detail.backtrace.join("\n")
1145  *     end
1146  *
1147  *  <em>produces:</em>
1148  *
1149  *     prog.rb:2:in `a'
1150  *     prog.rb:6:in `b'
1151  *     prog.rb:10
1152 */
1153 
1154 static VALUE
exc_backtrace(VALUE exc)1155 exc_backtrace(VALUE exc)
1156 {
1157     VALUE obj;
1158 
1159     obj = rb_attr_get(exc, id_bt);
1160 
1161     if (rb_backtrace_p(obj)) {
1162 	obj = rb_backtrace_to_str_ary(obj);
1163 	/* rb_ivar_set(exc, id_bt, obj); */
1164     }
1165 
1166     return obj;
1167 }
1168 
1169 VALUE
rb_get_backtrace(VALUE exc)1170 rb_get_backtrace(VALUE exc)
1171 {
1172     ID mid = id_backtrace;
1173     VALUE info;
1174     if (rb_method_basic_definition_p(CLASS_OF(exc), id_backtrace)) {
1175 	VALUE klass = rb_eException;
1176 	rb_execution_context_t *ec = GET_EC();
1177 	if (NIL_P(exc))
1178 	    return Qnil;
1179 	EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
1180 	info = exc_backtrace(exc);
1181 	EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
1182     }
1183     else {
1184 	info = rb_funcallv(exc, mid, 0, 0);
1185     }
1186     if (NIL_P(info)) return Qnil;
1187     return rb_check_backtrace(info);
1188 }
1189 
1190 /*
1191  *  call-seq:
1192  *     exception.backtrace_locations    -> array
1193  *
1194  *  Returns any backtrace associated with the exception. This method is
1195  *  similar to Exception#backtrace, but the backtrace is an array of
1196  *  Thread::Backtrace::Location.
1197  *
1198  *  Now, this method is not affected by Exception#set_backtrace().
1199  */
1200 static VALUE
exc_backtrace_locations(VALUE exc)1201 exc_backtrace_locations(VALUE exc)
1202 {
1203     VALUE obj;
1204 
1205     obj = rb_attr_get(exc, id_bt_locations);
1206     if (!NIL_P(obj)) {
1207 	obj = rb_backtrace_to_location_ary(obj);
1208     }
1209     return obj;
1210 }
1211 
1212 VALUE
rb_check_backtrace(VALUE bt)1213 rb_check_backtrace(VALUE bt)
1214 {
1215     long i;
1216     static const char err[] = "backtrace must be Array of String";
1217 
1218     if (!NIL_P(bt)) {
1219 	if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
1220 	if (rb_backtrace_p(bt)) return bt;
1221 	if (!RB_TYPE_P(bt, T_ARRAY)) {
1222 	    rb_raise(rb_eTypeError, err);
1223 	}
1224 	for (i=0;i<RARRAY_LEN(bt);i++) {
1225 	    VALUE e = RARRAY_AREF(bt, i);
1226 	    if (!RB_TYPE_P(e, T_STRING)) {
1227 		rb_raise(rb_eTypeError, err);
1228 	    }
1229 	}
1230     }
1231     return bt;
1232 }
1233 
1234 /*
1235  *  call-seq:
1236  *     exc.set_backtrace(backtrace)   ->  array
1237  *
1238  *  Sets the backtrace information associated with +exc+. The +backtrace+ must
1239  *  be an array of String objects or a single String in the format described
1240  *  in Exception#backtrace.
1241  *
1242  */
1243 
1244 static VALUE
exc_set_backtrace(VALUE exc,VALUE bt)1245 exc_set_backtrace(VALUE exc, VALUE bt)
1246 {
1247     return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
1248 }
1249 
1250 MJIT_FUNC_EXPORTED VALUE
rb_exc_set_backtrace(VALUE exc,VALUE bt)1251 rb_exc_set_backtrace(VALUE exc, VALUE bt)
1252 {
1253     return exc_set_backtrace(exc, bt);
1254 }
1255 
1256 /*
1257  * call-seq:
1258  *   exception.cause   -> an_exception or nil
1259  *
1260  * Returns the previous exception ($!) at the time this exception was raised.
1261  * This is useful for wrapping exceptions and retaining the original exception
1262  * information.
1263  */
1264 
1265 static VALUE
exc_cause(VALUE exc)1266 exc_cause(VALUE exc)
1267 {
1268     return rb_attr_get(exc, id_cause);
1269 }
1270 
1271 static VALUE
try_convert_to_exception(VALUE obj)1272 try_convert_to_exception(VALUE obj)
1273 {
1274     return rb_check_funcall(obj, idException, 0, 0);
1275 }
1276 
1277 /*
1278  *  call-seq:
1279  *     exc == obj   -> true or false
1280  *
1281  *  Equality---If <i>obj</i> is not an <code>Exception</code>, returns
1282  *  <code>false</code>. Otherwise, returns <code>true</code> if <i>exc</i> and
1283  *  <i>obj</i> share same class, messages, and backtrace.
1284  */
1285 
1286 static VALUE
exc_equal(VALUE exc,VALUE obj)1287 exc_equal(VALUE exc, VALUE obj)
1288 {
1289     VALUE mesg, backtrace;
1290 
1291     if (exc == obj) return Qtrue;
1292 
1293     if (rb_obj_class(exc) != rb_obj_class(obj)) {
1294 	int state;
1295 
1296 	obj = rb_protect(try_convert_to_exception, obj, &state);
1297 	if (state || obj == Qundef) {
1298 	    rb_set_errinfo(Qnil);
1299 	    return Qfalse;
1300 	}
1301 	if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
1302 	mesg = rb_check_funcall(obj, id_message, 0, 0);
1303 	if (mesg == Qundef) return Qfalse;
1304 	backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
1305 	if (backtrace == Qundef) return Qfalse;
1306     }
1307     else {
1308 	mesg = rb_attr_get(obj, id_mesg);
1309 	backtrace = exc_backtrace(obj);
1310     }
1311 
1312     if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
1313 	return Qfalse;
1314     if (!rb_equal(exc_backtrace(exc), backtrace))
1315 	return Qfalse;
1316     return Qtrue;
1317 }
1318 
1319 /*
1320  * call-seq:
1321  *   SystemExit.new              -> system_exit
1322  *   SystemExit.new(status)      -> system_exit
1323  *   SystemExit.new(status, msg) -> system_exit
1324  *   SystemExit.new(msg)         -> system_exit
1325  *
1326  * Create a new +SystemExit+ exception with the given status and message.
1327  * Status is true, false, or an integer.
1328  * If status is not given, true is used.
1329  */
1330 
1331 static VALUE
exit_initialize(int argc,VALUE * argv,VALUE exc)1332 exit_initialize(int argc, VALUE *argv, VALUE exc)
1333 {
1334     VALUE status;
1335     if (argc > 0) {
1336 	status = *argv;
1337 
1338 	switch (status) {
1339 	  case Qtrue:
1340 	    status = INT2FIX(EXIT_SUCCESS);
1341 	    ++argv;
1342 	    --argc;
1343 	    break;
1344 	  case Qfalse:
1345 	    status = INT2FIX(EXIT_FAILURE);
1346 	    ++argv;
1347 	    --argc;
1348 	    break;
1349 	  default:
1350 	    status = rb_check_to_int(status);
1351 	    if (NIL_P(status)) {
1352 		status = INT2FIX(EXIT_SUCCESS);
1353 	    }
1354 	    else {
1355 #if EXIT_SUCCESS != 0
1356 		if (status == INT2FIX(0))
1357 		    status = INT2FIX(EXIT_SUCCESS);
1358 #endif
1359 		++argv;
1360 		--argc;
1361 	    }
1362 	    break;
1363 	}
1364     }
1365     else {
1366 	status = INT2FIX(EXIT_SUCCESS);
1367     }
1368     rb_call_super(argc, argv);
1369     rb_ivar_set(exc, id_status, status);
1370     return exc;
1371 }
1372 
1373 
1374 /*
1375  * call-seq:
1376  *   system_exit.status   -> integer
1377  *
1378  * Return the status value associated with this system exit.
1379  */
1380 
1381 static VALUE
exit_status(VALUE exc)1382 exit_status(VALUE exc)
1383 {
1384     return rb_attr_get(exc, id_status);
1385 }
1386 
1387 
1388 /*
1389  * call-seq:
1390  *   system_exit.success?  -> true or false
1391  *
1392  * Returns +true+ if exiting successful, +false+ if not.
1393  */
1394 
1395 static VALUE
exit_success_p(VALUE exc)1396 exit_success_p(VALUE exc)
1397 {
1398     VALUE status_val = rb_attr_get(exc, id_status);
1399     int status;
1400 
1401     if (NIL_P(status_val))
1402 	return Qtrue;
1403     status = NUM2INT(status_val);
1404     if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
1405 	return Qtrue;
1406 
1407     return Qfalse;
1408 }
1409 
1410 void
rb_name_error(ID id,const char * fmt,...)1411 rb_name_error(ID id, const char *fmt, ...)
1412 {
1413     VALUE exc, argv[2];
1414     va_list args;
1415 
1416     va_start(args, fmt);
1417     argv[0] = rb_vsprintf(fmt, args);
1418     va_end(args);
1419 
1420     argv[1] = ID2SYM(id);
1421     exc = rb_class_new_instance(2, argv, rb_eNameError);
1422     rb_exc_raise(exc);
1423 }
1424 
1425 void
rb_name_error_str(VALUE str,const char * fmt,...)1426 rb_name_error_str(VALUE str, const char *fmt, ...)
1427 {
1428     VALUE exc, argv[2];
1429     va_list args;
1430 
1431     va_start(args, fmt);
1432     argv[0] = rb_vsprintf(fmt, args);
1433     va_end(args);
1434 
1435     argv[1] = str;
1436     exc = rb_class_new_instance(2, argv, rb_eNameError);
1437     rb_exc_raise(exc);
1438 }
1439 
1440 static VALUE
name_err_init_attr(VALUE exc,VALUE recv,VALUE method)1441 name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
1442 {
1443     const rb_execution_context_t *ec = GET_EC();
1444     rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
1445     cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
1446     rb_ivar_set(exc, id_name, method);
1447     if (recv != Qundef) rb_ivar_set(exc, id_recv, recv);
1448     if (cfp) rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
1449     return exc;
1450 }
1451 
1452 /*
1453  * call-seq:
1454  *   NameError.new(msg [, name])  -> name_error
1455  *   NameError.new(msg [, name], receiver:)  -> name_error
1456  *
1457  * Construct a new NameError exception. If given the <i>name</i>
1458  * parameter may subsequently be examined using the <code>NameError#name</code>
1459  * method.
1460  */
1461 
1462 static VALUE
name_err_initialize(int argc,VALUE * argv,VALUE self)1463 name_err_initialize(int argc, VALUE *argv, VALUE self)
1464 {
1465     ID keywords[1];
1466     VALUE values[numberof(keywords)], name, options;
1467 
1468     argc = rb_scan_args(argc, argv, "*:", NULL, &options);
1469     keywords[0] = id_receiver;
1470     rb_get_kwargs(options, keywords, 0, numberof(values), values);
1471     name = (argc > 1) ? argv[--argc] : Qnil;
1472     rb_call_super(argc, argv);
1473     name_err_init_attr(self, values[0], name);
1474     return self;
1475 }
1476 
1477 static VALUE
name_err_init(VALUE exc,VALUE mesg,VALUE recv,VALUE method)1478 name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method)
1479 {
1480     exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
1481     return name_err_init_attr(exc, recv, method);
1482 }
1483 
1484 VALUE
rb_name_err_new(VALUE mesg,VALUE recv,VALUE method)1485 rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
1486 {
1487     VALUE exc = rb_obj_alloc(rb_eNameError);
1488     return name_err_init(exc, mesg, recv, method);
1489 }
1490 
1491 /*
1492  *  call-seq:
1493  *    name_error.name    ->  string or nil
1494  *
1495  *  Return the name associated with this NameError exception.
1496  */
1497 
1498 static VALUE
name_err_name(VALUE self)1499 name_err_name(VALUE self)
1500 {
1501     return rb_attr_get(self, id_name);
1502 }
1503 
1504 /*
1505  *  call-seq:
1506  *    name_error.local_variables  ->  array
1507  *
1508  *  Return a list of the local variable names defined where this
1509  *  NameError exception was raised.
1510  *
1511  *  Internal use only.
1512  */
1513 
1514 static VALUE
name_err_local_variables(VALUE self)1515 name_err_local_variables(VALUE self)
1516 {
1517     VALUE vars = rb_attr_get(self, id_local_variables);
1518 
1519     if (NIL_P(vars)) {
1520 	VALUE iseqw = rb_attr_get(self, id_iseq);
1521 	if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
1522 	if (NIL_P(vars)) vars = rb_ary_new();
1523 	rb_ivar_set(self, id_local_variables, vars);
1524     }
1525     return vars;
1526 }
1527 
1528 static VALUE
nometh_err_init_attr(VALUE exc,VALUE args,int priv)1529 nometh_err_init_attr(VALUE exc, VALUE args, int priv)
1530 {
1531     rb_ivar_set(exc, id_args, args);
1532     rb_ivar_set(exc, id_private_call_p, priv ? Qtrue : Qfalse);
1533     return exc;
1534 }
1535 
1536 /*
1537  * call-seq:
1538  *   NoMethodError.new([msg, *, name [, args [, priv]]])  -> no_method_error
1539  *
1540  * Construct a NoMethodError exception for a method of the given name
1541  * called with the given arguments. The name may be accessed using
1542  * the <code>#name</code> method on the resulting object, and the
1543  * arguments using the <code>#args</code> method.
1544  */
1545 
1546 static VALUE
nometh_err_initialize(int argc,VALUE * argv,VALUE self)1547 nometh_err_initialize(int argc, VALUE *argv, VALUE self)
1548 {
1549     int priv;
1550     VALUE args, options;
1551     argc = rb_scan_args(argc, argv, "*:", NULL, &options);
1552     priv = (argc > 3) && (--argc, RTEST(argv[argc]));
1553     args = (argc > 2) ? argv[--argc] : Qnil;
1554     if (!NIL_P(options)) argv[argc++] = options;
1555     rb_call_super(argc, argv);
1556     return nometh_err_init_attr(self, args, priv);
1557 }
1558 
1559 VALUE
rb_nomethod_err_new(VALUE mesg,VALUE recv,VALUE method,VALUE args,int priv)1560 rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
1561 {
1562     VALUE exc = rb_obj_alloc(rb_eNoMethodError);
1563     name_err_init(exc, mesg, recv, method);
1564     return nometh_err_init_attr(exc, args, priv);
1565 }
1566 
1567 /* :nodoc: */
1568 enum {
1569     NAME_ERR_MESG__MESG,
1570     NAME_ERR_MESG__RECV,
1571     NAME_ERR_MESG__NAME,
1572     NAME_ERR_MESG_COUNT
1573 };
1574 
1575 static void
name_err_mesg_mark(void * p)1576 name_err_mesg_mark(void *p)
1577 {
1578     VALUE *ptr = p;
1579     rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT);
1580 }
1581 
1582 #define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE
1583 
1584 static size_t
name_err_mesg_memsize(const void * p)1585 name_err_mesg_memsize(const void *p)
1586 {
1587     return NAME_ERR_MESG_COUNT * sizeof(VALUE);
1588 }
1589 
1590 static const rb_data_type_t name_err_mesg_data_type = {
1591     "name_err_mesg",
1592     {
1593 	name_err_mesg_mark,
1594 	name_err_mesg_free,
1595 	name_err_mesg_memsize,
1596     },
1597     0, 0, RUBY_TYPED_FREE_IMMEDIATELY
1598 };
1599 
1600 /* :nodoc: */
1601 VALUE
rb_name_err_mesg_new(VALUE mesg,VALUE recv,VALUE method)1602 rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
1603 {
1604     VALUE result = TypedData_Wrap_Struct(rb_cNameErrorMesg, &name_err_mesg_data_type, 0);
1605     VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
1606 
1607     ptr[NAME_ERR_MESG__MESG] = mesg;
1608     ptr[NAME_ERR_MESG__RECV] = recv;
1609     ptr[NAME_ERR_MESG__NAME] = method;
1610     RTYPEDDATA_DATA(result) = ptr;
1611     return result;
1612 }
1613 
1614 /* :nodoc: */
1615 static VALUE
name_err_mesg_equal(VALUE obj1,VALUE obj2)1616 name_err_mesg_equal(VALUE obj1, VALUE obj2)
1617 {
1618     VALUE *ptr1, *ptr2;
1619     int i;
1620 
1621     if (obj1 == obj2) return Qtrue;
1622     if (rb_obj_class(obj2) != rb_cNameErrorMesg)
1623 	return Qfalse;
1624 
1625     TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
1626     TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
1627     for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
1628 	if (!rb_equal(ptr1[i], ptr2[i]))
1629 	    return Qfalse;
1630     }
1631     return Qtrue;
1632 }
1633 
1634 /* :nodoc: */
1635 static VALUE
name_err_mesg_to_str(VALUE obj)1636 name_err_mesg_to_str(VALUE obj)
1637 {
1638     VALUE *ptr, mesg;
1639     TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr);
1640 
1641     mesg = ptr[NAME_ERR_MESG__MESG];
1642     if (NIL_P(mesg)) return Qnil;
1643     else {
1644 	struct RString s_str, d_str;
1645 	VALUE c, s, d = 0, args[4];
1646 	int state = 0, singleton = 0;
1647 	rb_encoding *usascii = rb_usascii_encoding();
1648 
1649 #define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
1650 	obj = ptr[NAME_ERR_MESG__RECV];
1651 	switch (obj) {
1652 	  case Qnil:
1653 	    d = FAKE_CSTR(&d_str, "nil");
1654 	    break;
1655 	  case Qtrue:
1656 	    d = FAKE_CSTR(&d_str, "true");
1657 	    break;
1658 	  case Qfalse:
1659 	    d = FAKE_CSTR(&d_str, "false");
1660 	    break;
1661 	  default:
1662 	    d = rb_protect(rb_inspect, obj, &state);
1663 	    if (state)
1664 		rb_set_errinfo(Qnil);
1665 	    if (NIL_P(d) || RSTRING_LEN(d) > 65) {
1666 		d = rb_any_to_s(obj);
1667 	    }
1668 	    singleton = (RSTRING_LEN(d) > 0 && RSTRING_PTR(d)[0] == '#');
1669 	    d = QUOTE(d);
1670 	    break;
1671 	}
1672 	if (!singleton) {
1673 	    s = FAKE_CSTR(&s_str, ":");
1674 	    c = rb_class_name(CLASS_OF(obj));
1675 	}
1676 	else {
1677 	    c = s = FAKE_CSTR(&s_str, "");
1678 	}
1679 	args[0] = QUOTE(rb_obj_as_string(ptr[NAME_ERR_MESG__NAME]));
1680 	args[1] = d;
1681 	args[2] = s;
1682 	args[3] = c;
1683 	mesg = rb_str_format(4, args, mesg);
1684     }
1685     return mesg;
1686 }
1687 
1688 /* :nodoc: */
1689 static VALUE
name_err_mesg_dump(VALUE obj,VALUE limit)1690 name_err_mesg_dump(VALUE obj, VALUE limit)
1691 {
1692     return name_err_mesg_to_str(obj);
1693 }
1694 
1695 /* :nodoc: */
1696 static VALUE
name_err_mesg_load(VALUE klass,VALUE str)1697 name_err_mesg_load(VALUE klass, VALUE str)
1698 {
1699     return str;
1700 }
1701 
1702 /*
1703  * call-seq:
1704  *   name_error.receiver  -> object
1705  *
1706  * Return the receiver associated with this NameError exception.
1707  */
1708 
1709 static VALUE
name_err_receiver(VALUE self)1710 name_err_receiver(VALUE self)
1711 {
1712     VALUE *ptr, recv, mesg;
1713 
1714     recv = rb_ivar_lookup(self, id_recv, Qundef);
1715     if (recv != Qundef) return recv;
1716 
1717     mesg = rb_attr_get(self, id_mesg);
1718     if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
1719 	rb_raise(rb_eArgError, "no receiver is available");
1720     }
1721     ptr = DATA_PTR(mesg);
1722     return ptr[NAME_ERR_MESG__RECV];
1723 }
1724 
1725 /*
1726  * call-seq:
1727  *   no_method_error.args  -> obj
1728  *
1729  * Return the arguments passed in as the third parameter to
1730  * the constructor.
1731  */
1732 
1733 static VALUE
nometh_err_args(VALUE self)1734 nometh_err_args(VALUE self)
1735 {
1736     return rb_attr_get(self, id_args);
1737 }
1738 
1739 /*
1740  * call-seq:
1741  *   no_method_error.private_call?  -> true or false
1742  *
1743  * Return true if the caused method was called as private.
1744  */
1745 
1746 static VALUE
nometh_err_private_call_p(VALUE self)1747 nometh_err_private_call_p(VALUE self)
1748 {
1749     return rb_attr_get(self, id_private_call_p);
1750 }
1751 
1752 void
rb_invalid_str(const char * str,const char * type)1753 rb_invalid_str(const char *str, const char *type)
1754 {
1755     VALUE s = rb_str_new2(str);
1756 
1757     rb_raise(rb_eArgError, "invalid value for %s: %+"PRIsVALUE, type, s);
1758 }
1759 
1760 /*
1761  * call-seq:
1762  *   key_error.receiver  -> object
1763  *
1764  * Return the receiver associated with this KeyError exception.
1765  */
1766 
1767 static VALUE
key_err_receiver(VALUE self)1768 key_err_receiver(VALUE self)
1769 {
1770     VALUE recv;
1771 
1772     recv = rb_ivar_lookup(self, id_receiver, Qundef);
1773     if (recv != Qundef) return recv;
1774     rb_raise(rb_eArgError, "no receiver is available");
1775 }
1776 
1777 /*
1778  * call-seq:
1779  *   key_error.key  -> object
1780  *
1781  * Return the key caused this KeyError exception.
1782  */
1783 
1784 static VALUE
key_err_key(VALUE self)1785 key_err_key(VALUE self)
1786 {
1787     VALUE key;
1788 
1789     key = rb_ivar_lookup(self, id_key, Qundef);
1790     if (key != Qundef) return key;
1791     rb_raise(rb_eArgError, "no key is available");
1792 }
1793 
1794 VALUE
rb_key_err_new(VALUE mesg,VALUE recv,VALUE key)1795 rb_key_err_new(VALUE mesg, VALUE recv, VALUE key)
1796 {
1797     VALUE exc = rb_obj_alloc(rb_eKeyError);
1798     rb_ivar_set(exc, id_mesg, mesg);
1799     rb_ivar_set(exc, id_bt, Qnil);
1800     rb_ivar_set(exc, id_key, key);
1801     rb_ivar_set(exc, id_receiver, recv);
1802     return exc;
1803 }
1804 
1805 /*
1806  * call-seq:
1807  *   KeyError.new(message=nil, receiver: nil, key: nil) -> key_error
1808  *
1809  * Construct a new +KeyError+ exception with the given message,
1810  * receiver and key.
1811  */
1812 
1813 static VALUE
key_err_initialize(int argc,VALUE * argv,VALUE self)1814 key_err_initialize(int argc, VALUE *argv, VALUE self)
1815 {
1816     VALUE options;
1817 
1818     rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
1819 
1820     if (!NIL_P(options)) {
1821 	ID keywords[2];
1822 	VALUE values[numberof(keywords)];
1823 	int i;
1824 	keywords[0] = id_receiver;
1825 	keywords[1] = id_key;
1826 	rb_get_kwargs(options, keywords, 0, numberof(values), values);
1827 	for (i = 0; i < numberof(values); ++i) {
1828 	    if (values[i] != Qundef) {
1829 		rb_ivar_set(self, keywords[i], values[i]);
1830 	    }
1831 	}
1832     }
1833 
1834     return self;
1835 }
1836 
1837 /*
1838  * call-seq:
1839  *   SyntaxError.new([msg])  -> syntax_error
1840  *
1841  * Construct a SyntaxError exception.
1842  */
1843 
1844 static VALUE
syntax_error_initialize(int argc,VALUE * argv,VALUE self)1845 syntax_error_initialize(int argc, VALUE *argv, VALUE self)
1846 {
1847     VALUE mesg;
1848     if (argc == 0) {
1849 	mesg = rb_fstring_lit("compile error");
1850 	argc = 1;
1851 	argv = &mesg;
1852     }
1853     return rb_call_super(argc, argv);
1854 }
1855 
1856 /*
1857  *  Document-module: Errno
1858  *
1859  *  Ruby exception objects are subclasses of <code>Exception</code>.
1860  *  However, operating systems typically report errors using plain
1861  *  integers. Module <code>Errno</code> is created dynamically to map
1862  *  these operating system errors to Ruby classes, with each error
1863  *  number generating its own subclass of <code>SystemCallError</code>.
1864  *  As the subclass is created in module <code>Errno</code>, its name
1865  *  will start <code>Errno::</code>.
1866  *
1867  *  The names of the <code>Errno::</code> classes depend on
1868  *  the environment in which Ruby runs. On a typical Unix or Windows
1869  *  platform, there are <code>Errno</code> classes such as
1870  *  <code>Errno::EACCES</code>, <code>Errno::EAGAIN</code>,
1871  *  <code>Errno::EINTR</code>, and so on.
1872  *
1873  *  The integer operating system error number corresponding to a
1874  *  particular error is available as the class constant
1875  *  <code>Errno::</code><em>error</em><code>::Errno</code>.
1876  *
1877  *     Errno::EACCES::Errno   #=> 13
1878  *     Errno::EAGAIN::Errno   #=> 11
1879  *     Errno::EINTR::Errno    #=> 4
1880  *
1881  *  The full list of operating system errors on your particular platform
1882  *  are available as the constants of <code>Errno</code>.
1883  *
1884  *     Errno.constants   #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
1885  */
1886 
1887 static st_table *syserr_tbl;
1888 
1889 static VALUE
set_syserr(int n,const char * name)1890 set_syserr(int n, const char *name)
1891 {
1892     st_data_t error;
1893 
1894     if (!st_lookup(syserr_tbl, n, &error)) {
1895 	error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
1896 
1897 	/* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
1898 	switch (n) {
1899 	  case EAGAIN:
1900 	    rb_eEAGAIN = error;
1901 
1902 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1903 	    break;
1904 	  case EWOULDBLOCK:
1905 #endif
1906 
1907 	    rb_eEWOULDBLOCK = error;
1908 	    break;
1909 	  case EINPROGRESS:
1910 	    rb_eEINPROGRESS = error;
1911 	    break;
1912 	}
1913 
1914 	rb_define_const(error, "Errno", INT2NUM(n));
1915 	st_add_direct(syserr_tbl, n, error);
1916     }
1917     else {
1918 	rb_define_const(rb_mErrno, name, error);
1919     }
1920     return error;
1921 }
1922 
1923 static VALUE
get_syserr(int n)1924 get_syserr(int n)
1925 {
1926     st_data_t error;
1927 
1928     if (!st_lookup(syserr_tbl, n, &error)) {
1929 	char name[8];	/* some Windows' errno have 5 digits. */
1930 
1931 	snprintf(name, sizeof(name), "E%03d", n);
1932 	error = set_syserr(n, name);
1933     }
1934     return error;
1935 }
1936 
1937 /*
1938  * call-seq:
1939  *   SystemCallError.new(msg, errno)  -> system_call_error_subclass
1940  *
1941  * If _errno_ corresponds to a known system error code, constructs
1942  * the appropriate <code>Errno</code> class for that error, otherwise
1943  * constructs a generic <code>SystemCallError</code> object. The
1944  * error number is subsequently available via the <code>errno</code>
1945  * method.
1946  */
1947 
1948 static VALUE
syserr_initialize(int argc,VALUE * argv,VALUE self)1949 syserr_initialize(int argc, VALUE *argv, VALUE self)
1950 {
1951 #if !defined(_WIN32)
1952     char *strerror();
1953 #endif
1954     const char *err;
1955     VALUE mesg, error, func, errmsg;
1956     VALUE klass = rb_obj_class(self);
1957 
1958     if (klass == rb_eSystemCallError) {
1959 	st_data_t data = (st_data_t)klass;
1960 	rb_scan_args(argc, argv, "12", &mesg, &error, &func);
1961 	if (argc == 1 && FIXNUM_P(mesg)) {
1962 	    error = mesg; mesg = Qnil;
1963 	}
1964 	if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
1965 	    klass = (VALUE)data;
1966 	    /* change class */
1967 	    if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
1968 		rb_raise(rb_eTypeError, "invalid instance type");
1969 	    }
1970 	    RBASIC_SET_CLASS(self, klass);
1971 	}
1972     }
1973     else {
1974 	rb_scan_args(argc, argv, "02", &mesg, &func);
1975 	error = rb_const_get(klass, id_Errno);
1976     }
1977     if (!NIL_P(error)) err = strerror(NUM2INT(error));
1978     else err = "unknown error";
1979 
1980     errmsg = rb_enc_str_new_cstr(err, rb_locale_encoding());
1981     if (!NIL_P(mesg)) {
1982 	VALUE str = StringValue(mesg);
1983 
1984 	if (!NIL_P(func)) rb_str_catf(errmsg, " @ %"PRIsVALUE, func);
1985 	rb_str_catf(errmsg, " - %"PRIsVALUE, str);
1986 	OBJ_INFECT(errmsg, mesg);
1987     }
1988     mesg = errmsg;
1989 
1990     rb_call_super(1, &mesg);
1991     rb_ivar_set(self, id_errno, error);
1992     return self;
1993 }
1994 
1995 /*
1996  * call-seq:
1997  *   system_call_error.errno   -> integer
1998  *
1999  * Return this SystemCallError's error number.
2000  */
2001 
2002 static VALUE
syserr_errno(VALUE self)2003 syserr_errno(VALUE self)
2004 {
2005     return rb_attr_get(self, id_errno);
2006 }
2007 
2008 /*
2009  * call-seq:
2010  *   system_call_error === other  -> true or false
2011  *
2012  * Return +true+ if the receiver is a generic +SystemCallError+, or
2013  * if the error numbers +self+ and _other_ are the same.
2014  */
2015 
2016 static VALUE
syserr_eqq(VALUE self,VALUE exc)2017 syserr_eqq(VALUE self, VALUE exc)
2018 {
2019     VALUE num, e;
2020 
2021     if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
2022 	if (!rb_respond_to(exc, id_errno)) return Qfalse;
2023     }
2024     else if (self == rb_eSystemCallError) return Qtrue;
2025 
2026     num = rb_attr_get(exc, id_errno);
2027     if (NIL_P(num)) {
2028 	num = rb_funcallv(exc, id_errno, 0, 0);
2029     }
2030     e = rb_const_get(self, id_Errno);
2031     if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
2032 	return Qtrue;
2033     return Qfalse;
2034 }
2035 
2036 
2037 /*
2038  *  Document-class: StandardError
2039  *
2040  *  The most standard error types are subclasses of StandardError. A
2041  *  rescue clause without an explicit Exception class will rescue all
2042  *  StandardErrors (and only those).
2043  *
2044  *     def foo
2045  *       raise "Oups"
2046  *     end
2047  *     foo rescue "Hello"   #=> "Hello"
2048  *
2049  *  On the other hand:
2050  *
2051  *     require 'does/not/exist' rescue "Hi"
2052  *
2053  *  <em>raises the exception:</em>
2054  *
2055  *     LoadError: no such file to load -- does/not/exist
2056  *
2057  */
2058 
2059 /*
2060  *  Document-class: SystemExit
2061  *
2062  *  Raised by +exit+ to initiate the termination of the script.
2063  */
2064 
2065 /*
2066  *  Document-class: SignalException
2067  *
2068  *  Raised when a signal is received.
2069  *
2070  *     begin
2071  *       Process.kill('HUP',Process.pid)
2072  *       sleep # wait for receiver to handle signal sent by Process.kill
2073  *     rescue SignalException => e
2074  *       puts "received Exception #{e}"
2075  *     end
2076  *
2077  *  <em>produces:</em>
2078  *
2079  *     received Exception SIGHUP
2080  */
2081 
2082 /*
2083  *  Document-class: Interrupt
2084  *
2085  *  Raised when the interrupt signal is received, typically because the
2086  *  user has pressed Control-C (on most posix platforms). As such, it is a
2087  *  subclass of +SignalException+.
2088  *
2089  *     begin
2090  *       puts "Press ctrl-C when you get bored"
2091  *       loop {}
2092  *     rescue Interrupt => e
2093  *       puts "Note: You will typically use Signal.trap instead."
2094  *     end
2095  *
2096  *  <em>produces:</em>
2097  *
2098  *     Press ctrl-C when you get bored
2099  *
2100  *  <em>then waits until it is interrupted with Control-C and then prints:</em>
2101  *
2102  *     Note: You will typically use Signal.trap instead.
2103  */
2104 
2105 /*
2106  *  Document-class: TypeError
2107  *
2108  *  Raised when encountering an object that is not of the expected type.
2109  *
2110  *     [1, 2, 3].first("two")
2111  *
2112  *  <em>raises the exception:</em>
2113  *
2114  *     TypeError: no implicit conversion of String into Integer
2115  *
2116  */
2117 
2118 /*
2119  *  Document-class: ArgumentError
2120  *
2121  *  Raised when the arguments are wrong and there isn't a more specific
2122  *  Exception class.
2123  *
2124  *  Ex: passing the wrong number of arguments
2125  *
2126  *     [1, 2, 3].first(4, 5)
2127  *
2128  *  <em>raises the exception:</em>
2129  *
2130  *     ArgumentError: wrong number of arguments (given 2, expected 1)
2131  *
2132  *  Ex: passing an argument that is not acceptable:
2133  *
2134  *     [1, 2, 3].first(-4)
2135  *
2136  *  <em>raises the exception:</em>
2137  *
2138  *     ArgumentError: negative array size
2139  */
2140 
2141 /*
2142  *  Document-class: IndexError
2143  *
2144  *  Raised when the given index is invalid.
2145  *
2146  *     a = [:foo, :bar]
2147  *     a.fetch(0)   #=> :foo
2148  *     a[4]         #=> nil
2149  *     a.fetch(4)   #=> IndexError: index 4 outside of array bounds: -2...2
2150  *
2151  */
2152 
2153 /*
2154  *  Document-class: KeyError
2155  *
2156  *  Raised when the specified key is not found. It is a subclass of
2157  *  IndexError.
2158  *
2159  *     h = {"foo" => :bar}
2160  *     h.fetch("foo") #=> :bar
2161  *     h.fetch("baz") #=> KeyError: key not found: "baz"
2162  *
2163  */
2164 
2165 /*
2166  *  Document-class: RangeError
2167  *
2168  *  Raised when a given numerical value is out of range.
2169  *
2170  *     [1, 2, 3].drop(1 << 100)
2171  *
2172  *  <em>raises the exception:</em>
2173  *
2174  *     RangeError: bignum too big to convert into `long'
2175  */
2176 
2177 /*
2178  *  Document-class: ScriptError
2179  *
2180  *  ScriptError is the superclass for errors raised when a script
2181  *  can not be executed because of a +LoadError+,
2182  *  +NotImplementedError+ or a +SyntaxError+. Note these type of
2183  *  +ScriptErrors+ are not +StandardError+ and will not be
2184  *  rescued unless it is specified explicitly (or its ancestor
2185  *  +Exception+).
2186  */
2187 
2188 /*
2189  *  Document-class: SyntaxError
2190  *
2191  *  Raised when encountering Ruby code with an invalid syntax.
2192  *
2193  *     eval("1+1=2")
2194  *
2195  *  <em>raises the exception:</em>
2196  *
2197  *     SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
2198  */
2199 
2200 /*
2201  *  Document-class: LoadError
2202  *
2203  *  Raised when a file required (a Ruby script, extension library, ...)
2204  *  fails to load.
2205  *
2206  *     require 'this/file/does/not/exist'
2207  *
2208  *  <em>raises the exception:</em>
2209  *
2210  *     LoadError: no such file to load -- this/file/does/not/exist
2211  */
2212 
2213 /*
2214  *  Document-class: NotImplementedError
2215  *
2216  *  Raised when a feature is not implemented on the current platform. For
2217  *  example, methods depending on the +fsync+ or +fork+ system calls may
2218  *  raise this exception if the underlying operating system or Ruby
2219  *  runtime does not support them.
2220  *
2221  *  Note that if +fork+ raises a +NotImplementedError+, then
2222  *  <code>respond_to?(:fork)</code> returns +false+.
2223  */
2224 
2225 /*
2226  *  Document-class: NameError
2227  *
2228  *  Raised when a given name is invalid or undefined.
2229  *
2230  *     puts foo
2231  *
2232  *  <em>raises the exception:</em>
2233  *
2234  *     NameError: undefined local variable or method `foo' for main:Object
2235  *
2236  *  Since constant names must start with a capital:
2237  *
2238  *     Integer.const_set :answer, 42
2239  *
2240  *  <em>raises the exception:</em>
2241  *
2242  *     NameError: wrong constant name answer
2243  */
2244 
2245 /*
2246  *  Document-class: NoMethodError
2247  *
2248  *  Raised when a method is called on a receiver which doesn't have it
2249  *  defined and also fails to respond with +method_missing+.
2250  *
2251  *     "hello".to_ary
2252  *
2253  *  <em>raises the exception:</em>
2254  *
2255  *     NoMethodError: undefined method `to_ary' for "hello":String
2256  */
2257 
2258 /*
2259  *  Document-class: FrozenError
2260  *
2261  *  Raised when there is an attempt to modify a frozen object.
2262  *
2263  *     [1, 2, 3].freeze << 4
2264  *
2265  *  <em>raises the exception:</em>
2266  *
2267  *     FrozenError: can't modify frozen Array
2268  */
2269 
2270 /*
2271  *  Document-class: RuntimeError
2272  *
2273  *  A generic error class raised when an invalid operation is attempted.
2274  *  Kernel#raise will raise a RuntimeError if no Exception class is
2275  *  specified.
2276  *
2277  *     raise "ouch"
2278  *
2279  *  <em>raises the exception:</em>
2280  *
2281  *     RuntimeError: ouch
2282  */
2283 
2284 /*
2285  *  Document-class: SecurityError
2286  *
2287  *  Raised when attempting a potential unsafe operation, typically when
2288  *  the $SAFE level is raised above 0.
2289  *
2290  *     foo = "bar"
2291  *     proc = Proc.new do
2292  *       $SAFE = 3
2293  *       foo.untaint
2294  *     end
2295  *     proc.call
2296  *
2297  *  <em>raises the exception:</em>
2298  *
2299  *     SecurityError: Insecure: Insecure operation `untaint' at level 3
2300  */
2301 
2302 /*
2303  *  Document-class: NoMemoryError
2304  *
2305  *  Raised when memory allocation fails.
2306  */
2307 
2308 /*
2309  *  Document-class: SystemCallError
2310  *
2311  *  SystemCallError is the base class for all low-level
2312  *  platform-dependent errors.
2313  *
2314  *  The errors available on the current platform are subclasses of
2315  *  SystemCallError and are defined in the Errno module.
2316  *
2317  *     File.open("does/not/exist")
2318  *
2319  *  <em>raises the exception:</em>
2320  *
2321  *     Errno::ENOENT: No such file or directory - does/not/exist
2322  */
2323 
2324 /*
2325  * Document-class: EncodingError
2326  *
2327  * EncodingError is the base class for encoding errors.
2328  */
2329 
2330 /*
2331  *  Document-class: Encoding::CompatibilityError
2332  *
2333  *  Raised by Encoding and String methods when the source encoding is
2334  *  incompatible with the target encoding.
2335  */
2336 
2337 /*
2338  * Document-class: fatal
2339  *
2340  * fatal is an Exception that is raised when Ruby has encountered a fatal
2341  * error and must exit.  You are not able to rescue fatal.
2342  */
2343 
2344 /*
2345  * Document-class: NameError::message
2346  * :nodoc:
2347  */
2348 
2349 /*
2350  *  Descendants of class Exception are used to communicate between
2351  *  Kernel#raise and +rescue+ statements in <code>begin ... end</code> blocks.
2352  *  Exception objects carry information about the exception -- its type (the
2353  *  exception's class name), an optional descriptive string, and optional
2354  *  traceback information.  Exception subclasses may add additional
2355  *  information like NameError#name.
2356  *
2357  *  Programs may make subclasses of Exception, typically of StandardError or
2358  *  RuntimeError, to provide custom classes and add additional information.
2359  *  See the subclass list below for defaults for +raise+ and +rescue+.
2360  *
2361  *  When an exception has been raised but not yet handled (in +rescue+,
2362  *  +ensure+, +at_exit+ and +END+ blocks) the global variable <code>$!</code>
2363  *  will contain the current exception and <code>$@</code> contains the
2364  *  current exception's backtrace.
2365  *
2366  *  It is recommended that a library should have one subclass of StandardError
2367  *  or RuntimeError and have specific exception types inherit from it.  This
2368  *  allows the user to rescue a generic exception type to catch all exceptions
2369  *  the library may raise even if future versions of the library add new
2370  *  exception subclasses.
2371  *
2372  *  For example:
2373  *
2374  *    class MyLibrary
2375  *      class Error < RuntimeError
2376  *      end
2377  *
2378  *      class WidgetError < Error
2379  *      end
2380  *
2381  *      class FrobError < Error
2382  *      end
2383  *
2384  *    end
2385  *
2386  *  To handle both WidgetError and FrobError the library user can rescue
2387  *  MyLibrary::Error.
2388  *
2389  *  The built-in subclasses of Exception are:
2390  *
2391  *  * NoMemoryError
2392  *  * ScriptError
2393  *    * LoadError
2394  *    * NotImplementedError
2395  *    * SyntaxError
2396  *  * SecurityError
2397  *  * SignalException
2398  *    * Interrupt
2399  *  * StandardError -- default for +rescue+
2400  *    * ArgumentError
2401  *      * UncaughtThrowError
2402  *    * EncodingError
2403  *    * FiberError
2404  *    * IOError
2405  *      * EOFError
2406  *    * IndexError
2407  *      * KeyError
2408  *      * StopIteration
2409  *    * LocalJumpError
2410  *    * NameError
2411  *      * NoMethodError
2412  *    * RangeError
2413  *      * FloatDomainError
2414  *    * RegexpError
2415  *    * RuntimeError -- default for +raise+
2416  *      * FrozenError
2417  *    * SystemCallError
2418  *      * Errno::*
2419  *    * ThreadError
2420  *    * TypeError
2421  *    * ZeroDivisionError
2422  *  * SystemExit
2423  *  * SystemStackError
2424  *  * fatal -- impossible to rescue
2425  */
2426 
2427 void
Init_Exception(void)2428 Init_Exception(void)
2429 {
2430     rb_eException   = rb_define_class("Exception", rb_cObject);
2431     rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
2432     rb_define_singleton_method(rb_eException, "to_tty?", exc_s_to_tty_p, 0);
2433     rb_define_method(rb_eException, "exception", exc_exception, -1);
2434     rb_define_method(rb_eException, "initialize", exc_initialize, -1);
2435     rb_define_method(rb_eException, "==", exc_equal, 1);
2436     rb_define_method(rb_eException, "to_s", exc_to_s, 0);
2437     rb_define_method(rb_eException, "message", exc_message, 0);
2438     rb_define_method(rb_eException, "full_message", exc_full_message, -1);
2439     rb_define_method(rb_eException, "inspect", exc_inspect, 0);
2440     rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
2441     rb_define_method(rb_eException, "backtrace_locations", exc_backtrace_locations, 0);
2442     rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
2443     rb_define_method(rb_eException, "cause", exc_cause, 0);
2444 
2445     rb_eSystemExit  = rb_define_class("SystemExit", rb_eException);
2446     rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
2447     rb_define_method(rb_eSystemExit, "status", exit_status, 0);
2448     rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
2449 
2450     rb_eFatal  	    = rb_define_class("fatal", rb_eException);
2451     rb_eSignal      = rb_define_class("SignalException", rb_eException);
2452     rb_eInterrupt   = rb_define_class("Interrupt", rb_eSignal);
2453 
2454     rb_eStandardError = rb_define_class("StandardError", rb_eException);
2455     rb_eTypeError     = rb_define_class("TypeError", rb_eStandardError);
2456     rb_eArgError      = rb_define_class("ArgumentError", rb_eStandardError);
2457     rb_eIndexError    = rb_define_class("IndexError", rb_eStandardError);
2458     rb_eKeyError      = rb_define_class("KeyError", rb_eIndexError);
2459     rb_define_method(rb_eKeyError, "initialize", key_err_initialize, -1);
2460     rb_define_method(rb_eKeyError, "receiver", key_err_receiver, 0);
2461     rb_define_method(rb_eKeyError, "key", key_err_key, 0);
2462     rb_eRangeError    = rb_define_class("RangeError", rb_eStandardError);
2463 
2464     rb_eScriptError = rb_define_class("ScriptError", rb_eException);
2465     rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
2466     rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);
2467 
2468     rb_eLoadError   = rb_define_class("LoadError", rb_eScriptError);
2469     /* the path failed to load */
2470     rb_attr(rb_eLoadError, rb_intern_const("path"), 1, 0, Qfalse);
2471 
2472     rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
2473 
2474     rb_eNameError     = rb_define_class("NameError", rb_eStandardError);
2475     rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
2476     rb_define_method(rb_eNameError, "name", name_err_name, 0);
2477     rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0);
2478     rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0);
2479     rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
2480     rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
2481     rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
2482     rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_dump, 1);
2483     rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
2484     rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
2485     rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
2486     rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
2487     rb_define_method(rb_eNoMethodError, "private_call?", nometh_err_private_call_p, 0);
2488 
2489     rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
2490     rb_eFrozenError = rb_define_class("FrozenError", rb_eRuntimeError);
2491     rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
2492     rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
2493     rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
2494     rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
2495 
2496     syserr_tbl = st_init_numtable();
2497     rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
2498     rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
2499     rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
2500     rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
2501 
2502     rb_mErrno = rb_define_module("Errno");
2503 
2504     rb_mWarning = rb_define_module("Warning");
2505     rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, 1);
2506     rb_extend_object(rb_mWarning, rb_mWarning);
2507 
2508     /* :nodoc: */
2509     rb_cWarningBuffer = rb_define_class_under(rb_mWarning, "buffer", rb_cString);
2510     rb_define_method(rb_cWarningBuffer, "write", warning_write, -1);
2511 
2512     rb_define_global_function("warn", rb_warn_m, -1);
2513 
2514     id_cause = rb_intern_const("cause");
2515     id_message = rb_intern_const("message");
2516     id_backtrace = rb_intern_const("backtrace");
2517     id_name = rb_intern_const("name");
2518     id_key = rb_intern_const("key");
2519     id_args = rb_intern_const("args");
2520     id_receiver = rb_intern_const("receiver");
2521     id_private_call_p = rb_intern_const("private_call?");
2522     id_local_variables = rb_intern_const("local_variables");
2523     id_Errno = rb_intern_const("Errno");
2524     id_errno = rb_intern_const("errno");
2525     id_i_path = rb_intern_const("@path");
2526     id_warn = rb_intern_const("warn");
2527     id_top = rb_intern_const("top");
2528     id_bottom = rb_intern_const("bottom");
2529     id_iseq = rb_make_internal_id();
2530     id_recv = rb_make_internal_id();
2531 }
2532 
2533 void
rb_enc_raise(rb_encoding * enc,VALUE exc,const char * fmt,...)2534 rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
2535 {
2536     va_list args;
2537     VALUE mesg;
2538 
2539     va_start(args, fmt);
2540     mesg = rb_enc_vsprintf(enc, fmt, args);
2541     va_end(args);
2542 
2543     rb_exc_raise(rb_exc_new3(exc, mesg));
2544 }
2545 
2546 void
rb_raise(VALUE exc,const char * fmt,...)2547 rb_raise(VALUE exc, const char *fmt, ...)
2548 {
2549     va_list args;
2550     VALUE mesg;
2551 
2552     va_start(args, fmt);
2553     mesg = rb_vsprintf(fmt, args);
2554     va_end(args);
2555     rb_exc_raise(rb_exc_new3(exc, mesg));
2556 }
2557 
2558 NORETURN(static void raise_loaderror(VALUE path, VALUE mesg));
2559 
2560 static void
raise_loaderror(VALUE path,VALUE mesg)2561 raise_loaderror(VALUE path, VALUE mesg)
2562 {
2563     VALUE err = rb_exc_new3(rb_eLoadError, mesg);
2564     rb_ivar_set(err, id_i_path, path);
2565     rb_exc_raise(err);
2566 }
2567 
2568 void
rb_loaderror(const char * fmt,...)2569 rb_loaderror(const char *fmt, ...)
2570 {
2571     va_list args;
2572     VALUE mesg;
2573 
2574     va_start(args, fmt);
2575     mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
2576     va_end(args);
2577     raise_loaderror(Qnil, mesg);
2578 }
2579 
2580 void
rb_loaderror_with_path(VALUE path,const char * fmt,...)2581 rb_loaderror_with_path(VALUE path, const char *fmt, ...)
2582 {
2583     va_list args;
2584     VALUE mesg;
2585 
2586     va_start(args, fmt);
2587     mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
2588     va_end(args);
2589     raise_loaderror(path, mesg);
2590 }
2591 
2592 void
rb_notimplement(void)2593 rb_notimplement(void)
2594 {
2595     rb_raise(rb_eNotImpError,
2596 	     "%"PRIsVALUE"() function is unimplemented on this machine",
2597 	     rb_id2str(rb_frame_this_func()));
2598 }
2599 
2600 void
rb_fatal(const char * fmt,...)2601 rb_fatal(const char *fmt, ...)
2602 {
2603     va_list args;
2604     VALUE mesg;
2605 
2606     va_start(args, fmt);
2607     mesg = rb_vsprintf(fmt, args);
2608     va_end(args);
2609 
2610     rb_exc_fatal(rb_exc_new3(rb_eFatal, mesg));
2611 }
2612 
2613 static VALUE
make_errno_exc(const char * mesg)2614 make_errno_exc(const char *mesg)
2615 {
2616     int n = errno;
2617 
2618     errno = 0;
2619     if (n == 0) {
2620 	rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
2621     }
2622     return rb_syserr_new(n, mesg);
2623 }
2624 
2625 static VALUE
make_errno_exc_str(VALUE mesg)2626 make_errno_exc_str(VALUE mesg)
2627 {
2628     int n = errno;
2629 
2630     errno = 0;
2631     if (!mesg) mesg = Qnil;
2632     if (n == 0) {
2633 	const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
2634 	rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
2635     }
2636     return rb_syserr_new_str(n, mesg);
2637 }
2638 
2639 VALUE
rb_syserr_new(int n,const char * mesg)2640 rb_syserr_new(int n, const char *mesg)
2641 {
2642     VALUE arg;
2643     arg = mesg ? rb_str_new2(mesg) : Qnil;
2644     return rb_syserr_new_str(n, arg);
2645 }
2646 
2647 VALUE
rb_syserr_new_str(int n,VALUE arg)2648 rb_syserr_new_str(int n, VALUE arg)
2649 {
2650     return rb_class_new_instance(1, &arg, get_syserr(n));
2651 }
2652 
2653 void
rb_syserr_fail(int e,const char * mesg)2654 rb_syserr_fail(int e, const char *mesg)
2655 {
2656     rb_exc_raise(rb_syserr_new(e, mesg));
2657 }
2658 
2659 void
rb_syserr_fail_str(int e,VALUE mesg)2660 rb_syserr_fail_str(int e, VALUE mesg)
2661 {
2662     rb_exc_raise(rb_syserr_new_str(e, mesg));
2663 }
2664 
2665 void
rb_sys_fail(const char * mesg)2666 rb_sys_fail(const char *mesg)
2667 {
2668     rb_exc_raise(make_errno_exc(mesg));
2669 }
2670 
2671 void
rb_sys_fail_str(VALUE mesg)2672 rb_sys_fail_str(VALUE mesg)
2673 {
2674     rb_exc_raise(make_errno_exc_str(mesg));
2675 }
2676 
2677 #ifdef RUBY_FUNCTION_NAME_STRING
2678 void
rb_sys_fail_path_in(const char * func_name,VALUE path)2679 rb_sys_fail_path_in(const char *func_name, VALUE path)
2680 {
2681     int n = errno;
2682 
2683     errno = 0;
2684     rb_syserr_fail_path_in(func_name, n, path);
2685 }
2686 
2687 void
rb_syserr_fail_path_in(const char * func_name,int n,VALUE path)2688 rb_syserr_fail_path_in(const char *func_name, int n, VALUE path)
2689 {
2690     VALUE args[2];
2691 
2692     if (!path) path = Qnil;
2693     if (n == 0) {
2694 	const char *s = !NIL_P(path) ? RSTRING_PTR(path) : "";
2695 	if (!func_name) func_name = "(null)";
2696 	rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
2697 	       func_name, s);
2698     }
2699     args[0] = path;
2700     args[1] = rb_str_new_cstr(func_name);
2701     rb_exc_raise(rb_class_new_instance(2, args, get_syserr(n)));
2702 }
2703 #endif
2704 
2705 void
rb_mod_sys_fail(VALUE mod,const char * mesg)2706 rb_mod_sys_fail(VALUE mod, const char *mesg)
2707 {
2708     VALUE exc = make_errno_exc(mesg);
2709     rb_extend_object(exc, mod);
2710     rb_exc_raise(exc);
2711 }
2712 
2713 void
rb_mod_sys_fail_str(VALUE mod,VALUE mesg)2714 rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
2715 {
2716     VALUE exc = make_errno_exc_str(mesg);
2717     rb_extend_object(exc, mod);
2718     rb_exc_raise(exc);
2719 }
2720 
2721 void
rb_mod_syserr_fail(VALUE mod,int e,const char * mesg)2722 rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
2723 {
2724     VALUE exc = rb_syserr_new(e, mesg);
2725     rb_extend_object(exc, mod);
2726     rb_exc_raise(exc);
2727 }
2728 
2729 void
rb_mod_syserr_fail_str(VALUE mod,int e,VALUE mesg)2730 rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
2731 {
2732     VALUE exc = rb_syserr_new_str(e, mesg);
2733     rb_extend_object(exc, mod);
2734     rb_exc_raise(exc);
2735 }
2736 
2737 static void
syserr_warning(VALUE mesg,int err)2738 syserr_warning(VALUE mesg, int err)
2739 {
2740     rb_str_set_len(mesg, RSTRING_LEN(mesg)-1);
2741     rb_str_catf(mesg, ": %s\n", strerror(err));
2742     rb_write_warning_str(mesg);
2743 }
2744 
2745 #if 0
2746 void
2747 rb_sys_warn(const char *fmt, ...)
2748 {
2749     if (!NIL_P(ruby_verbose)) {
2750 	int errno_save = errno;
2751 	with_warning_string(mesg, 0, fmt) {
2752 	    syserr_warning(mesg, errno_save);
2753 	}
2754 	errno = errno_save;
2755     }
2756 }
2757 
2758 void
2759 rb_syserr_warn(int err, const char *fmt, ...)
2760 {
2761     if (!NIL_P(ruby_verbose)) {
2762 	with_warning_string(mesg, 0, fmt) {
2763 	    syserr_warning(mesg, err);
2764 	}
2765     }
2766 }
2767 
2768 void
2769 rb_sys_enc_warn(rb_encoding *enc, const char *fmt, ...)
2770 {
2771     if (!NIL_P(ruby_verbose)) {
2772 	int errno_save = errno;
2773 	with_warning_string(mesg, enc, fmt) {
2774 	    syserr_warning(mesg, errno_save);
2775 	}
2776 	errno = errno_save;
2777     }
2778 }
2779 
2780 void
2781 rb_syserr_enc_warn(int err, rb_encoding *enc, const char *fmt, ...)
2782 {
2783     if (!NIL_P(ruby_verbose)) {
2784 	with_warning_string(mesg, enc, fmt) {
2785 	    syserr_warning(mesg, err);
2786 	}
2787     }
2788 }
2789 #endif
2790 
2791 void
rb_sys_warning(const char * fmt,...)2792 rb_sys_warning(const char *fmt, ...)
2793 {
2794     if (RTEST(ruby_verbose)) {
2795 	int errno_save = errno;
2796 	with_warning_string(mesg, 0, fmt) {
2797 	    syserr_warning(mesg, errno_save);
2798 	}
2799 	errno = errno_save;
2800     }
2801 }
2802 
2803 #if 0
2804 void
2805 rb_syserr_warning(int err, const char *fmt, ...)
2806 {
2807     if (RTEST(ruby_verbose)) {
2808 	with_warning_string(mesg, 0, fmt) {
2809 	    syserr_warning(mesg, err);
2810 	}
2811     }
2812 }
2813 #endif
2814 
2815 void
rb_sys_enc_warning(rb_encoding * enc,const char * fmt,...)2816 rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...)
2817 {
2818     if (RTEST(ruby_verbose)) {
2819 	int errno_save = errno;
2820 	with_warning_string(mesg, enc, fmt) {
2821 	    syserr_warning(mesg, errno_save);
2822 	}
2823 	errno = errno_save;
2824     }
2825 }
2826 
2827 void
rb_syserr_enc_warning(int err,rb_encoding * enc,const char * fmt,...)2828 rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...)
2829 {
2830     if (RTEST(ruby_verbose)) {
2831 	with_warning_string(mesg, enc, fmt) {
2832 	    syserr_warning(mesg, err);
2833 	}
2834     }
2835 }
2836 
2837 void
rb_load_fail(VALUE path,const char * err)2838 rb_load_fail(VALUE path, const char *err)
2839 {
2840     VALUE mesg = rb_str_buf_new_cstr(err);
2841     rb_str_cat2(mesg, " -- ");
2842     rb_str_append(mesg, path);	/* should be ASCII compatible */
2843     raise_loaderror(path, mesg);
2844 }
2845 
2846 void
rb_error_frozen(const char * what)2847 rb_error_frozen(const char *what)
2848 {
2849     rb_raise(rb_eFrozenError, "can't modify frozen %s", what);
2850 }
2851 
2852 void
rb_error_frozen_object(VALUE frozen_obj)2853 rb_error_frozen_object(VALUE frozen_obj)
2854 {
2855     VALUE debug_info;
2856     const ID created_info = id_debug_created_info;
2857 
2858     if (!NIL_P(debug_info = rb_attr_get(frozen_obj, created_info))) {
2859 	VALUE path = rb_ary_entry(debug_info, 0);
2860 	VALUE line = rb_ary_entry(debug_info, 1);
2861 
2862 	rb_raise(rb_eFrozenError, "can't modify frozen %"PRIsVALUE", created at %"PRIsVALUE":%"PRIsVALUE,
2863 		 CLASS_OF(frozen_obj), path, line);
2864     }
2865     else {
2866 	rb_raise(rb_eFrozenError, "can't modify frozen %"PRIsVALUE,
2867 		 CLASS_OF(frozen_obj));
2868     }
2869 }
2870 
2871 #undef rb_check_frozen
2872 void
rb_check_frozen(VALUE obj)2873 rb_check_frozen(VALUE obj)
2874 {
2875     rb_check_frozen_internal(obj);
2876 }
2877 
2878 void
rb_error_untrusted(VALUE obj)2879 rb_error_untrusted(VALUE obj)
2880 {
2881 }
2882 
2883 #undef rb_check_trusted
2884 void
rb_check_trusted(VALUE obj)2885 rb_check_trusted(VALUE obj)
2886 {
2887 }
2888 
2889 void
rb_check_copyable(VALUE obj,VALUE orig)2890 rb_check_copyable(VALUE obj, VALUE orig)
2891 {
2892     if (!FL_ABLE(obj)) return;
2893     rb_check_frozen_internal(obj);
2894     if (!FL_ABLE(orig)) return;
2895     if ((~RBASIC(obj)->flags & RBASIC(orig)->flags) & FL_TAINT) {
2896 	if (rb_safe_level() > 0) {
2897 	    rb_raise(rb_eSecurityError, "Insecure: can't modify %"PRIsVALUE,
2898 		     RBASIC(obj)->klass);
2899 	}
2900     }
2901 }
2902 
2903 void
Init_syserr(void)2904 Init_syserr(void)
2905 {
2906     rb_eNOERROR = set_syserr(0, "NOERROR");
2907 #define defined_error(name, num) set_syserr((num), (name));
2908 #define undefined_error(name) set_syserr(0, (name));
2909 #include "known_errors.inc"
2910 #undef defined_error
2911 #undef undefined_error
2912 }
2913 
2914 /*!
2915  * \}
2916  */
2917