• 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 

Generated on Sat Jul 7 2012 15:29:02 for Ruby by  doxygen 1.7.1