예제 #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
파일: 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;
}
예제 #3
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;
}
예제 #4
0
파일: backtrace.c 프로젝트: okkez/mruby
static void
get_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data)
{
  mrb_value ary, str;
  char buf[32];
  int ai = mrb_gc_arena_save(mrb);

  ary = mrb_obj_value((struct RArray*)data);

  str = mrb_str_new_cstr(mrb, loc->filename);
  snprintf(buf, sizeof(buf), ":%d", loc->lineno);
  mrb_str_cat_cstr(mrb, str, buf);

  if (loc->method) {
    mrb_str_cat_lit(mrb, str, ":in ");

    if (loc->class_name) {
      mrb_str_cat_cstr(mrb, str, loc->class_name);
      mrb_str_cat(mrb, str, &loc->sep, 1);
    }

    mrb_str_cat_cstr(mrb, str, loc->method);
  }

  mrb_ary_push(mrb, ary, str);
  mrb_gc_arena_restore(mrb, ai);
}
예제 #5
0
파일: error.c 프로젝트: koie/mruby
static mrb_value
exc_inspect(mrb_state *mrb, mrb_value exc)
{
  mrb_value str, mesg, file, line;

  mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4));
  file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4));
  line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4));

  if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
    str = file;
    mrb_str_cat(mrb, str, ":", 1);
    mrb_str_append(mrb, str, line);
    mrb_str_cat(mrb, str, ": ", 2);
    if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
      mrb_str_append(mrb, str, mesg);
      mrb_str_cat(mrb, str, " (", 2);
    }
    mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
    if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
      mrb_str_cat(mrb, str, ")", 1);
    }
  }
  else {
    str = mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
    if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
      mrb_str_cat(mrb, str, ": ", 2);
      mrb_str_append(mrb, str, mesg);
    } else {
      mrb_str_cat(mrb, str, ": ", 2);
      mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
    }
  }
  return str;
}
예제 #6
0
파일: backtrace.c 프로젝트: Asmod4n/mruby
static void
get_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data)
{
  mrb_value ary, str;
  int ai;

  ai = mrb_gc_arena_save(mrb);
  ary = mrb_obj_value((struct RArray*)data);

  str = mrb_str_new_cstr(mrb, loc->filename);
  mrb_str_cat_lit(mrb, str, ":");
  mrb_str_concat(mrb, str, mrb_fixnum_to_str(mrb, mrb_fixnum_value(loc->lineno), 10));

  if (loc->method) {
    mrb_str_cat_lit(mrb, str, ":in ");

    if (loc->class_name) {
      mrb_str_cat_cstr(mrb, str, loc->class_name);
      mrb_str_cat_cstr(mrb, str, loc->sep);
    }

    mrb_str_cat_cstr(mrb, str, loc->method);
  }

  mrb_ary_push(mrb, ary, str);
  mrb_gc_arena_restore(mrb, ai);
}
예제 #7
0
파일: uart.c 프로젝트: pbosetti/mruby-mraa
mrb_value mrb_mraa_uart_read_to_prompt(mrb_state *mrb, mrb_value self) {
  mraa_uart_context uart;
  mrb_int timeout, nargs, i;
  char prompt, str_arg[1], buf[1];
  mrb_value result;  
  
  timeout = mrb_fixnum(IV_GET("@timeout"));
  
  nargs = mrb_get_args(mrb, "|z", &str_arg);
  if (nargs == 0) {
    char *str = mrb_str_to_cstr(mrb, IV_GET("@prompt"));
    prompt = str[0];
  }
  else
    prompt = str_arg[0];
  
  uart = (mraa_uart_context)mrb_data_get_ptr(mrb, self, &mrb_mraa_uart_ctx_type);
  result = mrb_str_buf_new(mrb, mrb_fixnum(IV_GET("@read_bufsize")));
  
  while (mraa_uart_data_available(uart, timeout) > 0) {
    i = mraa_uart_read(uart, buf, 1);
    if (i == 0)         break;
    if (*buf == prompt) break;
    result = mrb_str_cat_cstr(mrb, result, buf);
  }

  return result;
}
예제 #8
0
파일: proc.c 프로젝트: crimsonwoods/mruby
static mrb_value
mrb_proc_inspect(mrb_state *mrb, mrb_value self)
{
  struct RProc *p = mrb_proc_ptr(self);
  mrb_value str = mrb_str_new_lit(mrb, "#<Proc:");
  mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));

  if (!MRB_PROC_CFUNC_P(p)) {
    mrb_irep *irep = p->body.irep;
    const char *filename;
    int32_t line;
    mrb_str_cat_lit(mrb, str, "@");

    filename = mrb_debug_get_filename(irep, 0);
    mrb_str_cat_cstr(mrb, str, filename ? filename : "-");
    mrb_str_cat_lit(mrb, str, ":");

    line = mrb_debug_get_line(irep, 0);
    if (line != -1) {
      mrb_str_append(mrb, str, mrb_fixnum_value(line));
    }
    else {
      mrb_str_cat_lit(mrb, str, "-");
    }
  }

  if (MRB_PROC_STRICT_P(p)) {
    mrb_str_cat_lit(mrb, str, " (lambda)");
  }

  mrb_str_cat_lit(mrb, str, ">");
  return str;
}
예제 #9
0
파일: proc.c 프로젝트: kmasa/mruby
static mrb_value
mrb_proc_inspect(mrb_state *mrb, mrb_value self)
{
    struct RProc *p = mrb_proc_ptr(self);
    mrb_value str = mrb_str_new_lit(mrb, "#<Proc:");
    mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));

    if (!MRB_PROC_CFUNC_P(p)) {
        mrb_irep *irep = p->body.irep;
        mrb_str_cat_lit(mrb, str, "@");

        if (irep->filename) {
            mrb_str_cat_cstr(mrb, str, irep->filename);
        }
        else {
            mrb_str_cat_lit(mrb, str, "-");
        }
        mrb_str_cat_lit(mrb, str, ":");

        if (irep->lines) {
            mrb_str_append(mrb, str, mrb_fixnum_value(*irep->lines));
        }
        else {
            mrb_str_cat_lit(mrb, str, "-");
        }
    }

    if (MRB_PROC_STRICT_P(p)) {
        mrb_str_cat_lit(mrb, str, " (lambda)");
    }

    mrb_str_cat_lit(mrb, str, ">");
    return str;
}
예제 #10
0
파일: error.c 프로젝트: deweerdt/h2o
static mrb_value
exc_inspect(mrb_state *mrb, mrb_value exc)
{
  mrb_value str, mesg, file, line;
  mrb_bool append_mesg;

  mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
  file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file"));
  line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line"));

  append_mesg = !mrb_nil_p(mesg);
  if (append_mesg) {
    mesg = mrb_obj_as_string(mrb, mesg);
    append_mesg = RSTRING_LEN(mesg) > 0;
  }

  if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
    str = mrb_str_dup(mrb, file);
    mrb_str_cat_lit(mrb, str, ":");
    mrb_str_append(mrb, str, line);
    mrb_str_cat_lit(mrb, str, ": ");
    if (append_mesg) {
      mrb_str_cat_str(mrb, str, mesg);
      mrb_str_cat_lit(mrb, str, " (");
    }
    mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
    if (append_mesg) {
      mrb_str_cat_lit(mrb, str, ")");
    }
  }
  else {
    const char *cname = mrb_obj_classname(mrb, exc);
    str = mrb_str_new_cstr(mrb, cname);
    mrb_str_cat_lit(mrb, str, ": ");
    if (append_mesg) {
      mrb_str_cat_str(mrb, str, mesg);
    }
    else {
      mrb_str_cat_cstr(mrb, str, cname);
    }
  }
  return str;
}
예제 #11
0
파일: object.c 프로젝트: 14923523/mruby
MRB_API mrb_value
mrb_any_to_s(mrb_state *mrb, mrb_value obj)
{
  mrb_value str = mrb_str_buf_new(mrb, 20);
  const char *cname = mrb_obj_classname(mrb, obj);

  mrb_str_cat_lit(mrb, str, "#<");
  mrb_str_cat_cstr(mrb, str, cname);
  mrb_str_cat_lit(mrb, str, ":");
  mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj)));
  mrb_str_cat_lit(mrb, str, ">");

  return str;
}
예제 #12
0
dbgcmd_state
dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
{
  mrb_value expr;
  mrb_value result;
  mrb_value s;
  uint8_t wcnt;
  int ai;

  if (mrdb->wcnt <= 1) {
    puts("Parameter not specified.");
    return DBGST_PROMPT;
  }

  ai = mrb_gc_arena_save(mrb);

  /* eval expr */
  expr = mrb_str_new_cstr(mrb, NULL);
  for (wcnt=1; wcnt<mrdb->wcnt; wcnt++) {
    expr = mrb_str_cat_cstr(mrb, expr, " ");
    expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]);
  }

  result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL);

  /* $print_no = result */
  s = mrb_str_cat_cstr(mrb, result, "\0");
  printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));

  if (mrdb->print_no == 0) {
    mrdb->print_no = 1;
  }

  mrb_gc_arena_restore(mrb, ai);

  return DBGST_PROMPT;
}
예제 #13
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;
}
예제 #14
0
파일: variable.c 프로젝트: fetus-hina/h2o
mrb_value
mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
{
  iv_tbl *t = obj->iv;
  size_t len = iv_size(mrb, t);

  if (len > 0) {
    const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
    mrb_value str = mrb_str_new_capa(mrb, 30);

    mrb_str_cat_lit(mrb, str, "-<");
    mrb_str_cat_cstr(mrb, str, cn);
    mrb_str_cat_lit(mrb, str, ":");
    mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));

    iv_foreach(mrb, t, inspect_i, &str);
    mrb_str_cat_lit(mrb, str, ">");
    return str;
  }
  return mrb_any_to_s(mrb, mrb_obj_value(obj));
}
예제 #15
0
static mrb_value
mrb_grn_expr_code_inspect(mrb_state *mrb, mrb_value self)
{
  grn_ctx *ctx = (grn_ctx *)mrb->ud;
  grn_expr_code *code;
  mrb_value inspected;

  code = DATA_PTR(self);

  inspected = mrb_str_buf_new(mrb, 48);

  mrb_str_cat_lit(mrb, inspected, "#<");
  mrb_str_cat_cstr(mrb, inspected, mrb_obj_classname(mrb, self));
  mrb_str_cat_lit(mrb, inspected, ":");
  mrb_str_concat(mrb, inspected, mrb_ptr_to_str(mrb, mrb_cptr(self)));

  {
    int32_t weight;
    uint32_t offset;

    weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset);

    mrb_str_cat_lit(mrb, inspected, " weight=");
    mrb_str_concat(mrb, inspected,
                   mrb_funcall(mrb,
                               mrb_fixnum_value(weight),
                               "inspect",
                               0));
    mrb_str_cat_lit(mrb, inspected, ", offset=");
    mrb_str_concat(mrb, inspected,
                   mrb_funcall(mrb,
                               mrb_fixnum_value(offset),
                               "inspect",
                               0));
  }

  mrb_str_cat_lit(mrb, inspected, ", modify=");
  mrb_str_concat(mrb, inspected,
                 mrb_funcall(mrb,
                             mrb_fixnum_value(code->modify),
                             "inspect",
                             0));

  mrb_str_cat_lit(mrb, inspected, ", op=");
  mrb_str_concat(mrb, inspected,
                 mrb_funcall(mrb,
                             grn_mrb_value_from_operator(mrb, code->op),
                             "inspect",
                             0));

  mrb_str_cat_lit(mrb, inspected, ", flags=");
  mrb_str_concat(mrb, inspected,
                 mrb_funcall(mrb,
                             mrb_fixnum_value(code->flags),
                             "inspect",
                             0));

  mrb_str_cat_lit(mrb, inspected, ", value=");
  mrb_str_concat(mrb, inspected,
                 mrb_funcall(mrb,
                             grn_mrb_value_from_grn_obj(mrb, code->value),
                             "inspect",
                             0));

  mrb_str_cat_lit(mrb, inspected, ">");

  return inspected;
}
예제 #16
0
/*********************************************************
 * main
 *********************************************************/
