예제 #1
0
mrb_value
mrb_class_find_path(mrb_state *mrb, struct RClass *c)
{
  struct RClass *outer;
  mrb_value path;
  mrb_sym name;
  const char *str;
  mrb_int len;

  if (detect_outer_loop(mrb, c)) return mrb_nil_value();
  outer = outer_class(mrb, c);
  if (outer == NULL) return mrb_nil_value();
  name = find_class_sym(mrb, outer, c);
  if (name == 0) return mrb_nil_value();
  str = mrb_class_name(mrb, outer);
  path = mrb_str_new_capa(mrb, 40);
  mrb_str_cat_cstr(mrb, path, str);
  mrb_str_cat_cstr(mrb, path, "::");

  str = mrb_sym2name_len(mrb, name, &len);
  mrb_str_cat(mrb, path, str, len);
  if (RSTRING_PTR(path)[0] != '#') {
    iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL);
    iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
    mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
  }
  return path;
}
예제 #2
0
파일: method.c 프로젝트: chasonr/mruby
static mrb_value
method_to_s(mrb_state *mrb, mrb_value self)
{
  mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner"));
  mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass"));
  mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name"));
  mrb_value str = mrb_str_new_lit(mrb, "#<");
  struct RClass *rklass;

  mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self));
  mrb_str_cat_lit(mrb, str, ": ");
  rklass = mrb_class_ptr(klass);
  if (mrb_class_ptr(owner) == rklass) {
    mrb_str_cat_str(mrb, str, mrb_funcall(mrb, owner, "to_s", 0));
    mrb_str_cat_lit(mrb, str, "#");
    mrb_str_cat_str(mrb, str, mrb_funcall(mrb, name, "to_s", 0));
  }
  else {
    mrb_str_cat_cstr(mrb, str, mrb_class_name(mrb, rklass));
    mrb_str_cat_lit(mrb, str, "(");
    mrb_str_cat_str(mrb, str, mrb_funcall(mrb, owner, "to_s", 0));
    mrb_str_cat_lit(mrb, str, ")#");
    mrb_str_cat_str(mrb, str, mrb_funcall(mrb, name, "to_s", 0));
  }
  mrb_str_cat_lit(mrb, str, ">");
  return str;
}
예제 #3
0
mrb_value
cfunc_struct_define_struct(mrb_state *mrb, mrb_value klass)
{
    mrb_value elements_mrb;
    mrb_get_args(mrb, "A", &elements_mrb);
    struct RArray *elements = mrb_ary_ptr(elements_mrb);

    ffi_type *tm_type = mrb_malloc(mrb, sizeof(ffi_type));
    tm_type->type = FFI_TYPE_STRUCT;
    tm_type->size = tm_type->alignment = 0;

    ffi_type **tm_type_elements = mrb_malloc(mrb, sizeof(ffi_type*) * (elements->len + 1));
    int i;
    for(i = 0; i < elements->len; ++i) {
        tm_type_elements[i] = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(elements->ptr[i]))->ffi_type_value;
    }
    tm_type_elements[i] = NULL;
    tm_type->elements = tm_type_elements;

    struct mrb_ffi_type *mft = mrb_malloc(mrb, sizeof(struct mrb_ffi_type));
    mft->name = mrb_class_name(mrb, mrb_class_ptr(klass));
    mft->ffi_type_value = tm_type;
    mft->mrb_to_c = &cfunc_type_ffi_struct_mrb_to_c;
    mft->c_to_mrb = &cfunc_type_ffi_struct_c_to_mrb;

    mrb_value __ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_struct_data_type, mft));
    mrb_obj_iv_set(mrb, (struct RObject*)(mrb_class_ptr(klass)), mrb_intern_cstr(mrb, "@ffi_type"), __ffi_type);
    
    return mrb_nil_value();
}
예제 #4
0
파일: struct.c 프로젝트: nyanp/mruby
/*
 * code-seq:
 *   struct.eql?(other)   -> true or false
 *
 * Two structures are equal if they are the same object, or if all their
 * fields are equal (using <code>eql?</code>).
 */
