コード例 #1
0
ファイル: hash.c プロジェクト: denji/mruby
static mrb_value
inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
{
  mrb_value str, str2;
  khash_t(ht) *h = RHASH_TBL(hash);
  khiter_t k;

  if (recur) return mrb_str_new_lit(mrb, "{...}");

  str = mrb_str_new_lit(mrb, "{");
  if (h && kh_size(h) > 0) {
    for (k = kh_begin(h); k != kh_end(h); k++) {
      int ai;

      if (!kh_exist(h,k)) continue;

      ai = mrb_gc_arena_save(mrb);

      if (RSTRING_LEN(str) > 1) mrb_str_cat_lit(mrb, str, ", ");

      str2 = mrb_inspect(mrb, kh_key(h,k));
      mrb_str_append(mrb, str, str2);
      mrb_str_cat_lit(mrb, str, "=>");
      str2 = mrb_inspect(mrb, kh_value(h,k));
      mrb_str_append(mrb, str, str2);

      mrb_gc_arena_restore(mrb, ai);
    }
  }
  mrb_str_cat_lit(mrb, str, "}");

  return str;
}
コード例 #2
0
ファイル: range.c プロジェクト: FlowGroup/mruby
static mrb_value
range_inspect(mrb_state *mrb, mrb_value range)
{
  mrb_value str, str2;
  struct RRange *r = mrb_range_ptr(range);

  str  = mrb_inspect(mrb, r->edges->beg);
  str2 = mrb_inspect(mrb, r->edges->end);
  str  = mrb_str_dup(mrb, str);
  mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
  mrb_str_append(mrb, str, str2);

  return str;
}
コード例 #3
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;
}
コード例 #4
0
ファイル: variable.c プロジェクト: fetus-hina/h2o
static int
inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
  mrb_value str = *(mrb_value*)p;
  const char *s;
  mrb_int len;
  mrb_value ins;
  char *sp = RSTRING_PTR(str);

  /* need not to show internal data */
  if (sp[0] == '-') { /* first element */
    sp[0] = '#';
    mrb_str_cat_lit(mrb, str, " ");
  }
  else {
    mrb_str_cat_lit(mrb, str, ", ");
  }
  s = mrb_sym2name_len(mrb, sym, &len);
  mrb_str_cat(mrb, str, s, len);
  mrb_str_cat_lit(mrb, str, "=");
  if (mrb_type(v) == MRB_TT_OBJECT) {
    ins = mrb_any_to_s(mrb, v);
  }
  else {
    ins = mrb_inspect(mrb, v);
  }
  mrb_str_cat_str(mrb, str, ins);
  return 0;
}
コード例 #5
0
ファイル: range.c プロジェクト: anandkumaragrawal/mruby
static mrb_value
inspect_range(mrb_state *mrb, mrb_value range, mrb_value dummy, int recur)
{
  mrb_value str, str2;
  struct RRange *r = mrb_range_ptr(range);

  if (recur) {
    return mrb_str_new2(mrb, r->excl ? "(... ... ...)" : "(... .. ...)");
  }
  str  = mrb_inspect(mrb, r->edges->beg);
  str2 = mrb_inspect(mrb, r->edges->end);
  str  = mrb_str_dup(mrb, str);
  mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
  mrb_str_append(mrb, str, str2);

  return str;
}
コード例 #6
0
ファイル: mruby.c プロジェクト: crimsonwoods/mruby
static void
p(mrb_state *mrb, mrb_value obj)
{
  mrb_value val = mrb_inspect(mrb, obj);

  fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
  putc('\n', stdout);
}
コード例 #7
0
ファイル: hash.c プロジェクト: Zyxwvu/mruby
static khint_t
mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
{
  char type = mrb_type(key);
  mrb_value s1 = mrb_str_new(mrb, &type, 1);
  mrb_value s2 = mrb_inspect(mrb, key);
  s1 = mrb_str_cat(mrb, s1, RSTRING_PTR(s2), RSTRING_LEN(s2));
  return kh_str_hash_func(mrb, RSTRING_PTR(s1));
}
コード例 #8
0
ファイル: object.c プロジェクト: lemonhall/mruby
static mrb_value
inspect_type(mrb_state *mrb, mrb_value val)
{
  if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) {
    return mrb_inspect(mrb, val);
  }
  else {
    return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val));
  }
}
コード例 #9
0
ファイル: class.c プロジェクト: MichaelFrohberg/mruby
static mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
  mrb_value str;

  if (mrb_type(klass) == MRB_TT_SCLASS) {
    mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12));

    str = mrb_str_new(mrb, "#<Class:", 8);

    switch (mrb_type(v)) {
      case MRB_TT_CLASS:
      case MRB_TT_MODULE:
      case MRB_TT_SCLASS:
        mrb_str_append(mrb, str, mrb_inspect(mrb, v));
        break;
      default:
        mrb_str_append(mrb, str, mrb_any_to_s(mrb, v));
        break;
    }
    mrb_str_cat(mrb, str, ">", 1);
  }
  else {
    struct RClass *c;
    mrb_value path;

    str = mrb_str_buf_new(mrb, 32);
    c = mrb_class_ptr(klass);
    path = mrb_class_path(mrb, c);

    if (mrb_nil_p(path)) {
      switch (mrb_type(klass)) {
        case MRB_TT_CLASS:
          mrb_str_cat(mrb, str, "#<Class:", 8);
          break;

        case MRB_TT_MODULE:
          mrb_str_cat(mrb, str, "#<Module:", 9);
          break;

        default:
          /* Shouldn't be happened? */
          mrb_str_cat(mrb, str, "#<??????:", 9);
          break;
      }
      mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
      mrb_str_cat(mrb, str, ">", 1);
    }
    else {
      str = path;
    }
  }

  return str;
}
コード例 #10
0
ファイル: mrb4R.c プロジェクト: rcqls/mrb4R
//inspect
SEXP mrb4R_inspect(SEXP args) {
  mrb_value rbobj;

  if (inherits(CADR(args), "rbObj")) {
    rbobj=*((mrb_value*) R_ExternalPtrAddr(CADR(args)));
    //sometimes, it bugs !!! very strange!!!
    mrb_inspect(mrb,rbobj);
  }
  return R_NilValue;
  
}
コード例 #11
0
ファイル: range.c プロジェクト: jjue/mruby
static mrb_value
inspect_range(mrb_state *mrb, mrb_value range, mrb_value dummy, int recur)
{
  mrb_value str, str2;
  struct RRange *r = mrb_range_ptr(range);

  if (recur) {
    static const char s[2][14] = { "(... ... ...)", "(... .. ...)" };
    static const int n[] = { 13, 12 };
    int idx;

    idx = (r->excl) ? 0 : 1;
    return mrb_str_new(mrb, s[idx], n[idx]);
  }
  str  = mrb_inspect(mrb, r->edges->beg);
  str2 = mrb_inspect(mrb, r->edges->end);
  str  = mrb_str_dup(mrb, str);
  mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
  mrb_str_append(mrb, str, str2);

  return str;
}
コード例 #12
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));
    }
  }
}
コード例 #13
0
ファイル: compar.c プロジェクト: Constellation/mruby
void
mrb_cmperr(mrb_state *mrb, mrb_value x, mrb_value y)
{
  const char *classname;

  if (SPECIAL_CONST_P(y)) {
    y = mrb_inspect(mrb, y);
    //classname = StringValuePtr(y);
    classname = mrb_string_value_ptr(mrb, y);
  }
  else {
    classname = mrb_obj_classname(mrb, y);
  }
  mrb_raise(mrb, E_ARGUMENT_ERROR, "comparison of %s with %s failed",
	    mrb_obj_classname(mrb, x), classname);
}
コード例 #14
0
ファイル: kernel.c プロジェクト: 8823-scholar/cocos2dx-mruby
/*
 *  call-seq:
 *     obj.respond_to?(symbol, include_private=false) -> true or false
 *
 *  Returns +true+ if _obj_ responds to the given
 *  method. Private methods are included in the search only if the
 *  optional second parameter evaluates to +true+.
 *
 *  If the method is not implemented,
 *  as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
 *  false is returned.
 *
 *  If the method is not defined, <code>respond_to_missing?</code>
 *  method is called and the result is returned.
 */
