static int search_required(VALUE fname, volatile VALUE *path, int safe_level) { VALUE tmp; char *ext, *ftptr; int type, ft = 0; const char *loading; *path = 0; ext = strrchr(ftptr = RSTRING_PTR(fname), '.'); if (ext && !strchr(ext, '/')) { if (IS_RBEXT(ext)) { if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 'r'; } if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading) *path = tmp; return 'r'; } return 0; } else if (IS_SOEXT(ext)) { if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 's'; } tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname)); #ifdef DLEXT2 OBJ_FREEZE(tmp); if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) *path = tmp; return 's'; } #else rb_str_cat2(tmp, DLEXT); OBJ_FREEZE(tmp); if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) *path = tmp; return 's'; } #endif } else if (IS_DLEXT(ext)) { if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 's'; } if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) *path = tmp; return 's'; } } } else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 'r'; } tmp = fname; type = rb_find_file_ext_safe(&tmp, loadable_ext, safe_level); switch (type) { case 0: if (ft) goto statically_linked; ftptr = RSTRING_PTR(tmp); return rb_feature_p(ftptr, 0, FALSE, TRUE, 0); default: if (ft) { statically_linked: if (loading) *path = rb_filesystem_str_new_cstr(loading); return ft; } case 1: ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading) break; *path = tmp; } return type ? 's' : 'r'; }
static void error_print(void) { volatile VALUE errat = Qundef; rb_thread_t *th = GET_THREAD(); VALUE errinfo = th->errinfo; int raised_flag = th->raised_flag; volatile VALUE eclass = Qundef, e = Qundef; const char *volatile einfo; volatile long elen; if (NIL_P(errinfo)) return; rb_thread_raised_clear(th); TH_PUSH_TAG(th); if (TH_EXEC_TAG() == 0) { errat = get_backtrace(errinfo); } else if (errat == Qundef) { errat = Qnil; } else if (eclass == Qundef || e != Qundef) { goto error; } else { goto no_message; } if (NIL_P(errat)) { const char *file = rb_sourcefile(); int line = rb_sourceline(); if (!file) warn_printf("%d", line); else if (!line) warn_printf("%s", file); else warn_printf("%s:%d", file, line); } else if (RARRAY_LEN(errat) == 0) { error_pos(); } else { VALUE mesg = RARRAY_AREF(errat, 0); if (NIL_P(mesg)) error_pos(); else { warn_print_str(mesg); } } eclass = CLASS_OF(errinfo); if (eclass != Qundef && (e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0)) != Qundef && (RB_TYPE_P(e, T_STRING) || !NIL_P(e = rb_check_string_type(e)))) { einfo = RSTRING_PTR(e); elen = RSTRING_LEN(e); } else { no_message: einfo = ""; elen = 0; } if (eclass == rb_eRuntimeError && elen == 0) { warn_print(": unhandled exception\n"); } else { VALUE epath; epath = rb_class_name(eclass); if (elen == 0) { warn_print(": "); warn_print_str(epath); warn_print("\n"); } else { char *tail = 0; long len = elen; if (RSTRING_PTR(epath)[0] == '#') epath = 0; if ((tail = memchr(einfo, '\n', elen)) != 0) { len = tail - einfo; tail++; /* skip newline */ } warn_print(": "); warn_print_str(tail ? rb_str_subseq(e, 0, len) : e); if (epath) { warn_print(" ("); warn_print_str(epath); warn_print(")\n"); } if (tail) { warn_print_str(rb_str_subseq(e, tail - einfo, elen - len - 1)); } if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2("\n", 1); } } if (!NIL_P(errat)) { long i; long len = RARRAY_LEN(errat); int skip = eclass == rb_eSysStackError; #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) #define TRACE_HEAD 8 #define TRACE_TAIL 5 for (i = 1; i < len; i++) { VALUE line = RARRAY_AREF(errat, i); if (RB_TYPE_P(line, T_STRING)) { warn_printf("\tfrom %"PRIsVALUE"\n", line); } if (skip && i == TRACE_HEAD && len > TRACE_MAX) { warn_printf("\t ... %ld levels...\n", len - TRACE_HEAD - TRACE_TAIL); i = len - TRACE_TAIL; } } } error: TH_POP_TAG(); th->errinfo = errinfo; rb_thread_raised_set(th, raised_flag); }
VALUE string_spec_rb_str_subseq(VALUE self, VALUE str, VALUE beg, VALUE len) { return rb_str_subseq(str, FIX2INT(beg), FIX2INT(len)); }
VALUE rb_f_kill(int argc, const VALUE *argv) { #ifndef HAVE_KILLPG #define killpg(pg, sig) kill(-(pg), (sig)) #endif int negative = 0; int sig; int i; VALUE str; const char *s; rb_secure(2); rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS); switch (TYPE(argv[0])) { case T_FIXNUM: sig = FIX2INT(argv[0]); break; case T_SYMBOL: str = rb_sym2str(argv[0]); goto str_signal; case T_STRING: str = argv[0]; str_signal: s = RSTRING_PTR(str); if (s[0] == '-') { negative++; s++; } if (strncmp(signame_prefix, s, sizeof(signame_prefix)) == 0) s += 3; if ((sig = signm2signo(s)) == 0) { long ofs = s - RSTRING_PTR(str); if (ofs) str = rb_str_subseq(str, ofs, RSTRING_LEN(str)-ofs); rb_raise(rb_eArgError, "unsupported name `SIG%"PRIsVALUE"'", str); } if (negative) sig = -sig; break; default: str = rb_check_string_type(argv[0]); if (!NIL_P(str)) { goto str_signal; } rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0])); break; } if (argc <= 1) return INT2FIX(0); if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { if (killpg(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } else { const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1; int wakeup = 0; for (i=1; i<argc; i++) { rb_pid_t pid = NUM2PIDT(argv[i]); if ((sig != 0) && (self != -1) && (pid == self)) { int t; /* * When target pid is self, many caller assume signal will be * delivered immediately and synchronously. */ switch (sig) { case SIGSEGV: #ifdef SIGBUS case SIGBUS: #endif #ifdef SIGKILL case SIGKILL: #endif #ifdef SIGSTOP case SIGSTOP: #endif ruby_kill(pid, sig); break; default: t = signal_ignored(sig); if (t) { if (t < 0 && kill(pid, sig)) rb_sys_fail(0); break; } signal_enque(sig); wakeup = 1; } } else if (kill(pid, sig) < 0) { rb_sys_fail(0); } } if (wakeup) { rb_threadptr_check_signal(GET_VM()->main_thread); } } rb_thread_execute_interrupts(rb_thread_current()); return INT2FIX(i-1); }