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