mrb_value
obj_respond_to(mrb_state *mrb, mrb_value self)
{
  mrb_value *argv;
  int argc;
  mrb_value mid, priv;
  mrb_sym id, rtm_id;
  mrb_bool respond_to_p = TRUE;

  mrb_get_args(mrb, "*", &argv, &argc);
  mid = argv[0];
  if (argc > 1) priv = argv[1];
  else priv = mrb_nil_value();

  if (mrb_symbol_p(mid)) {
    id = mrb_symbol(mid);
  }
  else {
    mrb_value tmp;
    if (!mrb_string_p(mid)) {
      tmp = mrb_check_string_type(mrb, mid);
      if (mrb_nil_p(tmp)) {
        tmp = mrb_inspect(mrb, mid);
        mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
      }
    }
    tmp = mrb_check_intern_str(mrb, mid);
    if (mrb_nil_p(tmp)) {
      respond_to_p = FALSE;
    }
    else {
      id = mrb_symbol(tmp);
    }
  }

  if (respond_to_p) {
    respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv));
  }

  if (!respond_to_p) {
    rtm_id = mrb_intern2(mrb, "respond_to_missing?", 19);
    if (basic_obj_respond_to(mrb, self, rtm_id, !mrb_test(priv))) {
      return mrb_funcall_argv(mrb, self, rtm_id, argc, argv);
    }
  }
  return mrb_bool_value(respond_to_p);
}
コード例 #15
0
ファイル: array.c プロジェクト: Fleurer/mruby
static mrb_value
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
{
  mrb_int i;
  mrb_value s, arystr;
  char head[] = { '[' };
  char sep[] = { ',', ' ' };
  char tail[] = { ']' };

  /* check recursive */
  for(i=0; i<RARRAY_LEN(list); i++) {
    if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
      return mrb_str_new(mrb, "[...]", 5);
    }
  }

  mrb_ary_push(mrb, list, ary);

  arystr = mrb_str_buf_new(mrb, 64);
  mrb_str_buf_cat(mrb, arystr, head, sizeof(head));

  for(i=0; i<RARRAY_LEN(ary); i++) {
    int ai = mrb_gc_arena_save(mrb);

    if (i > 0) {
      mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
    }
    if (mrb_array_p(RARRAY_PTR(ary)[i])) {
      s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
    }
    else {
      s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
    }
    mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
    mrb_gc_arena_restore(mrb, ai);
  }

  mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail));
  mrb_ary_pop(mrb, list);

  return arystr;
}
コード例 #16
0
ファイル: variable.c プロジェクト: koie/mruby
static int
inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
    mrb_value str = *(mrb_value*)p;
    const char *s;
    size_t len;

    /* need not to show internal data */
    if (RSTRING_PTR(str)[0] == '-') { /* first element */
        RSTRING_PTR(str)[0] = '#';
        mrb_str_cat(mrb, str, " ", 1);
    }
    else {
        mrb_str_cat(mrb, str, ", ", 2);
    }
    s = mrb_sym2name_len(mrb, sym, &len);
    mrb_str_cat(mrb, str, s, len);
    mrb_str_cat(mrb, str, "=", 1);
    mrb_str_append(mrb, str, mrb_inspect(mrb, v));
    return 0;
}
コード例 #17
0
ファイル: kernel.c プロジェクト: Blorgus/mruby
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;
}
コード例 #18
0
ファイル: etc.c プロジェクト: Zyxwvu/mruby
mrb_sym
mrb_to_id(mrb_state *mrb, mrb_value name)
{
  mrb_value tmp;
  mrb_sym id;

  switch (mrb_type(name)) {
    default:
      tmp = mrb_check_string_type(mrb, name);
      if (mrb_nil_p(tmp)) {
        tmp = mrb_inspect(mrb, name);
        mrb_raise(mrb, E_TYPE_ERROR, "%s is not a symbol",
             RSTRING_PTR(tmp));
      }
      name = tmp;
      /* fall through */
    case MRB_TT_STRING:
      name = mrb_str_intern(mrb, name);
      /* fall through */
    case MRB_TT_SYMBOL:
      return SYM2ID(name);
  }
  return id;
}
コード例 #19
0
ファイル: codedump.c プロジェクト: mruby-Forum/mruby
static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
  int ai;
  mrb_code *pc, *pcend;
  mrb_code ins;
  const char *file = NULL, *next_file;

  if (!irep) return;
  printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d iseq=%d\n", (void*)irep,
         irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen, (int)irep->ilen);

  if (irep->lv) {
    int i;

    printf("local variable names:\n");
    for (i = 1; i < irep->nlocals; ++i) {
      char const *s = mrb_sym2name(mrb, irep->lv[i - 1].name);
      int n = irep->lv[i - 1].r ? irep->lv[i - 1].r : i;
      printf("  R%d:%s\n", n, s ? s : "");
    }
  }

  pc = irep->iseq;
  pcend = pc + irep->ilen;
  while (pc < pcend) {
    ptrdiff_t i;
    uint32_t a;
    uint16_t b;
    uint8_t c;

    ai = mrb_gc_arena_save(mrb);

    i = pc - irep->iseq;
    next_file = mrb_debug_get_filename(mrb, irep, i);
    if (next_file && file != next_file) {
      printf("file: %s\n", next_file);
      file = next_file;
    }
    print_header(mrb, irep, i);
    ins = READ_B();
    switch (ins) {
    CASE(OP_NOP, Z):
      printf("OP_NOP\n");
      break;
    CASE(OP_MOVE, BB):
      printf("OP_MOVE\tR%d\tR%d\t", a, b);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_LOADL, BB):
      {
        mrb_value v = irep->pool[b];
        mrb_value s = mrb_inspect(mrb, v);
        printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
      }
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADI, BB):
      printf("OP_LOADI\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADINEG, BB):
      printf("OP_LOADI\tR%d\t-%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADI__1, B):
      printf("OP_LOADI__1\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADI_0, B): goto L_LOADI;
    CASE(OP_LOADI_1, B): goto L_LOADI;
    CASE(OP_LOADI_2, B): goto L_LOADI;
    CASE(OP_LOADI_3, B): goto L_LOADI;
    CASE(OP_LOADI_4, B): goto L_LOADI;
    CASE(OP_LOADI_5, B): goto L_LOADI;
    CASE(OP_LOADI_6, B): goto L_LOADI;
    CASE(OP_LOADI_7, B):
    L_LOADI:
      printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADSYM, BB):
      printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADNIL, B):
      printf("OP_LOADNIL\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADSELF, B):
      printf("OP_LOADSELF\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADT, B):
      printf("OP_LOADT\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADF, B):
      printf("OP_LOADF\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETGV, BB):
      printf("OP_GETGV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETGV, BB):
      printf("OP_SETGV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETSV, BB):
      printf("OP_GETSV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETSV, BB):
      printf("OP_SETSV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETCONST, BB):
      printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETCONST, BB):
      printf("OP_SETCONST\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETMCNST, BB):
      printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETMCNST, BB):
      printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETIV, BB):
      printf("OP_GETIV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETIV, BB):
      printf("OP_SETIV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETUPVAR, BBB):
      printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETUPVAR, BBB):
      printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETCV, BB):
      printf("OP_GETCV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETCV, BB):
      printf("OP_SETCV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_JMP, S):
      printf("OP_JMP\t\t%03d\n", a);
      break;
    CASE(OP_JMPIF, BS):
      printf("OP_JMPIF\tR%d\t%03d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_JMPNOT, BS):
      printf("OP_JMPNOT\tR%d\t%03d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_JMPNIL, BS):
      printf("OP_JMPNIL\tR%d\t%03d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SENDV, BB):
      printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_SENDVB, BB):
      printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_SEND, BBB):
      printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
      break;
    CASE(OP_SENDB, BBB):
      printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
      break;
    CASE(OP_CALL, Z):
      printf("OP_CALL\n");
      break;
    CASE(OP_SUPER, BB):
      printf("OP_SUPER\tR%d\t%d\n", a, b);
      break;
    CASE(OP_ARGARY, BS):
      printf("OP_ARGARY\tR%d\t%d:%d:%d:%d (%d)", a,
             (b>>11)&0x3f,
             (b>>10)&0x1,
             (b>>5)&0x1f,
             (b>>4)&0x1,
             (b>>0)&0xf);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ENTER, W):
      printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
             (a>>18)&0x1f,
             (a>>13)&0x1f,
             (a>>12)&0x1,
             (a>>7)&0x1f,
             (a>>2)&0x1f,
             (a>>1)&0x1,
             a & 0x1);
      break;
    CASE(OP_KEY_P, BB):
      printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_KEYEND, Z):
      printf("OP_KEYEND\n");
      break;
    CASE(OP_KARG, BB):
      printf("OP_KARG\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_RETURN, B):
      printf("OP_RETURN\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_RETURN_BLK, B):
      printf("OP_RETURN_BLK\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_BREAK, B):
      printf("OP_BREAK\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_BLKPUSH, BS):
      printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d (%d)", a,
             (b>>11)&0x3f,
             (b>>10)&0x1,
             (b>>5)&0x1f,
             (b>>4)&0x1,
             (b>>0)&0xf);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LAMBDA, BB):
      printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
      break;
    CASE(OP_BLOCK, BB):
      printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
      break;
    CASE(OP_METHOD, BB):
      printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
      break;
    CASE(OP_RANGE_INC, B):
      printf("OP_RANGE_INC\tR%d\n", a);
      break;
    CASE(OP_RANGE_EXC, B):
      printf("OP_RANGE_EXC\tR%d\n", a);
      break;
    CASE(OP_DEF, BB):
      printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_UNDEF, B):
      printf("OP_UNDEF\t:%s\n", mrb_sym2name(mrb, irep->syms[a]));
      break;
    CASE(OP_ALIAS, BB):
      printf("OP_ALIAS\t:%s\t%s\n", mrb_sym2name(mrb, irep->syms[a]), mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_ADD, B):
      printf("OP_ADD\tR%d\t\n", a);
      break;
    CASE(OP_ADDI, BB):
      printf("OP_ADDI\tR%d\t%d\n", a, b);
      break;
    CASE(OP_SUB, B):
      printf("OP_SUB\tR%d\t\n", a);
      break;
    CASE(OP_SUBI, BB):
      printf("OP_SUBI\tR%d\t%d\n", a, b);
      break;
    CASE(OP_MUL, B):
      printf("OP_MUL\tR%d\t\n", a);
      break;
    CASE(OP_DIV, B):
      printf("OP_DIV\tR%d\t\n", a);
      break;
    CASE(OP_LT, B):
      printf("OP_LT\t\tR%d\t\n", a);
      break;
    CASE(OP_LE, B):
      printf("OP_LE\t\tR%d\t\n", a);
      break;
    CASE(OP_GT, B):
      printf("OP_GT\t\tR%d\t\n", a);
      break;
    CASE(OP_GE, B):
      printf("OP_GE\t\tR%d\t\n", a);
      break;
    CASE(OP_EQ, B):
      printf("OP_EQ\t\tR%d\t\n", a);
      break;
    CASE(OP_ARRAY, BB):
      printf("OP_ARRAY\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ARRAY2, BBB):
      printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_ARYCAT, B):
      printf("OP_ARYCAT\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ARYPUSH, B):
      printf("OP_ARYPUSH\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ARYDUP, B):
      printf("OP_ARYDUP\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_AREF, BBB):
      printf("OP_AREF\tR%d\tR%d\t%d", a, b, c);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_ASET, BBB):
      printf("OP_ASET\tR%d\tR%d\t%d", a, b, c);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_APOST, BBB):
      printf("OP_APOST\tR%d\t%d\t%d", a, b, c);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_INTERN, B):
      printf("OP_INTERN\tR%d", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_STRING, BB):
      {
        mrb_value v = irep->pool[b];
        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
        printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
      }
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_STRCAT, B):
      printf("OP_STRCAT\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_HASH, BB):
      printf("OP_HASH\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_HASHADD, BB):
      printf("OP_HASHADD\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_HASHCAT, B):
      printf("OP_HASHCAT\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;

    CASE(OP_OCLASS, B):
      printf("OP_OCLASS\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_CLASS, BB):
      printf("OP_CLASS\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_MODULE, BB):
      printf("OP_MODULE\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_EXEC, BB):
      printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SCLASS, B):
      printf("OP_SCLASS\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_TCLASS, B):
      printf("OP_TCLASS\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ERR, B):
      {
        mrb_value v = irep->pool[a];
        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
        printf("OP_ERR\t%s\n", RSTRING_PTR(s));
      }
      break;
    CASE(OP_EPUSH, B):
      printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]);
      break;
    CASE(OP_ONERR, S):
      printf("OP_ONERR\t%03d\n", a);
      break;
    CASE(OP_EXCEPT, B):
      printf("OP_EXCEPT\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_RESCUE, BB):
      printf("OP_RESCUE\tR%d\tR%d", a, b);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_RAISE, B):
      printf("OP_RAISE\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_POPERR, B):
      printf("OP_POPERR\t%d\t\t\n", a);
      break;
    CASE(OP_EPOP, B):
      printf("OP_EPOP\t%d\n", a);
      break;

    CASE(OP_DEBUG, BBB):
      printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c);
      break;

    CASE(OP_STOP, Z):
      printf("OP_STOP\n");
      break;

    CASE(OP_EXT1, Z):
      ins = READ_B();
      printf("OP_EXT1\n");
      print_header(mrb, irep, pc-irep->iseq-2);
      switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
      }
      break;
    CASE(OP_EXT2, Z):
      ins = READ_B();
      printf("OP_EXT2\n");
      print_header(mrb, irep, pc-irep->iseq-2);
      switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
      }
      break;
    CASE(OP_EXT3, Z):
      ins = READ_B();
      printf("OP_EXT3\n");
      print_header(mrb, irep, pc-irep->iseq-2);
      switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
      }
      break;

    default:
      printf("OP_unknown (0x%x)\n", ins);
      break;
    }
    mrb_gc_arena_restore(mrb, ai);
  }
  printf("\n");
}
コード例 #20
0
ファイル: print.c プロジェクト: miura1729/mruby
MRB_API void
mrb_p(mrb_state *mrb, mrb_value obj)
{
  printstr(mrb, mrb_inspect(mrb, obj), stdout);
}
コード例 #21
0
ファイル: codedump.c プロジェクト: cremno/mruby
static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
#ifndef MRB_DISABLE_STDIO
  int i;
  int ai;
  mrb_code c;
  const char *file = NULL, *next_file;
  int32_t line;

  if (!irep) return;
  printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep,
         irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);

  for (i = 0; i < (int)irep->ilen; i++) {
    ai = mrb_gc_arena_save(mrb);

    next_file = mrb_debug_get_filename(irep, i);
    if (next_file && file != next_file) {
      printf("file: %s\n", next_file);
      file = next_file;
    }
    line = mrb_debug_get_line(irep, i);
    if (line < 0) {
      printf("      ");
    }
    else {
      printf("%5d ", line);
    }

    printf("%03d ", i);
    c = irep->iseq[i];
    switch (GET_OPCODE(c)) {
    case OP_NOP:
      printf("OP_NOP\n");
      break;
    case OP_MOVE:
      printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_LOADL:
      {
        mrb_value v = irep->pool[GETARG_Bx(c)];
        mrb_value s = mrb_inspect(mrb, v);
        printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
      }
      print_lv(mrb, irep, c, RA);
      break;
    case OP_LOADI:
      printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_LOADSYM:
      printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_LOADNIL:
      printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_LOADSELF:
      printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_LOADT:
      printf("OP_LOADT\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_LOADF:
      printf("OP_LOADF\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_GETGLOBAL:
      printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_SETGLOBAL:
      printf("OP_SETGLOBAL\t:%s\tR%d\t",
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
             GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_GETCONST:
      printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_SETCONST:
      printf("OP_SETCONST\t:%s\tR%d\t",
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
             GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_GETMCNST:
      printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_SETMCNST:
      printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1,
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
             GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_GETIV:
      printf("OP_GETIV\tR%d\t%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_SETIV:
      printf("OP_SETIV\t%s\tR%d",
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
             GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_GETUPVAR:
      printf("OP_GETUPVAR\tR%d\t%d\t%d",
             GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_SETUPVAR:
      printf("OP_SETUPVAR\tR%d\t%d\t%d",
             GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_GETCV:
      printf("OP_GETCV\tR%d\t%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_SETCV:
      printf("OP_SETCV\t%s\tR%d",
             mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
             GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_JMP:
      printf("OP_JMP\t%03d\n", i+GETARG_sBx(c));
      break;
    case OP_JMPIF:
      printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
      break;
    case OP_JMPNOT:
      printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
      break;
    case OP_SEND:
      printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_SENDB:
      printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_TAILCALL:
      printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_SUPER:
      printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
             GETARG_C(c));
      break;
    case OP_ARGARY:
      printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c),
             (GETARG_Bx(c)>>10)&0x3f,
             (GETARG_Bx(c)>>9)&0x1,
             (GETARG_Bx(c)>>4)&0x1f,
             (GETARG_Bx(c)>>0)&0xf);
      print_lv(mrb, irep, c, RA);
      break;

    case OP_ENTER:
      printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
             (GETARG_Ax(c)>>18)&0x1f,
             (GETARG_Ax(c)>>13)&0x1f,
             (GETARG_Ax(c)>>12)&0x1,
             (GETARG_Ax(c)>>7)&0x1f,
             (GETARG_Ax(c)>>2)&0x1f,
             (GETARG_Ax(c)>>1)&0x1,
             GETARG_Ax(c) & 0x1);
      break;
    case OP_RETURN:
      printf("OP_RETURN\tR%d", GETARG_A(c));
      switch (GETARG_B(c)) {
      case OP_R_NORMAL:
      case OP_R_RETURN:
        printf("\treturn\t"); break;
      case OP_R_BREAK:
        printf("\tbreak\t"); break;
      default:
        printf("\tbroken\t"); break;
        break;
      }
      print_lv(mrb, irep, c, RA);
      break;
    case OP_BLKPUSH:
      printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c),
             (GETARG_Bx(c)>>10)&0x3f,
             (GETARG_Bx(c)>>9)&0x1,
             (GETARG_Bx(c)>>4)&0x1f,
             (GETARG_Bx(c)>>0)&0xf);
      print_lv(mrb, irep, c, RA);
      break;

    case OP_LAMBDA:
      printf("OP_LAMBDA\tR%d\tI(%+d)\t%d", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_RANGE:
      printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_METHOD:
      printf("OP_METHOD\tR%d\t:%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
      print_lv(mrb, irep, c, RA);
      break;

    case OP_ADD:
      printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_ADDI:
      printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_SUB:
      printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_SUBI:
      printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_MUL:
      printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_DIV:
      printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_LT:
      printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_LE:
      printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_GT:
      printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_GE:
      printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;
    case OP_EQ:
      printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
             GETARG_C(c));
      break;

    case OP_STOP:
      printf("OP_STOP\n");
      break;

    case OP_ARRAY:
      printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_ARYCAT:
      printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_ARYPUSH:
      printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_AREF:
      printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_APOST:
      printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_STRING:
      {
        mrb_value v = irep->pool[GETARG_Bx(c)];
        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
        printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
      }
      print_lv(mrb, irep, c, RA);
      break;
    case OP_STRCAT:
      printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_HASH:
      printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
      print_lv(mrb, irep, c, RAB);
      break;

    case OP_OCLASS:
      printf("OP_OCLASS\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_CLASS:
      printf("OP_CLASS\tR%d\t:%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_MODULE:
      printf("OP_MODULE\tR%d\t:%s", GETARG_A(c),
             mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_EXEC:
      printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1);
      print_lv(mrb, irep, c, RA);
      break;
    case OP_SCLASS:
      printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
      print_lv(mrb, irep, c, RAB);
      break;
    case OP_TCLASS:
      printf("OP_TCLASS\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_ERR:
      {
        mrb_value v = irep->pool[GETARG_Bx(c)];
        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
        printf("OP_ERR\t%s\n", RSTRING_PTR(s));
      }
      break;
    case OP_EPUSH:
      printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
      break;
    case OP_ONERR:
      printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
      break;
    case OP_RESCUE:
      printf("OP_RESCUE\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_RAISE:
      printf("OP_RAISE\tR%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_POPERR:
      printf("OP_POPERR\t%d\t\t", GETARG_A(c));
      print_lv(mrb, irep, c, RA);
      break;
    case OP_EPOP:
      printf("OP_EPOP\t%d\n", GETARG_A(c));
      break;

    default:
      printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
             GETARG_A(c), GETARG_B(c), GETARG_C(c));
      break;
    }
    mrb_gc_arena_restore(mrb, ai);
  }
  printf("\n");
#endif
}
コード例 #22
0
ファイル: nhash.c プロジェクト: christiank/libn
char *
nhash_inspect(const nhash *hash)
{
  return mrb_str_to_cstr(__LIBN_R, mrb_inspect(__LIBN_R, hash->_hash));
}
コード例 #23
0
ファイル: sprintf.c プロジェクト: Hozum/mruby
mrb_value
mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
{
  const char *p, *end;
  char *buf;
  mrb_int blen;
  mrb_int bsiz;
  mrb_value result;
  mrb_int n;
  mrb_int width;
  mrb_int prec;
  int flags = FNONE;
  int nextarg = 1;
  int posarg = 0;
  mrb_value nextvalue;
  mrb_value tmp;
  mrb_value str;
  mrb_value hash = mrb_undef_value();

#define CHECK_FOR_WIDTH(f)                                                  \
  if ((f) & FWIDTH) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "width given twice");         \
  }                                                                         \
  if ((f) & FPREC0) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "width after precision");     \
  }
#define CHECK_FOR_FLAGS(f)                                                  \
  if ((f) & FWIDTH) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after width");          \
  }                                                                         \
  if ((f) & FPREC0) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after precision");      \
  }

  ++argc;
  --argv;
  mrb_string_value(mrb, &fmt);
  p = RSTRING_PTR(fmt);
  end = p + RSTRING_LEN(fmt);
  blen = 0;
  bsiz = 120;
  result = mrb_str_buf_new(mrb, bsiz);
  buf = RSTRING_PTR(result);
  memset(buf, 0, bsiz);

  for (; p < end; p++) {
    const char *t;
    mrb_sym id = 0;

    for (t = p; t < end && *t != '%'; t++) ;
    PUSH(p, t - p);
    if (t >= end)
      goto sprint_exit; /* end of fmt string */

    p = t + 1;    /* skip `%' */

    width = prec = -1;
    nextvalue = mrb_undef_value();

retry:
    switch (*p) {
      default:
        mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - \\%%S", mrb_str_new(mrb, p, 1));
        break;

      case ' ':
        CHECK_FOR_FLAGS(flags);
        flags |= FSPACE;
        p++;
        goto retry;

      case '#':
        CHECK_FOR_FLAGS(flags);
        flags |= FSHARP;
        p++;
        goto retry;

      case '+':
        CHECK_FOR_FLAGS(flags);
        flags |= FPLUS;
        p++;
        goto retry;

      case '-':
        CHECK_FOR_FLAGS(flags);
        flags |= FMINUS;
        p++;
        goto retry;

      case '0':
        CHECK_FOR_FLAGS(flags);
        flags |= FZERO;
        p++;
        goto retry;

      case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
        n = 0;
        GETNUM(n, width);
        if (*p == '$') {
          if (!mrb_undef_p(nextvalue)) {
            mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %S$", mrb_fixnum_value(n));
          }
          nextvalue = GETPOSARG(n);
          p++;
          goto retry;
        }
        CHECK_FOR_WIDTH(flags);
        width = n;
        flags |= FWIDTH;
        goto retry;

      case '<':
      case '{': {
        const char *start = p;
        char term = (*p == '<') ? '>' : '}';
        mrb_value symname;

        for (; p < end && *p != term; )
          p++;
        if (id) {
          mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%S after <%S>",
                     mrb_str_new(mrb, start, p - start + 1), mrb_sym2str(mrb, id));
        }
        symname = mrb_str_new(mrb, start + 1, p - start - 1);
        id = mrb_intern_str(mrb, symname);
        nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1));
        if (mrb_undef_p(nextvalue)) {
          mrb_raisef(mrb, E_KEY_ERROR, "key%S not found", mrb_str_new(mrb, start, p - start + 1));
        }
        if (term == '}') goto format_s;
        p++;
        goto retry;
      }

      case '*':
        CHECK_FOR_WIDTH(flags);
        flags |= FWIDTH;
        GETASTER(width);
        if (width < 0) {
          flags |= FMINUS;
          width = -width;
        }
        p++;
        goto retry;

      case '.':
        if (flags & FPREC0) {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "precision given twice");
        }
        flags |= FPREC|FPREC0;

        prec = 0;
        p++;
        if (*p == '*') {
          GETASTER(prec);
          if (prec < 0) {  /* ignore negative precision */
            flags &= ~FPREC;
          }
          p++;
          goto retry;
        }

        GETNUM(prec, precision);
        goto retry;

      case '\n':
      case '\0':
        p--;

      case '%':
        if (flags != FNONE) {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format character - %");
        }
        PUSH("%", 1);
        break;

      case 'c': {
        mrb_value val = GETARG();
        mrb_value tmp;
        unsigned int c;

        tmp = mrb_check_string_type(mrb, val);
        if (!mrb_nil_p(tmp)) {
          if (RSTRING_LEN(tmp) != 1 ) {
            mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character");
          }
          c = RSTRING_PTR(tmp)[0];
          n = 1;
        }
        else {
          c = mrb_fixnum(val);
          n = 1;
        }
        if (n <= 0) {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
        }
        if (!(flags & FWIDTH)) {
          CHECK(n);
          buf[blen] = c;
          blen += n;
        }
        else if ((flags & FMINUS)) {
          CHECK(n);
          buf[blen] = c;
          blen += n;
          FILL(' ', width-1);
        }
        else {
          FILL(' ', width-1);
          CHECK(n);
          buf[blen] = c;
          blen += n;
        }
      }
      break;

      case 's':
      case 'p':
  format_s:
      {
        mrb_value arg = GETARG();
        mrb_int len;
        mrb_int slen;

        if (*p == 'p') arg = mrb_inspect(mrb, arg);
        str = mrb_obj_as_string(mrb, arg);
        len = RSTRING_LEN(str);
        RSTRING_LEN(result) = blen;
        if (flags&(FPREC|FWIDTH)) {
          slen = RSTRING_LEN(str);
          if (slen < 0) {
            mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid mbstring sequence");
          }
          if ((flags&FPREC) && (prec < slen)) {
            char *p = RSTRING_PTR(str) + prec;
            slen = prec;
            len = p - RSTRING_PTR(str);
          }
          /* need to adjust multi-byte string pos */
          if ((flags&FWIDTH) && (width > slen)) {
            width -= (int)slen;
            if (!(flags&FMINUS)) {
              CHECK(width);
              while (width--) {
                buf[blen++] = ' ';
              }
            }
            CHECK(len);
            memcpy(&buf[blen], RSTRING_PTR(str), len);
            blen += len;
            if (flags&FMINUS) {
              CHECK(width);
              while (width--) {
                buf[blen++] = ' ';
              }
            }
            break;
          }
        }
        PUSH(RSTRING_PTR(str), len);
      }
      break;

      case 'd':
      case 'i':
      case 'o':
      case 'x':
      case 'X':
      case 'b':
      case 'B':
      case 'u': {
        mrb_value val = GETARG();
        char fbuf[32], nbuf[64], *s;
        const char *prefix = NULL;
        int sign = 0, dots = 0;
        char sc = 0;
        mrb_int v = 0, org_v = 0;
        int base;
        mrb_int len;

        switch (*p) {
          case 'd':
          case 'i':
          case 'u':
            sign = 1; break;
          case 'o':
          case 'x':
          case 'X':
          case 'b':
          case 'B':
            if (flags&(FPLUS|FSPACE)) sign = 1;
            break;
          default:
            break;
        }
        if (flags & FSHARP) {
          switch (*p) {
            case 'o': prefix = "0"; break;
            case 'x': prefix = "0x"; break;
            case 'X': prefix = "0X"; break;
            case 'b': prefix = "0b"; break;
            case 'B': prefix = "0B"; break;
            default: break;
          }
        }

  bin_retry:
        switch (mrb_type(val)) {
          case MRB_TT_FLOAT:
            if (FIXABLE(mrb_float(val))) {
              val = mrb_fixnum_value((mrb_int)mrb_float(val));
              goto bin_retry;
            }
            val = mrb_flt2big(mrb, mrb_float(val));
            if (mrb_fixnum_p(val)) goto bin_retry;
            break;
          case MRB_TT_STRING:
            val = mrb_str_to_inum(mrb, val, 0, TRUE);
            goto bin_retry;
          case MRB_TT_FIXNUM:
            v = mrb_fixnum(val);
            break;
          default:
            val = mrb_Integer(mrb, val);
            goto bin_retry;
        }

        switch (*p) {
          case 'o':
            base = 8; break;
          case 'x':
          case 'X':
            base = 16; break;
          case 'b':
          case 'B':
            base = 2; break;
          case 'u':
          case 'd':
          case 'i':
          default:
            base = 10; break;
        }

        if (base == 2) {
          org_v = v;
          if ( v < 0 && !sign ) {
            val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
            dots = 1;
          }
          else {
            val = mrb_fix2str(mrb, mrb_fixnum_value(v), base);
          }
          v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, 0/*Qfalse*/));
        }
        if (sign) {
          char c = *p;
          if (c == 'i') c = 'd'; /* %d and %i are identical */
          if (base == 2) c = 'd';
          if (v < 0) {
            v = -v;
            sc = '-';
            width--;
          }
          else if (flags & FPLUS) {
            sc = '+';
            width--;
          }
          else if (flags & FSPACE) {
            sc = ' ';
            width--;
          }
          snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
          snprintf(nbuf, sizeof(nbuf), fbuf, v);
          s = nbuf;
        }
        else {
          char c = *p;
          if (c == 'X') c = 'x';
          if (base == 2) c = 'd';
          s = nbuf;
          if (v < 0) {
            dots = 1;
          }
          snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
          snprintf(++s, sizeof(nbuf) - 1, fbuf, v);
          if (v < 0) {
            char d;

            s = remove_sign_bits(s, base);
            switch (base) {
              case 16: d = 'f'; break;
              case 8:  d = '7'; break;
              case 2:  d = '1'; break;
              default: d = 0; break;
            }

            if (d && *s != d) {
              *--s = d;
            }
          }
        }
        {
          size_t size;
          size = strlen(s);
          /* PARANOID: assert(size <= MRB_INT_MAX) */
          len = (mrb_int)size;
        }

        if (dots) {
          prec -= 2;
          width -= 2;
        }

        if (*p == 'X') {
          char *pp = s;
          int c;
          while ((c = (int)(unsigned char)*pp) != 0) {
            *pp = toupper(c);
            pp++;
          }
        }

        if (prefix && !prefix[1]) { /* octal */
          if (dots) {
            prefix = NULL;
          }
          else if (len == 1 && *s == '0') {
            len = 0;
            if (flags & FPREC) prec--;
          }
          else if ((flags & FPREC) && (prec > len)) {
            prefix = NULL;
          }
        }
        else if (len == 1 && *s == '0') {
          prefix = NULL;
        }

        if (prefix) {
          size_t size;
          size = strlen(prefix);
          /* PARANOID: assert(size <= MRB_INT_MAX).
           *  this check is absolutely paranoid. */
          width -= (mrb_int)size;
        }

        if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
          prec = width;
          width = 0;
        }
        else {
          if (prec < len) {
            if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
            prec = len;
          }
          width -= prec;
        }

        if (!(flags&FMINUS)) {
          CHECK(width);
          while (width-- > 0) {
            buf[blen++] = ' ';
          }
        }

        if (sc) PUSH(&sc, 1);

        if (prefix) {
          int plen = (int)strlen(prefix);
          PUSH(prefix, plen);
        }
        CHECK(prec - len);
        if (dots) PUSH("..", 2);

        if (v < 0 || (base == 2 && org_v < 0)) {
          char c = sign_bits(base, p);
          while (len < prec--) {
            buf[blen++] = c;
          }
        }
        else if ((flags & (FMINUS|FPREC)) != FMINUS) {
          char c = '0';
          while (len < prec--) {
            buf[blen++] = c;
          }
        }

        PUSH(s, len);
        CHECK(width);
        while (width-- > 0) {
          buf[blen++] = ' ';
        }
      }
      break;

      case 'f':
      case 'g':
      case 'G':
      case 'e':
      case 'E':
      case 'a':
      case 'A': {
        mrb_value val = GETARG();
        double fval;
        int i, need = 6;
        char fbuf[32];

        fval = mrb_float(mrb_Float(mrb, val));
        if (isnan(fval) || isinf(fval)) {
          const char *expr;
          const int elen = 3;

          if (isnan(fval)) {
            expr = "NaN";
          }
          else {
            expr = "Inf";
          }
          need = elen;
          if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
            need++;
          if ((flags & FWIDTH) && need < width)
            need = width;

          CHECK(need + 1);
          n = snprintf(&buf[blen], need + 1, "%*s", need, "");
          if (flags & FMINUS) {
            if (!isnan(fval) && fval < 0.0)
              buf[blen++] = '-';
            else if (flags & FPLUS)
              buf[blen++] = '+';
            else if (flags & FSPACE)
              blen++;
            memcpy(&buf[blen], expr, elen);
          }
          else {
            if (!isnan(fval) && fval < 0.0)
              buf[blen + need - elen - 1] = '-';
            else if (flags & FPLUS)
              buf[blen + need - elen - 1] = '+';
            else if ((flags & FSPACE) && need > width)
              blen++;
            memcpy(&buf[blen + need - elen], expr, elen);
          }
          blen += strlen(&buf[blen]);
          break;
        }

        fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
        need = 0;
        if (*p != 'e' && *p != 'E') {
          i = INT_MIN;
          frexp(fval, &i);
          if (i > 0)
            need = BIT_DIGITS(i);
        }
        need += (flags&FPREC) ? prec : 6;
        if ((flags&FWIDTH) && need < width)
          need = width;
        need += 20;

        CHECK(need);
        n = snprintf(&buf[blen], need, fbuf, fval);
        blen += n;
      }
      break;
    }
    flags = FNONE;
  }

  sprint_exit:
#if 0
  /* XXX - We cannot validate the number of arguments if (digit)$ style used.
   */
  if (posarg >= 0 && nextarg < argc) {
    const char *mesg = "too many arguments for format string";
    if (mrb_test(ruby_debug)) mrb_raise(mrb, E_ARGUMENT_ERROR, mesg);
    if (mrb_test(ruby_verbose)) mrb_warn("%s", mesg);
  }
#endif
  mrb_str_resize(mrb, result, blen);

  return result;
}
コード例 #24
0
ファイル: sprintf.c プロジェクト: IceDragon200/mruby
mrb_value
mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fmt)
{
  const char *p, *end;
  char *buf;
  mrb_int blen;
  mrb_int bsiz;
  mrb_value result;
  mrb_int n;
  mrb_int width;
  mrb_int prec;
  int nextarg = 1;
  int posarg = 0;
  mrb_value nextvalue;
  mrb_value str;
  mrb_value hash = mrb_undef_value();

#define CHECK_FOR_WIDTH(f)                                                  \
  if ((f) & FWIDTH) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "width given twice");         \
  }                                                                         \
  if ((f) & FPREC0) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "width after precision");     \
  }
