(linenum→info "unix/slp.c:2238")

ruby/1.9.0/eval_error.c

    1: /* -*-c-*- */
    2: /*
    3:  * included by eval.c
    4:  */
    5: 
    6: const char *
    7: rb_sourcefile(void)
    8: {
    9:     rb_thread_t *th = GET_THREAD();
   10:     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
   11: 
   12:     if (cfp) {
   13:         return RSTRING_PTR(cfp->iseq->filename);
   14:     }
   15:     else {
   16:         return 0;
   17:     }
   18: }
   19: 
   20: int
   21: rb_sourceline(void)
   22: {
   23:     rb_thread_t *th = GET_THREAD();
   24:     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
   25: 
   26:     if (cfp) {
   27:         return vm_get_sourceline(cfp);
   28:     }
   29:     else {
   30:         return 0;
   31:     }
   32: }
   33: 
   34: static void
   35: warn_printf(const char *fmt, ...)
   36: {
   37:     char buf[BUFSIZ];
   38:     va_list args;
   39: 
   40:     va_init_list(args, fmt);
   41:     vsnprintf(buf, BUFSIZ, fmt, args);
   42:     va_end(args);
   43:     rb_write_error(buf);
   44: }
   45: 
   46: #define warn_print(x) rb_write_error(x)
   47: #define warn_print2(x,l) rb_write_error2(x,l)
   48: 
   49: static void
   50: error_pos(void)
   51: {
   52:     const char *sourcefile = rb_sourcefile();
   53:     int sourceline = rb_sourceline();
   54: 
   55:     if (sourcefile) {
   56:         if (sourceline == 0) {
   57:             warn_printf("%s", sourcefile);
   58:         }
   59:         else if (rb_frame_callee()) {
   60:             warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
   61:                         rb_id2name(rb_frame_callee()));
   62:         }
   63:         else {
   64:             warn_printf("%s:%d", sourcefile, sourceline);
   65:         }
   66:     }
   67: }
   68: 
   69: VALUE rb_check_backtrace(VALUE);
   70: 
   71: static VALUE
   72: get_backtrace(VALUE info)
   73: {
   74:     if (NIL_P(info))
   75:         return Qnil;
   76:     info = rb_funcall(info, rb_intern("backtrace"), 0);
   77:     if (NIL_P(info))
   78:         return Qnil;
   79:     return rb_check_backtrace(info);
   80: }
   81: 
   82: static void
   83: set_backtrace(VALUE info, VALUE bt)
   84: {
   85:     rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
   86: }
   87: 
   88: static void
   89: error_print(void)
   90: {
   91:     VALUE errat = Qnil;         /* OK */
   92:     VALUE errinfo = GET_THREAD()->errinfo;
   93:     volatile VALUE eclass, e;
   94:     char *einfo;
   95:     long elen;
   96: 
   97:     if (NIL_P(errinfo))
   98:         return;
   99: 
  100:     PUSH_TAG();
  101:     if (EXEC_TAG() == 0) {
  102:         errat = get_backtrace(errinfo);
  103:     }
  104:     else {
  105:         errat = Qnil;
  106:     }
  107:     if (EXEC_TAG())
  108:         goto error;
  109:     if (NIL_P(errat)) {
  110:         const char *file = rb_sourcefile();
  111:         int line = rb_sourceline();
  112:         if (file)
  113:             warn_printf("%s:%d", file, line);
  114:         else
  115:             warn_printf("%d", line);
  116:     }
  117:     else if (RARRAY_LEN(errat) == 0) {
  118:         error_pos();
  119:     }
  120:     else {
  121:         VALUE mesg = RARRAY_PTR(errat)[0];
  122: 
  123:         if (NIL_P(mesg))
  124:             error_pos();
  125:         else {
  126:             warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
  127:         }
  128:     }
  129: 
  130:     eclass = CLASS_OF(errinfo);
  131:     if (EXEC_TAG() == 0) {
  132:         e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
  133:         StringValue(e);
  134:         einfo = RSTRING_PTR(e);
  135:         elen = RSTRING_LEN(e);
  136:     }
  137:     else {
  138:         einfo = "";
  139:         elen = 0;
  140:     }
  141:     if (EXEC_TAG())
  142:         goto error;
  143:     if (eclass == rb_eRuntimeError && elen == 0) {
  144:         warn_print(": unhandled exception\n");
  145:     }
  146:     else {
  147:         VALUE epath;
  148: 
  149:         epath = rb_class_name(eclass);
  150:         if (elen == 0) {
  151:             warn_print(": ");
  152:             warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
  153:             warn_print("\n");
  154:         }
  155:         else {
  156:             char *tail = 0;
  157:             long len = elen;
  158: 
  159:             if (RSTRING_PTR(epath)[0] == '#')
  160:                 epath = 0;
  161:             if ((tail = memchr(einfo, '\n', elen)) != 0) {
  162:                 len = tail - einfo;
  163:                 tail++;               /* skip newline */
  164:             }
  165:             warn_print(": ");
  166:             warn_print2(einfo, len);
  167:             if (epath) {
  168:                 warn_print(" (");
  169:                 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
  170:                 warn_print(")\n");
  171:             }
  172:             if (tail) {
  173:                 warn_print2(tail, elen - len - 1);
  174:             }
  175:         }
  176:     }
  177: 
  178:     if (!NIL_P(errat)) {
  179:         long i;
  180:         long len = RARRAY_LEN(errat);
  181:         VALUE *ptr = RARRAY_PTR(errat);
  182:         int skip = eclass == rb_eSysStackError;
  183:         
  184: #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
  185: #define TRACE_HEAD 8
  186: #define TRACE_TAIL 5
  187: 
  188:         for (i = 1; i < len; i++) {
  189:             if (TYPE(ptr[i]) == T_STRING) {
  190:                 warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
  191:             }
  192:             if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
  193:                 warn_printf("\t ... %ld levels...\n",
  194:                             len - TRACE_HEAD - TRACE_TAIL);
  195:                 i = len - TRACE_TAIL;
  196:             }
  197:         }
  198:     }
  199:   error:
  200:     POP_TAG();
  201: }
  202: 
  203: void
  204: ruby_error_print(void)
  205: {
  206:     error_print();
  207: }
  208: 
  209: void
  210: rb_print_undef(VALUE klass, ID id, int scope)
  211: {
  212:     char *v;
  213: 
  214:     switch (scope) {
  215:       default:
  216:       case NOEX_PUBLIC: v = ""; break;
  217:       case NOEX_PRIVATE: v = " private"; break;
  218:       case NOEX_PROTECTED: v = " protected"; break;
  219:     }
  220:     rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
  221:                   rb_id2name(id),
  222:                   (TYPE(klass) == T_MODULE) ? "module" : "class",
  223:                   rb_class2name(klass));
  224: }
  225: 
  226: static int
  227: sysexit_status(VALUE err)
  228: {
  229:     VALUE st = rb_iv_get(err, "status");
  230:     return NUM2INT(st);
  231: }
  232: 
  233: static int
  234: error_handle(int ex)
  235: {
  236:     int status = EXIT_FAILURE;
  237:     rb_thread_t *th = GET_THREAD();
  238: 
  239:     if (thread_set_raised(th))
  240:         return EXIT_FAILURE;
  241:     switch (ex & TAG_MASK) {
  242:       case 0:
  243:         status = EXIT_SUCCESS;
  244:         break;
  245: 
  246:       case TAG_RETURN:
  247:         error_pos();
  248:         warn_print(": unexpected return\n");
  249:         break;
  250:       case TAG_NEXT:
  251:         error_pos();
  252:         warn_print(": unexpected next\n");
  253:         break;
  254:       case TAG_BREAK:
  255:         error_pos();
  256:         warn_print(": unexpected break\n");
  257:         break;
  258:       case TAG_REDO:
  259:         error_pos();
  260:         warn_print(": unexpected redo\n");
  261:         break;
  262:       case TAG_RETRY:
  263:         error_pos();
  264:         warn_print(": retry outside of rescue clause\n");
  265:         break;
  266:       case TAG_THROW:
  267:         /* TODO: fix me */
  268:         error_pos();
  269:         warn_printf(": unexpected throw\n");
  270:         break;
  271:       case TAG_RAISE:
  272:       case TAG_FATAL: {
  273:         VALUE errinfo = GET_THREAD()->errinfo;
  274:         if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
  275:             status = sysexit_status(errinfo);
  276:         }
  277:         else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
  278:             /* no message when exiting by signal */
  279:         }
  280:         else {
  281:             error_print();
  282:         }
  283:         break;
  284:       }
  285:       default:
  286:         rb_bug("Unknown longjmp status %d", ex);
  287:         break;
  288:     }
  289:     thread_reset_raised(th);
  290:     return status;
  291: }
Syntax (Markdown)