static mrb_value
mrb_struct_eql(mrb_state *mrb, mrb_value s)
{
  mrb_value s2;
  mrb_value *ptr, *ptr2;
  mrb_int i, len;
  mrb_bool eql_p;

  mrb_get_args(mrb, "o", &s2);
  if (mrb_obj_equal(mrb, s, s2)) {
    eql_p = 1;
  }
  else if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") ||
           mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
    eql_p = 0;
  }
  else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
    mrb_bug(mrb, "inconsistent struct"); /* should never happen */
    eql_p = 0; /* This substuture is just to suppress warnings. never called. */
  }
  else {
    ptr = RSTRUCT_PTR(s);
    ptr2 = RSTRUCT_PTR(s2);
    len = RSTRUCT_LEN(s);
    eql_p = 1;
    for (i=0; i<len; i++) {
      if (!mrb_eql(mrb, ptr[i], ptr2[i])) {
        eql_p = 0;
        break;
      }
    }
  }

  return mrb_bool_value(eql_p);
}
예제 #5
0
파일: backtrace.c 프로젝트: okkez/mruby
static void
print_backtrace_saved(mrb_state *mrb)
{
  int i, ai;
  FILE *stream = stderr;

  fprintf(stream, "trace:\n");
  ai = mrb_gc_arena_save(mrb);
  for (i = 0; i < mrb->backtrace.n; i++) {
    mrb_backtrace_entry *entry;

    entry = &(mrb->backtrace.entries[i]);
    fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno);

    if (entry->method_id != 0) {
      const char *method_name;

      method_name = mrb_sym2name(mrb, entry->method_id);
      if (entry->klass) {
        fprintf(stream, ":in %s%c%s",
                mrb_class_name(mrb, entry->klass),
                entry->sep,
                method_name);
      }
      else {
        fprintf(stream, ":in %s", method_name);
      }
      mrb_gc_arena_restore(mrb, ai);
    }

    fprintf(stream, "\n");
  }
}
예제 #6
0
파일: method.c 프로젝트: chasonr/mruby
static mrb_value
unbound_method_bind(mrb_state *mrb, mrb_value self)
{
  struct RObject *me;
  mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner"));
  mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name"));
  mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc"));
  mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass"));
  mrb_value recv;

  mrb_get_args(mrb, "o", &recv);

  if (mrb_type(owner) != MRB_TT_MODULE &&
      mrb_class_ptr(owner) != mrb_obj_class(mrb, recv) &&
      !mrb_obj_is_kind_of(mrb, recv, mrb_class_ptr(owner))) {
        if (mrb_type(owner) == MRB_TT_SCLASS) {
          mrb_raise(mrb, E_TYPE_ERROR, "singleton method called for a different object");
        } else {
          const char *s = mrb_class_name(mrb, mrb_class_ptr(owner));
          mrb_raisef(mrb, E_TYPE_ERROR, "bind argument must be an instance of %S", mrb_str_new_static(mrb, s, strlen(s)));
        }
  }
  me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
  mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@owner"), owner);
  mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@recv"), recv);
  mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@name"), name);
  mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "proc"), proc);
  mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@klass"), klass);

  return mrb_obj_value(me);
}
예제 #7
0
파일: variable.c 프로젝트: fetus-hina/h2o
mrb_value
mrb_class_find_path(mrb_state *mrb, struct RClass *c)
{
  mrb_value outer, path;
  mrb_sym name;
  const char *str;
  mrb_int len;
  mrb_sym osym = mrb_intern_lit(mrb, "__outer__");

  outer = mrb_obj_iv_get(mrb, (struct RObject*)c, osym);
  if (mrb_nil_p(outer)) return outer;
  name = find_class_sym(mrb, mrb_class_ptr(outer), c);
  if (name == 0) return mrb_nil_value();
  str = mrb_class_name(mrb, mrb_class_ptr(outer));
  path = mrb_str_new_capa(mrb, 40);
  mrb_str_cat_cstr(mrb, path, str);
  mrb_str_cat_cstr(mrb, path, "::");

  str = mrb_sym2name_len(mrb, name, &len);
  mrb_str_cat(mrb, path, str, len);
  iv_del(mrb, c->iv, osym, NULL);
  iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
  mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
  return path;
}
예제 #8
0
파일: backtrace.c 프로젝트: Asmod4n/mruby
static void
output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *data)
{
  int i;

  if (ciidx >= mrb->c->ciend - mrb->c->cibase)
    ciidx = 10; /* ciidx is broken... */

  for (i = ciidx; i >= 0; i--) {
    struct backtrace_location loc;
    mrb_callinfo *ci;
    mrb_irep *irep;
    mrb_code *pc;

    ci = &mrb->c->cibase[i];

    if (!ci->proc) continue;
    if (MRB_PROC_CFUNC_P(ci->proc)) continue;

    irep = ci->proc->body.irep;

    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;
    }
    loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
    loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));

    if (loc.lineno == -1) continue;

    if (ci->target_class == ci->proc->target_class) {
      loc.sep = ".";
    }
    else {
      loc.sep = "#";
    }

    if (!loc.filename) {
      loc.filename = "(unknown)";
    }

    loc.method = mrb_sym2name(mrb, ci->mid);
    loc.class_name = mrb_class_name(mrb, ci->proc->target_class);
    loc.i = i;
    func(mrb, &loc, data);
  }
}
예제 #9
0
파일: struct.c 프로젝트: nyanp/mruby
mrb_value
mrb_struct_members(mrb_state *mrb, mrb_value s)
{
  mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s)));
  if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) {
    if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
      mrb_raisef(mrb, E_TYPE_ERROR,
                 "struct size differs (%S required %S given)",
                 mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
    }
  }
  return members;
}
예제 #10
0
struct mrb_ffi_type*
rclass_to_mrb_ffi_type(mrb_state *mrb, struct RClass *cls)
{
    struct RClass *cls_ = cls;
    while(cls) {
        mrb_value ffi_type = mrb_obj_iv_get(mrb, (struct RObject*)cls, mrb_intern_cstr(mrb, "@ffi_type"));
        if(mrb_test(ffi_type)) {
            return (struct mrb_ffi_type*)DATA_PTR(ffi_type);
        }
        cls = cls->super;
    }
    mrb_raisef(mrb, E_TYPE_ERROR, "%s cannot convert to C value", mrb_class_name(mrb, cls_));
    return NULL;
}
예제 #11
0
파일: class.c 프로젝트: AndreOF/ArangoDB
static mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
  if (mrb_type(klass) == MRB_TT_SCLASS) {
    mrb_value s = mrb_str_new(mrb, "#<", 2);
    mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__"));

    mrb_str_cat2(mrb, s, "Class:");
    switch (mrb_type(v)) {
      case MRB_TT_CLASS:
      case MRB_TT_MODULE:
      case MRB_TT_SCLASS:
        mrb_str_append(mrb, s, mrb_inspect(mrb, v));
        break;
      default:
        mrb_str_append(mrb, s, mrb_any_to_s(mrb, v));
        break;
    }
    mrb_str_cat2(mrb, s, ">");

    return s;
  }
  else {
    struct RClass *c = mrb_class_ptr(klass);
    const char *cn = mrb_class_name(mrb, c);

    if (!cn) {
      char buf[256];
      int n = 0;

      switch (mrb_type(klass)) {
        case MRB_TT_CLASS:
          n = snprintf(buf, sizeof(buf), "#<Class:%p>", c);
          break;

        case MRB_TT_MODULE:
          n = snprintf(buf, sizeof(buf), "#<Module:%p>", c);
          break;

        default:
          break;
      }
      return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n));
    }
    else {
      return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn));
    }
  }
}
예제 #12
0
파일: backtrace.c 프로젝트: okkez/mruby
static void
output_backtrace_i(mrb_state *mrb, struct backtrace_location_raw *loc_raw, void *data)
{
  struct backtrace_location loc;
  struct output_backtrace_args *args = (struct output_backtrace_args *)data;

  loc.i          = loc_raw->i;
  loc.lineno     = loc_raw->lineno;
  loc.filename   = loc_raw->filename;
  loc.method     = mrb_sym2name(mrb, loc_raw->method_id);
  loc.sep        = loc_raw->sep;
  loc.class_name = mrb_class_name(mrb, loc_raw->klass);

  args->func(mrb, &loc, args->data);
}
예제 #13
0
파일: struct.c 프로젝트: nyanp/mruby
static mrb_value
inspect_struct(mrb_state *mrb, mrb_value s, int recur)
{
  const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s));
  mrb_value members, str = mrb_str_new_lit(mrb, "#<struct ");
  mrb_value *ptr, *ptr_members;
  mrb_int i, len;

  if (cn) {
    mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn));
  }
  if (recur) {
    return mrb_str_cat_lit(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_cat_lit(mrb, str, ", ");
    }
    else if (cn) {
      mrb_str_cat_lit(mrb, str, " ");
    }
    slot = ptr_members[i];
    id = mrb_symbol(slot);
    if (mrb_is_local_id(id) || mrb_is_const_id(id)) {
      const char *name;
      mrb_int len;

      name = mrb_sym2name_len(mrb, id, &len);
      mrb_str_append(mrb, str, mrb_str_new(mrb, name, len));
    }
    else {
      mrb_str_append(mrb, str, mrb_inspect(mrb, slot));
    }
    mrb_str_cat_lit(mrb, str, "=");
    mrb_str_append(mrb, str, mrb_inspect(mrb, ptr[i]));
  }
  mrb_str_cat_lit(mrb, str, ">");

  return str;
}
예제 #14
0
mrb_value
cfunc_pointer_inspect(mrb_state *mrb, mrb_value self)
{
    struct cfunc_type_data *data = DATA_PTR(self);
    
    mrb_value type = mrb_funcall(mrb, mrb_obj_value(mrb_class(mrb, self)), "type", 0);
    const char* classname = mrb_class_name(mrb, (struct RClass*)mrb_object(type));
    if(!classname) {
        classname = "Unknown pointer";
    }

    char cstr[256];
    snprintf(cstr, sizeof(cstr), "<%s pointer=%p>", classname, get_cfunc_pointer_data(data));
    
    return mrb_str_new_cstr(mrb, cstr);
}
예제 #15
0
파일: mruby.c 프로젝트: daniel-higa/mruby
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 : "");
  }
}
예제 #16
0
파일: variable.c 프로젝트: koie/mruby
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();
}
예제 #17
0
파일: backtrace.c 프로젝트: okkez/mruby
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;
}
예제 #18
0
파일: method.c 프로젝트: chasonr/mruby
static void
mrb_search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound)
{
  mrb_value ret;
  const char *s;

  *owner = c;
  *proc = method_search_vm(mrb, owner, name);
  if (!*proc) {
    if (unbound) {
      goto name_error;
    }
    if (!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "respond_to_missing?"))) {
      goto name_error;
    }
    ret = mrb_funcall(mrb, obj, "respond_to_missing?", 2, mrb_symbol_value(name), mrb_true_value());
    if (!mrb_test(ret)) {
      goto name_error;
    }
    *owner = c;
  }

  while ((*owner)->tt == MRB_TT_ICLASS)
    *owner = (*owner)->c;

  return;

