static void copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) { struct RClass *dc = mrb_class_ptr(dst); struct RClass *sc = mrb_class_ptr(src); /* if the origin is not the same as the class, then the origin and the current class need to be copied */ if (sc->flags & MRB_FL_CLASS_IS_PREPENDED) { struct RClass *c0 = sc->super; struct RClass *c1 = dc; /* copy prepended iclasses */ while (!(c0->flags & MRB_FL_CLASS_IS_ORIGIN)) { c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); c1 = c1->super; c0 = c0->super; } c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); c1->super->flags |= MRB_FL_CLASS_IS_ORIGIN; } if (sc->mt) { dc->mt = kh_copy(mt, mrb, sc->mt); } else { dc->mt = kh_init(mt, mrb); } dc->super = sc->super; MRB_SET_INSTANCE_TT(dc, MRB_INSTANCE_TT(sc)); }
static mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; mrb_value ary = mrb_ary_new(mrb); if (!h) return ary; for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)){ mrb_value v = kh_value(h,k); if ( !mrb_special_const_p(v) ) v = mrb_obj_dup(mrb, v); mrb_ary_push(mrb, ary, v); } } return ary; }
static mrb_value find_file_check(mrb_state *mrb, mrb_value path, mrb_value fname, mrb_value ext) { FILE *fp; char fpath[MAXPATHLEN]; mrb_value filepath = mrb_str_dup(mrb, path); #ifdef _WIN32 if (RSTRING_PTR(fname)[1] == ':') { #else if (RSTRING_PTR(fname)[0] == '/') { #endif /* when absolute path */ mrb_funcall(mrb, filepath, "replace", 1, fname); } else { mrb_str_cat2(mrb, filepath, "/"); mrb_str_buf_append(mrb, filepath, fname); } if (!mrb_string_p(filepath)) { return mrb_nil_value(); } if (mrb_string_p(ext)) { mrb_str_buf_append(mrb, filepath, ext); } debug("filepath: %s\n", RSTRING_PTR(filepath)); if (realpath(RSTRING_PTR(filepath), fpath) == NULL) { return mrb_nil_value(); } debug("fpath: %s\n", fpath); fp = fopen(fpath, "r"); if (fp == NULL) { return mrb_nil_value(); } fclose(fp); return mrb_str_new_cstr(mrb, fpath); } static mrb_value find_file(mrb_state *mrb, mrb_value filename, int comp) { char *ext, *ptr, *tmp; mrb_value exts; int i, j; char *fname = RSTRING_PTR(filename); mrb_value filepath = mrb_nil_value(); mrb_value load_path = mrb_obj_dup(mrb, mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$:"))); load_path = mrb_check_array_type(mrb, load_path); if(mrb_nil_p(load_path)) { mrb_raise(mrb, E_RUNTIME_ERROR, "invalid $:"); return mrb_undef_value(); } tmp = ptr = fname; while (tmp) { if ((tmp = strchr(ptr, '/')) || (tmp = strchr(ptr, '\\'))) { ptr = tmp + 1; } } ext = strrchr(ptr, '.'); exts = mrb_ary_new(mrb); if (ext == NULL && comp) { mrb_ary_push(mrb, exts, mrb_str_new_cstr(mrb, ".rb")); mrb_ary_push(mrb, exts, mrb_str_new_cstr(mrb, ".mrb")); mrb_ary_push(mrb, exts, mrb_str_new_cstr(mrb, ".so")); } else { mrb_ary_push(mrb, exts, mrb_nil_value()); } /* when a filename start with '.', $: = ['.'] */ if (*fname == '.') { load_path = mrb_ary_new(mrb); mrb_ary_push(mrb, load_path, mrb_str_new_cstr(mrb, ".")); } for (i = 0; i < RARRAY_LEN(load_path); i++) { for (j = 0; j < RARRAY_LEN(exts); j++) { filepath = find_file_check( mrb, mrb_ary_entry(load_path, i), filename, mrb_ary_entry(exts, j)); if (!mrb_nil_p(filepath)) { return filepath; } } } mrb_load_fail(mrb, filename, "cannot load such file"); return mrb_nil_value(); }