00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "ruby/st.h"
00014 #include "ruby/encoding.h"
00015 #include "internal.h"
00016 #include "vm_core.h"
00017
00018 #include <stdio.h>
00019 #include <stdarg.h>
00020 #ifdef HAVE_STDLIB_H
00021 #include <stdlib.h>
00022 #endif
00023 #include <errno.h>
00024 #ifdef HAVE_UNISTD_H
00025 #include <unistd.h>
00026 #endif
00027
00028 #ifndef EXIT_SUCCESS
00029 #define EXIT_SUCCESS 0
00030 #endif
00031
00032 #ifndef WIFEXITED
00033 #define WIFEXITED(status) 1
00034 #endif
00035
00036 #ifndef WEXITSTATUS
00037 #define WEXITSTATUS(status) (status)
00038 #endif
00039
00040 extern const char ruby_description[];
00041
00042 #define REPORTBUG_MSG \
00043 "[NOTE]\n" \
00044 "You may have encountered a bug in the Ruby interpreter" \
00045 " or extension libraries.\n" \
00046 "Bug reports are welcome.\n" \
00047 "For details: http://www.ruby-lang.org/bugreport.html\n\n" \
00048
00049 static const char *
00050 rb_strerrno(int err)
00051 {
00052 #define defined_error(name, num) if (err == (num)) return (name);
00053 #define undefined_error(name)
00054 #include "known_errors.inc"
00055 #undef defined_error
00056 #undef undefined_error
00057 return NULL;
00058 }
00059
00060 static int
00061 err_position_0(char *buf, long len, const char *file, int line)
00062 {
00063 if (!file) {
00064 return 0;
00065 }
00066 else if (line == 0) {
00067 return snprintf(buf, len, "%s: ", file);
00068 }
00069 else {
00070 return snprintf(buf, len, "%s:%d: ", file, line);
00071 }
00072 }
00073
00074 static int
00075 err_position(char *buf, long len)
00076 {
00077 return err_position_0(buf, len, rb_sourcefile(), rb_sourceline());
00078 }
00079
00080 static void
00081 err_snprintf(char *buf, long len, const char *fmt, va_list args)
00082 {
00083 long n;
00084
00085 n = err_position(buf, len);
00086 if (len > n) {
00087 vsnprintf((char*)buf+n, len-n, fmt, args);
00088 }
00089 }
00090
00091 static void
00092 compile_snprintf(char *buf, long len, const char *file, int line, const char *fmt, va_list args)
00093 {
00094 long n;
00095
00096 n = err_position_0(buf, len, file, line);
00097 if (len > n) {
00098 vsnprintf((char*)buf+n, len-n, fmt, args);
00099 }
00100 }
00101
00102 static void err_append(const char*, rb_encoding *);
00103
00104 void
00105 rb_compile_error_with_enc(const char *file, int line, void *enc, const char *fmt, ...)
00106 {
00107 va_list args;
00108 char buf[BUFSIZ];
00109
00110 va_start(args, fmt);
00111 compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
00112 va_end(args);
00113 err_append(buf, (rb_encoding *)enc);
00114 }
00115
00116 void
00117 rb_compile_error(const char *file, int line, const char *fmt, ...)
00118 {
00119 va_list args;
00120 char buf[BUFSIZ];
00121
00122 va_start(args, fmt);
00123 compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
00124 va_end(args);
00125 err_append(buf, NULL);
00126 }
00127
00128 void
00129 rb_compile_error_append(const char *fmt, ...)
00130 {
00131 va_list args;
00132 char buf[BUFSIZ];
00133
00134 va_start(args, fmt);
00135 vsnprintf(buf, BUFSIZ, fmt, args);
00136 va_end(args);
00137 err_append(buf, NULL);
00138 }
00139
00140 static void
00141 compile_warn_print(const char *file, int line, const char *fmt, va_list args)
00142 {
00143 char buf[BUFSIZ];
00144 int len;
00145
00146 compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
00147 len = (int)strlen(buf);
00148 buf[len++] = '\n';
00149 rb_write_error2(buf, len);
00150 }
00151
00152 void
00153 rb_compile_warn(const char *file, int line, const char *fmt, ...)
00154 {
00155 char buf[BUFSIZ];
00156 va_list args;
00157
00158 if (NIL_P(ruby_verbose)) return;
00159
00160 snprintf(buf, BUFSIZ, "warning: %s", fmt);
00161
00162 va_start(args, fmt);
00163 compile_warn_print(file, line, buf, args);
00164 va_end(args);
00165 }
00166
00167
00168 void
00169 rb_compile_warning(const char *file, int line, const char *fmt, ...)
00170 {
00171 char buf[BUFSIZ];
00172 va_list args;
00173
00174 if (!RTEST(ruby_verbose)) return;
00175
00176 snprintf(buf, BUFSIZ, "warning: %s", fmt);
00177
00178 va_start(args, fmt);
00179 compile_warn_print(file, line, buf, args);
00180 va_end(args);
00181 }
00182
00183 static void
00184 warn_print(const char *fmt, va_list args)
00185 {
00186 char buf[BUFSIZ];
00187 int len;
00188
00189 err_snprintf(buf, BUFSIZ, fmt, args);
00190 len = (int)strlen(buf);
00191 buf[len++] = '\n';
00192 rb_write_error2(buf, len);
00193 }
00194
00195 void
00196 rb_warn(const char *fmt, ...)
00197 {
00198 char buf[BUFSIZ];
00199 va_list args;
00200
00201 if (NIL_P(ruby_verbose)) return;
00202
00203 snprintf(buf, BUFSIZ, "warning: %s", fmt);
00204
00205 va_start(args, fmt);
00206 warn_print(buf, args);
00207 va_end(args);
00208 }
00209
00210
00211 void
00212 rb_warning(const char *fmt, ...)
00213 {
00214 char buf[BUFSIZ];
00215 va_list args;
00216
00217 if (!RTEST(ruby_verbose)) return;
00218
00219 snprintf(buf, BUFSIZ, "warning: %s", fmt);
00220
00221 va_start(args, fmt);
00222 warn_print(buf, args);
00223 va_end(args);
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static VALUE
00235 rb_warn_m(VALUE self, VALUE mesg)
00236 {
00237 if (!NIL_P(ruby_verbose)) {
00238 rb_io_write(rb_stderr, mesg);
00239 rb_io_write(rb_stderr, rb_default_rs);
00240 }
00241 return Qnil;
00242 }
00243
00244 static void
00245 report_bug(const char *file, int line, const char *fmt, va_list args)
00246 {
00247 char buf[BUFSIZ];
00248 FILE *out = stderr;
00249 int len = err_position_0(buf, BUFSIZ, file, line);
00250
00251 if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len ||
00252 (ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) {
00253
00254 fputs("[BUG] ", out);
00255 vfprintf(out, fmt, args);
00256 fprintf(out, "\n%s\n\n", ruby_description);
00257
00258 rb_vm_bugreport();
00259
00260 fprintf(out, REPORTBUG_MSG);
00261 }
00262 }
00263
00264 void
00265 rb_bug(const char *fmt, ...)
00266 {
00267 va_list args;
00268 const char *file = NULL;
00269 int line = 0;
00270
00271 if (GET_THREAD()) {
00272 file = rb_sourcefile();
00273 line = rb_sourceline();
00274 }
00275
00276 va_start(args, fmt);
00277 report_bug(file, line, fmt, args);
00278 va_end(args);
00279
00280 #if defined(_WIN32) && defined(RT_VER) && RT_VER >= 80
00281 _set_abort_behavior( 0, _CALL_REPORTFAULT);
00282 #endif
00283
00284 abort();
00285 }
00286
00287 void
00288 rb_bug_errno(const char *mesg, int errno_arg)
00289 {
00290 if (errno_arg == 0)
00291 rb_bug("%s: errno == 0 (NOERROR)", mesg);
00292 else {
00293 const char *errno_str = rb_strerrno(errno_arg);
00294 if (errno_str)
00295 rb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
00296 else
00297 rb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
00298 }
00299 }
00300
00301
00302
00303
00304
00305 #define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
00306 #define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
00307
00308 void
00309 rb_async_bug_errno(const char *mesg, int errno_arg)
00310 {
00311 WRITE_CONST(2, "[ASYNC BUG] ");
00312 write_or_abort(2, mesg, strlen(mesg));
00313 WRITE_CONST(2, "\n");
00314
00315 if (errno_arg == 0) {
00316 WRITE_CONST(2, "errno == 0 (NOERROR)\n");
00317 }
00318 else {
00319 const char *errno_str = rb_strerrno(errno_arg);
00320
00321 if (!errno_str)
00322 errno_str = "undefined errno";
00323 write_or_abort(2, errno_str, strlen(errno_str));
00324 }
00325 WRITE_CONST(2, "\n\n");
00326 write_or_abort(2, ruby_description, strlen(ruby_description));
00327 WRITE_CONST(2, "\n\n");
00328 WRITE_CONST(2, REPORTBUG_MSG);
00329 abort();
00330 }
00331
00332 void
00333 rb_compile_bug(const char *file, int line, const char *fmt, ...)
00334 {
00335 va_list args;
00336
00337 va_start(args, fmt);
00338 report_bug(file, line, fmt, args);
00339 va_end(args);
00340
00341 abort();
00342 }
00343
00344 static const struct types {
00345 int type;
00346 const char *name;
00347 } builtin_types[] = {
00348 {T_NIL, "nil"},
00349 {T_OBJECT, "Object"},
00350 {T_CLASS, "Class"},
00351 {T_ICLASS, "iClass"},
00352 {T_MODULE, "Module"},
00353 {T_FLOAT, "Float"},
00354 {T_STRING, "String"},
00355 {T_REGEXP, "Regexp"},
00356 {T_ARRAY, "Array"},
00357 {T_FIXNUM, "Fixnum"},
00358 {T_HASH, "Hash"},
00359 {T_STRUCT, "Struct"},
00360 {T_BIGNUM, "Bignum"},
00361 {T_FILE, "File"},
00362 {T_RATIONAL,"Rational"},
00363 {T_COMPLEX, "Complex"},
00364 {T_TRUE, "true"},
00365 {T_FALSE, "false"},
00366 {T_SYMBOL, "Symbol"},
00367 {T_DATA, "Data"},
00368 {T_MATCH, "MatchData"},
00369 {T_NODE, "Node"},
00370 {T_UNDEF, "undef"},
00371 };
00372
00373 void
00374 rb_check_type(VALUE x, int t)
00375 {
00376 const struct types *type = builtin_types;
00377 const struct types *const typeend = builtin_types +
00378 sizeof(builtin_types) / sizeof(builtin_types[0]);
00379 int xt;
00380
00381 if (x == Qundef) {
00382 rb_bug("undef leaked to the Ruby space");
00383 }
00384
00385 xt = TYPE(x);
00386 if (xt != t || (xt == T_DATA && RTYPEDDATA_P(x))) {
00387 while (type < typeend) {
00388 if (type->type == t) {
00389 const char *etype;
00390
00391 if (NIL_P(x)) {
00392 etype = "nil";
00393 }
00394 else if (FIXNUM_P(x)) {
00395 etype = "Fixnum";
00396 }
00397 else if (SYMBOL_P(x)) {
00398 etype = "Symbol";
00399 }
00400 else if (rb_special_const_p(x)) {
00401 x = rb_obj_as_string(x);
00402 etype = StringValuePtr(x);
00403 }
00404 else {
00405 etype = rb_obj_classname(x);
00406 }
00407 rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
00408 etype, type->name);
00409 }
00410 type++;
00411 }
00412 if (xt > T_MASK && xt <= 0x3f) {
00413 rb_fatal("unknown type 0x%x (0x%x given, probably comes from extension library for ruby 1.8)", t, xt);
00414 }
00415 rb_bug("unknown type 0x%x (0x%x given)", t, xt);
00416 }
00417 }
00418
00419 int
00420 rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
00421 {
00422 while (child) {
00423 if (child == parent) return 1;
00424 child = child->parent;
00425 }
00426 return 0;
00427 }
00428
00429 int
00430 rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
00431 {
00432 if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA ||
00433 !RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
00434 return 0;
00435 }
00436 return 1;
00437 }
00438
00439 void *
00440 rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
00441 {
00442 const char *etype;
00443 static const char mesg[] = "wrong argument type %s (expected %s)";
00444
00445 if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA) {
00446 Check_Type(obj, T_DATA);
00447 }
00448 if (!RTYPEDDATA_P(obj)) {
00449 etype = rb_obj_classname(obj);
00450 rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name);
00451 }
00452 else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
00453 etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
00454 rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name);
00455 }
00456 return DATA_PTR(obj);
00457 }
00458
00459
00460 VALUE rb_eException;
00461 VALUE rb_eSystemExit;
00462 VALUE rb_eInterrupt;
00463 VALUE rb_eSignal;
00464 VALUE rb_eFatal;
00465 VALUE rb_eStandardError;
00466 VALUE rb_eRuntimeError;
00467 VALUE rb_eTypeError;
00468 VALUE rb_eArgError;
00469 VALUE rb_eIndexError;
00470 VALUE rb_eKeyError;
00471 VALUE rb_eRangeError;
00472 VALUE rb_eNameError;
00473 VALUE rb_eEncodingError;
00474 VALUE rb_eEncCompatError;
00475 VALUE rb_eNoMethodError;
00476 VALUE rb_eSecurityError;
00477 VALUE rb_eNotImpError;
00478 VALUE rb_eNoMemError;
00479 VALUE rb_cNameErrorMesg;
00480
00481 VALUE rb_eScriptError;
00482 VALUE rb_eSyntaxError;
00483 VALUE rb_eLoadError;
00484
00485 VALUE rb_eSystemCallError;
00486 VALUE rb_mErrno;
00487 static VALUE rb_eNOERROR;
00488
00489 #undef rb_exc_new2
00490
00491 VALUE
00492 rb_exc_new(VALUE etype, const char *ptr, long len)
00493 {
00494 return rb_funcall(etype, rb_intern("new"), 1, rb_str_new(ptr, len));
00495 }
00496
00497 VALUE
00498 rb_exc_new2(VALUE etype, const char *s)
00499 {
00500 return rb_exc_new(etype, s, strlen(s));
00501 }
00502
00503 VALUE
00504 rb_exc_new3(VALUE etype, VALUE str)
00505 {
00506 StringValue(str);
00507 return rb_funcall(etype, rb_intern("new"), 1, str);
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 static VALUE
00519 exc_initialize(int argc, VALUE *argv, VALUE exc)
00520 {
00521 VALUE arg;
00522
00523 rb_scan_args(argc, argv, "01", &arg);
00524 rb_iv_set(exc, "mesg", arg);
00525 rb_iv_set(exc, "bt", Qnil);
00526
00527 return exc;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 static VALUE
00544 exc_exception(int argc, VALUE *argv, VALUE self)
00545 {
00546 VALUE exc;
00547
00548 if (argc == 0) return self;
00549 if (argc == 1 && self == argv[0]) return self;
00550 exc = rb_obj_clone(self);
00551 exc_initialize(argc, argv, exc);
00552
00553 return exc;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 static VALUE
00565 exc_to_s(VALUE exc)
00566 {
00567 VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
00568 VALUE r = Qnil;
00569
00570 if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
00571 r = rb_String(mesg);
00572 OBJ_INFECT(r, exc);
00573 return r;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 static VALUE
00587 exc_message(VALUE exc)
00588 {
00589 return rb_funcall(exc, rb_intern("to_s"), 0, 0);
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599 static VALUE
00600 exc_inspect(VALUE exc)
00601 {
00602 VALUE str, klass;
00603
00604 klass = CLASS_OF(exc);
00605 exc = rb_obj_as_string(exc);
00606 if (RSTRING_LEN(exc) == 0) {
00607 return rb_str_dup(rb_class_name(klass));
00608 }
00609
00610 str = rb_str_buf_new2("#<");
00611 klass = rb_class_name(klass);
00612 rb_str_buf_append(str, klass);
00613 rb_str_buf_cat(str, ": ", 2);
00614 rb_str_buf_append(str, exc);
00615 rb_str_buf_cat(str, ">", 1);
00616
00617 return str;
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 static VALUE
00650 exc_backtrace(VALUE exc)
00651 {
00652 ID bt;
00653
00654 CONST_ID(bt, "bt");
00655 return rb_attr_get(exc, bt);
00656 }
00657
00658 VALUE
00659 rb_check_backtrace(VALUE bt)
00660 {
00661 long i;
00662 static const char err[] = "backtrace must be Array of String";
00663
00664 if (!NIL_P(bt)) {
00665 int t = TYPE(bt);
00666
00667 if (t == T_STRING) return rb_ary_new3(1, bt);
00668 if (t != T_ARRAY) {
00669 rb_raise(rb_eTypeError, err);
00670 }
00671 for (i=0;i<RARRAY_LEN(bt);i++) {
00672 if (TYPE(RARRAY_PTR(bt)[i]) != T_STRING) {
00673 rb_raise(rb_eTypeError, err);
00674 }
00675 }
00676 }
00677 return bt;
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 static VALUE
00691 exc_set_backtrace(VALUE exc, VALUE bt)
00692 {
00693 return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 static VALUE
00706 exc_equal(VALUE exc, VALUE obj)
00707 {
00708 VALUE mesg, backtrace;
00709 ID id_mesg;
00710
00711 if (exc == obj) return Qtrue;
00712 CONST_ID(id_mesg, "mesg");
00713
00714 if (rb_obj_class(exc) != rb_obj_class(obj)) {
00715 ID id_message, id_backtrace;
00716 CONST_ID(id_message, "message");
00717 CONST_ID(id_backtrace, "backtrace");
00718
00719 mesg = rb_check_funcall(obj, id_message, 0, 0);
00720 if (mesg == Qundef) return Qfalse;
00721 backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
00722 if (backtrace == Qundef) return Qfalse;
00723 }
00724 else {
00725 mesg = rb_attr_get(obj, id_mesg);
00726 backtrace = exc_backtrace(obj);
00727 }
00728
00729 if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
00730 return Qfalse;
00731 if (!rb_equal(exc_backtrace(exc), backtrace))
00732 return Qfalse;
00733 return Qtrue;
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743 static VALUE
00744 exit_initialize(int argc, VALUE *argv, VALUE exc)
00745 {
00746 VALUE status = INT2FIX(EXIT_SUCCESS);
00747 if (argc > 0 && FIXNUM_P(argv[0])) {
00748 status = *argv++;
00749 --argc;
00750 }
00751 rb_call_super(argc, argv);
00752 rb_iv_set(exc, "status", status);
00753 return exc;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 static VALUE
00765 exit_status(VALUE exc)
00766 {
00767 return rb_attr_get(exc, rb_intern("status"));
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 static VALUE
00779 exit_success_p(VALUE exc)
00780 {
00781 VALUE status_val = rb_attr_get(exc, rb_intern("status"));
00782 int status;
00783
00784 if (NIL_P(status_val))
00785 return Qtrue;
00786 status = NUM2INT(status_val);
00787 if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
00788 return Qtrue;
00789
00790 return Qfalse;
00791 }
00792
00793 void
00794 rb_name_error(ID id, const char *fmt, ...)
00795 {
00796 VALUE exc, argv[2];
00797 va_list args;
00798
00799 va_start(args, fmt);
00800 argv[0] = rb_vsprintf(fmt, args);
00801 va_end(args);
00802
00803 argv[1] = ID2SYM(id);
00804 exc = rb_class_new_instance(2, argv, rb_eNameError);
00805 rb_exc_raise(exc);
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 static VALUE
00818 name_err_initialize(int argc, VALUE *argv, VALUE self)
00819 {
00820 VALUE name;
00821
00822 name = (argc > 1) ? argv[--argc] : Qnil;
00823 rb_call_super(argc, argv);
00824 rb_iv_set(self, "name", name);
00825 return self;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835 static VALUE
00836 name_err_name(VALUE self)
00837 {
00838 return rb_attr_get(self, rb_intern("name"));
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848 static VALUE
00849 name_err_to_s(VALUE exc)
00850 {
00851 VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
00852 VALUE str = mesg;
00853
00854 if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
00855 StringValue(str);
00856 if (str != mesg) {
00857 rb_iv_set(exc, "mesg", mesg = str);
00858 }
00859 OBJ_INFECT(mesg, exc);
00860 return mesg;
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 static VALUE
00874 nometh_err_initialize(int argc, VALUE *argv, VALUE self)
00875 {
00876 VALUE args = (argc > 2) ? argv[--argc] : Qnil;
00877 name_err_initialize(argc, argv, self);
00878 rb_iv_set(self, "args", args);
00879 return self;
00880 }
00881
00882
00883 #define NAME_ERR_MESG_COUNT 3
00884
00885 static void
00886 name_err_mesg_mark(void *p)
00887 {
00888 VALUE *ptr = p;
00889 rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT);
00890 }
00891
00892 #define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE
00893
00894 static size_t
00895 name_err_mesg_memsize(const void *p)
00896 {
00897 return p ? (NAME_ERR_MESG_COUNT * sizeof(VALUE)) : 0;
00898 }
00899
00900 static const rb_data_type_t name_err_mesg_data_type = {
00901 "name_err_mesg",
00902 {
00903 name_err_mesg_mark,
00904 name_err_mesg_free,
00905 name_err_mesg_memsize,
00906 },
00907 };
00908
00909
00910 VALUE
00911 rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method)
00912 {
00913 VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
00914 VALUE result;
00915
00916 ptr[0] = mesg;
00917 ptr[1] = recv;
00918 ptr[2] = method;
00919 result = TypedData_Wrap_Struct(rb_cNameErrorMesg, &name_err_mesg_data_type, ptr);
00920 RB_GC_GUARD(mesg);
00921 RB_GC_GUARD(recv);
00922 RB_GC_GUARD(method);
00923 return result;
00924 }
00925
00926
00927 static VALUE
00928 name_err_mesg_equal(VALUE obj1, VALUE obj2)
00929 {
00930 VALUE *ptr1, *ptr2;
00931 int i;
00932
00933 if (obj1 == obj2) return Qtrue;
00934 if (rb_obj_class(obj2) != rb_cNameErrorMesg)
00935 return Qfalse;
00936
00937 TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
00938 TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
00939 for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
00940 if (!rb_equal(ptr1[i], ptr2[i]))
00941 return Qfalse;
00942 }
00943 return Qtrue;
00944 }
00945
00946
00947 static VALUE
00948 name_err_mesg_to_str(VALUE obj)
00949 {
00950 VALUE *ptr, mesg;
00951 TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr);
00952
00953 mesg = ptr[0];
00954 if (NIL_P(mesg)) return Qnil;
00955 else {
00956 const char *desc = 0;
00957 VALUE d = 0, args[NAME_ERR_MESG_COUNT];
00958 int state = 0;
00959
00960 obj = ptr[1];
00961 switch (TYPE(obj)) {
00962 case T_NIL:
00963 desc = "nil";
00964 break;
00965 case T_TRUE:
00966 desc = "true";
00967 break;
00968 case T_FALSE:
00969 desc = "false";
00970 break;
00971 default:
00972 d = rb_protect(rb_inspect, obj, &state);
00973 if (state)
00974 rb_set_errinfo(Qnil);
00975 if (NIL_P(d) || RSTRING_LEN(d) > 65) {
00976 d = rb_any_to_s(obj);
00977 }
00978 desc = RSTRING_PTR(d);
00979 break;
00980 }
00981 if (desc && desc[0] != '#') {
00982 d = d ? rb_str_dup(d) : rb_str_new2(desc);
00983 rb_str_cat2(d, ":");
00984 rb_str_cat2(d, rb_obj_classname(obj));
00985 }
00986 args[0] = mesg;
00987 args[1] = ptr[2];
00988 args[2] = d;
00989 mesg = rb_f_sprintf(NAME_ERR_MESG_COUNT, args);
00990 }
00991 OBJ_INFECT(mesg, obj);
00992 return mesg;
00993 }
00994
00995
00996 static VALUE
00997 name_err_mesg_load(VALUE klass, VALUE str)
00998 {
00999 return str;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 static VALUE
01011 nometh_err_args(VALUE self)
01012 {
01013 return rb_attr_get(self, rb_intern("args"));
01014 }
01015
01016 void
01017 rb_invalid_str(const char *str, const char *type)
01018 {
01019 volatile VALUE s = rb_str_inspect(rb_str_new2(str));
01020
01021 rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING_PTR(s));
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 static st_table *syserr_tbl;
01056
01057 static VALUE
01058 set_syserr(int n, const char *name)
01059 {
01060 st_data_t error;
01061
01062 if (!st_lookup(syserr_tbl, n, &error)) {
01063 error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
01064 rb_define_const(error, "Errno", INT2NUM(n));
01065 st_add_direct(syserr_tbl, n, error);
01066 }
01067 else {
01068 rb_define_const(rb_mErrno, name, error);
01069 }
01070 return error;
01071 }
01072
01073 static VALUE
01074 get_syserr(int n)
01075 {
01076 st_data_t error;
01077
01078 if (!st_lookup(syserr_tbl, n, &error)) {
01079 char name[8];
01080
01081 snprintf(name, sizeof(name), "E%03d", n);
01082 error = set_syserr(n, name);
01083 }
01084 return error;
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 static VALUE
01099 syserr_initialize(int argc, VALUE *argv, VALUE self)
01100 {
01101 #if !defined(_WIN32)
01102 char *strerror();
01103 #endif
01104 const char *err;
01105 VALUE mesg, error;
01106 VALUE klass = rb_obj_class(self);
01107
01108 if (klass == rb_eSystemCallError) {
01109 st_data_t data = (st_data_t)klass;
01110 rb_scan_args(argc, argv, "11", &mesg, &error);
01111 if (argc == 1 && FIXNUM_P(mesg)) {
01112 error = mesg; mesg = Qnil;
01113 }
01114 if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
01115 klass = (VALUE)data;
01116
01117 if (TYPE(self) != T_OBJECT) {
01118 rb_raise(rb_eTypeError, "invalid instance type");
01119 }
01120 RBASIC(self)->klass = klass;
01121 }
01122 }
01123 else {
01124 rb_scan_args(argc, argv, "01", &mesg);
01125 error = rb_const_get(klass, rb_intern("Errno"));
01126 }
01127 if (!NIL_P(error)) err = strerror(NUM2INT(error));
01128 else err = "unknown error";
01129 if (!NIL_P(mesg)) {
01130 rb_encoding *le = rb_locale_encoding();
01131 VALUE str = StringValue(mesg);
01132 rb_encoding *me = rb_enc_get(mesg);
01133
01134 mesg = rb_sprintf("%s - %.*s", err,
01135 (int)RSTRING_LEN(str), RSTRING_PTR(str));
01136 if (le != me && rb_enc_asciicompat(me)) {
01137 le = me;
01138 }
01139 OBJ_INFECT(mesg, str);
01140 rb_enc_associate(mesg, le);
01141 }
01142 else {
01143 mesg = rb_str_new2(err);
01144 rb_enc_associate(mesg, rb_locale_encoding());
01145 }
01146 rb_call_super(1, &mesg);
01147 rb_iv_set(self, "errno", error);
01148 return self;
01149 }
01150
01151
01152
01153
01154
01155
01156
01157
01158 static VALUE
01159 syserr_errno(VALUE self)
01160 {
01161 return rb_attr_get(self, rb_intern("errno"));
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 static VALUE
01173 syserr_eqq(VALUE self, VALUE exc)
01174 {
01175 VALUE num, e;
01176 ID en;
01177
01178 CONST_ID(en, "errno");
01179
01180 if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
01181 if (!rb_respond_to(exc, en)) return Qfalse;
01182 }
01183 else if (self == rb_eSystemCallError) return Qtrue;
01184
01185 num = rb_attr_get(exc, rb_intern("errno"));
01186 if (NIL_P(num)) {
01187 num = rb_funcall(exc, en, 0, 0);
01188 }
01189 e = rb_const_get(self, rb_intern("Errno"));
01190 if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
01191 return Qtrue;
01192 return Qfalse;
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 void
01514 Init_Exception(void)
01515 {
01516 rb_eException = rb_define_class("Exception", rb_cObject);
01517 rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
01518 rb_define_method(rb_eException, "exception", exc_exception, -1);
01519 rb_define_method(rb_eException, "initialize", exc_initialize, -1);
01520 rb_define_method(rb_eException, "==", exc_equal, 1);
01521 rb_define_method(rb_eException, "to_s", exc_to_s, 0);
01522 rb_define_method(rb_eException, "message", exc_message, 0);
01523 rb_define_method(rb_eException, "inspect", exc_inspect, 0);
01524 rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
01525 rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
01526
01527 rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
01528 rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
01529 rb_define_method(rb_eSystemExit, "status", exit_status, 0);
01530 rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
01531
01532 rb_eFatal = rb_define_class("fatal", rb_eException);
01533 rb_eSignal = rb_define_class("SignalException", rb_eException);
01534 rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal);
01535
01536 rb_eStandardError = rb_define_class("StandardError", rb_eException);
01537 rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
01538 rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
01539 rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
01540 rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
01541 rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
01542
01543 rb_eScriptError = rb_define_class("ScriptError", rb_eException);
01544 rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
01545 rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
01546 rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
01547
01548 rb_eNameError = rb_define_class("NameError", rb_eStandardError);
01549 rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
01550 rb_define_method(rb_eNameError, "name", name_err_name, 0);
01551 rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
01552 rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
01553 rb_define_singleton_method(rb_cNameErrorMesg, "!", rb_name_err_mesg_new, NAME_ERR_MESG_COUNT);
01554 rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
01555 rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
01556 rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1);
01557 rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
01558 rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
01559 rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
01560 rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
01561
01562 rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
01563 rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
01564 rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
01565 rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
01566 rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
01567
01568 syserr_tbl = st_init_numtable();
01569 rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
01570 rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
01571 rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
01572 rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
01573
01574 rb_mErrno = rb_define_module("Errno");
01575
01576 rb_define_global_function("warn", rb_warn_m, 1);
01577 }
01578
01579 void
01580 rb_raise(VALUE exc, const char *fmt, ...)
01581 {
01582 va_list args;
01583 VALUE mesg;
01584
01585 va_start(args, fmt);
01586 mesg = rb_vsprintf(fmt, args);
01587 va_end(args);
01588 rb_exc_raise(rb_exc_new3(exc, mesg));
01589 }
01590
01591 void
01592 rb_loaderror(const char *fmt, ...)
01593 {
01594 va_list args;
01595 VALUE mesg;
01596
01597 va_start(args, fmt);
01598 mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
01599 va_end(args);
01600 rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg));
01601 }
01602
01603 void
01604 rb_notimplement(void)
01605 {
01606 rb_raise(rb_eNotImpError,
01607 "%s() function is unimplemented on this machine",
01608 rb_id2name(rb_frame_this_func()));
01609 }
01610
01611 void
01612 rb_fatal(const char *fmt, ...)
01613 {
01614 va_list args;
01615 VALUE mesg;
01616
01617 va_start(args, fmt);
01618 mesg = rb_vsprintf(fmt, args);
01619 va_end(args);
01620
01621 rb_exc_fatal(rb_exc_new3(rb_eFatal, mesg));
01622 }
01623
01624 static VALUE
01625 make_errno_exc(const char *mesg)
01626 {
01627 int n = errno;
01628
01629 errno = 0;
01630 if (n == 0) {
01631 rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
01632 }
01633 return rb_syserr_new(n, mesg);
01634 }
01635
01636 static VALUE
01637 make_errno_exc_str(VALUE mesg)
01638 {
01639 int n = errno;
01640
01641 errno = 0;
01642 if (!mesg) mesg = Qnil;
01643 if (n == 0) {
01644 const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
01645 rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
01646 }
01647 return rb_syserr_new_str(n, mesg);
01648 }
01649
01650 VALUE
01651 rb_syserr_new(int n, const char *mesg)
01652 {
01653 VALUE arg;
01654 arg = mesg ? rb_str_new2(mesg) : Qnil;
01655 return rb_syserr_new_str(n, arg);
01656 }
01657
01658 VALUE
01659 rb_syserr_new_str(int n, VALUE arg)
01660 {
01661 return rb_class_new_instance(1, &arg, get_syserr(n));
01662 }
01663
01664 void
01665 rb_syserr_fail(int e, const char *mesg)
01666 {
01667 rb_exc_raise(rb_syserr_new(e, mesg));
01668 }
01669
01670 void
01671 rb_syserr_fail_str(int e, VALUE mesg)
01672 {
01673 rb_exc_raise(rb_syserr_new_str(e, mesg));
01674 }
01675
01676 void
01677 rb_sys_fail(const char *mesg)
01678 {
01679 rb_exc_raise(make_errno_exc(mesg));
01680 }
01681
01682 void
01683 rb_sys_fail_str(VALUE mesg)
01684 {
01685 rb_exc_raise(make_errno_exc_str(mesg));
01686 }
01687
01688 void
01689 rb_mod_sys_fail(VALUE mod, const char *mesg)
01690 {
01691 VALUE exc = make_errno_exc(mesg);
01692 rb_extend_object(exc, mod);
01693 rb_exc_raise(exc);
01694 }
01695
01696 void
01697 rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
01698 {
01699 VALUE exc = make_errno_exc_str(mesg);
01700 rb_extend_object(exc, mod);
01701 rb_exc_raise(exc);
01702 }
01703
01704 void
01705 rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
01706 {
01707 VALUE exc = rb_syserr_new(e, mesg);
01708 rb_extend_object(exc, mod);
01709 rb_exc_raise(exc);
01710 }
01711
01712 void
01713 rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
01714 {
01715 VALUE exc = rb_syserr_new_str(e, mesg);
01716 rb_extend_object(exc, mod);
01717 rb_exc_raise(exc);
01718 }
01719
01720 void
01721 rb_sys_warning(const char *fmt, ...)
01722 {
01723 char buf[BUFSIZ];
01724 va_list args;
01725 int errno_save;
01726
01727 errno_save = errno;
01728
01729 if (!RTEST(ruby_verbose)) return;
01730
01731 snprintf(buf, BUFSIZ, "warning: %s", fmt);
01732 snprintf(buf+strlen(buf), BUFSIZ-strlen(buf), ": %s", strerror(errno_save));
01733
01734 va_start(args, fmt);
01735 warn_print(buf, args);
01736 va_end(args);
01737 errno = errno_save;
01738 }
01739
01740 void
01741 rb_load_fail(const char *path)
01742 {
01743 rb_loaderror("%s -- %s", strerror(errno), path);
01744 }
01745
01746 void
01747 rb_error_frozen(const char *what)
01748 {
01749 rb_raise(rb_eRuntimeError, "can't modify frozen %s", what);
01750 }
01751
01752 #undef rb_check_frozen
01753 void
01754 rb_check_frozen(VALUE obj)
01755 {
01756 rb_check_frozen_internal(obj);
01757 }
01758
01759 void
01760 Init_syserr(void)
01761 {
01762 rb_eNOERROR = set_syserr(0, "NOERROR");
01763 #define defined_error(name, num) set_syserr((num), (name));
01764 #define undefined_error(name) set_syserr(0, (name));
01765 #include "known_errors.inc"
01766 #undef defined_error
01767 #undef undefined_error
01768 }
01769
01770 static void
01771 err_append(const char *s, rb_encoding *enc)
01772 {
01773 rb_thread_t *th = GET_THREAD();
01774 VALUE err = th->errinfo;
01775
01776 if (th->mild_compile_error) {
01777 if (!RTEST(err)) {
01778 err = rb_exc_new3(rb_eSyntaxError,
01779 rb_enc_str_new(s, strlen(s), enc));
01780 th->errinfo = err;
01781 }
01782 else {
01783 VALUE str = rb_obj_as_string(err);
01784
01785 rb_str_cat2(str, "\n");
01786 rb_str_cat2(str, s);
01787 th->errinfo = rb_exc_new3(rb_eSyntaxError, str);
01788 }
01789 }
01790 else {
01791 if (!RTEST(err)) {
01792 err = rb_exc_new2(rb_eSyntaxError, "compile error");
01793 th->errinfo = err;
01794 }
01795 rb_write_error(s);
01796 rb_write_error("\n");
01797 }
01798 }
01799