static mrb_value
mrb_value_to_string(mrb_state* mrb, mrb_value value) {
  mrb_value str;

  if (mrb_nil_p(value)) {
    return mrb_str_new_cstr(mrb, "null");
  }

  switch (mrb_type(value)) {
  case MRB_TT_FIXNUM:
  case MRB_TT_FLOAT:
  case MRB_TT_TRUE:
  case MRB_TT_FALSE:
  case MRB_TT_UNDEF:
    str = mrb_funcall(mrb, value, "to_s", 0, NULL);
    break;
  case MRB_TT_SYMBOL:
    value = mrb_funcall(mrb, value, "to_s", 0, NULL);
    /* FALLTHROUGH */
  case MRB_TT_STRING:
    {
      int ai = mrb_gc_arena_save(mrb);
      char* ptr = RSTRING_PTR(value);
      char* end = RSTRING_END(value);
      str = mrb_str_new_cstr(mrb, "\""); 
      while (ptr < end && *ptr) {
        switch (*ptr) {
        case '\\':
          str = mrb_str_cat_cstr(mrb, str, "\\\\");
          break;
        case '"':
          str = mrb_str_cat_cstr(mrb, str, "\\\"");
          break;
        case '\b':
          str = mrb_str_cat_cstr(mrb, str, "\\b");
          break;
        case '\f':
          str = mrb_str_cat_cstr(mrb, str, "\\f");
          break;
        case '\n':
          str = mrb_str_cat_cstr(mrb, str, "\\n");
          break;
        case '\r':
          str = mrb_str_cat_cstr(mrb, str, "\\r");
          break;
        case '\t':
          str = mrb_str_cat_cstr(mrb, str, "\\t");
          break;
        default:
          // TODO: handle unicode
          str = mrb_str_cat(mrb, str, ptr, 1);
        }
        ptr++;
      }
      mrb_str_cat_cstr(mrb, str, "\""); 
      mrb_gc_arena_restore(mrb, ai);
    }
    break;
  case MRB_TT_HASH:
    {
      mrb_value keys;
      int n, l;
      str = mrb_str_new_cstr(mrb, "{");
      keys = mrb_hash_keys(mrb, value);
      l = RARRAY_LEN(keys);
      for (n = 0; n < l; n++) {
        mrb_value obj;
        int ai = mrb_gc_arena_save(mrb);
        mrb_value key = mrb_ary_entry(keys, n);
        mrb_value enckey = mrb_funcall(mrb, key, "to_s", 0, NULL);
        enckey = mrb_funcall(mrb, enckey, "inspect", 0, NULL);
        mrb_str_concat(mrb, str, enckey);
        mrb_str_cat_cstr(mrb, str, ":");
        obj = mrb_hash_get(mrb, value, key);
        mrb_str_concat(mrb, str, mrb_value_to_string(mrb, obj));
        if (n != l - 1) {
          mrb_str_cat_cstr(mrb, str, ",");
        }
        mrb_gc_arena_restore(mrb, ai);
      }
      mrb_str_cat_cstr(mrb, str, "}");
      break;
    }
  case MRB_TT_ARRAY:
    {
      int n, l;
      str = mrb_str_new_cstr(mrb, "[");
      l = RARRAY_LEN(value);
      for (n = 0; n < l; n++) {
        int ai = mrb_gc_arena_save(mrb);
        mrb_value obj = mrb_ary_entry(value, n);
        mrb_str_concat(mrb, str, mrb_value_to_string(mrb, obj));
        if (n != l - 1) {
          mrb_str_cat_cstr(mrb, str, ",");
        }
        mrb_gc_arena_restore(mrb, ai);
      }
      mrb_str_cat_cstr(mrb, str, "]");
      break;
    }
  default:
    mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument");
  }
  return str;
}
예제 #17
0
파일: string.c 프로젝트: Asmod4n/mruby
/*
 *  call-seq:
 *     string.succ    ->  string
 *
 *  Returns next sequence of the string;
 *
 *     a = "abc"
 *     a.succ    #=> "abd"
 */