#define CHECK_FOR_FLAGS(f)                                                  \
  if ((f) & FWIDTH) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after width");          \
  }                                                                         \
  if ((f) & FPREC0) {                                                       \
    mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after precision");      \
  }

  ++argc;
  --argv;
  mrb_to_str(mrb, fmt);
  p = RSTRING_PTR(fmt);
  end = p + RSTRING_LEN(fmt);
  blen = 0;
  bsiz = 120;
  result = mrb_str_new_capa(mrb, bsiz);
  buf = RSTRING_PTR(result);
  memset(buf, 0, bsiz);

  for (; p < end; p++) {
    const char *t;
    mrb_sym id = 0;
    int flags = FNONE;

    for (t = p; t < end && *t != '%'; t++) ;
    if (t + 1 == end) ++t;
    PUSH(p, t - p);
    if (t >= end)
      goto sprint_exit; /* end of fmt string */

    p = t + 1;    /* skip '%' */

    width = prec = -1;
    nextvalue = mrb_undef_value();

retry:
    switch (*p) {
      default:
        mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - \\%%S", mrb_str_new(mrb, p, 1));
        break;

      case ' ':
        CHECK_FOR_FLAGS(flags);
        flags |= FSPACE;
        p++;
        goto retry;

      case '#':
        CHECK_FOR_FLAGS(flags);
        flags |= FSHARP;
        p++;
        goto retry;

      case '+':
        CHECK_FOR_FLAGS(flags);
        flags |= FPLUS;
        p++;
        goto retry;

      case '-':
        CHECK_FOR_FLAGS(flags);
        flags |= FMINUS;
        p++;
        goto retry;

      case '0':
        CHECK_FOR_FLAGS(flags);
        flags |= FZERO;
        p++;
        goto retry;

      case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
        n = 0;
        GETNUM(n, width);
        if (*p == '$') {
          if (!mrb_undef_p(nextvalue)) {
            mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %S$", mrb_fixnum_value(n));
          }
          nextvalue = GETPOSARG(n);
          p++;
          goto retry;
        }
        CHECK_FOR_WIDTH(flags);
        width = n;
        flags |= FWIDTH;
        goto retry;

      case '<':
      case '{': {
        const char *start = p;
        char term = (*p == '<') ? '>' : '}';
        mrb_value symname;

        for (; p < end && *p != term; )
          p++;
        if (id) {
          mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%S after <%S>",
                     mrb_str_new(mrb, start, p - start + 1), mrb_sym2str(mrb, id));
        }
        symname = mrb_str_new(mrb, start + 1, p - start - 1);
        id = mrb_intern_str(mrb, symname);
        nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (mrb_int)(p - start + 1));
        if (mrb_undef_p(nextvalue)) {
          mrb_raisef(mrb, E_KEY_ERROR, "key%S not found", mrb_str_new(mrb, start, p - start + 1));
        }
        if (term == '}') goto format_s;
        p++;
        goto retry;
      }

      case '*':
        CHECK_FOR_WIDTH(flags);
        flags |= FWIDTH;
        GETASTER(width);
        if (width < 0) {
          flags |= FMINUS;
          width = -width;
        }
        p++;
        goto retry;

      case '.':
        if (flags & FPREC0) {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "precision given twice");
        }
        flags |= FPREC|FPREC0;

        prec = 0;
        p++;
        if (*p == '*') {
          GETASTER(prec);
          if (prec < 0) {  /* ignore negative precision */
            flags &= ~FPREC;
          }
          p++;
          goto retry;
        }

        GETNUM(prec, precision);
        goto retry;

      case '\n':
      case '\0':
        p--;
        /* fallthrough */
      case '%':
        if (flags != FNONE) {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format character - %");
        }
        PUSH("%", 1);
        break;

      case 'c': {
        mrb_value val = GETARG();
        mrb_value tmp;
        char *c;

        tmp = mrb_check_string_type(mrb, val);
        if (!mrb_nil_p(tmp)) {
          if (RSTRING_LEN(tmp) != 1) {
            mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character");
          }
        }
        else if (mrb_fixnum_p(val)) {
          mrb_int n = mrb_fixnum(val);

          if (n < 0x80) {
            char buf[1];

            buf[0] = (char)n;
            tmp = mrb_str_new(mrb, buf, 1);
          }
          else {
            tmp = mrb_funcall(mrb, val, "chr", 0);
            mrb_check_type(mrb, tmp, MRB_TT_STRING);
          }
        }
        else {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
        }
        c = RSTRING_PTR(tmp);
        n = RSTRING_LEN(tmp);
        if (!(flags & FWIDTH)) {
          PUSH(c, n);
        }
        else if ((flags & FMINUS)) {
          PUSH(c, n);
          if (width>0) FILL(' ', width-1);
        }
        else {
          if (width>0) FILL(' ', width-1);
          PUSH(c, n);
        }
      }
      break;

      case 's':
      case 'p':
  format_s:
      {
        mrb_value arg = GETARG();
        mrb_int len;
        mrb_int slen;

        if (*p == 'p') arg = mrb_inspect(mrb, arg);
        str = mrb_obj_as_string(mrb, arg);
        len = RSTRING_LEN(str);
        if (RSTRING(result)->flags & MRB_STR_EMBED) {
          mrb_int tmp_n = len;
          RSTRING(result)->flags &= ~MRB_STR_EMBED_LEN_MASK;
          RSTRING(result)->flags |= tmp_n << MRB_STR_EMBED_LEN_SHIFT;
        }
        else {
          RSTRING(result)->as.heap.len = blen;
        }
        if (flags&(FPREC|FWIDTH)) {
          slen = RSTRING_LEN(str);
          if (slen < 0) {
            mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid mbstring sequence");
          }
          if ((flags&FPREC) && (prec < slen)) {
            char *p = RSTRING_PTR(str) + prec;
            slen = prec;
            len = (mrb_int)(p - RSTRING_PTR(str));
          }
          /* need to adjust multi-byte string pos */
          if ((flags&FWIDTH) && (width > slen)) {
            width -= (int)slen;
            if (!(flags&FMINUS)) {
              FILL(' ', width);
            }
            PUSH(RSTRING_PTR(str), len);
            if (flags&FMINUS) {
              FILL(' ', width);
            }
            break;
          }
        }
        PUSH(RSTRING_PTR(str), len);
      }
      break;

      case 'd':
      case 'i':
      case 'o':
      case 'x':
      case 'X':
      case 'b':
      case 'B':
      case 'u': {
        mrb_value val = GETARG();
        char nbuf[68], *s;
        const char *prefix = NULL;
        int sign = 0, dots = 0;
        char sc = 0;
        mrb_int v = 0;
        int base;
        mrb_int len;

        if (flags & FSHARP) {
          switch (*p) {
            case 'o': prefix = "0"; break;
            case 'x': prefix = "0x"; break;
            case 'X': prefix = "0X"; break;
            case 'b': prefix = "0b"; break;
            case 'B': prefix = "0B"; break;
            default: break;
          }
        }

  bin_retry:
        switch (mrb_type(val)) {
#ifndef MRB_WITHOUT_FLOAT
          case MRB_TT_FLOAT:
            val = mrb_flo_to_fixnum(mrb, val);
            if (mrb_fixnum_p(val)) goto bin_retry;
            break;
#endif
          case MRB_TT_STRING:
            val = mrb_str_to_inum(mrb, val, 0, TRUE);
            goto bin_retry;
          case MRB_TT_FIXNUM:
            v = mrb_fixnum(val);
            break;
          default:
            val = mrb_Integer(mrb, val);
            goto bin_retry;
        }

        switch (*p) {
          case 'o':
            base = 8; break;
          case 'x':
          case 'X':
            base = 16; break;
          case 'b':
          case 'B':
            base = 2; break;
          case 'u':
          case 'd':
          case 'i':
            sign = 1;
          default:
            base = 10; break;
        }

        if (sign) {
          if (v >= 0) {
            if (flags & FPLUS) {
              sc = '+';
              width--;
            }
            else if (flags & FSPACE) {
              sc = ' ';
              width--;
            }
          }
          else {
            sc = '-';
            width--;
          }
          mrb_assert(base == 10);
          snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
          s = nbuf;
          if (v < 0) s++;       /* skip minus sign */
        }
        else {
          s = nbuf;
          if (v < 0) {
            dots = 1;
          }
          switch (base) {
          case 2:
            if (v < 0) {
              val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
            }
            else {
              val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
            }
            strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1);
            break;
          case 8:
            snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v);
            break;
          case 16:
            snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v);
            break;
          }
          if (v < 0) {
            char d;

            s = remove_sign_bits(s, base);
            switch (base) {
              case 16: d = 'f'; break;
              case 8:  d = '7'; break;
              case 2:  d = '1'; break;
              default: d = 0; break;
            }

            if (d && *s != d) {
              *--s = d;
            }
          }
        }
        {
          size_t size;
          size = strlen(s);
          /* PARANOID: assert(size <= MRB_INT_MAX) */
          len = (mrb_int)size;
        }

        if (*p == 'X') {
          char *pp = s;
          int c;
          while ((c = (int)(unsigned char)*pp) != 0) {
            *pp = toupper(c);
            pp++;
          }
        }

        if (prefix && !prefix[1]) { /* octal */
          if (dots) {
            prefix = NULL;
          }
          else if (len == 1 && *s == '0') {
            len = 0;
            if (flags & FPREC) prec--;
          }
          else if ((flags & FPREC) && (prec > len)) {
            prefix = NULL;
          }
        }
        else if (len == 1 && *s == '0') {
          prefix = NULL;
        }

        if (prefix) {
          size_t size;
          size = strlen(prefix);
          /* PARANOID: assert(size <= MRB_INT_MAX).
           *  this check is absolutely paranoid. */
          width -= (mrb_int)size;
        }

        if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
          prec = width;
          width = 0;
        }
        else {
          if (prec < len) {
            if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
            prec = len;
          }
          width -= prec;
        }

        if (!(flags&FMINUS) && width > 0) {
          FILL(' ', width);
          width = 0;
        }

        if (sc) PUSH(&sc, 1);

        if (prefix) {
          int plen = (int)strlen(prefix);
          PUSH(prefix, plen);
        }
        if (dots) {
          prec -= 2;
          width -= 2;
          PUSH("..", 2);
        }

        if (prec > len) {
          CHECK(prec - len);
          if ((flags & (FMINUS|FPREC)) != FMINUS) {
            char c = '0';
            FILL(c, prec - len);
          } else if (v < 0) {
            char c = sign_bits(base, p);
            FILL(c, prec - len);
          }
        }
        PUSH(s, len);
        if (width > 0) {
          FILL(' ', width);
        }
      }
      break;

