Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# eval_error.c

Go to the documentation of this file.

    00001 /* -*-c-*- */
    00002 /*
    00003  * included by eval.c
    00004  */
    00005
    00006 static void
    00007 warn_printf(const char *fmt, ...)
    00008 {
    00009     char buf[BUFSIZ];
    00010     va_list args;
    00011
    00012     va_init_list(args, fmt);
    00013     vsnprintf(buf, BUFSIZ, fmt, args);
    00014     va_end(args);
    00015     rb_write_error(buf);
    00016 }
    00017
    00018 #define warn_print(x) rb_write_error(x)
    00019 #define warn_print2(x,l) rb_write_error2(x,l)
    00020
    00021 static void
    00022 error_pos(void)
    00023 {
    00024     const char *sourcefile = rb_sourcefile();
    00025     int sourceline = rb_sourceline();
    00026
    00027     if (sourcefile) {
    00028         if (sourceline == 0) {
    00029             warn_printf("%s", sourcefile);
    00030         }
    00031         else if (rb_frame_callee()) {
    00032             warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
    00033                         rb_id2name(rb_frame_callee()));
    00034         }
    00035         else {
    00036             warn_printf("%s:%d", sourcefile, sourceline);
    00037         }
    00038     }
    00039 }
    00040
    00041 VALUE rb_check_backtrace(VALUE);
    00042
    00043 static VALUE
    00044 get_backtrace(VALUE info)
    00045 {
    00046     if (NIL_P(info))
    00047         return Qnil;
    00048     info = rb_funcall(info, rb_intern("backtrace"), 0);
    00049     if (NIL_P(info))
    00050         return Qnil;
    00051     return rb_check_backtrace(info);
    00052 }
    00053
    00054 VALUE
    00055 rb_get_backtrace(VALUE info)
    00056 {
    00057     return get_backtrace(info);
    00058 }
    00059
    00060 static void
    00061 set_backtrace(VALUE info, VALUE bt)
    00062 {
    00063     rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
    00064 }
    00065
    00066 static void
    00067 error_print(void)
    00068 {
    00069     volatile VALUE errat = Qnil;                /* OK */
    00070     rb_thread_t *th = GET_THREAD();
    00071     VALUE errinfo = th->errinfo;
    00072     int raised_flag = th->raised_flag;
    00073     volatile VALUE eclass, e;
    00074     const char *volatile einfo;
    00075     volatile long elen;
    00076
    00077     if (NIL_P(errinfo))
    00078         return;
    00079     rb_thread_raised_clear(th);
    00080
    00081     PUSH_TAG();
    00082     if (EXEC_TAG() == 0) {
    00083         errat = get_backtrace(errinfo);
    00084     }
    00085     else {
    00086         errat = Qnil;
    00087     }
    00088     if (EXEC_TAG())
    00089         goto error;
    00090     if (NIL_P(errat)) {
    00091         const char *file = rb_sourcefile();
    00092         int line = rb_sourceline();
    00093         if (!file)
    00094             warn_printf("%d", line);
    00095         else if (!line)
    00096             warn_printf("%s", file);
    00097         else
    00098             warn_printf("%s:%d", file, line);
    00099     }
    00100     else if (RARRAY_LEN(errat) == 0) {
    00101         error_pos();
    00102     }
    00103     else {
    00104         VALUE mesg = RARRAY_PTR(errat)[0];
    00105
    00106         if (NIL_P(mesg))
    00107             error_pos();
    00108         else {
    00109             warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
    00110         }
    00111     }
    00112
    00113     eclass = CLASS_OF(errinfo);
    00114     if (EXEC_TAG() == 0) {
    00115         e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
    00116         StringValue(e);
    00117         einfo = RSTRING_PTR(e);
    00118         elen = RSTRING_LEN(e);
    00119     }
    00120     else {
    00121         einfo = "";
    00122         elen = 0;
    00123     }
    00124     if (EXEC_TAG())
    00125         goto error;
    00126     if (eclass == rb_eRuntimeError && elen == 0) {
    00127         warn_print(": unhandled exception\n");
    00128     }
    00129     else {
    00130         VALUE epath;
    00131
    00132         epath = rb_class_name(eclass);
    00133         if (elen == 0) {
    00134             warn_print(": ");
    00135             warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
    00136             warn_print("\n");
    00137         }
    00138         else {
    00139             char *tail = 0;
    00140             long len = elen;
    00141
    00142             if (RSTRING_PTR(epath)[0] == '#')
    00143                 epath = 0;
    00144             if ((tail = memchr(einfo, '\n', elen)) != 0) {
    00145                 len = tail - einfo;
    00146                 tail++;         /* skip newline */
    00147             }
    00148             warn_print(": ");
    00149             warn_print2(einfo, len);
    00150             if (epath) {
    00151                 warn_print(" (");
    00152                 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
    00153                 warn_print(")\n");
    00154             }
    00155             if (tail) {
    00156                 warn_print2(tail, elen - len - 1);
    00157                 if (einfo[elen-1] != '\n') warn_print2("\n", 1);
    00158             }
    00159         }
    00160     }
    00161
    00162     if (!NIL_P(errat)) {
    00163         long i;
    00164         long len = RARRAY_LEN(errat);
    00165         VALUE *ptr = RARRAY_PTR(errat);
    00166         int skip = eclass == rb_eSysStackError;
    00167
    00168 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
    00169 #define TRACE_HEAD 8
    00170 #define TRACE_TAIL 5
    00171
    00172         for (i = 1; i < len; i++) {
    00173             if (TYPE(ptr[i]) == T_STRING) {
    00174                 warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
    00175             }
    00176             if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
    00177                 warn_printf("\t ... %ld levels...\n",
    00178                             len - TRACE_HEAD - TRACE_TAIL);
    00179                 i = len - TRACE_TAIL;
    00180             }
    00181         }
    00182     }
    00183   error:
    00184     POP_TAG();
    00185     rb_thread_raised_set(th, raised_flag);
    00186 }
    00187
    00188 void
    00189 ruby_error_print(void)
    00190 {
    00191     error_print();
    00192 }
    00193
    00194 void
    00195 rb_print_undef(VALUE klass, ID id, int scope)
    00196 {
    00197     const char *v;
    00198
    00199     switch (scope) {
    00200       default:
    00201       case NOEX_PUBLIC: v = ""; break;
    00202       case NOEX_PRIVATE: v = " private"; break;
    00203       case NOEX_PROTECTED: v = " protected"; break;
    00204     }
    00205     rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
    00206                   rb_id2name(id),
    00207                   (TYPE(klass) == T_MODULE) ? "module" : "class",
    00208                   rb_class2name(klass));
    00209 }
    00210
    00211 static int
    00212 sysexit_status(VALUE err)
    00213 {
    00214     VALUE st = rb_iv_get(err, "status");
    00215     return NUM2INT(st);
    00216 }
    00217
    00218 static int
    00219 error_handle(int ex)
    00220 {
    00221     int status = EXIT_FAILURE;
    00222     rb_thread_t *th = GET_THREAD();
    00223
    00224     if (rb_threadptr_set_raised(th))
    00225         return EXIT_FAILURE;
    00226     switch (ex & TAG_MASK) {
    00227       case 0:
    00228         status = EXIT_SUCCESS;
    00229         break;
    00230
    00231       case TAG_RETURN:
    00232         error_pos();
    00233         warn_print(": unexpected return\n");
    00234         break;
    00235       case TAG_NEXT:
    00236         error_pos();
    00237         warn_print(": unexpected next\n");
    00238         break;
    00239       case TAG_BREAK:
    00240         error_pos();
    00241         warn_print(": unexpected break\n");
    00242         break;
    00243       case TAG_REDO:
    00244         error_pos();
    00245         warn_print(": unexpected redo\n");
    00246         break;
    00247       case TAG_RETRY:
    00248         error_pos();
    00249         warn_print(": retry outside of rescue clause\n");
    00250         break;
    00251       case TAG_THROW:
    00252         /* TODO: fix me */
    00253         error_pos();
    00254         warn_printf(": unexpected throw\n");
    00255         break;
    00256       case TAG_RAISE: {
    00257         VALUE errinfo = GET_THREAD()->errinfo;
    00258         if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
    00259             status = sysexit_status(errinfo);
    00260         }
    00261         else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
    00262             /* no message when exiting by signal */
    00263         }
    00264         else {
    00265             error_print();
    00266         }
    00267         break;
    00268       }
    00269       case TAG_FATAL:
    00270         error_print();
    00271         break;
    00272       default:
    00273         rb_bug("Unknown longjmp status %d", ex);
    00274         break;
    00275     }
    00276     rb_threadptr_reset_raised(th);
    00277     return status;
    00278 }
    00279