name_error:
  s = mrb_class_name(mrb, c);
  mrb_raisef(
    mrb, E_NAME_ERROR,
    "undefined method `%S' for class `%S'",
    mrb_sym2str(mrb, name),
    mrb_str_new_static(mrb, s, strlen(s))
  );
}
예제 #19
0
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
}
예제 #20
0
파일: backtrace.c 프로젝트: kelcecil/mruby
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");
    }
  }
}
예제 #21
0
static mrb_value
cfunc_call(mrb_state *mrb, mrb_value self)
{
    int margc;
    mrb_value mresult_type, mname, *margs;
    void **values = NULL;
    ffi_type **args = NULL;

    mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc);

    void *fp = NULL;
    if(mrb_string_p(mname) || mrb_symbol_p(mname)) {
        void *dlh = dlopen(NULL, RTLD_LAZY);
        fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname));
        dlclose(dlh);
    }
    else {
        fp = cfunc_pointer_ptr(mname);
    }

    if(fp == NULL) {
        mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname));
        goto cfunc_call_exit;
    }

    args = malloc(sizeof(ffi_type*) * margc);
    values = malloc(sizeof(void*) * margc);
    mrb_sym sym_to_ffi_value = mrb_intern(mrb, "to_ffi_value");

    mrb_value nil_ary[1];
    nil_ary[0] = mrb_nil_value();
    for(int i = 0; i < margc; ++i) {
        if(mrb_respond_to(mrb, margs[i], sym_to_ffi_value)) {
            args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value;
            values[i] = cfunc_pointer_ptr(mrb_funcall_argv(mrb, margs[i], sym_to_ffi_value, 1, nil_ary));
        }
        else {
            cfunc_mrb_raise_without_jump(mrb, E_TYPE_ERROR, "ignore argument type %s", mrb_obj_classname(mrb, margs[i]));
            goto cfunc_call_exit;
        }
    }

    ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value;
    if (result_type == NULL) {
        cfunc_mrb_raise_without_jump(mrb, E_ARGUMENT_ERROR, "ignore return type %s", mrb_class_name(mrb, mrb_class_ptr(mresult_type)));
        goto cfunc_call_exit;
    }

    mrb_value mresult = mrb_nil_value();
    ffi_cif cif;
    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) {
        void *result;
        if(result_type->size > sizeof(long)) {
            result = malloc(result_type->size);
        }
        else if(result_type->size) {
            result = malloc(sizeof(long));
        }
        else {
            result = NULL;
        }
        ffi_call(&cif, fp, result, values);

        if(result) {
            mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, true);
            mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr);
        }
    }
    else {
        mrb_raisef(mrb, E_NAME_ERROR, "Can't find C function %s", mname);
        goto cfunc_call_exit;
    }

cfunc_call_exit:
    free(values);
    free(args);
    return mresult;
}
예제 #22
0
파일: class.c 프로젝트: AndreOF/ArangoDB
const char*
mrb_obj_classname(mrb_state *mrb, mrb_value obj)
{
  return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
}