summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backtrace.c1
-rw-r--r--src/class.c6
-rw-r--r--src/codegen.c37
-rw-r--r--src/dump.c1
-rw-r--r--src/error.c31
-rw-r--r--src/gc.c16
-rw-r--r--src/hash.c3
-rw-r--r--src/init.c13
-rw-r--r--src/kernel.c2
-rw-r--r--src/mruby_core.rake4
-rw-r--r--src/parse.y65
-rw-r--r--src/proc.c10
-rw-r--r--src/state.c57
-rw-r--r--src/string.c312
-rw-r--r--src/variable.c12
-rw-r--r--src/vm.c6
16 files changed, 296 insertions, 280 deletions
diff --git a/src/backtrace.c b/src/backtrace.c
index 7768a3206..1e1f9fa1a 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -71,7 +71,6 @@ output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_fun
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)) {
diff --git a/src/class.c b/src/class.c
index db9a8ac26..42e2d5d33 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1216,8 +1216,7 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
repr = mrb_any_to_s(mrb, mod);
}
- mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S",
- mrb_sym2str(mrb, name), repr);
+ mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr);
/* not reached */
return mrb_nil_value();
}
@@ -1980,6 +1979,9 @@ mrb_init_class(mrb_state *mrb)
name_class(mrb, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
name_class(mrb, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */
+ mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */
+ MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
+
MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE());
mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE());
diff --git a/src/codegen.c b/src/codegen.c
index cec0d226f..03c752826 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -475,6 +475,8 @@ new_msym(codegen_scope *s, mrb_sym sym)
{
size_t i, len;
+ mrb_assert(s->irep);
+
len = s->irep->slen;
if (len > 256) len = 256;
for (i=0; i<len; i++) {
@@ -549,7 +551,8 @@ for_body(codegen_scope *s, node *tree)
/* generate receiver */
codegen(s, tree->cdr->car, VAL);
/* generate loop-block */
- s = scope_new(s->mrb, s, tree->car);
+ s = scope_new(s->mrb, s, NULL);
+ push(); /* push for a block parameter */
lp = loop_push(s, LOOP_FOR);
lp->pc1 = new_label(s);
@@ -1105,21 +1108,23 @@ readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_boo
codegen_error(s, "malformed readint input");
}
- if (neg) {
- if ((MRB_INT_MIN + n)/base > result) {
- *overflow = TRUE;
- return 0;
+ if(base > 0) {
+ if (neg) {
+ if ((MRB_INT_MIN + n)/base > result) {
+ *overflow = TRUE;
+ return 0;
+ }
+ result *= base;
+ result -= n;
}
- result *= base;
- result -= n;
- }
- else {
- if ((MRB_INT_MAX - n)/base < result) {
- *overflow = TRUE;
- return 0;
+ else {
+ if ((MRB_INT_MAX - n)/base < result) {
+ *overflow = TRUE;
+ return 0;
+ }
+ result *= base;
+ result += n;
}
- result *= base;
- result += n;
}
p++;
}
@@ -2651,7 +2656,7 @@ print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre)
if (n == 0) return 0;
- for (i=0; i<irep->nlocals; i++) {
+ for (i=0; i+1<irep->nlocals; i++) {
if (irep->lv[i].r == n) {
mrb_sym sym = irep->lv[i].name;
if (pre) printf(" ");
@@ -2994,7 +2999,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
{
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_B(c), RSTRING_PTR(s));
+ 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;
diff --git a/src/dump.c b/src/dump.c
index 1acb466a0..b820f1a68 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -343,7 +343,6 @@ write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin)
if (result != MRB_DUMP_OK) {
return result;
}
- cur += rsize;
section_size += rsize;
write_section_irep_header(mrb, section_size, bin);
diff --git a/src/error.c b/src/error.c
index 360df8f2e..5ca013527 100644
--- a/src/error.c
+++ b/src/error.c
@@ -227,7 +227,9 @@ mrb_noreturn void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
mrb->exc = mrb_obj_ptr(exc);
- exc_debug_info(mrb, mrb->exc);
+ if (!mrb->out_of_memory) {
+ exc_debug_info(mrb, mrb->exc);
+ }
if (!mrb->jmp) {
mrb_p(mrb, exc);
abort();
@@ -442,12 +444,26 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
}
}
+mrb_noreturn void
+mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...)
+{
+ mrb_value exc;
+ va_list ap;
+
+ va_start(ap, fmt);
+ exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3,
+ mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id),
+ mrb_ary_new_from_values(mrb, argc, argv));
+ va_end(ap);
+ mrb_exc_raise(mrb, exc);
+}
+
void
mrb_init_exception(mrb_state *mrb)
{
- struct RClass *exception, *script_error;
+ struct RClass *exception, *runtime_error, *script_error;
- mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
+ mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_ANY());
mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_ANY());
mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_ANY());
@@ -457,8 +473,9 @@ mrb_init_exception(mrb_state *mrb)
mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE());
- mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
- mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
- script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
- mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */
+ mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
+ runtime_error = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
+ mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str(mrb, runtime_error, mrb_str_new_lit(mrb, "Out of memory")));
+ script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
+ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */
}
diff --git a/src/gc.c b/src/gc.c
index 4478b71f3..6eb9808e3 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -34,7 +34,7 @@
== Two White Types
- There're two white color types in a flip-flop fassion: White-A and White-B,
+ There're two white color types in a flip-flop fashion: White-A and White-B,
which respectively represent the Current White color (the newly allocated
objects in the current GC cycle) and the Sweep Target White color (the
dead objects to be swept).
@@ -43,8 +43,8 @@
that time, all the dead objects have been swept, while the newly created
objects in the current GC cycle which finally remains White are now
regarded as dead objects. Instead of traversing all the White-A objects and
- paint them as White-B, just switch the meaning of White-A and White-B would
- be much cheaper.
+ painting them as White-B, just switch the meaning of White-A and White-B as
+ this will be much cheaper.
As a result, the objects we sweep in the current GC cycle are always
left from the previous GC cycle. This allows us to sweep objects
@@ -73,8 +73,8 @@
mruby's GC offers an Generational Mode while re-using the tri-color GC
infrastructure. It will treat the Black objects as Old objects after each
- sweep phase, instead of paint them to White. The key idea are still same as
- the traditional generational GC:
+ sweep phase, instead of painting them White. The key ideas are still the same
+ as traditional generational GC:
* Minor GC - just traverse the Young objects (Gray objects) in the mark
phase, then only sweep the newly created objects, and leave
@@ -82,7 +82,7 @@
* Major GC - same as a full regular GC cycle.
- The difference to a "traditional" generational GC is, that the major GC
+ The difference from "traditional" generational GC is, that the major GC
in mruby is triggered incrementally in a tri-color manner.
@@ -189,7 +189,7 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
}
else {
mrb->out_of_memory = TRUE;
- mrb_raise(mrb, E_RUNTIME_ERROR, "Out of memory");
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
}
}
else {
@@ -705,6 +705,8 @@ root_scan_phase(mrb_state *mrb)
mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
/* mark exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
+ /* mark pre-allocated exception */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err);
mark_context(mrb, mrb->root_c);
if (mrb->root_c->fib) {
diff --git a/src/hash.c b/src/hash.c
index 997610953..1d449db3f 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -216,11 +216,12 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
if (r != 0) {
/* expand */
int ai = mrb_gc_arena_save(mrb);
- kh_key(h, k) = KEY(key);
+ key = kh_key(h, k) = KEY(key);
mrb_gc_arena_restore(mrb, ai);
kh_value(h, k).n = kh_size(h)-1;
}
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key);
mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
return;
}
diff --git a/src/init.c b/src/init.c
index c08c4b046..955d6e3a1 100644
--- a/src/init.c
+++ b/src/init.c
@@ -24,8 +24,6 @@ void mrb_init_gc(mrb_state*);
void mrb_init_math(mrb_state*);
void mrb_init_version(mrb_state*);
void mrb_init_mrblib(mrb_state*);
-void mrb_init_mrbgems(mrb_state*);
-void mrb_final_mrbgems(mrb_state*);
#define DONE mrb_gc_arena_restore(mrb, 0);
void
@@ -50,15 +48,4 @@ mrb_init_core(mrb_state *mrb)
mrb_init_gc(mrb); DONE;
mrb_init_version(mrb); DONE;
mrb_init_mrblib(mrb); DONE;
-#ifndef DISABLE_GEMS
- mrb_init_mrbgems(mrb); DONE;
-#endif
-}
-
-void
-mrb_final_core(mrb_state *mrb)
-{
-#ifndef DISABLE_GEMS
- mrb_final_mrbgems(mrb); DONE;
-#endif
}
diff --git a/src/kernel.c b/src/kernel.c
index f6f2872ea..0258e5c15 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -1118,7 +1118,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */
mrb_define_class_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.2.7 */
; /* 15.3.1.2.11 */
- mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.2.12 */
+ mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */
mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE());
diff --git a/src/mruby_core.rake b/src/mruby_core.rake
index 04be0736c..88fca83fc 100644
--- a/src/mruby_core.rake
+++ b/src/mruby_core.rake
@@ -13,7 +13,7 @@ MRuby.each_target do
cxx_abi_dependency = %w(codegen error vm)
cxx_abi_objs = cxx_abi_dependency.map { |v|
src = "#{current_build_dir}/#{v}.cxx"
- file src => "#{current_dir}/#{v}.c" do |t|
+ file src => ["#{current_dir}/#{v}.c", __FILE__] do |t|
File.open(t.name, 'w') do |f|
f.write <<EOS
#define __STDC_CONSTANT_MACROS
@@ -37,7 +37,7 @@ EOS
}
cxx_abi_objs << objfile("#{current_build_dir}/y.tab")
- file "#{current_build_dir}/y.tab.cxx" => "#{current_build_dir}/y.tab.c" do |t|
+ file "#{current_build_dir}/y.tab.cxx" => ["#{current_build_dir}/y.tab.c", __FILE__] do |t|
File.open(t.name, 'w') do |f|
f.write <<EOS
#define __STDC_CONSTANT_MACROS
diff --git a/src/parse.y b/src/parse.y
index 9f185ee73..0a215f393 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -42,11 +42,7 @@ static void yywarning(parser_state *p, const char *s);
static void backref_error(parser_state *p, node *n);
static void tokadd(parser_state *p, int32_t c);
-#ifndef isascii
-#define isascii(c) (((c) & ~0x7f) == 0)
-#endif
-
-#define identchar(c) (isalnum(c) || (c) == '_' || !isascii(c))
+#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
typedef unsigned int stack_type;
@@ -257,7 +253,11 @@ local_var_p(parser_state *p, mrb_sym sym)
static void
local_add_f(parser_state *p, mrb_sym sym)
{
- p->locals->car = push(p->locals->car, nsym(sym));
+ if (p->locals->car && !p->locals->car->car) {
+ p->locals->car->car = nsym(sym);
+ } else {
+ p->locals->car = push(p->locals->car, nsym(sym));
+ }
}
static void
@@ -2875,15 +2875,15 @@ var_ref : variable
| keyword_self
{
$$ = new_self(p);
- }
+ }
| keyword_true
{
$$ = new_true(p);
- }
+ }
| keyword_false
{
$$ = new_false(p);
- }
+ }
| keyword__FILE__
{
if (!p->filename) {
@@ -3377,7 +3377,9 @@ nextc(parser_state *p)
c = (unsigned char)*p->s++;
}
}
- p->column++;
+ if (c >= 0) {
+ p->column++;
+ }
if (c == '\r') {
c = nextc(p);
if (c != '\n') {
@@ -3392,16 +3394,17 @@ nextc(parser_state *p)
if (!p->cxt) return -1;
else {
if (p->cxt->partial_hook(p) < 0)
- return -1;
- return -2;
+ return -1; /* end of program(s) */
+ return -2; /* end of a file in the program files */
}
}
static void
pushback(parser_state *p, int c)
{
- if (c < 0) return;
- p->column--;
+ if (c >= 0) {
+ p->column--;
+ }
p->pb = cons((node*)(intptr_t)c, p->pb);
}
@@ -3425,7 +3428,7 @@ peekc_n(parser_state *p, int n)
do {
c0 = nextc(p);
- if (c0 < 0) return c0;
+ if (c0 == -1) return c0; /* do not skip partial EOF */
list = push(list, (node*)(intptr_t)c0);
} while(n--);
if (p->pb) {
@@ -3781,7 +3784,7 @@ read_escape(parser_state *p)
eof:
case -1:
- case -2:
+ case -2: /* end of a file */
yyerror(p, "Invalid escape character syntax");
return '\0';
@@ -3911,7 +3914,8 @@ parse_string(parser_state *p)
return tHD_LITERAL_DELIM;
}
}
- } while (ISSPACE(c = nextc(p)));
+ c = nextc(p);
+ } while (ISSPACE(c));
pushback(p, c);
return tLITERAL_DELIM;
}
@@ -4096,7 +4100,7 @@ parser_yylex(parser_state *p)
case '#': /* it's a comment */
skip(p, '\n');
/* fall through */
- case -2: /* end of partial script. */
+ case -2: /* end of a file */
case '\n':
maybe_heredoc:
heredoc_treat_nextline(p);
@@ -4131,7 +4135,7 @@ parser_yylex(parser_state *p)
goto retry;
}
case -1: /* EOF */
- case -2: /* end of partial script */
+ case -2: /* end of a file */
goto normal_newline;
default:
pushback(p, c);
@@ -4205,14 +4209,14 @@ parser_yylex(parser_state *p)
static const char end[] = "\n=end";
if (peeks(p, begin)) {
c = peekc_n(p, sizeof(begin)-1);
- if (c < 0 || isspace(c)) {
+ if (c < 0 || ISSPACE(c)) {
do {
if (!skips(p, end)) {
yyerror(p, "embedded document meets end of file");
return 0;
}
c = nextc(p);
- } while (!(c < 0 || isspace(c)));
+ } while (!(c < 0 || ISSPACE(c)));
if (c != '\n') skip(p, '\n');
p->lineno++;
p->column = 0;
@@ -4243,7 +4247,6 @@ parser_yylex(parser_state *p)
return '=';
case '<':
- last_state = p->lstate;
c = nextc(p);
if (c == '<' &&
p->lstate != EXPR_DOT &&
@@ -4337,7 +4340,7 @@ parser_yylex(parser_state *p)
yyerror(p, "incomplete character syntax");
return 0;
}
- if (isspace(c)) {
+ if (ISSPACE(c)) {
if (!IS_ARG()) {
int c2;
switch (c) {
@@ -4374,7 +4377,7 @@ parser_yylex(parser_state *p)
p->lstate = EXPR_VALUE;
return '?';
}
- token_column = newtok(p);
+ newtok(p);
/* need support UTF-8 if configured */
if ((isalnum(c) || c == '_')) {
int c2 = nextc(p);
@@ -4538,7 +4541,7 @@ parser_yylex(parser_state *p)
is_float = seen_point = seen_e = nondigit = 0;
p->lstate = EXPR_END;
- token_column = newtok(p);
+ newtok(p);
if (c == '-' || c == '+') {
tokadd(p, c);
c = nextc(p);
@@ -5160,7 +5163,6 @@ parser_yylex(parser_state *p)
{
int result = 0;
- last_state = p->lstate;
switch (tok(p)[0]) {
case '$':
p->lstate = EXPR_END;
@@ -5190,7 +5192,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
}
}
- if (result == 0 && isupper((int)(unsigned char)tok(p)[0])) {
+ if (result == 0 && ISUPPER(tok(p)[0])) {
result = tCONSTANT;
}
else {
@@ -5556,7 +5558,12 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
if (c->target_class) {
target = c->target_class;
}
- keep = c->slen + 1;
+ if (c->keep_lv) {
+ keep = c->slen + 1;
+ }
+ else {
+ c->keep_lv = TRUE;
+ }
}
proc->target_class = target;
if (mrb->c->ci) {
@@ -5857,7 +5864,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
node *n2 = tree->car;
mrb_bool first_lval = TRUE;
- if (n2 && (n2->car || n2->cdr)) {
+ if (n2 && (n2->car || n2->cdr)) {
dump_prefix(offset+1);
printf("local variables:\n");
dump_prefix(offset+2);
diff --git a/src/proc.c b/src/proc.c
index d4fe86680..a61296ed4 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -149,9 +149,14 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self)
{
struct RProc *p = mrb_proc_ptr(self);
mrb_code *iseq = mrb_proc_iseq(mrb, p);
- mrb_aspec aspec = GETARG_Ax(*iseq);
+ mrb_aspec aspec;
int ma, ra, pa, arity;
+ if (MRB_PROC_CFUNC_P(p)) {
+ // TODO cfunc aspec not implemented yet
+ return mrb_fixnum_value(-1);
+ }
+ aspec = GETARG_Ax(*iseq);
ma = MRB_ASPEC_REQ(aspec);
ra = MRB_ASPEC_REST(aspec);
pa = MRB_ASPEC_POST(aspec);
@@ -201,9 +206,6 @@ mrb_init_proc(mrb_state *mrb)
call_irep->iseq = call_iseq;
call_irep->ilen = 1;
- mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */
- MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
-
mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE());
mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
diff --git a/src/state.c b/src/state.c
index 9dd798f92..8857d3294 100644
--- a/src/state.c
+++ b/src/state.c
@@ -14,7 +14,7 @@
void mrb_init_heap(mrb_state*);
void mrb_init_core(mrb_state*);
-void mrb_final_core(mrb_state*);
+void mrb_init_mrbgems(mrb_state*);
static mrb_value
inspect_main(mrb_state *mrb, mrb_value mod)
@@ -23,14 +23,14 @@ inspect_main(mrb_state *mrb, mrb_value mod)
}
mrb_state*
-mrb_open_allocf(mrb_allocf f, void *ud)
+mrb_open_core(mrb_allocf f, void *ud)
{
static const mrb_state mrb_state_zero = { 0 };
static const struct mrb_context mrb_context_zero = { 0 };
mrb_state *mrb;
#ifdef MRB_NAN_BOXING
- mrb_assert(sizeof(void*) == 4);
+ mrb_static_assert(sizeof(void*) == 4, "when using NaN boxing sizeof pointer must be 4 byte");
#endif
mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
@@ -40,6 +40,7 @@ mrb_open_allocf(mrb_allocf f, void *ud)
mrb->ud = ud;
mrb->allocf = f;
mrb->current_white_part = MRB_GC_WHITE_A;
+ mrb->atexit_stack_len = 0;
#ifndef MRB_GC_FIXED_ARENA
mrb->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
@@ -50,13 +51,14 @@ mrb_open_allocf(mrb_allocf f, void *ud)
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
*mrb->c = mrb_context_zero;
mrb->root_c = mrb->c;
+
mrb_init_core(mrb);
return mrb;
}
-static void*
-allocf(mrb_state *mrb, void *p, size_t size, void *ud)
+void*
+mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
{
if (size == 0) {
free(p);
@@ -102,8 +104,20 @@ mrb_alloca_free(mrb_state *mrb)
mrb_state*
mrb_open(void)
{
- mrb_state *mrb = mrb_open_allocf(allocf, NULL);
+ mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL);
+
+ return mrb;
+}
+mrb_state*
+mrb_open_allocf(mrb_allocf f, void *ud)
+{
+ mrb_state *mrb = mrb_open_core(f, ud);
+
+#ifndef DISABLE_GEMS
+ mrb_init_mrbgems(mrb);
+ mrb_gc_arena_restore(mrb, 0);
+#endif
return mrb;
}
@@ -221,7 +235,15 @@ mrb_free_context(mrb_state *mrb, struct mrb_context *c)
void
mrb_close(mrb_state *mrb)
{
- mrb_final_core(mrb);
+ if (mrb->atexit_stack_len > 0) {
+ mrb_int i;
+ for (i = mrb->atexit_stack_len; i > 0; --i) {
+ mrb->atexit_stack[i - 1](mrb);
+ }
+#ifndef MRB_FIXED_STATE_ATEXIT_STACK
+ mrb_free(mrb, mrb->atexit_stack);
+#endif
+ }
/* free */
mrb_gc_free_gv(mrb);
@@ -258,3 +280,24 @@ mrb_top_self(mrb_state *mrb)
}
return mrb_obj_value(mrb->top_self);
}
+
+void
+mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f)
+{
+#ifdef MRB_FIXED_STATE_ATEXIT_STACK
+ if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit");
+ }
+#else
+ size_t stack_size;
+
+ stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1);
+ if (mrb->atexit_stack_len == 0) {
+ mrb->atexit_stack = (mrb_atexit_func*)mrb_malloc(mrb, stack_size);
+ } else {
+ mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size);
+ }
+#endif
+
+ mrb->atexit_stack[mrb->atexit_stack_len++] = f;
+}
diff --git a/src/string.c b/src/string.c
index 1572cab14..6570c89fb 100644
--- a/src/string.c
+++ b/src/string.c
@@ -17,28 +17,6 @@
#include "mruby/string.h"
#include "mruby/re.h"
-#define STR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED)
-#define STR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED)
-#define STR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK))
-#define STR_SET_EMBED_LEN(s, n) do {\
- size_t tmp_n = (n);\
- s->flags &= ~MRB_STR_EMBED_LEN_MASK;\
- s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\
-} while (0)
-#define STR_SET_LEN(s, n) do {\
- if (STR_EMBED_P(s)) {\
- STR_SET_EMBED_LEN((s),(n));\
- } else {\
- s->as.heap.len = (mrb_int)(n);\
- }\
-} while (0)
-#define RSTRING_EMBED_LEN(s) \
- (mrb_int)((RSTRING(s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT)
-#define STR_EMBED_LEN(s)\
- (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT)
-#define STR_PTR(s) ((STR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr)
-#define STR_LEN(s) ((STR_EMBED_P(s)) ? STR_EMBED_LEN(s) : (s)->as.heap.len)
-
const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
typedef struct mrb_shared_string {
@@ -48,18 +26,14 @@ typedef struct mrb_shared_string {
mrb_int len;
} mrb_shared_string;
-#define STR_SHARED_P(s) ((s)->flags & MRB_STR_SHARED)
-#define STR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
-#define STR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
-
static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2);
static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
mrb_int
mrb_str_strlen(mrb_state *mrb, struct RString *s)
{
- mrb_int i, max = STR_LEN(s);
- char *p = STR_PTR(s);
+ mrb_int i, max = RSTR_LEN(s);
+ char *p = RSTR_PTR(s);
if (!p) return 0;
for (i=0; i<max; i++) {
@@ -73,19 +47,19 @@ mrb_str_strlen(mrb_state *mrb, struct RString *s)
static inline void
resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity)
{
- if (STR_EMBED_P(s)) {
+ if (RSTR_EMBED_P(s)) {
if (RSTRING_EMBED_LEN_MAX < capacity) {
char *const tmp = (char *)mrb_malloc(mrb, capacity+1);
- const mrb_int len = STR_EMBED_LEN(s);
+ const mrb_int len = RSTR_EMBED_LEN(s);
memcpy(tmp, s->as.ary, len);
- STR_UNSET_EMBED_FLAG(s);
+ RSTR_UNSET_EMBED_FLAG(s);
s->as.heap.ptr = tmp;
s->as.heap.len = len;
s->as.heap.aux.capa = capacity;
}
}
else {
- s->as.heap.ptr = (char *)mrb_realloc(mrb, STR_PTR(s), capacity+1);
+ s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
s->as.heap.aux.capa = capacity;
}
}
@@ -105,20 +79,20 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared)
void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
- if (STR_SHARED_P(s)) {
+ if (RSTR_SHARED_P(s)) {
mrb_shared_string *shared = s->as.heap.aux.shared;
if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
s->as.heap.ptr = shared->ptr;
s->as.heap.aux.capa = shared->len;
- STR_PTR(s)[s->as.heap.len] = '\0';
+ RSTR_PTR(s)[s->as.heap.len] = '\0';
mrb_free(mrb, shared);
}
else {
char *ptr, *p;
mrb_int len;
- p = STR_PTR(s);
+ p = RSTR_PTR(s);
len = s->as.heap.len;
ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
if (p) {
@@ -129,19 +103,19 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
s->as.heap.aux.capa = len;
str_decref(mrb, shared);
}
- STR_UNSET_SHARED_FLAG(s);
+ RSTR_UNSET_SHARED_FLAG(s);
return;
}
- if (s->flags & MRB_STR_NOFREE) {
+ if (RSTR_NOFREE_P(s)) {
char *p = s->as.heap.ptr;
s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1);
if (p) {
- memcpy(STR_PTR(s), p, s->as.heap.len);
+ memcpy(RSTR_PTR(s), p, s->as.heap.len);
}
- STR_PTR(s)[s->as.heap.len] = '\0';
+ RSTR_PTR(s)[s->as.heap.len] = '\0';
s->as.heap.aux.capa = s->as.heap.len;
- s->flags &= ~MRB_STR_NOFREE;
+ RSTR_UNSET_NOFREE_FLAG(s);
return;
}
}
@@ -153,13 +127,13 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
- slen = STR_LEN(s);
+ slen = RSTR_LEN(s);
if (len != slen) {
if (slen < len || slen - len > 256) {
resize_capa(mrb, s, len);
}
- STR_SET_LEN(s, len);
- STR_PTR(s)[len] = '\0'; /* sentinel */
+ RSTR_SET_LEN(s, len);
+ RSTR_PTR(s)[len] = '\0'; /* sentinel */
}
return str;
}
@@ -173,8 +147,8 @@ str_new(mrb_state *mrb, const char *p, size_t len)
s = mrb_obj_alloc_string(mrb);
if (len < RSTRING_EMBED_LEN_MAX) {
- STR_SET_EMBED_FLAG(s);
- STR_SET_EMBED_LEN(s,len);
+ RSTR_SET_EMBED_FLAG(s);
+ RSTR_SET_EMBED_LEN(s,len);
if (p) {
memcpy(s->as.ary, p, len);
}
@@ -189,7 +163,7 @@ str_new(mrb_state *mrb, const char *p, size_t len)
memcpy(s->as.heap.ptr, p, len);
}
}
- STR_PTR(s)[len] = '\0';
+ RSTR_PTR(s)[len] = '\0';
return s;
}
@@ -228,7 +202,7 @@ mrb_str_buf_new(mrb_state *mrb, size_t capa)
s->as.heap.len = 0;
s->as.heap.aux.capa = capa;
s->as.heap.ptr = (char *)mrb_malloc(mrb, capa+1);
- STR_PTR(s)[0] = '\0';
+ RSTR_PTR(s)[0] = '\0';
return mrb_obj_value(s);
}
@@ -242,19 +216,19 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
if (len == 0) return;
mrb_str_modify(mrb, s);
- if (ptr >= STR_PTR(s) && ptr <= STR_PTR(s) + (size_t)STR_LEN(s)) {
- off = ptr - STR_PTR(s);
+ if (ptr >= RSTR_PTR(s) && ptr <= RSTR_PTR(s) + (size_t)RSTR_LEN(s)) {
+ off = ptr - RSTR_PTR(s);
}
- if (STR_EMBED_P(s))
+ if (RSTR_EMBED_P(s))
capa = RSTRING_EMBED_LEN_MAX;
else
capa = s->as.heap.aux.capa;
- if (STR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) {
+ if (RSTR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
}
- total = STR_LEN(s)+len;
+ total = RSTR_LEN(s)+len;
if (capa <= total) {
while (total > capa) {
if (capa + 1 >= MRB_INT_MAX / 2) {
@@ -266,12 +240,12 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
resize_capa(mrb, s, capa);
}
if (off != -1) {
- ptr = STR_PTR(s) + off;
+ ptr = RSTR_PTR(s) + off;
}
- memcpy(STR_PTR(s) + STR_LEN(s), ptr, len);
+ memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len);
mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX);
- STR_SET_LEN(s, total);
- STR_PTR(s)[total] = '\0'; /* sentinel */
+ RSTR_SET_LEN(s, total);
+ RSTR_PTR(s)[total] = '\0'; /* sentinel */
}
mrb_value
@@ -324,11 +298,11 @@ mrb_str_new_static(mrb_state *mrb, const char *p, size_t len)
void
mrb_gc_free_str(mrb_state *mrb, struct RString *str)
{
- if (STR_EMBED_P(str))
+ if (RSTR_EMBED_P(str))
/* no code */;
- else if (STR_SHARED_P(str))
+ else if (RSTR_SHARED_P(str))
str_decref(mrb, str->as.heap.aux.shared);
- else if ((str->flags & MRB_STR_NOFREE) == 0)
+ else if (!RSTR_NOFREE_P(str))
mrb_free(mrb, str->as.heap.ptr);
}
@@ -342,34 +316,34 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
}
s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
- if ((strlen(STR_PTR(s)) ^ STR_LEN(s)) != 0) {
+ if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
}
- return STR_PTR(s);
+ return RSTR_PTR(s);
}
static void
str_make_shared(mrb_state *mrb, struct RString *s)
{
- if (!STR_SHARED_P(s)) {
+ if (!RSTR_SHARED_P(s)) {
mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
shared->refcnt = 1;
- if (STR_EMBED_P(s)) {
- const mrb_int len = STR_EMBED_LEN(s);
+ if (RSTR_EMBED_P(s)) {
+ const mrb_int len = RSTR_EMBED_LEN(s);
char *const tmp = (char *)mrb_malloc(mrb, len+1);
memcpy(tmp, s->as.ary, len);
tmp[len] = '\0';
- STR_UNSET_EMBED_FLAG(s);
+ RSTR_UNSET_EMBED_FLAG(s);
s->as.heap.ptr = tmp;
s->as.heap.len = len;
shared->nofree = FALSE;
shared->ptr = s->as.heap.ptr;
}
- else if (s->flags & MRB_STR_NOFREE) {
+ else if (RSTR_NOFREE_P(s)) {
shared->nofree = TRUE;
shared->ptr = s->as.heap.ptr;
- s->flags &= ~MRB_STR_NOFREE;
+ RSTR_UNSET_NOFREE_FLAG(s);
}
else {
shared->nofree = FALSE;
@@ -382,7 +356,7 @@ str_make_shared(mrb_state *mrb, struct RString *s)
}
shared->len = s->as.heap.len;
s->as.heap.aux.shared = shared;
- STR_SET_SHARED_FLAG(s);
+ RSTR_SET_SHARED_FLAG(s);
}
}
@@ -397,8 +371,8 @@ mrb_str_body(mrb_value str, int *len_p)
{
struct RString *s = mrb_str_ptr(str);
- *len_p = STR_LEN(s);
- return STR_PTR(s);
+ *len_p = RSTR_LEN(s);
+ return RSTR_PTR(s);
}
/*
@@ -418,14 +392,14 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
other = mrb_str_to_str(mrb, other);
}
s2 = mrb_str_ptr(other);
- len = STR_LEN(s1) + STR_LEN(s2);
+ len = RSTR_LEN(s1) + RSTR_LEN(s2);
if (RSTRING_CAPA(self) < len) {
resize_capa(mrb, s1, len);
}
- memcpy(STR_PTR(s1)+STR_LEN(s1), STR_PTR(s2), STR_LEN(s2));
- STR_SET_LEN(s1, len);
- STR_PTR(s1)[len] = '\0';
+ memcpy(RSTR_PTR(s1)+RSTR_LEN(s1), RSTR_PTR(s2), RSTR_LEN(s2));
+ RSTR_SET_LEN(s1, len);
+ RSTR_PTR(s1)[len] = '\0';
}
/*
@@ -441,9 +415,9 @@ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
struct RString *s2 = mrb_str_ptr(b);
struct RString *t;
- t = str_new(mrb, 0, STR_LEN(s) + STR_LEN(s2));
- memcpy(STR_PTR(t), STR_PTR(s), STR_LEN(s));
- memcpy(STR_PTR(t) + STR_LEN(s), STR_PTR(s2), STR_LEN(s2));
+ t = str_new(mrb, 0, RSTR_LEN(s) + RSTR_LEN(s2));
+ memcpy(RSTR_PTR(t), RSTR_PTR(s), RSTR_LEN(s));
+ memcpy(RSTR_PTR(t) + RSTR_LEN(s), RSTR_PTR(s2), RSTR_LEN(s2));
return mrb_obj_value(t);
}
@@ -475,7 +449,7 @@ static mrb_value
mrb_str_bytesize(mrb_state *mrb, mrb_value self)
{
struct RString *s = mrb_str_ptr(self);
- return mrb_fixnum_value(STR_LEN(s));
+ return mrb_fixnum_value(RSTR_LEN(s));
}
/* 15.2.10.5.26 */
@@ -490,7 +464,7 @@ mrb_value
mrb_str_size(mrb_state *mrb, mrb_value self)
{
struct RString *s = mrb_str_ptr(self);
- return mrb_fixnum_value(STR_LEN(s));
+ return mrb_fixnum_value(RSTR_LEN(s));
}
/* 15.2.10.5.1 */
@@ -521,7 +495,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
len = RSTRING_LEN(self)*times;
str2 = str_new(mrb, 0, len);
str_with_class(mrb, str2, self);
- p = STR_PTR(str2);
+ p = RSTR_PTR(str2);
if (len > 0) {
n = RSTRING_LEN(self);
memcpy(p, RSTRING_PTR(self), n);
@@ -531,7 +505,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
}
memcpy(p + n, p, len-n);
}
- p[STR_LEN(str2)] = '\0';
+ p[RSTR_LEN(str2)] = '\0';
return mrb_obj_value(str2);
}
@@ -555,11 +529,11 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2)
struct RString *s1 = mrb_str_ptr(str1);
struct RString *s2 = mrb_str_ptr(str2);
- len = lesser(STR_LEN(s1), STR_LEN(s2));
- retval = memcmp(STR_PTR(s1), STR_PTR(s2), len);
+ len = lesser(RSTR_LEN(s1), RSTR_LEN(s2));
+ retval = memcmp(RSTR_PTR(s1), RSTR_PTR(s2), len);
if (retval == 0) {
- if (STR_LEN(s1) == STR_LEN(s2)) return 0;
- if (STR_LEN(s1) > STR_LEN(s2)) return 1;
+ if (RSTR_LEN(s1) == RSTR_LEN(s2)) return 0;
+ if (RSTR_LEN(s1) > RSTR_LEN(s2)) return 1;
return -1;
}
if (retval > 0) return 1;
@@ -840,8 +814,6 @@ num_index:
* str.slice(fixnum) => fixnum or nil
* str.slice(fixnum, fixnum) => new_str or nil
* str.slice(range) => new_str or nil
- * str.slice(regexp) => new_str or nil
- * str.slice(regexp, fixnum) => new_str or nil
* str.slice(other_str) => new_str or nil
*
* Element Reference---If passed a single <code>Fixnum</code>, returns the code
@@ -853,10 +825,7 @@ num_index:
* <code>nil</code> if the initial offset falls outside the string, the length
* is negative, or the beginning of the range is greater than the end.
*
- * If a <code>Regexp</code> is supplied, the matching portion of <i>str</i> is
- * returned. If a numeric parameter follows the regular expression, that
- * component of the <code>MatchData</code> is returned instead. If a
- * <code>String</code> is given, that string is returned if it occurs in
+ * If a <code>String</code> is given, that string is returned if it occurs in
* <i>str</i>. In both cases, <code>nil</code> is returned if there is no
* match.
*
@@ -868,10 +837,6 @@ num_index:
* a[-4..-2] #=> "her"
* a[12..-1] #=> nil
* a[-2..-4] #=> ""
- * a[/[aeiou](.)\1/] #=> "ell"
- * a[/[aeiou](.)\1/, 0] #=> "ell"
- * a[/[aeiou](.)\1/, 1] #=> "l"
- * a[/[aeiou](.)\1/, 2] #=> nil
* a["lo"] #=> "lo"
* a["bye"] #=> nil
*/
@@ -913,8 +878,8 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
- if (STR_LEN(s) == 0 || !STR_PTR(s)) return mrb_nil_value();
- p = STR_PTR(s); pend = STR_PTR(s) + STR_LEN(s);
+ if (RSTR_LEN(s) == 0 || !RSTR_PTR(s)) return mrb_nil_value();
+ p = RSTR_PTR(s); pend = RSTR_PTR(s) + RSTR_LEN(s);
if (ISLOWER(*p)) {
*p = TOUPPER(*p);
modify = TRUE;
@@ -970,29 +935,29 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
- len = STR_LEN(s);
+ len = RSTR_LEN(s);
if (mrb_get_args(mrb, "|S", &rs) == 0) {
if (len == 0) return mrb_nil_value();
smart_chomp:
- if (STR_PTR(s)[len-1] == '\n') {
- STR_SET_LEN(s, STR_LEN(s) - 1);
- if (STR_LEN(s) > 0 &&
- STR_PTR(s)[STR_LEN(s)-1] == '\r') {
- STR_SET_LEN(s, STR_LEN(s) - 1);
+ if (RSTR_PTR(s)[len-1] == '\n') {
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
+ if (RSTR_LEN(s) > 0 &&
+ RSTR_PTR(s)[RSTR_LEN(s)-1] == '\r') {
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
}
}
- else if (STR_PTR(s)[len-1] == '\r') {
- STR_SET_LEN(s, STR_LEN(s) - 1);
+ else if (RSTR_PTR(s)[len-1] == '\r') {
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
}
else {
return mrb_nil_value();
}
- STR_PTR(s)[STR_LEN(s)] = '\0';
+ RSTR_PTR(s)[RSTR_LEN(s)] = '\0';
return str;
}
if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value();
- p = STR_PTR(s);
+ p = RSTR_PTR(s);
rslen = RSTRING_LEN(rs);
if (rslen == 0) {
while (len>0 && p[len-1] == '\n') {
@@ -1000,8 +965,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
if (len>0 && p[len-1] == '\r')
len--;
}
- if (len < STR_LEN(s)) {
- STR_SET_LEN(s, len);
+ if (len < RSTR_LEN(s)) {
+ RSTR_SET_LEN(s, len);
p[len] = '\0';
return str;
}
@@ -1018,8 +983,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
if (p[len-1] == newline &&
(rslen <= 1 ||
memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
- STR_SET_LEN(s, len - rslen);
- p[STR_LEN(s)] = '\0';
+ RSTR_SET_LEN(s, len - rslen);
+ p[RSTR_LEN(s)] = '\0';
return str;
}
return mrb_nil_value();
@@ -1069,17 +1034,17 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
- if (STR_LEN(s) > 0) {
+ if (RSTR_LEN(s) > 0) {
mrb_int len;
- len = STR_LEN(s) - 1;
- if (STR_PTR(s)[len] == '\n') {
+ len = RSTR_LEN(s) - 1;
+ if (RSTR_PTR(s)[len] == '\n') {
if (len > 0 &&
- STR_PTR(s)[len-1] == '\r') {
+ RSTR_PTR(s)[len-1] == '\r') {
len--;
}
}
- STR_SET_LEN(s, len);
- STR_PTR(s)[len] = '\0';
+ RSTR_SET_LEN(s, len);
+ RSTR_PTR(s)[len] = '\0';
return str;
}
return mrb_nil_value();
@@ -1127,8 +1092,8 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
- p = STR_PTR(s);
- pend = STR_PTR(s) + STR_LEN(s);
+ p = RSTR_PTR(s);
+ pend = RSTR_PTR(s) + RSTR_LEN(s);
while (p < pend) {
if (ISUPPER(*p)) {
*p = TOLOWER(*p);
@@ -1177,7 +1142,7 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self)
{
struct RString *s = mrb_str_ptr(self);
- return mrb_bool_value(STR_LEN(s) == 0);
+ return mrb_bool_value(RSTR_LEN(s) == 0);
}
/* 15.2.10.5.17 */
@@ -1206,7 +1171,7 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
mrb_shared_string *shared;
orig = mrb_str_ptr(str);
- if (STR_EMBED_P(orig)) {
+ if (RSTR_EMBED_P(orig)) {
s = str_new(mrb, orig->as.ary+beg, len);
} else {
str_make_shared(mrb, orig);
@@ -1215,7 +1180,7 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
s->as.heap.ptr = orig->as.heap.ptr + beg;
s->as.heap.len = len;
s->as.heap.aux.shared = shared;
- STR_SET_SHARED_FLAG(s);
+ RSTR_SET_SHARED_FLAG(s);
shared->refcnt++;
}
@@ -1247,8 +1212,8 @@ mrb_str_hash(mrb_state *mrb, mrb_value str)
{
/* 1-8-7 */
struct RString *s = mrb_str_ptr(str);
- mrb_int len = STR_LEN(s);
- char *p = STR_PTR(s);
+ mrb_int len = RSTR_LEN(s);
+ char *p = RSTR_PTR(s);
mrb_int key = 0;
while (len--) {
@@ -1393,27 +1358,31 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
long len;
- len = STR_LEN(s2);
- if (STR_SHARED_P(s2)) {
- L_SHARE:
- if (STR_SHARED_P(s1)) {
- str_decref(mrb, s1->as.heap.aux.shared);
- }
- else if (!STR_EMBED_P(s1) && !(s1->flags & MRB_STR_NOFREE)) {
- mrb_free(mrb, s1->as.heap.ptr);
- }
- STR_UNSET_EMBED_FLAG(s1);
+ len = RSTR_LEN(s2);
+ if (RSTR_SHARED_P(s1)) {
+ str_decref(mrb, s1->as.heap.aux.shared);
+ }
+ else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) {
+ mrb_free(mrb, s1->as.heap.ptr);
+ }
+
+ RSTR_UNSET_NOFREE_FLAG(s1);
+
+ if (RSTR_SHARED_P(s2)) {
+L_SHARE:
+ RSTR_UNSET_EMBED_FLAG(s1);
s1->as.heap.ptr = s2->as.heap.ptr;
s1->as.heap.len = len;
s1->as.heap.aux.shared = s2->as.heap.aux.shared;
- STR_SET_SHARED_FLAG(s1);
+ RSTR_SET_SHARED_FLAG(s1);
s1->as.heap.aux.shared->refcnt++;
}
else {
if (len <= RSTRING_EMBED_LEN_MAX) {
- STR_SET_EMBED_FLAG(s1);
- memcpy(s1->as.ary, STR_PTR(s2), len);
- STR_SET_EMBED_LEN(s1, len);
+ RSTR_UNSET_SHARED_FLAG(s1);
+ RSTR_SET_EMBED_FLAG(s1);
+ memcpy(s1->as.ary, RSTR_PTR(s2), len);
+ RSTR_SET_EMBED_LEN(s1, len);
}
else {
str_make_shared(mrb, s2);
@@ -1510,7 +1479,7 @@ mrb_ptr_to_str(mrb_state *mrb, void *p)
uintptr_t n = (uintptr_t)p;
p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4);
- p1 = STR_PTR(p_str);
+ p1 = RSTR_PTR(p_str);
*p1++ = '0';
*p1++ = 'x';
p2 = p1;
@@ -1520,7 +1489,7 @@ mrb_ptr_to_str(mrb_state *mrb, void *p)
n /= 16;
} while (n > 0);
*p2 = '\0';
- STR_SET_LEN(p_str, (mrb_int)(p2 - STR_PTR(p_str)));
+ RSTR_SET_LEN(p_str, (mrb_int)(p2 - RSTR_PTR(p_str)));
while (p1 < p2) {
const char c = *p1;
@@ -1564,7 +1533,7 @@ mrb_str_reverse(mrb_state *mrb, mrb_value str)
s2 = str_new(mrb, 0, RSTRING_LEN(str));
str_with_class(mrb, s2, str);
s = RSTRING_PTR(str); e = RSTRING_END(str) - 1;
- p = STR_PTR(s2);
+ p = RSTR_PTR(s2);
while (e >= s) {
*p++ = *e--;
@@ -1587,9 +1556,9 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
char c;
mrb_str_modify(mrb, s);
- if (STR_LEN(s) > 1) {
- p = STR_PTR(s);
- e = p + STR_LEN(s) - 1;
+ if (RSTR_LEN(s) > 1) {
+ p = RSTR_PTR(s);
+ e = p + RSTR_LEN(s) - 1;
while (p < e) {
c = *p;
*p++ = *e;
@@ -1625,17 +1594,17 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
mrb_int len = RSTRING_LEN(sub);
/* substring longer than string */
- if (STR_LEN(ps) < len) return -1;
- if (STR_LEN(ps) - pos < len) {
- pos = STR_LEN(ps) - len;
+ if (RSTR_LEN(ps) < len) return -1;
+ if (RSTR_LEN(ps) - pos < len) {
+ pos = RSTR_LEN(ps) - len;
}
- sbeg = STR_PTR(ps);
- s = STR_PTR(ps) + pos;
+ sbeg = RSTR_PTR(ps);
+ s = RSTR_PTR(ps) + pos;
t = RSTRING_PTR(sub);
if (len) {
while (sbeg <= s) {
if (memcmp(s, t, len) == 0) {
- return s - STR_PTR(ps);
+ return s - RSTR_PTR(ps);
}
s--;
}
@@ -1728,27 +1697,6 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
return mrb_nil_value();
}
-static const char isspacetable[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-#define ascii_isspace(c) isspacetable[(unsigned char)(c)]
-
/* 15.2.10.5.35 */
/*
@@ -1844,7 +1792,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int ai = mrb_gc_arena_save(mrb);
c = (unsigned char)*ptr++;
if (skip) {
- if (ascii_isspace(c)) {
+ if (ISSPACE(c)) {
beg = ptr - bptr;
}
else {
@@ -1853,7 +1801,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
if (lim_p && lim <= i) break;
}
}
- else if (ascii_isspace(c)) {
+ else if (ISSPACE(c)) {
mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
mrb_gc_arena_restore(mrb, ai);
skip = TRUE;
@@ -2068,11 +2016,11 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr)
{
struct RString *ps = mrb_str_ptr(*ptr);
mrb_int len = mrb_str_strlen(mrb, ps);
- char *p = STR_PTR(ps);
+ char *p = RSTR_PTR(ps);
if (!p || p[len] != '\0') {
mrb_str_modify(mrb, ps);
- return STR_PTR(ps);
+ return RSTR_PTR(ps);
}
return p;
}
@@ -2094,7 +2042,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck)
len = RSTRING_LEN(str);
if (s[len]) { /* no sentinel somehow */
struct RString *temp_str = str_new(mrb, s, len);
- s = STR_PTR(temp_str);
+ s = RSTR_PTR(temp_str);
}
}
return mrb_cstr_to_inum(mrb, s, base, badcheck);
@@ -2214,7 +2162,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck)
}
if (s[len]) { /* no sentinel somehow */
struct RString *temp_str = str_new(mrb, s, len);
- s = STR_PTR(temp_str);
+ s = RSTR_PTR(temp_str);
}
}
return mrb_cstr_to_dbl(mrb, s, badcheck);
@@ -2308,6 +2256,8 @@ mrb_str_upcase(mrb_state *mrb, mrb_value self)
return str;
}
+#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
+
/*
* call-seq:
* str.dump -> new_str
@@ -2353,7 +2303,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
result = str_new(mrb, 0, len);
str_with_class(mrb, result, str);
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
- q = STR_PTR(result);
+ q = RSTR_PTR(result);
*q++ = '"';
while (p < pend) {
unsigned char c = *p++;
@@ -2532,8 +2482,8 @@ static mrb_value
mrb_str_bytes(mrb_state *mrb, mrb_value str)
{
struct RString *s = mrb_str_ptr(str);
- mrb_value a = mrb_ary_new_capa(mrb, STR_LEN(s));
- unsigned char *p = (unsigned char *)(STR_PTR(s)), *pend = p + STR_LEN(s);
+ mrb_value a = mrb_ary_new_capa(mrb, RSTR_LEN(s));
+ unsigned char *p = (unsigned char *)(RSTR_PTR(s)), *pend = p + RSTR_LEN(s);
while (p < pend) {
mrb_ary_push(mrb, a, mrb_fixnum_value(p[0]));
@@ -2548,6 +2498,8 @@ mrb_init_string(mrb_state *mrb)
{
struct RClass *s;
+ mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string");
+
s = mrb->string_class = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
diff --git a/src/variable.c b/src/variable.c
index 5f762dd0b..74bb591cf 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -124,10 +124,10 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
* mrb
* t the variable table to be searched.
* sym the symbol to be used as the key.
- * vp the value pointer. Recieves the value if the specified symbol contains
- * in the instance variable table.
+ * vp the value pointer. Receives the value if the specified symbol is
+ * contained in the instance variable table.
* Returns
- * true if the specfiyed symbol contains in the instance variable table.
+ * true if the specified symbol is contained in the instance variable table.
*/
static mrb_bool
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
@@ -159,10 +159,10 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
* Parameters
* t the variable table to be searched.
* sym the symbol to be used as the key.
- * vp the value pointer. Recieve the deleted value if the symbol contans
- * in the instance varible table.
+ * vp the value pointer. Receive the deleted value if the symbol is
+ * contained in the instance variable table.
* Returns
- * true if the specfied symbol contains in the instance variable table.
+ * true if the specified symbol is contained in the instance variable table.
*/
static mrb_bool
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
diff --git a/src/vm.c b/src/vm.c
index d604e5d9e..9a0f03aba 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -625,7 +625,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
stack_extend(mrb, ci->nregs, 0);
}
else {
- ci->nregs = p->body.irep->nregs + 1;
+ ci->nregs = p->body.irep->nregs;
stack_extend(mrb, ci->nregs, argc+2);
}
@@ -793,7 +793,7 @@ RETRY_TRY_BLOCK:
}
stack_extend(mrb, irep->nregs, stack_keep);
mrb->c->ci->proc = proc;
- mrb->c->ci->nregs = irep->nregs + 1;
+ mrb->c->ci->nregs = irep->nregs;
regs = mrb->c->stack;
regs[0] = self;
@@ -811,7 +811,7 @@ RETRY_TRY_BLOCK:
CASE(OP_LOADL) {
/* A Bx R(A) := Pool(Bx) */
- regs[GETARG_A(i)] = pool[GETARG_Bx(i)];
+ regs[GETARG_A(i)] = pool[GETARG_Bx(i)];
NEXT;
}