Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# error.c

Go to the documentation of this file.

    00001 /**********************************************************************
    00002
    00003   error.c -
    00004
    00005   $Author: yugui $
    00006   created at: Mon Aug  9 16:11:34 JST 1993
    00007
    00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
    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 /* rb_compile_warning() reports only in verbose mode */
    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 /* rb_warning() reports only in verbose mode */
    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  * call-seq:
    00197  *    warn(msg)   -> nil
    00198  *
    00199  * Display the given message (followed by a newline) on STDERR unless
    00200  * warnings are disabled (for example with the <code>-W0</code> flag).
    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"},      /* internal use: mixed-in module holder */
    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"},      /* :symbol */
    00305     {T_DATA,    "Data"},        /* internal use: wrapped C pointers */
    00306     {T_MATCH,   "MatchData"},   /* data of $~ */
    00307     {T_NODE,    "Node"},        /* internal use: syntax tree node */
    00308     {T_UNDEF,   "undef"},       /* internal use: #undef; should not happen */
    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                     etype = RSTRING_PTR(rb_obj_as_string(x));
    00340                 }
    00341                 else {
    00342                     etype = rb_obj_classname(x);
    00343                 }
    00344                 rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
    00345                          etype, type->name);
    00346             }
    00347             type++;
    00348         }
    00349         rb_bug("unknown type 0x%x (0x%x given)", t, TYPE(x));
    00350     }
    00351 }
    00352
    00353 int
    00354 rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
    00355 {
    00356     if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA ||
    00357         !RTYPEDDATA_P(obj) || RTYPEDDATA_TYPE(obj) != data_type) {
    00358         return 0;
    00359     }
    00360     return 1;
    00361 }
    00362
    00363 void *
    00364 rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
    00365 {
    00366     const char *etype;
    00367     static const char mesg[] = "wrong argument type %s (expected %s)";
    00368
    00369     if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA) {
    00370         Check_Type(obj, T_DATA);
    00371     }
    00372     if (!RTYPEDDATA_P(obj)) {
    00373         etype = rb_obj_classname(obj);
    00374         rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name);
    00375     }
    00376     else if (RTYPEDDATA_TYPE(obj) != data_type) {
    00377         etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
    00378         rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name);
    00379     }
    00380     return DATA_PTR(obj);
    00381 }
    00382
    00383 /* exception classes */
    00384 VALUE rb_eException;
    00385 VALUE rb_eSystemExit;
    00386 VALUE rb_eInterrupt;
    00387 VALUE rb_eSignal;
    00388 VALUE rb_eFatal;
    00389 VALUE rb_eStandardError;
    00390 VALUE rb_eRuntimeError;
    00391 VALUE rb_eTypeError;
    00392 VALUE rb_eArgError;
    00393 VALUE rb_eIndexError;
    00394 VALUE rb_eKeyError;
    00395 VALUE rb_eRangeError;
    00396 VALUE rb_eNameError;
    00397 VALUE rb_eEncodingError;
    00398 VALUE rb_eEncCompatError;
    00399 VALUE rb_eNoMethodError;
    00400 VALUE rb_eSecurityError;
    00401 VALUE rb_eNotImpError;
    00402 VALUE rb_eNoMemError;
    00403 VALUE rb_cNameErrorMesg;
    00404
    00405 VALUE rb_eScriptError;
    00406 VALUE rb_eSyntaxError;
    00407 VALUE rb_eLoadError;
    00408
    00409 VALUE rb_eSystemCallError;
    00410 VALUE rb_mErrno;
    00411 static VALUE rb_eNOERROR;
    00412
    00413 #undef rb_exc_new2
    00414
    00415 VALUE
    00416 rb_exc_new(VALUE etype, const char *ptr, long len)
    00417 {
    00418     return rb_funcall(etype, rb_intern("new"), 1, rb_str_new(ptr, len));
    00419 }
    00420
    00421 VALUE
    00422 rb_exc_new2(VALUE etype, const char *s)
    00423 {
    00424     return rb_exc_new(etype, s, strlen(s));
    00425 }
    00426
    00427 VALUE
    00428 rb_exc_new3(VALUE etype, VALUE str)
    00429 {
    00430     StringValue(str);
    00431     return rb_funcall(etype, rb_intern("new"), 1, str);
    00432 }
    00433
    00434 /*
    00435  * call-seq:
    00436  *    Exception.new(msg = nil)   ->  exception
    00437  *
    00438  *  Construct a new Exception object, optionally passing in
    00439  *  a message.
    00440  */
    00441
    00442 static VALUE
    00443 exc_initialize(int argc, VALUE *argv, VALUE exc)
    00444 {
    00445     VALUE arg;
    00446
    00447     rb_scan_args(argc, argv, "01", &arg);
    00448     rb_iv_set(exc, "mesg", arg);
    00449     rb_iv_set(exc, "bt", Qnil);
    00450
    00451     return exc;
    00452 }
    00453
    00454 /*
    00455  *  Document-method: exception
    00456  *
    00457  *  call-seq:
    00458  *     exc.exception(string)  ->  an_exception or exc
    00459  *
    00460  *  With no argument, or if the argument is the same as the receiver,
    00461  *  return the receiver. Otherwise, create a new
    00462  *  exception object of the same class as the receiver, but with a
    00463  *  message equal to <code>string.to_str</code>.
    00464  *
    00465  */
    00466
    00467 static VALUE
    00468 exc_exception(int argc, VALUE *argv, VALUE self)
    00469 {
    00470     VALUE exc;
    00471
    00472     if (argc == 0) return self;
    00473     if (argc == 1 && self == argv[0]) return self;
    00474     exc = rb_obj_clone(self);
    00475     exc_initialize(argc, argv, exc);
    00476
    00477     return exc;
    00478 }
    00479
    00480 /*
    00481  * call-seq:
    00482  *   exception.to_s   ->  string
    00483  *
    00484  * Returns exception's message (or the name of the exception if
    00485  * no message is set).
    00486  */
    00487
    00488 static VALUE
    00489 exc_to_s(VALUE exc)
    00490 {
    00491     VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
    00492
    00493     if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
    00494     if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
    00495     return mesg;
    00496 }
    00497
    00498 /*
    00499  * call-seq:
    00500  *   exception.message   ->  string
    00501  *
    00502  * Returns the result of invoking <code>exception.to_s</code>.
    00503  * Normally this returns the exception's message or name. By
    00504  * supplying a to_str method, exceptions are agreeing to
    00505  * be used where Strings are expected.
    00506  */
    00507
    00508 static VALUE
    00509 exc_message(VALUE exc)
    00510 {
    00511     return rb_funcall(exc, rb_intern("to_s"), 0, 0);
    00512 }
    00513
    00514 /*
    00515  * call-seq:
    00516  *   exception.inspect   -> string
    00517  *
    00518  * Return this exception's class name an message
    00519  */
    00520
    00521 static VALUE
    00522 exc_inspect(VALUE exc)
    00523 {
    00524     VALUE str, klass;
    00525
    00526     klass = CLASS_OF(exc);
    00527     exc = rb_obj_as_string(exc);
    00528     if (RSTRING_LEN(exc) == 0) {
    00529         return rb_str_dup(rb_class_name(klass));
    00530     }
    00531
    00532     str = rb_str_buf_new2("#<");
    00533     klass = rb_class_name(klass);
    00534     rb_str_buf_append(str, klass);
    00535     rb_str_buf_cat(str, ": ", 2);
    00536     rb_str_buf_append(str, exc);
    00537     rb_str_buf_cat(str, ">", 1);
    00538
    00539     return str;
    00540 }
    00541
    00542 /*
    00543  *  call-seq:
    00544  *     exception.backtrace    -> array
    00545  *
    00546  *  Returns any backtrace associated with the exception. The backtrace
    00547  *  is an array of strings, each containing either ``filename:lineNo: in
    00548  *  `method''' or ``filename:lineNo.''
    00549  *
    00550  *     def a
    00551  *       raise "boom"
    00552  *     end
    00553  *
    00554  *     def b
    00555  *       a()
    00556  *     end
    00557  *
    00558  *     begin
    00559  *       b()
    00560  *     rescue => detail
    00561  *       print detail.backtrace.join("\n")
    00562  *     end
    00563  *
    00564  *  <em>produces:</em>
    00565  *
    00566  *     prog.rb:2:in `a'
    00567  *     prog.rb:6:in `b'
    00568  *     prog.rb:10
    00569 */
    00570
    00571 static VALUE
    00572 exc_backtrace(VALUE exc)
    00573 {
    00574     ID bt;
    00575
    00576     CONST_ID(bt, "bt");
    00577     return rb_attr_get(exc, bt);
    00578 }
    00579
    00580 VALUE
    00581 rb_check_backtrace(VALUE bt)
    00582 {
    00583     long i;
    00584     static const char err[] = "backtrace must be Array of String";
    00585
    00586     if (!NIL_P(bt)) {
    00587         int t = TYPE(bt);
    00588
    00589         if (t == T_STRING) return rb_ary_new3(1, bt);
    00590         if (t != T_ARRAY) {
    00591             rb_raise(rb_eTypeError, err);
    00592         }
    00593         for (i=0;i<RARRAY_LEN(bt);i++) {
    00594             if (TYPE(RARRAY_PTR(bt)[i]) != T_STRING) {
    00595                 rb_raise(rb_eTypeError, err);
    00596             }
    00597         }
    00598     }
    00599     return bt;
    00600 }
    00601
    00602 /*
    00603  *  call-seq:
    00604  *     exc.set_backtrace(array)   ->  array
    00605  *
    00606  *  Sets the backtrace information associated with <i>exc</i>. The
    00607  *  argument must be an array of <code>String</code> objects in the
    00608  *  format described in <code>Exception#backtrace</code>.
    00609  *
    00610  */
    00611
    00612 static VALUE
    00613 exc_set_backtrace(VALUE exc, VALUE bt)
    00614 {
    00615     return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
    00616 }
    00617
    00618 /*
    00619  *  call-seq:
    00620  *     exc == obj   -> true or false
    00621  *
    00622  *  Equality---If <i>obj</i> is not an <code>Exception</code>, returns
    00623  *  <code>false</code>. Otherwise, returns <code>true</code> if <i>exc</i> and
    00624  *  <i>obj</i> share same class, messages, and backtrace.
    00625  */
    00626
    00627 static VALUE
    00628 exc_equal(VALUE exc, VALUE obj)
    00629 {
    00630     VALUE mesg, backtrace;
    00631     ID id_mesg;
    00632
    00633     if (exc == obj) return Qtrue;
    00634     CONST_ID(id_mesg, "mesg");
    00635
    00636     if (rb_obj_class(exc) != rb_obj_class(obj)) {
    00637         ID id_message, id_backtrace;
    00638         CONST_ID(id_message, "message");
    00639         CONST_ID(id_backtrace, "backtrace");
    00640
    00641         mesg = rb_check_funcall(obj, id_message, 0, 0);
    00642         if (mesg == Qundef) return Qfalse;
    00643         backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
    00644         if (backtrace == Qundef) return Qfalse;
    00645     }
    00646     else {
    00647         mesg = rb_attr_get(obj, id_mesg);
    00648         backtrace = exc_backtrace(obj);
    00649     }
    00650
    00651     if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
    00652         return Qfalse;
    00653     if (!rb_equal(exc_backtrace(exc), backtrace))
    00654         return Qfalse;
    00655     return Qtrue;
    00656 }
    00657
    00658 /*
    00659  * call-seq:
    00660  *   SystemExit.new(status=0)   -> system_exit
    00661  *
    00662  * Create a new +SystemExit+ exception with the given status.
    00663  */
    00664
    00665 static VALUE
    00666 exit_initialize(int argc, VALUE *argv, VALUE exc)
    00667 {
    00668     VALUE status = INT2FIX(EXIT_SUCCESS);
    00669     if (argc > 0 && FIXNUM_P(argv[0])) {
    00670         status = *argv++;
    00671         --argc;
    00672     }
    00673     rb_call_super(argc, argv);
    00674     rb_iv_set(exc, "status", status);
    00675     return exc;
    00676 }
    00677
    00678
    00679 /*
    00680  * call-seq:
    00681  *   system_exit.status   -> fixnum
    00682  *
    00683  * Return the status value associated with this system exit.
    00684  */
    00685
    00686 static VALUE
    00687 exit_status(VALUE exc)
    00688 {
    00689     return rb_attr_get(exc, rb_intern("status"));
    00690 }
    00691
    00692
    00693 /*
    00694  * call-seq:
    00695  *   system_exit.success?  -> true or false
    00696  *
    00697  * Returns +true+ if exiting successful, +false+ if not.
    00698  */
    00699
    00700 static VALUE
    00701 exit_success_p(VALUE exc)
    00702 {
    00703     VALUE status = rb_attr_get(exc, rb_intern("status"));
    00704     if (NIL_P(status)) return Qtrue;
    00705     if (status == INT2FIX(EXIT_SUCCESS)) return Qtrue;
    00706     return Qfalse;
    00707 }
    00708
    00709 void
    00710 rb_name_error(ID id, const char *fmt, ...)
    00711 {
    00712     VALUE exc, argv[2];
    00713     va_list args;
    00714
    00715     va_start(args, fmt);
    00716     argv[0] = rb_vsprintf(fmt, args);
    00717     va_end(args);
    00718
    00719     argv[1] = ID2SYM(id);
    00720     exc = rb_class_new_instance(2, argv, rb_eNameError);
    00721     rb_exc_raise(exc);
    00722 }
    00723
    00724 /*
    00725  * call-seq:
    00726  *   NameError.new(msg [, name])  -> name_error
    00727  *
    00728  * Construct a new NameError exception. If given the <i>name</i>
    00729  * parameter may subsequently be examined using the <code>NameError.name</code>
    00730  * method.
    00731  */
    00732
    00733 static VALUE
    00734 name_err_initialize(int argc, VALUE *argv, VALUE self)
    00735 {
    00736     VALUE name;
    00737
    00738     name = (argc > 1) ? argv[--argc] : Qnil;
    00739     rb_call_super(argc, argv);
    00740     rb_iv_set(self, "name", name);
    00741     return self;
    00742 }
    00743
    00744 /*
    00745  *  call-seq:
    00746  *    name_error.name    ->  string or nil
    00747  *
    00748  *  Return the name associated with this NameError exception.
    00749  */
    00750
    00751 static VALUE
    00752 name_err_name(VALUE self)
    00753 {
    00754     return rb_attr_get(self, rb_intern("name"));
    00755 }
    00756
    00757 /*
    00758  * call-seq:
    00759  *  name_error.to_s   -> string
    00760  *
    00761  * Produce a nicely-formatted string representing the +NameError+.
    00762  */
    00763
    00764 static VALUE
    00765 name_err_to_s(VALUE exc)
    00766 {
    00767     VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
    00768     VALUE str = mesg;
    00769
    00770     if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
    00771     StringValue(str);
    00772     if (str != mesg) {
    00773         rb_iv_set(exc, "mesg", mesg = str);
    00774     }
    00775     if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
    00776     return mesg;
    00777 }
    00778
    00779 /*
    00780  * call-seq:
    00781  *   NoMethodError.new(msg, name [, args])  -> no_method_error
    00782  *
    00783  * Construct a NoMethodError exception for a method of the given name
    00784  * called with the given arguments. The name may be accessed using
    00785  * the <code>#name</code> method on the resulting object, and the
    00786  * arguments using the <code>#args</code> method.
    00787  */
    00788
    00789 static VALUE
    00790 nometh_err_initialize(int argc, VALUE *argv, VALUE self)
    00791 {
    00792     VALUE args = (argc > 2) ? argv[--argc] : Qnil;
    00793     name_err_initialize(argc, argv, self);
    00794     rb_iv_set(self, "args", args);
    00795     return self;
    00796 }
    00797
    00798 /* :nodoc: */
    00799 #define NAME_ERR_MESG_COUNT 3
    00800
    00801 static void
    00802 name_err_mesg_mark(void *p)
    00803 {
    00804     VALUE *ptr = p;
    00805     rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT);
    00806 }
    00807
    00808 #define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE
    00809
    00810 static size_t
    00811 name_err_mesg_memsize(const void *p)
    00812 {
    00813     return p ? (NAME_ERR_MESG_COUNT * sizeof(VALUE)) : 0;
    00814 }
    00815
    00816 static const rb_data_type_t name_err_mesg_data_type = {
    00817     "name_err_mesg",
    00818     name_err_mesg_mark,
    00819     name_err_mesg_free,
    00820     name_err_mesg_memsize,
    00821 };
    00822
    00823 /* :nodoc: */
    00824 VALUE
    00825 rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method)
    00826 {
    00827     VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
    00828     VALUE result;
    00829
    00830     ptr[0] = mesg;
    00831     ptr[1] = recv;
    00832     ptr[2] = method;
    00833     result = TypedData_Wrap_Struct(rb_cNameErrorMesg, &name_err_mesg_data_type, ptr);
    00834     RB_GC_GUARD(mesg);
    00835     RB_GC_GUARD(recv);
    00836     RB_GC_GUARD(method);
    00837     return result;
    00838 }
    00839
    00840 /* :nodoc: */
    00841 static VALUE
    00842 name_err_mesg_equal(VALUE obj1, VALUE obj2)
    00843 {
    00844     VALUE *ptr1, *ptr2;
    00845     int i;
    00846
    00847     if (obj1 == obj2) return Qtrue;
    00848     if (rb_obj_class(obj2) != rb_cNameErrorMesg)
    00849         return Qfalse;
    00850
    00851     TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
    00852     TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
    00853     for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
    00854         if (!rb_equal(ptr1[i], ptr2[i]))
    00855             return Qfalse;
    00856     }
    00857     return Qtrue;
    00858 }
    00859
    00860 /* :nodoc: */
    00861 static VALUE
    00862 name_err_mesg_to_str(VALUE obj)
    00863 {
    00864     VALUE *ptr, mesg;
    00865     TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr);
    00866
    00867     mesg = ptr[0];
    00868     if (NIL_P(mesg)) return Qnil;
    00869     else {
    00870         const char *desc = 0;
    00871         VALUE d = 0, args[NAME_ERR_MESG_COUNT];
    00872
    00873         obj = ptr[1];
    00874         switch (TYPE(obj)) {
    00875           case T_NIL:
    00876             desc = "nil";
    00877             break;
    00878           case T_TRUE:
    00879             desc = "true";
    00880             break;
    00881           case T_FALSE:
    00882             desc = "false";
    00883             break;
    00884           default:
    00885             d = rb_protect(rb_inspect, obj, 0);
    00886             if (NIL_P(d) || RSTRING_LEN(d) > 65) {
    00887                 d = rb_any_to_s(obj);
    00888             }
    00889             desc = RSTRING_PTR(d);
    00890             break;
    00891         }
    00892         if (desc && desc[0] != '#') {
    00893             d = d ? rb_str_dup(d) : rb_str_new2(desc);
    00894             rb_str_cat2(d, ":");
    00895             rb_str_cat2(d, rb_obj_classname(obj));
    00896         }
    00897         args[0] = mesg;
    00898         args[1] = ptr[2];
    00899         args[2] = d;
    00900         mesg = rb_f_sprintf(NAME_ERR_MESG_COUNT, args);
    00901     }
    00902     if (OBJ_TAINTED(obj)) OBJ_TAINT(mesg);
    00903     return mesg;
    00904 }
    00905
    00906 /* :nodoc: */
    00907 static VALUE
    00908 name_err_mesg_load(VALUE klass, VALUE str)
    00909 {
    00910     return str;
    00911 }
    00912
    00913 /*
    00914  * call-seq:
    00915  *   no_method_error.args  -> obj
    00916  *
    00917  * Return the arguments passed in as the third parameter to
    00918  * the constructor.
    00919  */
    00920
    00921 static VALUE
    00922 nometh_err_args(VALUE self)
    00923 {
    00924     return rb_attr_get(self, rb_intern("args"));
    00925 }
    00926
    00927 void
    00928 rb_invalid_str(const char *str, const char *type)
    00929 {
    00930     VALUE s = rb_str_inspect(rb_str_new2(str));
    00931
    00932     rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING_PTR(s));
    00933 }
    00934
    00935 /*
    00936  *  Document-module: Errno
    00937  *
    00938  *  Ruby exception objects are subclasses of <code>Exception</code>.
    00939  *  However, operating systems typically report errors using plain
    00940  *  integers. Module <code>Errno</code> is created dynamically to map
    00941  *  these operating system errors to Ruby classes, with each error
    00942  *  number generating its own subclass of <code>SystemCallError</code>.
    00943  *  As the subclass is created in module <code>Errno</code>, its name
    00944  *  will start <code>Errno::</code>.
    00945  *
    00946  *  The names of the <code>Errno::</code> classes depend on
    00947  *  the environment in which Ruby runs. On a typical Unix or Windows
    00948  *  platform, there are <code>Errno</code> classes such as
    00949  *  <code>Errno::EACCES</code>, <code>Errno::EAGAIN</code>,
    00950  *  <code>Errno::EINTR</code>, and so on.
    00951  *
    00952  *  The integer operating system error number corresponding to a
    00953  *  particular error is available as the class constant
    00954  *  <code>Errno::</code><em>error</em><code>::Errno</code>.
    00955  *
    00956  *     Errno::EACCES::Errno   #=> 13
    00957  *     Errno::EAGAIN::Errno   #=> 11
    00958  *     Errno::EINTR::Errno    #=> 4
    00959  *
    00960  *  The full list of operating system errors on your particular platform
    00961  *  are available as the constants of <code>Errno</code>.
    00962  *
    00963  *     Errno.constants   #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
    00964  */
    00965
    00966 static st_table *syserr_tbl;
    00967
    00968 static VALUE
    00969 set_syserr(int n, const char *name)
    00970 {
    00971     VALUE error;
    00972
    00973     if (!st_lookup(syserr_tbl, n, &error)) {
    00974         error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
    00975         rb_define_const(error, "Errno", INT2NUM(n));
    00976         st_add_direct(syserr_tbl, n, error);
    00977     }
    00978     else {
    00979         rb_define_const(rb_mErrno, name, error);
    00980     }
    00981     return error;
    00982 }
    00983
    00984 static VALUE
    00985 get_syserr(int n)
    00986 {
    00987     VALUE error;
    00988
    00989     if (!st_lookup(syserr_tbl, n, &error)) {
    00990         char name[8];   /* some Windows' errno have 5 digits. */
    00991
    00992         snprintf(name, sizeof(name), "E%03d", n);
    00993         error = set_syserr(n, name);
    00994     }
    00995     return error;
    00996 }
    00997
    00998 /*
    00999  * call-seq:
    01000  *   SystemCallError.new(msg, errno)  -> system_call_error_subclass
    01001  *
    01002  * If _errno_ corresponds to a known system error code, constructs
    01003  * the appropriate <code>Errno</code> class for that error, otherwise
    01004  * constructs a generic <code>SystemCallError</code> object. The
    01005  * error number is subsequently available via the <code>errno</code>
    01006  * method.
    01007  */
    01008
    01009 static VALUE
    01010 syserr_initialize(int argc, VALUE *argv, VALUE self)
    01011 {
    01012 #if !defined(_WIN32)
    01013     char *strerror();
    01014 #endif
    01015     const char *err;
    01016     VALUE mesg, error;
    01017     VALUE klass = rb_obj_class(self);
    01018
    01019     if (klass == rb_eSystemCallError) {
    01020         rb_scan_args(argc, argv, "11", &mesg, &error);
    01021         if (argc == 1 && FIXNUM_P(mesg)) {
    01022             error = mesg; mesg = Qnil;
    01023         }
    01024         if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &klass)) {
    01025             /* change class */
    01026             if (TYPE(self) != T_OBJECT) { /* insurance to avoid type crash */
    01027                 rb_raise(rb_eTypeError, "invalid instance type");
    01028             }
    01029             RBASIC(self)->klass = klass;
    01030         }
    01031     }
    01032     else {
    01033         rb_scan_args(argc, argv, "01", &mesg);
    01034         error = rb_const_get(klass, rb_intern("Errno"));
    01035     }
    01036     if (!NIL_P(error)) err = strerror(NUM2INT(error));
    01037     else err = "unknown error";
    01038     if (!NIL_P(mesg)) {
    01039         VALUE str = mesg;
    01040
    01041         StringValue(str);
    01042         mesg = rb_sprintf("%s - %.*s", err,
    01043                           (int)RSTRING_LEN(str), RSTRING_PTR(str));
    01044     }
    01045     else {
    01046         mesg = rb_str_new2(err);
    01047     }
    01048     rb_enc_associate(mesg, rb_locale_encoding());
    01049     rb_call_super(1, &mesg);
    01050     rb_iv_set(self, "errno", error);
    01051     return self;
    01052 }
    01053
    01054 /*
    01055  * call-seq:
    01056  *   system_call_error.errno   -> fixnum
    01057  *
    01058  * Return this SystemCallError's error number.
    01059  */
    01060
    01061 static VALUE
    01062 syserr_errno(VALUE self)
    01063 {
    01064     return rb_attr_get(self, rb_intern("errno"));
    01065 }
    01066
    01067 /*
    01068  * call-seq:
    01069  *   system_call_error === other  -> true or false
    01070  *
    01071  * Return +true+ if the receiver is a generic +SystemCallError+, or
    01072  * if the error numbers +self+ and _other_ are the same.
    01073  */
    01074
    01075 static VALUE
    01076 syserr_eqq(VALUE self, VALUE exc)
    01077 {
    01078     VALUE num, e;
    01079     ID en;
    01080
    01081     CONST_ID(en, "errno");
    01082
    01083     if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
    01084         if (!rb_respond_to(exc, en)) return Qfalse;
    01085     }
    01086     else if (self == rb_eSystemCallError) return Qtrue;
    01087
    01088     num = rb_attr_get(exc, rb_intern("errno"));
    01089     if (NIL_P(num)) {
    01090         num = rb_funcall(exc, en, 0, 0);
    01091     }
    01092     e = rb_const_get(self, rb_intern("Errno"));
    01093     if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
    01094         return Qtrue;
    01095     return Qfalse;
    01096 }
    01097
    01098
    01099 /*
    01100  *  Document-class: StandardError
    01101  *
    01102  *  The most standard error types are subclasses of StandardError. A
    01103  *  rescue clause without an explicit Exception class will rescue all
    01104  *  StandardErrors (and only those).
    01105  *
    01106  *     def foo
    01107  *       raise "Oups"
    01108  *     end
    01109  *     foo rescue "Hello"   #=> "Hello"
    01110  *
    01111  *  On the other hand:
    01112  *
    01113  *     require 'does/not/exist' rescue "Hi"
    01114  *
    01115  *  <em>raises the exception:</em>
    01116  *
    01117  *     LoadError: no such file to load -- does/not/exist
    01118  *
    01119  */
    01120
    01121 /*
    01122  *  Document-class: SystemExit
    01123  *
    01124  *  Raised by +exit+ to initiate the termination of the script.
    01125  */
    01126
    01127 /*
    01128  *  Document-class: SignalException
    01129  *
    01130  *  Raised when a signal is received.
    01131  *
    01132  *     begin
    01133  *       Process.kill('HUP',Process.pid)
    01134  *     rescue SignalException => e
    01135  *       puts "received Exception #{e}"
    01136  *     end
    01137  *
    01138  *  <em>produces:</em>
    01139  *
    01140  *     received Exception SIGHUP
    01141  */
    01142
    01143 /*
    01144  *  Document-class: Interrupt
    01145  *
    01146  *  Raised with the interrupt signal is received, typically because the
    01147  *  user pressed on Control-C (on most posix platforms). As such, it is a
    01148  *  subclass of +SignalException+.
    01149  *
    01150  *     begin
    01151  *       puts "Press ctrl-C when you get bored"
    01152  *       loop {}
    01153  *     rescue Interrupt => e
    01154  *       puts "Note: You will typically use Signal.trap instead."
    01155  *     end
    01156  *
    01157  *  <em>produces:</em>
    01158  *
    01159  *     Press ctrl-C when you get bored
    01160  *
    01161  *  <em>then waits until it is interrupted with Control-C and then prints:</em>
    01162  *
    01163  *     Note: You will typically use Signal.trap instead.
    01164  */
    01165
    01166 /*
    01167  *  Document-class: TypeError
    01168  *
    01169  *  Raised when encountering an object that is not of the expected type.
    01170  *
    01171  *     [1, 2, 3].first("two")
    01172  *
    01173  *  <em>raises the exception:</em>
    01174  *
    01175  *     TypeError: can't convert String into Integer
    01176  *
    01177  */
    01178
    01179 /*
    01180  *  Document-class: ArgumentError
    01181  *
    01182  *  Raised when the arguments are wrong and there isn't a more specific
    01183  *  Exception class.
    01184  *
    01185  *  Ex: passing the wrong number of arguments
    01186  *
    01187  *     [1, 2, 3].first(4, 5)
    01188  *
    01189  *  <em>raises the exception:</em>
    01190  *
    01191  *     ArgumentError: wrong number of arguments (2 for 1)
    01192  *
    01193  *  Ex: passing an argument that is not acceptable:
    01194  *
    01195  *     [1, 2, 3].first(-4)
    01196  *
    01197  *  <em>raises the exception:</em>
    01198  *
    01199  *     ArgumentError: negative array size
    01200  */
    01201
    01202 /*
    01203  *  Document-class: IndexError
    01204  *
    01205  *  Raised when the given index is invalid.
    01206  *
    01207  *     a = [:foo, :bar]
    01208  *     a.fetch(0)   #=> :foo
    01209  *     a[4]         #=> nil
    01210  *     a.fetch(4)   #=> IndexError: index 4 outside of array bounds: -2...2
    01211  *
    01212  */
    01213
    01214 /*
    01215  *  Document-class: KeyError
    01216  *
    01217  *  Raised when the specified key is not found. It is a subclass of
    01218  *  IndexError.
    01219  *
    01220  *     h = {"foo" => :bar}
    01221  *     h.fetch("foo") #=> :bar
    01222  *     h.fetch("baz") #=> KeyError: key not found: "baz"
    01223  *
    01224  */
    01225
    01226 /*
    01227  *  Document-class: RangeError
    01228  *
    01229  *  Raised when a given numerical value is out of range.
    01230  *
    01231  *     [1, 2, 3].drop(1 << 100)
    01232  *
    01233  *  <em>raises the exception:</em>
    01234  *
    01235  *     RangeError: bignum too big to convert into `long'
    01236  */
    01237
    01238 /*
    01239  *  Document-class: ScriptError
    01240  *
    01241  *  ScriptError is the superclass for errors raised when a script
    01242  *  can not be executed because of a +LoadError+,
    01243  *  +NotImplementedError+ or a +SyntaxError+. Note these type of
    01244  *  +ScriptErrors+ are not +StandardError+ and will not be
    01245  *  rescued unless it is specified explicitly (or its ancestor
    01246  *  +Exception+).
    01247  */
    01248
    01249 /*
    01250  *  Document-class: SyntaxError
    01251  *
    01252  *  Raised when encountering Ruby code with an invalid syntax.
    01253  *
    01254  *     eval("1+1=2")
    01255  *
    01256  *  <em>raises the exception:</em>
    01257  *
    01258  *     SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
    01259  */
    01260
    01261 /*
    01262  *  Document-class: LoadError
    01263  *
    01264  *  Raised when a file required (a Ruby script, extension library, ...)
    01265  *  fails to load.
    01266  *
    01267  *     require 'this/file/does/not/exist'
    01268  *
    01269  *  <em>raises the exception:</em>
    01270  *
    01271  *     LoadError: no such file to load -- this/file/does/not/exist
    01272  */
    01273
    01274 /*
    01275  *  Document-class: NotImplementedError
    01276  *
    01277  *  Raised when a feature is not implemented on the current platform. For
    01278  *  example, methods depending on the +fsync+ or +fork+ system calls may
    01279  *  raise this exception if the underlying operating system or Ruby
    01280  *  runtime does not support them.
    01281  *
    01282  *  Note that if +fork+ raises a +NotImplementedError+, then
    01283  *  <code>respond_to?(:fork)</code> returns +false+.
    01284  */
    01285
    01286 /*
    01287  *  Document-class: NameError
    01288  *
    01289  *  Raised when a given name is invalid or undefined.
    01290  *
    01291  *     puts foo
    01292  *
    01293  *  <em>raises the exception:</em>
    01294  *
    01295  *     NameError: undefined local variable or method `foo' for main:Object
    01296  *
    01297  *  Since constant names must start with a capital:
    01298  *
    01299  *     Fixnum.const_set :answer, 42
    01300  *
    01301  *  <em>raises the exception:</em>
    01302  *
    01303  *     NameError: wrong constant name answer
    01304  */
    01305
    01306 /*
    01307  *  Document-class: NoMethodError
    01308  *
    01309  *  Raised when a method is called on a receiver which doesn't have it
    01310  *  defined and also fails to respond with +method_missing+.
    01311  *
    01312  *     "hello".to_ary
    01313  *
    01314  *  <em>raises the exception:</em>
    01315  *
    01316  *     NoMethodError: undefined method `to_ary' for "hello":String
    01317  */
    01318
    01319 /*
    01320  *  Document-class: RuntimeError
    01321  *
    01322  *  A generic error class raised when an invalid operation is attempted.
    01323  *
    01324  *     [1, 2, 3].freeze << 4
    01325  *
    01326  *  <em>raises the exception:</em>
    01327  *
    01328  *     RuntimeError: can't modify frozen array
    01329  *
    01330  *  Kernel.raise will raise a RuntimeError if no Exception class is
    01331  *  specified.
    01332  *
    01333  *     raise "ouch"
    01334  *
    01335  *  <em>raises the exception:</em>
    01336  *
    01337  *     RuntimeError: ouch
    01338  */
    01339
    01340 /*
    01341  *  Document-class: SecurityError
    01342  *
    01343  *  Raised when attempting a potential unsafe operation, typically when
    01344  *  the $SAFE level is raised above 0.
    01345  *
    01346  *     foo = "bar"
    01347  *     proc = Proc.new do
    01348  *       $SAFE = 4
    01349  *       foo.gsub! "a", "*"
    01350  *     end
    01351  *     proc.call
    01352  *
    01353  *  <em>raises the exception:</em>
    01354  *
    01355  *     SecurityError: Insecure: can't modify string
    01356  */
    01357
    01358 /*
    01359  *  Document-class: NoMemoryError
    01360  *
    01361  *  Raised when memory allocation fails.
    01362  */
    01363
    01364 /*
    01365  *  Document-class: SystemCallError
    01366  *
    01367  *  SystemCallError is the base class for all low-level
    01368  *  platform-dependent errors.
    01369  *
    01370  *  The errors available on the current platform are subclasses of
    01371  *  SystemCallError and are defined in the Errno module.
    01372  *
    01373  *     File.open("does/not/exist")
    01374  *
    01375  *  <em>raises the exception:</em>
    01376  *
    01377  *     Errno::ENOENT: No such file or directory - does/not/exist
    01378  */
    01379
    01380 /*
    01381  *  Document-class: Encoding::CompatibilityError
    01382  *
    01383  *  Raised by Encoding and String methods when the source encoding is
    01384  *  incompatible with the target encoding.
    01385  */
    01386
    01387 /*
    01388  *  Descendants of class <code>Exception</code> are used to communicate
    01389  *  between <code>raise</code> methods and <code>rescue</code>
    01390  *  statements in <code>begin/end</code> blocks. <code>Exception</code>
    01391  *  objects carry information about the exception---its type (the
    01392  *  exception's class name), an optional descriptive string, and
    01393  *  optional traceback information. Programs may subclass
    01394  *  <code>Exception</code>, or more typically <code>StandardError</code>
    01395  *  to provide custom classes and add additional information.
    01396  */
    01397
    01398 void
    01399 Init_Exception(void)
    01400 {
    01401     rb_eException   = rb_define_class("Exception", rb_cObject);
    01402     rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
    01403     rb_define_method(rb_eException, "exception", exc_exception, -1);
    01404     rb_define_method(rb_eException, "initialize", exc_initialize, -1);
    01405     rb_define_method(rb_eException, "==", exc_equal, 1);
    01406     rb_define_method(rb_eException, "to_s", exc_to_s, 0);
    01407     rb_define_method(rb_eException, "message", exc_message, 0);
    01408     rb_define_method(rb_eException, "inspect", exc_inspect, 0);
    01409     rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
    01410     rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
    01411
    01412     rb_eSystemExit  = rb_define_class("SystemExit", rb_eException);
    01413     rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
    01414     rb_define_method(rb_eSystemExit, "status", exit_status, 0);
    01415     rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
    01416
    01417     rb_eFatal       = rb_define_class("fatal", rb_eException);
    01418     rb_eSignal      = rb_define_class("SignalException", rb_eException);
    01419     rb_eInterrupt   = rb_define_class("Interrupt", rb_eSignal);
    01420
    01421     rb_eStandardError = rb_define_class("StandardError", rb_eException);
    01422     rb_eTypeError     = rb_define_class("TypeError", rb_eStandardError);
    01423     rb_eArgError      = rb_define_class("ArgumentError", rb_eStandardError);
    01424     rb_eIndexError    = rb_define_class("IndexError", rb_eStandardError);
    01425     rb_eKeyError      = rb_define_class("KeyError", rb_eIndexError);
    01426     rb_eRangeError    = rb_define_class("RangeError", rb_eStandardError);
    01427
    01428     rb_eScriptError = rb_define_class("ScriptError", rb_eException);
    01429     rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
    01430     rb_eLoadError   = rb_define_class("LoadError", rb_eScriptError);
    01431     rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
    01432
    01433     rb_eNameError     = rb_define_class("NameError", rb_eStandardError);
    01434     rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
    01435     rb_define_method(rb_eNameError, "name", name_err_name, 0);
    01436     rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
    01437     rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
    01438     rb_define_singleton_method(rb_cNameErrorMesg, "!", rb_name_err_mesg_new, NAME_ERR_MESG_COUNT);
    01439     rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
    01440     rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
    01441     rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1);
    01442     rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
    01443     rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
    01444     rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
    01445     rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
    01446
    01447     rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
    01448     rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
    01449     rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
    01450     rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
    01451     rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
    01452
    01453     syserr_tbl = st_init_numtable();
    01454     rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
    01455     rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
    01456     rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
    01457     rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
    01458
    01459     rb_mErrno = rb_define_module("Errno");
    01460
    01461     rb_define_global_function("warn", rb_warn_m, 1);
    01462 }
    01463
    01464 void
    01465 rb_raise(VALUE exc, const char *fmt, ...)
    01466 {
    01467     va_list args;
    01468     VALUE mesg;
    01469
    01470     va_start(args, fmt);
    01471     mesg = rb_vsprintf(fmt, args);
    01472     va_end(args);
    01473     rb_exc_raise(rb_exc_new3(exc, mesg));
    01474 }
    01475
    01476 void
    01477 rb_loaderror(const char *fmt, ...)
    01478 {
    01479     va_list args;
    01480     VALUE mesg;
    01481
    01482     va_start(args, fmt);
    01483     mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
    01484     va_end(args);
    01485     rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg));
    01486 }
    01487
    01488 void
    01489 rb_notimplement(void)
    01490 {
    01491     rb_raise(rb_eNotImpError,
    01492              "%s() function is unimplemented on this machine",
    01493              rb_id2name(rb_frame_this_func()));
    01494 }
    01495
    01496 void
    01497 rb_fatal(const char *fmt, ...)
    01498 {
    01499     va_list args;
    01500     VALUE mesg;
    01501
    01502     va_start(args, fmt);
    01503     mesg = rb_vsprintf(fmt, args);
    01504     va_end(args);
    01505
    01506     rb_exc_fatal(rb_exc_new3(rb_eFatal, mesg));
    01507 }
    01508
    01509 static VALUE
    01510 make_errno_exc(const char *mesg)
    01511 {
    01512     int n = errno;
    01513     VALUE arg;
    01514
    01515     errno = 0;
    01516     if (n == 0) {
    01517         rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
    01518     }
    01519
    01520     arg = mesg ? rb_str_new2(mesg) : Qnil;
    01521     return rb_class_new_instance(1, &arg, get_syserr(n));
    01522 }
    01523
    01524 void
    01525 rb_sys_fail(const char *mesg)
    01526 {
    01527     rb_exc_raise(make_errno_exc(mesg));
    01528 }
    01529
    01530 void
    01531 rb_mod_sys_fail(VALUE mod, const char *mesg)
    01532 {
    01533     VALUE exc = make_errno_exc(mesg);
    01534     rb_extend_object(exc, mod);
    01535     rb_exc_raise(exc);
    01536 }
    01537
    01538 void
    01539 rb_sys_warning(const char *fmt, ...)
    01540 {
    01541     char buf[BUFSIZ];
    01542     va_list args;
    01543     int errno_save;
    01544
    01545     errno_save = errno;
    01546
    01547     if (!RTEST(ruby_verbose)) return;
    01548
    01549     snprintf(buf, BUFSIZ, "warning: %s", fmt);
    01550     snprintf(buf+strlen(buf), BUFSIZ-strlen(buf), ": %s", strerror(errno_save));
    01551
    01552     va_start(args, fmt);
    01553     warn_print(buf, args);
    01554     va_end(args);
    01555     errno = errno_save;
    01556 }
    01557
    01558 void
    01559 rb_load_fail(const char *path)
    01560 {
    01561     rb_loaderror("%s -- %s", strerror(errno), path);
    01562 }
    01563
    01564 void
    01565 rb_error_frozen(const char *what)
    01566 {
    01567     rb_raise(rb_eRuntimeError, "can't modify frozen %s", what);
    01568 }
    01569
    01570 void
    01571 rb_check_frozen(VALUE obj)
    01572 {
    01573     if (OBJ_FROZEN(obj)) rb_error_frozen(rb_obj_classname(obj));
    01574 }
    01575
    01576 void
    01577 Init_syserr(void)
    01578 {
    01579     rb_eNOERROR = set_syserr(0, "NOERROR");
    01580 #define defined_error(name, num) set_syserr(num, name);
    01581 #define undefined_error(name) set_syserr(0, name);
    01582 #include "known_errors.inc"
    01583 #undef defined_error
    01584 #undef undefined_error
    01585 }
    01586
    01587 static void
    01588 err_append(const char *s)
    01589 {
    01590     rb_thread_t *th = GET_THREAD();
    01591     VALUE err = th->errinfo;
    01592
    01593     if (th->mild_compile_error) {
    01594         if (!RTEST(err)) {
    01595             err = rb_exc_new2(rb_eSyntaxError, s);
    01596             th->errinfo = err;
    01597         }
    01598         else {
    01599             VALUE str = rb_obj_as_string(err);
    01600
    01601             rb_str_cat2(str, "\n");
    01602             rb_str_cat2(str, s);
    01603             th->errinfo = rb_exc_new3(rb_eSyntaxError, str);
    01604         }
    01605     }
    01606     else {
    01607         if (!RTEST(err)) {
    01608             err = rb_exc_new2(rb_eSyntaxError, "compile error");
    01609             th->errinfo = err;
    01610         }
    01611         rb_write_error(s);
    01612         rb_write_error("\n");
    01613     }
    01614 }
    01615