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