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 return r;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 static VALUE
00586 exc_message(VALUE exc)
00587 {
00588 return rb_funcall(exc, rb_intern("to_s"), 0, 0);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598 static VALUE
00599 exc_inspect(VALUE exc)
00600 {
00601 VALUE str, klass;
00602
00603 klass = CLASS_OF(exc);
00604 exc = rb_obj_as_string(exc);
00605 if (RSTRING_LEN(exc) == 0) {
00606 return rb_str_dup(rb_class_name(klass));
00607 }
00608
00609 str = rb_str_buf_new2("#<");
00610 klass = rb_class_name(klass);
00611 rb_str_buf_append(str, klass);
00612 rb_str_buf_cat(str, ": ", 2);
00613 rb_str_buf_append(str, exc);
00614 rb_str_buf_cat(str, ">", 1);
00615
00616 return str;
00617 }
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 static VALUE
00649 exc_backtrace(VALUE exc)
00650 {
00651 ID bt;
00652
00653 CONST_ID(bt, "bt");
00654 return rb_attr_get(exc, bt);
00655 }
00656
00657 VALUE
00658 rb_check_backtrace(VALUE bt)
00659 {
00660 long i;
00661 static const char err[] = "backtrace must be Array of String";
00662
00663 if (!NIL_P(bt)) {
00664 int t = TYPE(bt);
00665
00666 if (t == T_STRING) return rb_ary_new3(1, bt);
00667 if (t != T_ARRAY) {
00668 rb_raise(rb_eTypeError, err);
00669 }
00670 for (i=0;i<RARRAY_LEN(bt);i++) {
00671 if (TYPE(RARRAY_PTR(bt)[i]) != T_STRING) {
00672 rb_raise(rb_eTypeError, err);
00673 }
00674 }
00675 }
00676 return bt;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 static VALUE
00690 exc_set_backtrace(VALUE exc, VALUE bt)
00691 {
00692 return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 static VALUE
00705 exc_equal(VALUE exc, VALUE obj)
00706 {
00707 VALUE mesg, backtrace;
00708 ID id_mesg;
00709
00710 if (exc == obj) return Qtrue;
00711 CONST_ID(id_mesg, "mesg");
00712
00713 if (rb_obj_class(exc) != rb_obj_class(obj)) {
00714 ID id_message, id_backtrace;
00715 CONST_ID(id_message, "message");
00716 CONST_ID(id_backtrace, "backtrace");
00717
00718 mesg = rb_check_funcall(obj, id_message, 0, 0);
00719 if (mesg == Qundef) return Qfalse;
00720 backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
00721 if (backtrace == Qundef) return Qfalse;
00722 }
00723 else {
00724 mesg = rb_attr_get(obj, id_mesg);
00725 backtrace = exc_backtrace(obj);
00726 }
00727
00728 if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
00729 return Qfalse;
00730 if (!rb_equal(exc_backtrace(exc), backtrace))
00731 return Qfalse;
00732 return Qtrue;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742 static VALUE
00743 exit_initialize(int argc, VALUE *argv, VALUE exc)
00744 {
00745 VALUE status = INT2FIX(EXIT_SUCCESS);
00746 if (argc > 0 && FIXNUM_P(argv[0])) {
00747 status = *argv++;
00748 --argc;
00749 }
00750 rb_call_super(argc, argv);
00751 rb_iv_set(exc, "status", status);
00752 return exc;
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 static VALUE
00764 exit_status(VALUE exc)
00765 {
00766 return rb_attr_get(exc, rb_intern("status"));
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 static VALUE
00778 exit_success_p(VALUE exc)
00779 {
00780 VALUE status_val = rb_attr_get(exc, rb_intern("status"));
00781 int status;
00782
00783 if (NIL_P(status_val))
00784 return Qtrue;
00785 status = NUM2INT(status_val);
00786 if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
00787 return Qtrue;
00788
00789 return Qfalse;
00790 }
00791
00792 void
00793 rb_name_error(ID id, const char *fmt, ...)
00794 {
00795 VALUE exc, argv[2];
00796 va_list args;
00797
00798 va_start(args, fmt);
00799 argv[0] = rb_vsprintf(fmt, args);
00800 va_end(args);
00801
00802 argv[1] = ID2SYM(id);
00803 exc = rb_class_new_instance(2, argv, rb_eNameError);
00804 rb_exc_raise(exc);
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 static VALUE
00817 name_err_initialize(int argc, VALUE *argv, VALUE self)
00818 {
00819 VALUE name;
00820
00821 name = (argc > 1) ? argv[--argc] : Qnil;
00822 rb_call_super(argc, argv);
00823 rb_iv_set(self, "name", name);
00824 return self;
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834 static VALUE
00835 name_err_name(VALUE self)
00836 {
00837 return rb_attr_get(self, rb_intern("name"));
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847 static VALUE
00848 name_err_to_s(VALUE exc)
00849 {
00850 VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
00851 VALUE str = mesg;
00852
00853 if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
00854 StringValue(str);
00855 return str;
00856 }
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 static VALUE
00869 nometh_err_initialize(int argc, VALUE *argv, VALUE self)
00870 {
00871 VALUE args = (argc > 2) ? argv[--argc] : Qnil;
00872 name_err_initialize(argc, argv, self);
00873 rb_iv_set(self, "args", args);
00874 return self;
00875 }
00876
00877
00878 #define NAME_ERR_MESG_COUNT 3
00879
00880 static void
00881 name_err_mesg_mark(void *p)
00882 {
00883 VALUE *ptr = p;
00884 rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT);
00885 }
00886
00887 #define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE
00888
00889 static size_t
00890 name_err_mesg_memsize(const void *p)
00891 {
00892 return p ? (NAME_ERR_MESG_COUNT * sizeof(VALUE)) : 0;
00893 }
00894
00895 static const rb_data_type_t name_err_mesg_data_type = {
00896 "name_err_mesg",
00897 {
00898 name_err_mesg_mark,
00899 name_err_mesg_free,
00900 name_err_mesg_memsize,
00901 },
00902 };
00903
00904
00905 VALUE
00906 rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method)
00907 {
00908 VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
00909 VALUE result;
00910
00911 ptr[0] = mesg;
00912 ptr[1] = recv;
00913 ptr[2] = method;
00914 result = TypedData_Wrap_Struct(rb_cNameErrorMesg, &name_err_mesg_data_type, ptr);
00915 RB_GC_GUARD(mesg);
00916 RB_GC_GUARD(recv);
00917 RB_GC_GUARD(method);
00918 return result;
00919 }
00920
00921
00922 static VALUE
00923 name_err_mesg_equal(VALUE obj1, VALUE obj2)
00924 {
00925 VALUE *ptr1, *ptr2;
00926 int i;
00927
00928 if (obj1 == obj2) return Qtrue;
00929 if (rb_obj_class(obj2) != rb_cNameErrorMesg)
00930 return Qfalse;
00931
00932 TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
00933 TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
00934 for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
00935 if (!rb_equal(ptr1[i], ptr2[i]))
00936 return Qfalse;
00937 }
00938 return Qtrue;
00939 }
00940
00941
00942 static VALUE
00943 name_err_mesg_to_str(VALUE obj)
00944 {
00945 VALUE *ptr, mesg;
00946 TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr);
00947
00948 mesg = ptr[0];
00949 if (NIL_P(mesg)) return Qnil;
00950 else {
00951 const char *desc = 0;
00952 VALUE d = 0, args[NAME_ERR_MESG_COUNT];
00953 int state = 0;
00954
00955 obj = ptr[1];
00956 switch (TYPE(obj)) {
00957 case T_NIL:
00958 desc = "nil";
00959 break;
00960 case T_TRUE:
00961 desc = "true";
00962 break;
00963 case T_FALSE:
00964 desc = "false";
00965 break;
00966 default:
00967 d = rb_protect(rb_inspect, obj, &state);
00968 if (state)
00969 rb_set_errinfo(Qnil);
00970 if (NIL_P(d) || RSTRING_LEN(d) > 65) {
00971 d = rb_any_to_s(obj);
00972 }
00973 desc = RSTRING_PTR(d);
00974 break;
00975 }
00976 if (desc && desc[0] != '#') {
00977 d = d ? rb_str_dup(d) : rb_str_new2(desc);
00978 rb_str_cat2(d, ":");
00979 rb_str_cat2(d, rb_obj_classname(obj));
00980 }
00981 args[0] = mesg;
00982 args[1] = ptr[2];
00983 args[2] = d;
00984 mesg = rb_f_sprintf(NAME_ERR_MESG_COUNT, args);
00985 }
00986 return mesg;
00987 }
00988
00989
00990 static VALUE
00991 name_err_mesg_load(VALUE klass, VALUE str)
00992 {
00993 return str;
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 static VALUE
01005 nometh_err_args(VALUE self)
01006 {
01007 return rb_attr_get(self, rb_intern("args"));
01008 }
01009
01010 void
01011 rb_invalid_str(const char *str, const char *type)
01012 {
01013 volatile VALUE s = rb_str_inspect(rb_str_new2(str));
01014
01015 rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING_PTR(s));
01016 }
01017
01018
01019
01020
01021
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 static st_table *syserr_tbl;
01050
01051 static VALUE
01052 set_syserr(int n, const char *name)
01053 {
01054 st_data_t error;
01055
01056 if (!st_lookup(syserr_tbl, n, &error)) {
01057 error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
01058 rb_define_const(error, "Errno", INT2NUM(n));
01059 st_add_direct(syserr_tbl, n, error);
01060 }
01061 else {
01062 rb_define_const(rb_mErrno, name, error);
01063 }
01064 return error;
01065 }
01066
01067 static VALUE
01068 get_syserr(int n)
01069 {
01070 st_data_t error;
01071
01072 if (!st_lookup(syserr_tbl, n, &error)) {
01073 char name[8];
01074
01075 snprintf(name, sizeof(name), "E%03d", n);
01076 error = set_syserr(n, name);
01077 }
01078 return error;
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 static VALUE
01093 syserr_initialize(int argc, VALUE *argv, VALUE self)
01094 {
01095 #if !defined(_WIN32)
01096 char *strerror();
01097 #endif
01098 const char *err;
01099 VALUE mesg, error;
01100 VALUE klass = rb_obj_class(self);
01101
01102 if (klass == rb_eSystemCallError) {
01103 st_data_t data = (st_data_t)klass;
01104 rb_scan_args(argc, argv, "11", &mesg, &error);
01105 if (argc == 1 && FIXNUM_P(mesg)) {
01106 error = mesg; mesg = Qnil;
01107 }
01108 if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
01109 klass = (VALUE)data;
01110
01111 if (TYPE(self) != T_OBJECT) {
01112 rb_raise(rb_eTypeError, "invalid instance type");
01113 }
01114 RBASIC(self)->klass = klass;
01115 }
01116 }
01117 else {
01118 rb_scan_args(argc, argv, "01", &mesg);
01119 error = rb_const_get(klass, rb_intern("Errno"));
01120 }
01121 if (!NIL_P(error)) err = strerror(NUM2INT(error));
01122 else err = "unknown error";
01123 if (!NIL_P(mesg)) {
01124 rb_encoding *le = rb_locale_encoding();
01125 VALUE str = StringValue(mesg);
01126 rb_encoding *me = rb_enc_get(mesg);
01127
01128 mesg = rb_sprintf("%s - %.*s", err,
01129 (int)RSTRING_LEN(str), RSTRING_PTR(str));
01130 if (le != me && rb_enc_asciicompat(me)) {
01131 le = me;
01132 }
01133 OBJ_INFECT(mesg, str);
01134 rb_enc_associate(mesg, le);
01135 }
01136 else {
01137 mesg = rb_str_new2(err);
01138 rb_enc_associate(mesg, rb_locale_encoding());
01139 }
01140 rb_call_super(1, &mesg);
01141 rb_iv_set(self, "errno", error);
01142 return self;
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152 static VALUE
01153 syserr_errno(VALUE self)
01154 {
01155 return rb_attr_get(self, rb_intern("errno"));
01156 }
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 static VALUE
01167 syserr_eqq(VALUE self, VALUE exc)
01168 {
01169 VALUE num, e;
01170 ID en;
01171
01172 CONST_ID(en, "errno");
01173
01174 if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
01175 if (!rb_respond_to(exc, en)) return Qfalse;
01176 }
01177 else if (self == rb_eSystemCallError) return Qtrue;
01178
01179 num = rb_attr_get(exc, rb_intern("errno"));
01180 if (NIL_P(num)) {
01181 num = rb_funcall(exc, en, 0, 0);
01182 }
01183 e = rb_const_get(self, rb_intern("Errno"));
01184 if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
01185 return Qtrue;
01186 return Qfalse;
01187 }
01188
01189
01190
01191
01192
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 void
01508 Init_Exception(void)
01509 {
01510 rb_eException = rb_define_class("Exception", rb_cObject);
01511 rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
01512 rb_define_method(rb_eException, "exception", exc_exception, -1);
01513 rb_define_method(rb_eException, "initialize", exc_initialize, -1);
01514 rb_define_method(rb_eException, "==", exc_equal, 1);
01515 rb_define_method(rb_eException, "to_s", exc_to_s, 0);
01516 rb_define_method(rb_eException, "message", exc_message, 0);
01517 rb_define_method(rb_eException, "inspect", exc_inspect, 0);
01518 rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
01519 rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
01520
01521 rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
01522 rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
01523 rb_define_method(rb_eSystemExit, "status", exit_status, 0);
01524 rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
01525
01526 rb_eFatal = rb_define_class("fatal", rb_eException);
01527 rb_eSignal = rb_define_class("SignalException", rb_eException);
01528 rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal);
01529
01530 rb_eStandardError = rb_define_class("StandardError", rb_eException);
01531 rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
01532 rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
01533 rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
01534 rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
01535 rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
01536
01537 rb_eScriptError = rb_define_class("ScriptError", rb_eException);
01538 rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
01539 rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
01540 rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
01541
01542 rb_eNameError = rb_define_class("NameError", rb_eStandardError);
01543 rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
01544 rb_define_method(rb_eNameError, "name", name_err_name, 0);
01545 rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
01546 rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
01547 rb_define_singleton_method(rb_cNameErrorMesg, "!", rb_name_err_mesg_new, NAME_ERR_MESG_COUNT);
01548 rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
01549 rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
01550 rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1);
01551 rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
01552 rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
01553 rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
01554 rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
01555
01556 rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
01557 rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
01558 rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
01559 rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
01560 rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
01561
01562 syserr_tbl = st_init_numtable();
01563 rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
01564 rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
01565 rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
01566 rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
01567
01568 rb_mErrno = rb_define_module("Errno");
01569
01570 rb_define_global_function("warn", rb_warn_m, 1);
01571 }
01572
01573 void
01574 rb_raise(VALUE exc, const char *fmt, ...)
01575 {
01576 va_list args;
01577 VALUE mesg;
01578
01579 va_start(args, fmt);
01580 mesg = rb_vsprintf(fmt, args);
01581 va_end(args);
01582 rb_exc_raise(rb_exc_new3(exc, mesg));
01583 }
01584
01585 void
01586 rb_loaderror(const char *fmt, ...)
01587 {
01588 va_list args;
01589 VALUE mesg;
01590
01591 va_start(args, fmt);
01592 mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
01593 va_end(args);
01594 rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg));
01595 }
01596
01597 void
01598 rb_notimplement(void)
01599 {
01600 rb_raise(rb_eNotImpError,
01601 "%s() function is unimplemented on this machine",
01602 rb_id2name(rb_frame_this_func()));
01603 }
01604
01605 void
01606 rb_fatal(const char *fmt, ...)
01607 {
01608 va_list args;
01609 VALUE mesg;
01610
01611 va_start(args, fmt);
01612 mesg = rb_vsprintf(fmt, args);
01613 va_end(args);
01614
01615 rb_exc_fatal(rb_exc_new3(rb_eFatal, mesg));
01616 }
01617
01618 static VALUE
01619 make_errno_exc(const char *mesg)
01620 {
01621 int n = errno;
01622
01623 errno = 0;
01624 if (n == 0) {
01625 rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
01626 }
01627 return rb_syserr_new(n, mesg);
01628 }
01629
01630 static VALUE
01631 make_errno_exc_str(VALUE mesg)
01632 {
01633 int n = errno;
01634
01635 errno = 0;
01636 if (!mesg) mesg = Qnil;
01637 if (n == 0) {
01638 const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
01639 rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
01640 }
01641 return rb_syserr_new_str(n, mesg);
01642 }
01643
01644 VALUE
01645 rb_syserr_new(int n, const char *mesg)
01646 {
01647 VALUE arg;
01648 arg = mesg ? rb_str_new2(mesg) : Qnil;
01649 return rb_syserr_new_str(n, arg);
01650 }
01651
01652 VALUE
01653 rb_syserr_new_str(int n, VALUE arg)
01654 {
01655 return rb_class_new_instance(1, &arg, get_syserr(n));
01656 }
01657
01658 void
01659 rb_syserr_fail(int e, const char *mesg)
01660 {
01661 rb_exc_raise(rb_syserr_new(e, mesg));
01662 }
01663
01664 void
01665 rb_syserr_fail_str(int e, VALUE mesg)
01666 {
01667 rb_exc_raise(rb_syserr_new_str(e, mesg));
01668 }
01669
01670 void
01671 rb_sys_fail(const char *mesg)
01672 {
01673 rb_exc_raise(make_errno_exc(mesg));
01674 }
01675
01676 void
01677 rb_sys_fail_str(VALUE mesg)
01678 {
01679 rb_exc_raise(make_errno_exc_str(mesg));
01680 }
01681
01682 void
01683 rb_mod_sys_fail(VALUE mod, const char *mesg)
01684 {
01685 VALUE exc = make_errno_exc(mesg);
01686 rb_extend_object(exc, mod);
01687 rb_exc_raise(exc);
01688 }
01689
01690 void
01691 rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
01692 {
01693 VALUE exc = make_errno_exc_str(mesg);
01694 rb_extend_object(exc, mod);
01695 rb_exc_raise(exc);
01696 }
01697
01698 void
01699 rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
01700 {
01701 VALUE exc = rb_syserr_new(e, mesg);
01702 rb_extend_object(exc, mod);
01703 rb_exc_raise(exc);
01704 }
01705
01706 void
01707 rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
01708 {
01709 VALUE exc = rb_syserr_new_str(e, mesg);
01710 rb_extend_object(exc, mod);
01711 rb_exc_raise(exc);
01712 }
01713
01714 void
01715 rb_sys_warning(const char *fmt, ...)
01716 {
01717 char buf[BUFSIZ];
01718 va_list args;
01719 int errno_save;
01720
01721 errno_save = errno;
01722
01723 if (!RTEST(ruby_verbose)) return;
01724
01725 snprintf(buf, BUFSIZ, "warning: %s", fmt);
01726 snprintf(buf+strlen(buf), BUFSIZ-strlen(buf), ": %s", strerror(errno_save));
01727
01728 va_start(args, fmt);
01729 warn_print(buf, args);
01730 va_end(args);
01731 errno = errno_save;
01732 }
01733
01734 void
01735 rb_load_fail(const char *path)
01736 {
01737 rb_loaderror("%s -- %s", strerror(errno), path);
01738 }
01739
01740 void
01741 rb_error_frozen(const char *what)
01742 {
01743 rb_raise(rb_eRuntimeError, "can't modify frozen %s", what);
01744 }
01745
01746 #undef rb_check_frozen
01747 void
01748 rb_check_frozen(VALUE obj)
01749 {
01750 rb_check_frozen_internal(obj);
01751 }
01752
01753 void
01754 Init_syserr(void)
01755 {
01756 rb_eNOERROR = set_syserr(0, "NOERROR");
01757 #define defined_error(name, num) set_syserr((num), (name));
01758 #define undefined_error(name) set_syserr(0, (name));
01759 #include "known_errors.inc"
01760 #undef defined_error
01761 #undef undefined_error
01762 }
01763
01764 static void
01765 err_append(const char *s, rb_encoding *enc)
01766 {
01767 rb_thread_t *th = GET_THREAD();
01768 VALUE err = th->errinfo;
01769
01770 if (th->mild_compile_error) {
01771 if (!RTEST(err)) {
01772 err = rb_exc_new3(rb_eSyntaxError,
01773 rb_enc_str_new(s, strlen(s), enc));
01774 th->errinfo = err;
01775 }
01776 else {
01777 VALUE str = rb_obj_as_string(err);
01778
01779 rb_str_cat2(str, "\n");
01780 rb_str_cat2(str, s);
01781 th->errinfo = rb_exc_new3(rb_eSyntaxError, str);
01782 }
01783 }
01784 else {
01785 if (!RTEST(err)) {
01786 err = rb_exc_new2(rb_eSyntaxError, "compile error");
01787 th->errinfo = err;
01788 }
01789 rb_write_error(s);
01790 rb_write_error("\n");
01791 }
01792 }
01793