static int print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre) { size_t i; if (n == 0) return 0; for (i=0; i+1<irep->nlocals; i++) { if (irep->lv[i].r == n) { mrb_sym sym = irep->lv[i].name; if (pre) printf(" "); printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym)); return 1; } } return 0; }
void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...) { mrb_value exc, argv[2]; va_list args; char buf[256]; va_start(args, fmt); //argv[0] = mrb_vsprintf(fmt, args); vsnprintf(buf, 256, fmt, args); argv[0] = mrb_str_new(mrb, buf, strlen(buf)); va_end(args); argv[1] = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)); exc = mrb_class_new_instance(mrb, 2, argv, E_NAME_ERROR); mrb_exc_raise(mrb, exc); }
static void showcallinfo(mrb_state *mrb) { mrb_callinfo *ci; mrb_int ciidx; const char *filename, *method, *sep; int i, line; printf("trace:\n"); ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx"))); if (ciidx >= mrb->ciend - mrb->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->cibase[i]; filename = "(unknown)"; line = -1; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; } else { mrb_irep *irep = ci->proc->body.irep; if (irep->filename != NULL) filename = irep->filename; if (irep->lines != NULL && i+1 <= ciidx) { mrb_code *pc = mrb->cibase[i+1].pc; if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { line = irep->lines[pc - irep->iseq - 1]; } } } if (ci->target_class == ci->proc->target_class) sep = "."; else sep = "#"; method = mrb_sym2name(mrb, ci->mid); printf("\t[%d] %s:%d%s%s%s%s\n", i, filename, line, method ? ":in " : "", method ? mrb_class_name(mrb, ci->proc->target_class) : "", method ? sep : "", method ? method : ""); } }
static struct RClass * mrb_class_from_path(mrb_state *mrb, mrb_value path) { char *path_s; switch (path.tt) { case MRB_TT_SYMBOL : path_s = (char*) mrb_sym2name(mrb, mrb_symbol(path)); break; case MRB_TT_STRING : path_s = (char*) RSTRING_PTR(path); break; default: throw Exception(Exception::ArgumentError, "dump format error for symbol"); } /* If a symbol contains any colons, mrb_sym2name * will return the string with "s around it * (e.g. :Mod::Class => :"Mod::Class"), * so we need to skip those. */ if (path_s[0] == '\"') path_s++; char *p, *pbgn; mrb_value klass = mrb_obj_value(mrb->object_class); p = pbgn = path_s; while (*p && *p != '\"') { while (*p && *p != ':' && *p != '\"') p++; mrb_sym sym = mrb_intern(mrb, pbgn, p-pbgn); klass = mrb_const_get(mrb, klass, sym); if (p[0] == ':') { if (p[1] != ':') return 0; p += 2; pbgn = p; } } return (struct RClass*) mrb_obj_ptr(klass); }
static mrb_value inspect_struct(mrb_state *mrb, mrb_value s, mrb_value dummy, int recur) { const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s)); mrb_value members, str = mrb_str_new2(mrb, "#<struct "); mrb_value *ptr, *ptr_members; long i, len; if (cn) { mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn)); } if (recur) { return mrb_str_cat2(mrb, str, ":...>"); } members = mrb_struct_members(mrb, s); ptr_members = RARRAY_PTR(members); ptr = RSTRUCT_PTR(s); len = RSTRUCT_LEN(s); for (i=0; i<len; i++) { mrb_value slot; mrb_sym id; if (i > 0) { mrb_str_cat2(mrb, str, ", "); } else if (cn) { mrb_str_cat2(mrb, str, " "); } slot = ptr_members[i]; id = SYM2ID(slot); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { //mrb_str_append(str, mrb_id2str(id)); mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id))); } else { mrb_str_append(mrb, str, mrb_inspect(mrb, slot)); } mrb_str_cat2(mrb, str, "="); mrb_str_append(mrb, str, mrb_inspect(mrb, ptr[i])); } mrb_str_cat2(mrb, str, ">"); return str; }
static mrb_value mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id) { mrb_value *ptr, members, *ptr_members; long i, len; ptr = RSTRUCT_PTR(s); members = mrb_struct_members(mrb, s); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i<len; i++) { if (SYM2ID(ptr_members[i]) == id) { return ptr[i]; } } mrb_name_error(mrb, id, "no member '%s' in struct", mrb_sym2name(mrb, id)); return mrb_nil_value(); /* not reached */ }
static void argnum_error(mrb_state *mrb, int num) { char buf[256]; mrb_value exc; if (mrb->ci->mid) { snprintf(buf, 256, "'%s': wrong number of arguments (%d for %d)", mrb_sym2name(mrb, mrb->ci->mid), mrb->ci->argc, num); } else { snprintf(buf, 256, "wrong number of arguments (%d for %d)", mrb->ci->argc, num); } exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, strlen(buf)); mrb->exc = mrb_object(exc); }
static mrb_value mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id) { mrb_value *ptr, members, *ptr_members; mrb_int i, len; ptr = RSTRUCT_PTR(s); members = mrb_struct_members(mrb, s); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i<len; i++) { if (mrb_symbol(ptr_members[i]) == id) { return ptr[i]; } } mrb_raisef(mrb, E_NAME_ERROR, "no member '%s' in struct", mrb_sym2name(mrb, id)); return mrb_nil_value(); /* not reached */ }
static void argnum_error(mrb_state *mrb, int num) { char buf[256]; int len; mrb_value exc; if (mrb->ci->mid) { len = snprintf(buf, sizeof(buf), "'%s': wrong number of arguments (%d for %d)", mrb_sym2name(mrb, mrb->ci->mid), mrb->ci->argc, num); } else { len = snprintf(buf, sizeof(buf), "wrong number of arguments (%d for %d)", mrb->ci->argc, num); } exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len); mrb->exc = (struct RObject*)mrb_object(exc); }
static int write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) { int sym_no; char *buf_top = buf; char *char_buf; uint16_t buf_size =0; buf_size = MRB_DUMP_DEFAULT_STR_LEN; if ((char_buf = mrb_malloc(mrb, buf_size)) == 0) goto error_exit; buf += uint32_dump((uint32_t)irep->slen, buf, type); /* number of symbol */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { const char * name; uint16_t nlen =0; if (irep->syms[sym_no] != 0) { name = mrb_sym2name(mrb, irep->syms[sym_no]); nlen = str_dump_len((char*)name, strlen(name), type); if ( nlen > buf_size - 1) { buf_size = nlen + 1; if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0) goto error_exit; } memset(char_buf, 0, buf_size); str_dump((char*)name, char_buf, strlen(name), type); buf += uint16_dump(nlen, buf, type); /* length of symbol name */ memcpy(buf, char_buf, nlen); /* symbol name */ buf += nlen; } else { buf += uint16_dump(MRB_DUMP_NULL_SYM_LEN, buf, type); /* length of symbol name */ } } error_exit: if (char_buf) mrb_free(mrb, char_buf); return (int)(buf - buf_top); }
struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) { struct RClass * c; mrb_sym id = mrb_intern(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { c = mrb_class_from_sym(mrb, outer, id); if (c->tt != MRB_TT_MODULE) { mrb_raise(mrb, E_TYPE_ERROR, "%s is not a module", mrb_sym2name(mrb, id)); } return c; } c = mrb_module_new(mrb); setup_class(mrb, mrb_obj_value(outer), c, id); mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c)); return c; }
mrb_value mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) { mrb_value members, slot, *ptr, *ptr_members; long i, len; ptr = RSTRUCT_PTR(obj); members = mrb_struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); slot = mrb_symbol_value(id); len = RARRAY_LEN(members); for (i=0; i<len; i++) { if (mrb_obj_equal(mrb, ptr_members[i], slot)) { return ptr[i]; } } mrb_name_error(mrb, id, "%s is not struct member", mrb_sym2name(mrb, id)); return mrb_nil_value(); /* not reached */ }
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) { struct RClass * cls = c; while (c) { if (c->iv) { iv_tbl *t = c->iv; mrb_value v; if (iv_get(mrb, t, sym, &v)) return v; } c = c->super; } mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %s in %s", mrb_sym2name(mrb, sym), mrb_class_name(mrb, cls)); /* not reached */ return mrb_nil_value(); }
mrb_value mrb_struct_define(mrb_state *mrb, const char *name, ...) { va_list ar; mrb_value nm, ary; char *mem; if (!name) nm = mrb_nil_value(); else nm = mrb_str_new2(mrb, name); ary = mrb_ary_new(mrb); va_start(ar, name); while ((mem = va_arg(ar, char*)) != 0) { mrb_sym slot = mrb_intern(mrb, mem); mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, slot))); } va_end(ar); return make_struct(mrb, nm, ary, struct_class(mrb)); }
void error_pos(void) { #if 0 const char *sourcefile = mrb_sourcefile(); int sourceline = mrb_sourceline(); if (sourcefile) { if (sourceline == 0) { warn_printf("%s", sourcefile); } else if (mrb_frame_callee()) { warn_printf("%s:%d:in `%s'", sourcefile, sourceline, mrb_sym2name(mrb, mrb_frame_callee())); } else { warn_printf("%s:%d", sourcefile, sourceline); } } #endif }
static mrb_value mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) { mrb_value members, slot, *ptr, *ptr_members; long i, len; members = mrb_struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); mrb_struct_modify(obj); ptr = RSTRUCT_PTR(obj); for (i=0; i<len; i++) { slot = ptr_members[i]; if (mrb_id_attrset(SYM2ID(slot)) == 0/*rb_frame_this_func(mrb)*/) { return ptr[i] = val; } } mrb_name_error(mrb, 0/*rb_frame_this_func(mrb)*/, "`%s' is not a struct member", mrb_sym2name(mrb, 0/*rb_frame_this_func(mrb)*/)); return mrb_nil_value(); /* not reached */ }
struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { struct RClass *c, *s; if (mrb_const_defined(mrb, outer, id)) { mrb_value v = mrb_const_get(mrb, outer, id); mrb_check_type(mrb, v, MRB_TT_CLASS); c = mrb_class_ptr(v); if (!mrb_nil_p(super)) { if (mrb_type(super) != MRB_TT_CLASS) { mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); } if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) { mrb_raise(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id)); } } return c; } if (!mrb_nil_p(super)) { if (mrb_type(super) != MRB_TT_CLASS) { mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); } s = mrb_class_ptr(super); } else { s = mrb->object_class; } c = mrb_class_new(mrb, s); setup_class(mrb, outer, c, id); mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); return c; }
/* * call-seq: * obj.instance_variables -> array * * Returns an array of instance variable names for the receiver. Note * that simply defining an accessor does not create the corresponding * instance variable. * * class Fred * attr_accessor :a1 * def initialize * @iv = 3 * end * end * Fred.new.instance_variables #=> [:@iv] */ mrb_value mrb_obj_instance_variables(mrb_state *mrb, mrb_value self) { mrb_value ary; kh_iv_t *h = RCLASS_IV_TBL(self); int i; const char* p; ary = mrb_ary_new(mrb); if (h) { for (i=0;i<kh_end(h);i++) { if (kh_exist(h, i)) { p = mrb_sym2name(mrb, kh_key(h,i)); if (*p == '@') { if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF) mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, p)); } } } } return ary; }
static mrb_value mrb_vedis_append_s(mrb_state *mrb, mrb_value key_obj, mrb_value val_obj, vedis *vstore) { int ret; const char *key = NULL; switch (mrb_type(key_obj)) { case MRB_TT_STRING: key = RSTRING_PTR(key_obj); break; case MRB_TT_SYMBOL: key = mrb_sym2name(mrb, mrb_obj_to_sym(mrb, key_obj)); break; default: mrb_raise(mrb, E_RUNTIME_ERROR, "vedis key type is string or symbol"); } val_obj = mrb_obj_as_string(mrb, val_obj); ret = vedis_kv_append(vstore, key, strlen(key), RSTRING_PTR(val_obj), RSTRING_LEN(val_obj)); if (ret != VEDIS_OK) { mrb_vedis_error(mrb, vstore, 0); } return mrb_true_value(); }
/* * call-seq: * obj.method_missing(symbol [, *args] ) -> result * * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle. * <i>symbol</i> is the symbol for the method called, and <i>args</i> * are any arguments that were passed to it. By default, the interpreter * raises an error when this method is called. However, it is possible * to override the method to provide more dynamic behavior. * If it is decided that a particular method should not be handled, then * <i>super</i> should be called, so that ancestors can pick up the * missing method. * The example below creates * a class <code>Roman</code>, which responds to methods with names * consisting of roman numerals, returning the corresponding integer * values. * * class Roman * def romanToInt(str) * # ... * end * def method_missing(methId) * str = methId.id2name * romanToInt(str) * end * end * * r = Roman.new * r.iv #=> 4 * r.xxiii #=> 23 * r.mm #=> 2000 */ static mrb_value mrb_bob_missing(mrb_state *mrb, mrb_value mod) { mrb_value name, *a; int alen; mrb_value inspect; mrb_get_args(mrb, "o*", &name, &a, &alen); if (!mrb_symbol_p(name)) { mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); } inspect = mrb_funcall(mrb, mod, "inspect", 0); if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mod); } mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%s' for %s", mrb_sym2name(mrb, mrb_symbol(name)), RSTRING_PTR(inspect)); /* not reached */ return mrb_nil_value(); }
/* * call-seq: * obj.remove_instance_variable(symbol) -> obj * * Removes the named instance variable from <i>obj</i>, returning that * variable's value. * * class Dummy * attr_reader :var * def initialize * @var = 99 * end * def remove * remove_instance_variable(:@var) * end * end * d = Dummy.new * d.var #=> 99 * d.remove #=> 99 * d.var #=> nil */ mrb_value mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) { mrb_sym sym; mrb_value name; khash_t(iv) *h; khiter_t k; mrb_value val; mrb_value Qundef = mrb_undef_value(); mrb_get_args(mrb, "o", &name); sym = mrb_to_id(mrb, name); //if (OBJ_FROZEN(obj)) mrb_error_frozen("object"); //if (!mrb_is_instance_id(id)) { // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id)); //} switch (mrb_type(self)) { case MRB_TT_OBJECT: case MRB_TT_CLASS: case MRB_TT_MODULE: if (!mrb_obj_ptr(self)->iv) break; h = mrb_obj_ptr(self)->iv; if (!h) break; k = kh_get(iv, h, sym); if (k != kh_end(h)) { val = kh_value(h, k); if (!mrb_obj_equal(mrb, val, Qundef)) { kh_value(h, k) = Qundef; return val; } } break; default: break; } mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym)); return mrb_nil_value(); /* not reached */ }
static mrb_value const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) { struct RClass *c = base; mrb_value v; iv_tbl *t; mrb_bool retry = 0; mrb_sym cm; L_RETRY: while (c) { if (c->iv) { t = c->iv; if (iv_get(mrb, t, sym, &v)) return v; } c = c->super; } if (!retry && base && base->tt == MRB_TT_MODULE) { c = mrb->object_class; retry = 1; goto L_RETRY; } c = base; cm = mrb_intern2(mrb, "const_missing", 13); while (c) { if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) { mrb_value name = mrb_symbol_value(sym); return mrb_funcall_argv(mrb, mrb_obj_value(c), cm, 1, &name); } c = c->super; } mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %s", mrb_sym2name(mrb, sym)); /* not reached */ return mrb_nil_value(); }
mrb_value mrb_restore_backtrace(mrb_state *mrb) { int i; mrb_value backtrace; backtrace = mrb_ary_new(mrb); for (i = 0; i < mrb->backtrace.n; i++) { int ai; mrb_backtrace_entry *entry; mrb_value mrb_entry; char buf[32]; ai = mrb_gc_arena_save(mrb); entry = &(mrb->backtrace.entries[i]); mrb_entry = mrb_str_new_cstr(mrb, entry->filename); snprintf(buf, sizeof(buf), ":%d", entry->lineno); mrb_str_cat_cstr(mrb, mrb_entry, buf); if (entry->method_id != 0) { mrb_str_cat_lit(mrb, mrb_entry, ":in "); if (entry->klass) { mrb_str_cat_cstr(mrb, mrb_entry, mrb_class_name(mrb, entry->klass)); mrb_str_cat(mrb, mrb_entry, &entry->sep, 1); } mrb_str_cat_cstr(mrb, mrb_entry, mrb_sym2name(mrb, entry->method_id)); } mrb_ary_push(mrb, backtrace, mrb_entry); mrb_gc_arena_restore(mrb, ai); } return backtrace; }
static mrb_value mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) { mrb_value members, *ptr, *ptr_members; mrb_int i, len; members = mrb_struct_members(mrb, s); len = RARRAY_LEN(members); if (RSTRUCT_LEN(s) != len) { mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%" PRIdMRB_INT " required %" PRIdMRB_INT " given)", len, RSTRUCT_LEN(s)); } ptr = RSTRUCT_PTR(s); ptr_members = RARRAY_PTR(members); for (i=0; i<len; i++) { if (mrb_symbol(ptr_members[i]) == id) { ptr[i] = val; return val; } } mrb_raisef(mrb, E_NAME_ERROR, "no member '%s' in struct", mrb_sym2name(mrb, id)); return val; /* not reach */ }
static mrb_value mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) { mrb_value members, *ptr, *ptr_members; long i, len; members = mrb_struct_members(mrb, s); len = RARRAY_LEN(members); mrb_struct_modify(s); if (RSTRUCT_LEN(s) != len) { mrb_raise(mrb, E_TYPE_ERROR, "struct size differs (%ld required %ld given)", len, RSTRUCT_LEN(s)); } ptr = RSTRUCT_PTR(s); ptr_members = RARRAY_PTR(members); for (i=0; i<len; i++) { if (SYM2ID(ptr_members[i]) == id) { ptr[i] = val; return val; } } mrb_name_error(mrb, id, "no member '%s' in struct", mrb_sym2name(mrb, id)); return val; /* not reach */ }
static uint32_t get_syms_block_size(mrb_state *mrb, mrb_irep *irep, int type) { uint32_t size = 0; int sym_no; size += MRB_DUMP_SIZE_OF_LONG; /* slen */ size += MRB_DUMP_SIZE_OF_SHORT; /* crc */ size = DUMP_SIZE(size, type); for (sym_no = 0; sym_no < irep->slen; sym_no++) { const char * name; uint16_t nlen =0; size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type); /* snl(n) */ if (irep->syms[sym_no] != 0) { name = mrb_sym2name(mrb, irep->syms[sym_no]); nlen = str_dump_len((char*)name, strlen(name), type); size += nlen; /* sn(n) */ } } return size; }
static mrb_value inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur) { if (recur) { mrb_str_cat2(mrb, str, " ..."); } else { khiter_t k; kh_iv_t *h = RCLASS_IV_TBL(obj); if (h) { for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)){ mrb_sym id = kh_key(h, k); mrb_value value = kh_value(h, k); /* need not to show internal data */ if (RSTRING_PTR(str)[0] == '-') { /* first element */ RSTRING_PTR(str)[0] = '#'; mrb_str_cat2(mrb, str, " "); } else { mrb_str_cat2(mrb, str, ", "); } mrb_str_cat2(mrb, str, mrb_sym2name(mrb, id)); mrb_str_cat2(mrb, str, "="); mrb_str_append(mrb, str, mrb_inspect(mrb, value)); } } } } mrb_str_cat2(mrb, str, ">"); RSTRING_PTR(str)[0] = '#'; return str; }
void mrb_print_backtrace(mrb_state *mrb) { #ifdef ENABLE_STDIO mrb_callinfo *ci; mrb_int ciidx; const char *filename, *method, *sep; int i, line; printf("trace:\n"); ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx"))); if (ciidx >= mrb->ciend - mrb->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->cibase[i]; filename = "(unknown)"; line = -1; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; } else { mrb_irep *irep = ci->proc->body.irep; if (irep->filename != NULL) filename = irep->filename; if (irep->lines != NULL) { mrb_code *pc; if (i+1 <= ciidx) { pc = mrb->cibase[i+1].pc; } else { pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc"))); } if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { line = irep->lines[pc - irep->iseq - 1]; } } } if (line == -1) continue; if (ci->target_class == ci->proc->target_class) sep = "."; else sep = "#"; method = mrb_sym2name(mrb, ci->mid); if (method) { const char *cn = mrb_class_name(mrb, ci->proc->target_class); if (cn) { printf("\t[%d] %s:%d:in %s%s%s\n", i, filename, line, cn, sep, method); } else { printf("\t[%d] %s:%d:in %s\n", i, filename, line, method); } } else { printf("\t[%d] %s:%d\n", i, filename, line); } } #endif }
int make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f) { mrb_irep *irep = mrb->irep[irep_no]; int n; char *buf = 0; size_t buf_len, str_len; if (irep == 0) return -1; buf_len = MRB_CDUMP_LINE_LEN; if ((buf = mrb_malloc(mrb, buf_len)) == 0 ) { return MRB_CDUMP_GENERAL_FAILURE; } SOURCE_CODE0 (" ai = mrb->arena_idx;"); SOURCE_CODE0 (" irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep));"); SOURCE_CODE0 (" irep->idx = idx++;"); SOURCE_CODE (" irep->flags = %d | MRB_ISEQ_NOFREE;", irep->flags); SOURCE_CODE (" irep->nlocals = %d;", irep->nlocals); SOURCE_CODE (" irep->nregs = %d;", irep->nregs); SOURCE_CODE (" irep->ilen = %d;", irep->ilen); SOURCE_CODE (" irep->iseq = iseq_%d;", irep_no); SOURCE_CODE (" irep->slen = %d;", irep->slen); if(irep->slen > 0) { SOURCE_CODE (" irep->syms = mrb_malloc(mrb, sizeof(mrb_sym)*%d);", irep->slen); for (n=0; n<irep->slen; n++) if (irep->syms[n]) { SOURCE_CODE (" irep->syms[%d] = mrb_intern(mrb, \"%s\");", n, mrb_sym2name(mrb, irep->syms[n])); } } else SOURCE_CODE0 (" irep->syms = NULL;"); SOURCE_CODE (" irep->plen = %d;", irep->plen); if(irep->plen > 0) { SOURCE_CODE (" irep->pool = mrb_malloc(mrb, sizeof(mrb_value)*%d);", irep->plen); for (n=0; n<irep->plen; n++) { switch (irep->pool[n].tt) { case MRB_TT_FLOAT: SOURCE_CODE(" irep->pool[%d] = mrb_float_value(%.16e);", n, irep->pool[n].value.f); break; case MRB_TT_FIXNUM: SOURCE_CODE(" irep->pool[%d] = mrb_fixnum_value(%d);", n, irep->pool[n].value.i); break; case MRB_TT_STRING: str_len = str_format_len(irep->pool[n]) + 1; if ( str_len > buf_len ) { buf_len = str_len; if ((buf = mrb_realloc(mrb, buf, buf_len)) == 0 ) { return MRB_CDUMP_GENERAL_FAILURE; } } memset(buf, 0, buf_len); SOURCE_CODE(" irep->pool[%d] = mrb_str_new(mrb, \"%s\", %d);", n, str_to_format(irep->pool[n], buf), RSTRING_LEN(irep->pool[n])); break; /* TODO MRB_TT_REGEX */ default: break; } } } else SOURCE_CODE0 (" irep->pool = NULL;"); SOURCE_CODE0 (" mrb->irep_len = idx;"); SOURCE_CODE0 (" mrb->arena_idx = ai;"); SOURCE_CODE0(""); return MRB_CDUMP_OK; }
static void output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *stream) { mrb_callinfo *ci; const char *filename, *method, *sep; int i, lineno, tracehead = 1; if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->c->cibase[i]; filename = NULL; lineno = -1; if (!ci->proc) continue; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; } else { mrb_irep *irep = ci->proc->body.irep; mrb_code *pc; if (mrb->c->cibase[i].err) { pc = mrb->c->cibase[i].err; } else if (i+1 <= ciidx) { pc = mrb->c->cibase[i+1].pc - 1; } else { pc = pc0; } filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); } if (lineno == -1) continue; if (ci->target_class == ci->proc->target_class) sep = "."; else sep = "#"; if (!filename) { filename = "(unknown)"; } if (tracehead) { func(mrb, stream, 1, "trace:\n"); tracehead = 0; } method = mrb_sym2name(mrb, ci->mid); if (method) { const char *cn = mrb_class_name(mrb, ci->proc->target_class); if (cn) { func(mrb, stream, 1, "\t[%d] ", i); func(mrb, stream, 0, "%s:%d:in %s%s%s", filename, lineno, cn, sep, method); func(mrb, stream, 1, "\n"); } else { func(mrb, stream, 1, "\t[%d] ", i); func(mrb, stream, 0, "%s:%d:in %s", filename, lineno, method); func(mrb, stream, 1, "\n"); } } else { func(mrb, stream, 1, "\t[%d] ", i); func(mrb, stream, 0, "%s:%d", filename, lineno); func(mrb, stream, 1, "\n"); } } }