static mrb_value
mrb_str_succ_bang(mrb_state *mrb, mrb_value self)
{
  mrb_value result;
  unsigned char *p, *e, *b, *t;
  const char *prepend;
  struct RString *s = mrb_str_ptr(self);
  size_t l;

  if (RSTRING_LEN(self) == 0)
    return self;

  mrb_str_modify(mrb, s);
  l = RSTRING_LEN(self);
  b = p = (unsigned char*) RSTRING_PTR(self);
  t = e = p + l;
  *(e--) = 0;

  // find trailing ascii/number
  while (e >= b) {
    if (ISALNUM(*e))
      break;
    e--;
  }
  if (e < b) {
    e = p + l - 1;
    result = mrb_str_new_lit(mrb, "");
  } else {
    // find leading letter of the ascii/number
    b = e;
    while (b > p) {
      if (!ISALNUM(*b) || (ISALNUM(*b) && *b != '9' && *b != 'z' && *b != 'Z'))
        break;
      b--;
    }
    if (!ISALNUM(*b))
      b++;
    result = mrb_str_new(mrb, (char*) p, b - p);
  }

  while (e >= b) {
    if (!ISALNUM(*e)) {
      if (*e == 0xff) {
        mrb_str_cat_lit(mrb, result, "\x01");
        (*e) = 0;
      } else
        (*e)++;
      break;
    }
    prepend = NULL;
    if (*e == '9') {
      if (e == b) prepend = "1";
      *e = '0';
    } else if (*e == 'z') {
      if (e == b) prepend = "a";
      *e = 'a';
    } else if (*e == 'Z') {
      if (e == b) prepend = "A";
      *e = 'A';
    } else {
      (*e)++;
      break;
    }
    if (prepend) mrb_str_cat_cstr(mrb, result, prepend);
    e--;
  }
  result = mrb_str_cat(mrb, result, (char*) b, t - b);
  l = RSTRING_LEN(result);
  mrb_str_resize(mrb, self, l);
  memcpy(RSTRING_PTR(self), RSTRING_PTR(result), l);
  return self;
}