#ifndef MRB_WITHOUT_FLOAT
      case 'f':
      case 'g':
      case 'G':
      case 'e':
      case 'E':
      case 'a':
      case 'A': {
        mrb_value val = GETARG();
        double fval;
        mrb_int i;
        mrb_int need = 6;
        char fbuf[32];
        int frexp_result;

        fval = mrb_float(mrb_Float(mrb, val));
        if (!isfinite(fval)) {
          const char *expr;
          const mrb_int elen = 3;
          char sign = '\0';

          if (isnan(fval)) {
            expr = "NaN";
          }
          else {
            expr = "Inf";
          }
          need = elen;
          if (!isnan(fval) && fval < 0.0)
            sign = '-';
          else if (flags & (FPLUS|FSPACE))
            sign = (flags & FPLUS) ? '+' : ' ';
          if (sign)
            ++need;
          if ((flags & FWIDTH) && need < width)
            need = width;

          if (need < 0) {
            mrb_raise(mrb, E_ARGUMENT_ERROR, "width too big");
          }
          FILL(' ', need);
          if (flags & FMINUS) {
            if (sign)
              buf[blen - need--] = sign;
            memcpy(&buf[blen - need], expr, elen);
          }
          else {
            if (sign)
              buf[blen - elen - 1] = sign;
            memcpy(&buf[blen - elen], expr, elen);
          }
          break;
        }

        fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
        need = 0;
        if (*p != 'e' && *p != 'E') {
          i = INT_MIN;
          frexp(fval, &frexp_result);
          i = (mrb_int)frexp_result;
          if (i > 0)
            need = BIT_DIGITS(i);
        }
        if (need > MRB_INT_MAX - ((flags&FPREC) ? prec : 6)) {
        too_big_width:
          mrb_raise(mrb, E_ARGUMENT_ERROR,
                    (width > prec ? "width too big" : "prec too big"));
        }
        need += (flags&FPREC) ? prec : 6;
        if ((flags&FWIDTH) && need < width)
          need = width;
        if (need > MRB_INT_MAX - 20) {
          goto too_big_width;
        }
        need += 20;

        CHECK(need);
        n = snprintf(&buf[blen], need, fbuf, fval);
        if (n < 0 || n >= need) {
          mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
        }
        blen += n;
      }
      break;
#endif
    }
    flags = FNONE;
  }

  sprint_exit:
#if 0
  /* XXX - We cannot validate the number of arguments if (digit)$ style used.
   */
  if (posarg >= 0 && nextarg < argc) {
    const char *mesg = "too many arguments for format string";
    if (mrb_test(ruby_debug)) mrb_raise(mrb, E_ARGUMENT_ERROR, mesg);
    if (mrb_test(ruby_verbose)) mrb_warn(mrb, "%S", mrb_str_new_cstr(mrb, mesg));
  }
#endif
  mrb_str_resize(mrb, result, blen);

  return result;
}