mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* eval.c (POP_VARS): propagate DVAR_DONT_RECYCLE, if
SCOPE_DONT_RECYCLE of ruby_scope is set. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@1157 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
78f3616c56
commit
a137ddddee
10 changed files with 285 additions and 110 deletions
48
ChangeLog
48
ChangeLog
|
@ -1,3 +1,11 @@
|
||||||
|
Fri Feb 2 16:14:51 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* array.c (rb_ary_sort_bang): returns self, even if its length is
|
||||||
|
less than 2.
|
||||||
|
|
||||||
|
* eval.c (POP_VARS): propagate DVAR_DONT_RECYCLE, if
|
||||||
|
SCOPE_DONT_RECYCLE of ruby_scope is set.
|
||||||
|
|
||||||
Wed Jan 31 22:27:29 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
Wed Jan 31 22:27:29 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||||
|
|
||||||
* configure.in: gcc-2.95.2-7(cygwin) support.
|
* configure.in: gcc-2.95.2-7(cygwin) support.
|
||||||
|
@ -5,11 +13,45 @@ Wed Jan 31 22:27:29 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||||
|
|
||||||
* cygwin/GNUmakefile: ditto.
|
* cygwin/GNUmakefile: ditto.
|
||||||
|
|
||||||
|
Mon Jan 29 17:36:19 2001 TOYOFUKU Chikanobu <toyofuku@juice.or.jp>
|
||||||
|
|
||||||
|
* eval.c (rb_eval): nd_iter evaluation should be wrapped by
|
||||||
|
BEGIN_CALLARGS and END_CALLARGS.
|
||||||
|
|
||||||
|
Mon Jan 29 01:40:27 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* string.c (str_independent): should not clear str->orig here.
|
||||||
|
it's too early.
|
||||||
|
|
||||||
|
Wed Jan 24 01:45:49 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* eval.c (POP_BLOCK_TAG): call rb_gc_force_recycle() if block has
|
||||||
|
not been objectified.
|
||||||
|
|
||||||
|
* eval.c (rb_callcc): should nail down block->tag history to avoid
|
||||||
|
rb_gc_force_recycle().
|
||||||
|
|
||||||
Tue Jan 23 18:51:57 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Tue Jan 23 18:51:57 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* gc.c (rb_gc_call_finalizer_at_exit): should finalize objects in
|
* gc.c (rb_gc_call_finalizer_at_exit): should finalize objects in
|
||||||
deferred_final_list too.
|
deferred_final_list too.
|
||||||
|
|
||||||
|
Tue Jan 23 16:10:12 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* gc.c (os_live_obj): do not list terminated object.
|
||||||
|
|
||||||
|
* gc.c (os_obj_of): ditto.
|
||||||
|
|
||||||
|
* gc.c (rb_gc_mark): support new T_BLKTAG tag.
|
||||||
|
|
||||||
|
* gc.c (obj_free): ditto.
|
||||||
|
|
||||||
|
* eval.c (new_blktag): creation of new block tag, which holds
|
||||||
|
destination of global jump and orphan status.
|
||||||
|
|
||||||
|
* eval.c (block_pass): break from orphan Proc object will raise a
|
||||||
|
LocalJumpError exception.
|
||||||
|
|
||||||
Mon Jan 22 16:33:16 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
Mon Jan 22 16:33:16 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||||
|
|
||||||
* mkconfig.rb: autoconf 2.49 support.
|
* mkconfig.rb: autoconf 2.49 support.
|
||||||
|
@ -81,6 +123,12 @@ Mon Jan 8 21:24:37 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
* bignum.c (bigdivrem): t2 might be too big for signed long; do
|
* bignum.c (bigdivrem): t2 might be too big for signed long; do
|
||||||
not use rb_int2big(), but rb_uint2big().
|
not use rb_int2big(), but rb_uint2big().
|
||||||
|
|
||||||
|
Mon Jan 8 03:09:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* error.c (rb_load_fail): new func to report LoadError.
|
||||||
|
|
||||||
|
* ruby.c (load_file): use rb_load_fail.
|
||||||
|
|
||||||
Sat Jan 6 00:55:59 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Sat Jan 6 00:55:59 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* pack.c (pack_pack): template "m2" or "u2" caused inifinite loop.
|
* pack.c (pack_pack): template "m2" or "u2" caused inifinite loop.
|
||||||
|
|
7
error.c
7
error.c
|
@ -694,6 +694,13 @@ rb_sys_fail(mesg)
|
||||||
rb_exc_raise(ee);
|
rb_exc_raise(ee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_load_fail(path)
|
||||||
|
char *path;
|
||||||
|
{
|
||||||
|
rb_loaderror("%s -- %s", strerror(errno), path);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_error_frozen(what)
|
rb_error_frozen(what)
|
||||||
char *what;
|
char *what;
|
||||||
|
|
157
eval.c
157
eval.c
|
@ -527,14 +527,20 @@ static struct SCOPE *top_scope;
|
||||||
ruby_sourceline = _frame.line; \
|
ruby_sourceline = _frame.line; \
|
||||||
ruby_frame = _frame.prev; }
|
ruby_frame = _frame.prev; }
|
||||||
|
|
||||||
|
struct BLOCKTAG {
|
||||||
|
struct RBasic super;
|
||||||
|
long dst;
|
||||||
|
long flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct BLOCK {
|
struct BLOCK {
|
||||||
NODE *var;
|
NODE *var;
|
||||||
NODE *body;
|
NODE *body;
|
||||||
VALUE self;
|
VALUE self;
|
||||||
struct FRAME frame;
|
struct FRAME frame;
|
||||||
struct SCOPE *scope;
|
struct SCOPE *scope;
|
||||||
|
struct BLOCKTAG *tag;
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
struct tag *tag;
|
|
||||||
int iter;
|
int iter;
|
||||||
int vmode;
|
int vmode;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -545,12 +551,23 @@ struct BLOCK {
|
||||||
|
|
||||||
#define BLOCK_D_SCOPE 1
|
#define BLOCK_D_SCOPE 1
|
||||||
#define BLOCK_DYNAMIC 2
|
#define BLOCK_DYNAMIC 2
|
||||||
|
#define BLOCK_ORPHAN 4
|
||||||
|
|
||||||
static struct BLOCK *ruby_block;
|
static struct BLOCK *ruby_block;
|
||||||
|
|
||||||
|
static struct BLOCKTAG*
|
||||||
|
new_blktag()
|
||||||
|
{
|
||||||
|
NEWOBJ(blktag, struct BLOCKTAG);
|
||||||
|
OBJSETUP(blktag, 0, T_BLKTAG);
|
||||||
|
blktag->dst = 0;
|
||||||
|
blktag->flags = 0;
|
||||||
|
return blktag;
|
||||||
|
}
|
||||||
|
|
||||||
#define PUSH_BLOCK(v,b) { \
|
#define PUSH_BLOCK(v,b) { \
|
||||||
struct BLOCK _block; \
|
struct BLOCK _block; \
|
||||||
_block.tag = prot_tag; \
|
_block.tag = new_blktag(); \
|
||||||
_block.var = v; \
|
_block.var = v; \
|
||||||
_block.body = b; \
|
_block.body = b; \
|
||||||
_block.self = self; \
|
_block.self = self; \
|
||||||
|
@ -566,19 +583,18 @@ static struct BLOCK *ruby_block;
|
||||||
_block.dyna_vars = ruby_dyna_vars; \
|
_block.dyna_vars = ruby_dyna_vars; \
|
||||||
ruby_block = &_block;
|
ruby_block = &_block;
|
||||||
|
|
||||||
|
#define POP_BLOCK_TAG(tag) do { \
|
||||||
|
if ((tag)->flags & BLOCK_DYNAMIC) \
|
||||||
|
(tag)->flags |= BLOCK_ORPHAN; \
|
||||||
|
else \
|
||||||
|
rb_gc_force_recycle((VALUE)tag); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define POP_BLOCK() \
|
#define POP_BLOCK() \
|
||||||
|
POP_BLOCK_TAG(_block.tag); \
|
||||||
ruby_block = _block.prev; \
|
ruby_block = _block.prev; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PUSH_BLOCK2(b) { \
|
|
||||||
struct BLOCK * volatile _old; \
|
|
||||||
_old = ruby_block; \
|
|
||||||
ruby_block = b;
|
|
||||||
|
|
||||||
#define POP_BLOCK2() \
|
|
||||||
ruby_block = _old; \
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RVarmap *ruby_dyna_vars;
|
struct RVarmap *ruby_dyna_vars;
|
||||||
#define PUSH_VARS() { \
|
#define PUSH_VARS() { \
|
||||||
struct RVarmap * volatile _old; \
|
struct RVarmap * volatile _old; \
|
||||||
|
@ -586,6 +602,8 @@ struct RVarmap *ruby_dyna_vars;
|
||||||
ruby_dyna_vars = 0;
|
ruby_dyna_vars = 0;
|
||||||
|
|
||||||
#define POP_VARS() \
|
#define POP_VARS() \
|
||||||
|
if (_old && (ruby_scope->flag & SCOPE_DONT_RECYCLE)) \
|
||||||
|
FL_SET(_old, DVAR_DONT_RECYCLE); \
|
||||||
ruby_dyna_vars = _old; \
|
ruby_dyna_vars = _old; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,7 +1069,7 @@ static int
|
||||||
error_handle(ex)
|
error_handle(ex)
|
||||||
int ex;
|
int ex;
|
||||||
{
|
{
|
||||||
switch (ex & 0xf) {
|
switch (ex & TAG_MASK) {
|
||||||
case 0:
|
case 0:
|
||||||
ex = 0;
|
ex = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -2211,15 +2229,14 @@ rb_eval(self, n)
|
||||||
case NODE_FOR:
|
case NODE_FOR:
|
||||||
{
|
{
|
||||||
iter_retry:
|
iter_retry:
|
||||||
PUSH_BLOCK(node->nd_var, node->nd_body);
|
|
||||||
PUSH_TAG(PROT_FUNC);
|
PUSH_TAG(PROT_FUNC);
|
||||||
|
PUSH_BLOCK(node->nd_var, node->nd_body);
|
||||||
|
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
if (nd_type(node) == NODE_ITER) {
|
|
||||||
PUSH_ITER(ITER_PRE);
|
PUSH_ITER(ITER_PRE);
|
||||||
|
if (nd_type(node) == NODE_ITER) {
|
||||||
result = rb_eval(self, node->nd_iter);
|
result = rb_eval(self, node->nd_iter);
|
||||||
POP_ITER();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALUE recv;
|
VALUE recv;
|
||||||
|
@ -2227,13 +2244,14 @@ rb_eval(self, n)
|
||||||
int line = ruby_sourceline;
|
int line = ruby_sourceline;
|
||||||
|
|
||||||
_block.flags &= ~BLOCK_D_SCOPE;
|
_block.flags &= ~BLOCK_D_SCOPE;
|
||||||
|
BEGIN_CALLARGS;
|
||||||
recv = rb_eval(self, node->nd_iter);
|
recv = rb_eval(self, node->nd_iter);
|
||||||
PUSH_ITER(ITER_PRE);
|
END_CALLARGS;
|
||||||
ruby_sourcefile = file;
|
ruby_sourcefile = file;
|
||||||
ruby_sourceline = line;
|
ruby_sourceline = line;
|
||||||
result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
|
result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
|
||||||
POP_ITER();
|
|
||||||
}
|
}
|
||||||
|
POP_ITER();
|
||||||
}
|
}
|
||||||
else if (_block.tag->dst == state) {
|
else if (_block.tag->dst == state) {
|
||||||
state &= TAG_MASK;
|
state &= TAG_MASK;
|
||||||
|
@ -2241,8 +2259,8 @@ rb_eval(self, n)
|
||||||
result = prot_tag->retval;
|
result = prot_tag->retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
POP_TAG();
|
|
||||||
POP_BLOCK();
|
POP_BLOCK();
|
||||||
|
POP_TAG();
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -3562,26 +3580,58 @@ rb_yield_0(val, self, klass, acheck)
|
||||||
pop_state:
|
pop_state:
|
||||||
POP_ITER();
|
POP_ITER();
|
||||||
POP_CLASS();
|
POP_CLASS();
|
||||||
if ((block->flags & BLOCK_D_SCOPE) &&
|
#if 0
|
||||||
|
if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
|
||||||
|
(!(ruby_scope->flags & SCOPE_DONT_RECYCLE) ||
|
||||||
|
!(block->tag->flags & BLOCK_DYNAMIC) ||
|
||||||
|
!FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE))) {
|
||||||
|
struct RVarmap *vars, *tmp;
|
||||||
|
|
||||||
|
if (ruby_dyna_vars->id == 0) {
|
||||||
|
vars = ruby_dyna_vars->next;
|
||||||
|
rb_gc_force_recycle((VALUE)ruby_dyna_vars);
|
||||||
|
while (vars && vars->id != 0) {
|
||||||
|
tmp = vars->next;
|
||||||
|
rb_gc_force_recycle((VALUE)vars);
|
||||||
|
vars = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
|
||||||
!FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) {
|
!FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) {
|
||||||
struct RVarmap *vars = ruby_dyna_vars;
|
struct RVarmap *vars = ruby_dyna_vars;
|
||||||
|
|
||||||
|
if (ruby_dyna_vars->id == 0) {
|
||||||
|
vars = ruby_dyna_vars->next;
|
||||||
|
rb_gc_force_recycle((VALUE)ruby_dyna_vars);
|
||||||
while (vars && vars->id != 0) {
|
while (vars && vars->id != 0) {
|
||||||
struct RVarmap *tmp = vars->next;
|
struct RVarmap *tmp = vars->next;
|
||||||
rb_gc_force_recycle((VALUE)vars);
|
rb_gc_force_recycle((VALUE)vars);
|
||||||
vars = tmp;
|
vars = tmp;
|
||||||
}
|
}
|
||||||
if (ruby_dyna_vars && ruby_dyna_vars->id == 0) {
|
|
||||||
rb_gc_force_recycle((VALUE)ruby_dyna_vars);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
POP_VARS();
|
POP_VARS();
|
||||||
ruby_block = block;
|
ruby_block = block;
|
||||||
ruby_frame = ruby_frame->prev;
|
ruby_frame = ruby_frame->prev;
|
||||||
if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
|
if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
|
||||||
scope_dup(old_scope);
|
scope_dup(old_scope);
|
||||||
ruby_scope = old_scope;
|
ruby_scope = old_scope;
|
||||||
if (state) JUMP_TAG(state);
|
if (state) {
|
||||||
|
if (!block->tag) {
|
||||||
|
switch (state & TAG_MASK) {
|
||||||
|
case TAG_BREAK:
|
||||||
|
rb_raise(rb_eLocalJumpError, "unexpected break");
|
||||||
|
break;
|
||||||
|
case TAG_RETURN:
|
||||||
|
rb_raise(rb_eLocalJumpError, "unexpected return");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JUMP_TAG(state);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4420,6 +4470,9 @@ rb_call(klass, recv, mid, argc, argv, scope)
|
||||||
ID id = mid;
|
ID id = mid;
|
||||||
struct cache_entry *ent;
|
struct cache_entry *ent;
|
||||||
|
|
||||||
|
if (!klass) {
|
||||||
|
rb_raise(rb_eNotImpError, "method call on terminated obejct");
|
||||||
|
}
|
||||||
/* is it in the method cache? */
|
/* is it in the method cache? */
|
||||||
ent = cache + EXPR1(klass, mid);
|
ent = cache + EXPR1(klass, mid);
|
||||||
if (ent->mid == mid && ent->klass == klass) {
|
if (ent->mid == mid && ent->klass == klass) {
|
||||||
|
@ -4705,7 +4758,6 @@ eval(self, src, scope, file, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
Data_Get_Struct(scope, struct BLOCK, data);
|
Data_Get_Struct(scope, struct BLOCK, data);
|
||||||
|
|
||||||
/* PUSH BLOCK from data */
|
/* PUSH BLOCK from data */
|
||||||
frame = data->frame;
|
frame = data->frame;
|
||||||
frame.tmp = ruby_frame; /* gc protection */
|
frame.tmp = ruby_frame; /* gc protection */
|
||||||
|
@ -4751,14 +4803,33 @@ eval(self, src, scope, file, line)
|
||||||
POP_CLASS();
|
POP_CLASS();
|
||||||
ruby_in_eval--;
|
ruby_in_eval--;
|
||||||
if (!NIL_P(scope)) {
|
if (!NIL_P(scope)) {
|
||||||
|
int dont_recycle = ruby_scope->flag & SCOPE_DONT_RECYCLE;
|
||||||
|
|
||||||
ruby_frame = frame.tmp;
|
ruby_frame = frame.tmp;
|
||||||
if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
|
|
||||||
scope_dup(old_scope);
|
|
||||||
ruby_scope = old_scope;
|
ruby_scope = old_scope;
|
||||||
ruby_block = old_block;
|
ruby_block = old_block;
|
||||||
ruby_dyna_vars = old_dyna_vars;
|
ruby_dyna_vars = old_dyna_vars;
|
||||||
data->vmode = scope_vmode; /* write back visibility mode */
|
data->vmode = scope_vmode; /* write back visibility mode */
|
||||||
scope_vmode = old_vmode;
|
scope_vmode = old_vmode;
|
||||||
|
if (dont_recycle) {
|
||||||
|
struct tag *tag;
|
||||||
|
struct RVarmap *vars;
|
||||||
|
|
||||||
|
scope_dup(ruby_scope);
|
||||||
|
for (tag=prot_tag; tag; tag=tag->prev) {
|
||||||
|
scope_dup(tag->scope);
|
||||||
|
}
|
||||||
|
if (ruby_block) {
|
||||||
|
struct BLOCK *block = ruby_block;
|
||||||
|
while (block) {
|
||||||
|
block->tag->flags |= BLOCK_DYNAMIC;
|
||||||
|
block = block->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (vars = ruby_dyna_vars; vars; vars = vars->next) {
|
||||||
|
FL_SET(vars, DVAR_DONT_RECYCLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ruby_frame->iter = iter;
|
ruby_frame->iter = iter;
|
||||||
|
@ -5171,7 +5242,7 @@ rb_feature_p(feature, wait)
|
||||||
|
|
||||||
while (st_lookup(loading_tbl, f, &th)) {
|
while (st_lookup(loading_tbl, f, &th)) {
|
||||||
if (th == curr_thread) {
|
if (th == curr_thread) {
|
||||||
rb_raise(rb_eLoadError, "infinite load loop -- %s", f);
|
return Qtrue;
|
||||||
}
|
}
|
||||||
CHECK_INTS;
|
CHECK_INTS;
|
||||||
rb_thread_schedule();
|
rb_thread_schedule();
|
||||||
|
@ -5887,6 +5958,7 @@ blk_mark(data)
|
||||||
rb_gc_mark(data->self);
|
rb_gc_mark(data->self);
|
||||||
rb_gc_mark(data->dyna_vars);
|
rb_gc_mark(data->dyna_vars);
|
||||||
rb_gc_mark(data->klass);
|
rb_gc_mark(data->klass);
|
||||||
|
rb_gc_mark(data->tag);
|
||||||
data = data->prev;
|
data = data->prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5929,6 +6001,7 @@ blk_copy_prev(block)
|
||||||
MEMCPY(tmp->frame.argv, block->prev->frame.argv, VALUE, tmp->frame.argc);
|
MEMCPY(tmp->frame.argv, block->prev->frame.argv, VALUE, tmp->frame.argc);
|
||||||
}
|
}
|
||||||
scope_dup(tmp->scope);
|
scope_dup(tmp->scope);
|
||||||
|
tmp->tag->flags |= BLOCK_DYNAMIC;
|
||||||
block->prev = tmp;
|
block->prev = tmp;
|
||||||
block = tmp;
|
block = tmp;
|
||||||
}
|
}
|
||||||
|
@ -6006,6 +6079,8 @@ rb_f_binding(self)
|
||||||
else {
|
else {
|
||||||
data->prev = 0;
|
data->prev = 0;
|
||||||
}
|
}
|
||||||
|
data->flags |= BLOCK_DYNAMIC;
|
||||||
|
data->tag->flags |= BLOCK_DYNAMIC;
|
||||||
|
|
||||||
for (p = data; p; p = p->prev) {
|
for (p = data; p; p = p->prev) {
|
||||||
for (vars = p->dyna_vars; vars; vars = vars->next) {
|
for (vars = p->dyna_vars; vars; vars = vars->next) {
|
||||||
|
@ -6081,7 +6156,6 @@ proc_new(klass)
|
||||||
|
|
||||||
data->orig_thread = rb_thread_current();
|
data->orig_thread = rb_thread_current();
|
||||||
data->iter = data->prev?Qtrue:Qfalse;
|
data->iter = data->prev?Qtrue:Qfalse;
|
||||||
data->tag = 0; /* should not point into stack */
|
|
||||||
frame_dup(&data->frame);
|
frame_dup(&data->frame);
|
||||||
if (data->iter) {
|
if (data->iter) {
|
||||||
blk_copy_prev(data);
|
blk_copy_prev(data);
|
||||||
|
@ -6090,6 +6164,7 @@ proc_new(klass)
|
||||||
data->prev = 0;
|
data->prev = 0;
|
||||||
}
|
}
|
||||||
data->flags |= BLOCK_DYNAMIC;
|
data->flags |= BLOCK_DYNAMIC;
|
||||||
|
data->tag->flags |= BLOCK_DYNAMIC;
|
||||||
|
|
||||||
for (p = data; p; p = p->prev) {
|
for (p = data; p; p = p->prev) {
|
||||||
for (vars = p->dyna_vars; vars; vars = vars->next) {
|
for (vars = p->dyna_vars; vars; vars = vars->next) {
|
||||||
|
@ -6190,7 +6265,6 @@ proc_call(proc, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSH_TAG(PROT_NONE);
|
PUSH_TAG(PROT_NONE);
|
||||||
_block.tag = prot_tag;
|
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
proc_set_safe_level(proc);
|
proc_set_safe_level(proc);
|
||||||
|
@ -6286,7 +6360,6 @@ block_pass(self, node)
|
||||||
ruby_frame->iter = ITER_PRE;
|
ruby_frame->iter = ITER_PRE;
|
||||||
|
|
||||||
PUSH_TAG(PROT_NONE);
|
PUSH_TAG(PROT_NONE);
|
||||||
_block.tag = prot_tag;
|
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
proc_set_safe_level(block);
|
proc_set_safe_level(block);
|
||||||
|
@ -6308,25 +6381,33 @@ block_pass(self, node)
|
||||||
}
|
}
|
||||||
ptr = ptr->prev;
|
ptr = ptr->prev;
|
||||||
}
|
}
|
||||||
|
if (!ptr) {
|
||||||
|
state &= TAG_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ruby_block = old_block;
|
ruby_block = old_block;
|
||||||
ruby_safe_level = safe;
|
ruby_safe_level = safe;
|
||||||
|
|
||||||
if (state) {
|
|
||||||
switch (state) {/* escape from orphan procedure */
|
switch (state) {/* escape from orphan procedure */
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
case TAG_BREAK:
|
case TAG_BREAK:
|
||||||
rb_raise(rb_eLocalJumpError, "break from proc-closure");
|
if (orphan) {
|
||||||
|
rb_raise(rb_eLocalJumpError, "retry from proc-closure");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TAG_RETRY:
|
case TAG_RETRY:
|
||||||
rb_raise(rb_eLocalJumpError, "retry from proc-closure");
|
rb_raise(rb_eLocalJumpError, "retry from proc-closure");
|
||||||
break;
|
break;
|
||||||
case TAG_RETURN:
|
case TAG_RETURN:
|
||||||
|
if (orphan) {
|
||||||
rb_raise(rb_eLocalJumpError, "return from proc-closure");
|
rb_raise(rb_eLocalJumpError, "return from proc-closure");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
JUMP_TAG(state);
|
JUMP_TAG(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6619,7 +6700,7 @@ rb_mod_define_method(argc, argv, mod)
|
||||||
VALUE mod;
|
VALUE mod;
|
||||||
{
|
{
|
||||||
ID id;
|
ID id;
|
||||||
VALUE name, body;
|
VALUE body;
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
id = rb_to_id(argv[0]);
|
id = rb_to_id(argv[0]);
|
||||||
|
@ -8031,8 +8112,6 @@ static VALUE
|
||||||
rb_thread_start(klass, args)
|
rb_thread_start(klass, args)
|
||||||
VALUE klass, args;
|
VALUE klass, args;
|
||||||
{
|
{
|
||||||
rb_thread_t th;
|
|
||||||
|
|
||||||
if (!rb_block_given_p()) {
|
if (!rb_block_given_p()) {
|
||||||
rb_raise(rb_eThreadError, "must be called with a block");
|
rb_raise(rb_eThreadError, "must be called with a block");
|
||||||
}
|
}
|
||||||
|
@ -8379,6 +8458,14 @@ rb_callcc(self)
|
||||||
for (tag=prot_tag; tag; tag=tag->prev) {
|
for (tag=prot_tag; tag; tag=tag->prev) {
|
||||||
scope_dup(tag->scope);
|
scope_dup(tag->scope);
|
||||||
}
|
}
|
||||||
|
if (ruby_block) {
|
||||||
|
struct BLOCK *block = ruby_block;
|
||||||
|
|
||||||
|
while (block) {
|
||||||
|
block->tag->flags |= BLOCK_DYNAMIC;
|
||||||
|
block = block->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
th->thread = curr_thread->thread;
|
th->thread = curr_thread->thread;
|
||||||
|
|
||||||
for (vars = th->dyna_vars; vars; vars = vars->next) {
|
for (vars = th->dyna_vars; vars; vars = vars->next) {
|
||||||
|
|
2
gc.c
2
gc.c
|
@ -613,6 +613,7 @@ rb_gc_mark(ptr)
|
||||||
case T_REGEXP:
|
case T_REGEXP:
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
|
case T_BLKTAG:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_MATCH:
|
case T_MATCH:
|
||||||
|
@ -829,6 +830,7 @@ obj_free(obj)
|
||||||
|
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
case T_VARMAP:
|
case T_VARMAP:
|
||||||
|
case T_BLKTAG:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
|
|
3
intern.h
3
intern.h
|
@ -107,7 +107,8 @@ VALUE rb_exc_new3 _((VALUE, VALUE));
|
||||||
void rb_loaderror __((const char*, ...)) NORETURN;
|
void rb_loaderror __((const char*, ...)) NORETURN;
|
||||||
void rb_compile_error __((const char*, ...));
|
void rb_compile_error __((const char*, ...));
|
||||||
void rb_compile_error_append __((const char*, ...));
|
void rb_compile_error_append __((const char*, ...));
|
||||||
void rb_error_frozen _((char*));
|
void rb_load_fail _((char*)) NORETURN;
|
||||||
|
void rb_error_frozen _((char*)) NORETURN;
|
||||||
/* eval.c */
|
/* eval.c */
|
||||||
void rb_exc_raise _((VALUE)) NORETURN;
|
void rb_exc_raise _((VALUE)) NORETURN;
|
||||||
void rb_exc_fatal _((VALUE)) NORETURN;
|
void rb_exc_fatal _((VALUE)) NORETURN;
|
||||||
|
|
136
parse.y
136
parse.y
|
@ -6,7 +6,7 @@
|
||||||
$Date$
|
$Date$
|
||||||
created at: Fri May 28 18:02:42 JST 1993
|
created at: Fri May 28 18:02:42 JST 1993
|
||||||
|
|
||||||
Copyright (C) 1993-2000 Yukihiro Matsumoto
|
Copyright (C) 1993-2001 Yukihiro Matsumoto
|
||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
|
@ -56,8 +56,16 @@ static enum lex_state {
|
||||||
EXPR_CLASS, /* immediate after `class', no here document. */
|
EXPR_CLASS, /* immediate after `class', no here document. */
|
||||||
} lex_state;
|
} lex_state;
|
||||||
|
|
||||||
|
#if SIZEOF_LONG_LONG > 0
|
||||||
|
typedef unsigned long long stack_type;
|
||||||
|
#elif SIZEOF___INT64 > 0
|
||||||
|
typedef unsigned __int64 stack_type;
|
||||||
|
#else
|
||||||
|
typedef unsigned long stack_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int cond_nest = 0;
|
static int cond_nest = 0;
|
||||||
static unsigned long cond_stack = 0;
|
static stack_type cond_stack = 0;
|
||||||
#define COND_PUSH do {\
|
#define COND_PUSH do {\
|
||||||
cond_nest++;\
|
cond_nest++;\
|
||||||
cond_stack = (cond_stack<<1)|1;\
|
cond_stack = (cond_stack<<1)|1;\
|
||||||
|
@ -68,6 +76,15 @@ static unsigned long cond_stack = 0;
|
||||||
} while (0)
|
} while (0)
|
||||||
#define COND_P() (cond_nest > 0 && (cond_stack&1))
|
#define COND_P() (cond_nest > 0 && (cond_stack&1))
|
||||||
|
|
||||||
|
static stack_type cmdarg_stack = 0;
|
||||||
|
#define CMDARG_PUSH do {\
|
||||||
|
cmdarg_stack = (cmdarg_stack<<1)|1;\
|
||||||
|
} while(0)
|
||||||
|
#define CMDARG_POP do {\
|
||||||
|
cmdarg_stack >>= 1;\
|
||||||
|
} while (0)
|
||||||
|
#define CMDARG_P() (cmdarg_stack && (cmdarg_stack&1))
|
||||||
|
|
||||||
static int class_nest = 0;
|
static int class_nest = 0;
|
||||||
static int in_single = 0;
|
static int in_single = 0;
|
||||||
static int compile_for_eval = 0;
|
static int compile_for_eval = 0;
|
||||||
|
@ -154,7 +171,8 @@ static void top_local_setup();
|
||||||
kRETRY
|
kRETRY
|
||||||
kIN
|
kIN
|
||||||
kDO
|
kDO
|
||||||
kDO2
|
kDO_COND
|
||||||
|
kDO_BLOCK
|
||||||
kRETURN
|
kRETURN
|
||||||
kYIELD
|
kYIELD
|
||||||
kSUPER
|
kSUPER
|
||||||
|
@ -186,8 +204,8 @@ static void top_local_setup();
|
||||||
%type <node> compstmt stmts stmt expr arg primary command command_call method_call
|
%type <node> compstmt stmts stmt expr arg primary command command_call method_call
|
||||||
%type <node> if_tail opt_else case_body cases rescue exc_list exc_var ensure
|
%type <node> if_tail opt_else case_body cases rescue exc_list exc_var ensure
|
||||||
%type <node> args ret_args when_args call_args paren_args opt_paren_args
|
%type <node> args ret_args when_args call_args paren_args opt_paren_args
|
||||||
%type <node> aref_args opt_block_arg block_arg var_ref
|
%type <node> command_args aref_args opt_block_arg block_arg var_ref
|
||||||
%type <node> mrhs mrhs_basic superclass generic_call block_call call_block
|
%type <node> mrhs mrhs_basic superclass block_call block_command
|
||||||
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
|
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
|
||||||
%type <node> assoc_list assocs assoc undef_list backref
|
%type <node> assoc_list assocs assoc undef_list backref
|
||||||
%type <node> block_var opt_block_var brace_block do_block lhs none
|
%type <node> block_var opt_block_var brace_block do_block lhs none
|
||||||
|
@ -444,38 +462,38 @@ expr : mlhs '=' mrhs
|
||||||
| arg
|
| arg
|
||||||
|
|
||||||
command_call : command
|
command_call : command
|
||||||
| block_call
|
| block_command
|
||||||
|
|
||||||
block_call : call_block
|
block_command : block_call
|
||||||
| call_block '.' operation2 call_args
|
| block_call '.' operation2 command_args
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_call($1, $3, $4);
|
$$ = new_call($1, $3, $4);
|
||||||
}
|
}
|
||||||
| call_block tCOLON2 operation2 call_args
|
| block_call tCOLON2 operation2 command_args
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_call($1, $3, $4);
|
$$ = new_call($1, $3, $4);
|
||||||
}
|
}
|
||||||
|
|
||||||
command : operation call_args
|
command : operation command_args
|
||||||
{
|
{
|
||||||
$$ = new_fcall($1, $2);
|
$$ = new_fcall($1, $2);
|
||||||
fixpos($$, $2);
|
fixpos($$, $2);
|
||||||
}
|
}
|
||||||
| primary '.' operation2 call_args
|
| primary '.' operation2 command_args
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_call($1, $3, $4);
|
$$ = new_call($1, $3, $4);
|
||||||
fixpos($$, $1);
|
fixpos($$, $1);
|
||||||
}
|
}
|
||||||
| primary tCOLON2 operation2 call_args
|
| primary tCOLON2 operation2 command_args
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_call($1, $3, $4);
|
$$ = new_call($1, $3, $4);
|
||||||
fixpos($$, $1);
|
fixpos($$, $1);
|
||||||
}
|
}
|
||||||
| kSUPER call_args
|
| kSUPER command_args
|
||||||
{
|
{
|
||||||
if (!compile_for_eval && !cur_mid && !in_single)
|
if (!compile_for_eval && !cur_mid && !in_single)
|
||||||
yyerror("super called outside of method");
|
yyerror("super called outside of method");
|
||||||
|
@ -488,7 +506,6 @@ command : operation call_args
|
||||||
fixpos($$, $2);
|
fixpos($$, $2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mlhs : mlhs_basic
|
mlhs : mlhs_basic
|
||||||
| tLPAREN mlhs_entry ')'
|
| tLPAREN mlhs_entry ')'
|
||||||
{
|
{
|
||||||
|
@ -996,6 +1013,12 @@ call_args : command
|
||||||
}
|
}
|
||||||
| block_arg
|
| block_arg
|
||||||
|
|
||||||
|
command_args : {CMDARG_PUSH;} call_args
|
||||||
|
{
|
||||||
|
CMDARG_POP;
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
|
||||||
block_arg : tAMPER arg
|
block_arg : tAMPER arg
|
||||||
{
|
{
|
||||||
value_expr($2);
|
value_expr($2);
|
||||||
|
@ -1347,7 +1370,7 @@ then : term
|
||||||
| term kTHEN
|
| term kTHEN
|
||||||
|
|
||||||
do : term
|
do : term
|
||||||
| kDO2
|
| kDO_COND
|
||||||
|
|
||||||
if_tail : opt_else
|
if_tail : opt_else
|
||||||
| kELSIF expr then
|
| kELSIF expr then
|
||||||
|
@ -1383,7 +1406,7 @@ opt_block_var : none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
do_block : kDO
|
do_block : kDO_BLOCK
|
||||||
{
|
{
|
||||||
$<vars>$ = dyna_push();
|
$<vars>$ = dyna_push();
|
||||||
}
|
}
|
||||||
|
@ -1396,35 +1419,7 @@ do_block : kDO
|
||||||
dyna_pop($<vars>2);
|
dyna_pop($<vars>2);
|
||||||
}
|
}
|
||||||
|
|
||||||
brace_block : '{'
|
block_call : command do_block
|
||||||
{
|
|
||||||
$<vars>$ = dyna_push();
|
|
||||||
}
|
|
||||||
opt_block_var
|
|
||||||
compstmt '}'
|
|
||||||
{
|
|
||||||
$$ = NEW_ITER($3, 0, $4);
|
|
||||||
fixpos($$, $4);
|
|
||||||
dyna_pop($<vars>2);
|
|
||||||
}
|
|
||||||
|
|
||||||
generic_call : tIDENTIFIER
|
|
||||||
{
|
|
||||||
$$ = NEW_VCALL($1);
|
|
||||||
}
|
|
||||||
| tCONSTANT
|
|
||||||
{
|
|
||||||
$$ = NEW_VCALL($1);
|
|
||||||
}
|
|
||||||
| tFID
|
|
||||||
{
|
|
||||||
$$ = NEW_VCALL($1);
|
|
||||||
}
|
|
||||||
| method_call
|
|
||||||
| command_call
|
|
||||||
|
|
||||||
|
|
||||||
call_block : generic_call do_block
|
|
||||||
{
|
{
|
||||||
if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
|
if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
|
||||||
rb_compile_error("both block arg and actual block given");
|
rb_compile_error("both block arg and actual block given");
|
||||||
|
@ -1433,12 +1428,12 @@ call_block : generic_call do_block
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
fixpos($$, $2);
|
fixpos($$, $2);
|
||||||
}
|
}
|
||||||
| call_block '.' operation2 opt_paren_args
|
| block_call '.' operation2 opt_paren_args
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_call($1, $3, $4);
|
$$ = new_call($1, $3, $4);
|
||||||
}
|
}
|
||||||
| call_block tCOLON2 operation2 opt_paren_args
|
| block_call tCOLON2 operation2 opt_paren_args
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_call($1, $3, $4);
|
$$ = new_call($1, $3, $4);
|
||||||
|
@ -1481,6 +1476,29 @@ method_call : operation paren_args
|
||||||
$$ = NEW_ZSUPER();
|
$$ = NEW_ZSUPER();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
brace_block : '{'
|
||||||
|
{
|
||||||
|
$<vars>$ = dyna_push();
|
||||||
|
}
|
||||||
|
opt_block_var
|
||||||
|
compstmt '}'
|
||||||
|
{
|
||||||
|
$$ = NEW_ITER($3, 0, $4);
|
||||||
|
fixpos($$, $4);
|
||||||
|
dyna_pop($<vars>2);
|
||||||
|
}
|
||||||
|
| kDO
|
||||||
|
{
|
||||||
|
$<vars>$ = dyna_push();
|
||||||
|
}
|
||||||
|
opt_block_var
|
||||||
|
compstmt kEND
|
||||||
|
{
|
||||||
|
$$ = NEW_ITER($3, 0, $4);
|
||||||
|
fixpos($$, $4);
|
||||||
|
dyna_pop($<vars>2);
|
||||||
|
}
|
||||||
|
|
||||||
case_body : kWHEN when_args then
|
case_body : kWHEN when_args then
|
||||||
compstmt
|
compstmt
|
||||||
cases
|
cases
|
||||||
|
@ -2033,10 +2051,7 @@ rb_compile_file(f, file, start)
|
||||||
return yycompile(strdup(f), start);
|
return yycompile(strdup(f), start);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 2
|
static inline int
|
||||||
__inline__
|
|
||||||
#endif
|
|
||||||
static int
|
|
||||||
nextc()
|
nextc()
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
@ -3604,8 +3619,10 @@ yylex()
|
||||||
if (state == EXPR_FNAME) {
|
if (state == EXPR_FNAME) {
|
||||||
yylval.id = rb_intern(kw->name);
|
yylval.id = rb_intern(kw->name);
|
||||||
}
|
}
|
||||||
if (kw->id[0] == kDO && COND_P()) {
|
if (kw->id[0] == kDO) {
|
||||||
return kDO2;
|
if (COND_P()) return kDO_COND;
|
||||||
|
if (CMDARG_P()) return kDO_BLOCK;
|
||||||
|
return kDO;
|
||||||
}
|
}
|
||||||
return kw->id[state != EXPR_BEG];
|
return kw->id[state != EXPR_BEG];
|
||||||
}
|
}
|
||||||
|
@ -4361,6 +4378,9 @@ void_expr(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NODE *cond2 _((NODE*));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
void_stmts(node)
|
void_stmts(node)
|
||||||
NODE *node;
|
NODE *node;
|
||||||
|
@ -4376,8 +4396,6 @@ void_stmts(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NODE *cond2();
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
assign_in_cond(node)
|
assign_in_cond(node)
|
||||||
NODE *node;
|
NODE *node;
|
||||||
|
@ -4424,6 +4442,14 @@ assign_in_cond(node)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
warn_unless_e_option(str)
|
||||||
|
const char *str;
|
||||||
|
{
|
||||||
|
if (strcmp(ruby_sourcefile, "-e") != 0)
|
||||||
|
rb_warning(str);
|
||||||
|
}
|
||||||
|
|
||||||
static NODE*
|
static NODE*
|
||||||
cond0(node)
|
cond0(node)
|
||||||
NODE *node;
|
NODE *node;
|
||||||
|
|
2
ruby.c
2
ruby.c
|
@ -728,7 +728,7 @@ load_file(fname, script)
|
||||||
FILE *fp = fopen(fname, "r");
|
FILE *fp = fopen(fname, "r");
|
||||||
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
rb_raise(rb_eLoadError, "No such file to load -- %s", fname);
|
rb_load_fail(fname);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
|
1
ruby.h
1
ruby.h
|
@ -164,6 +164,7 @@ VALUE rb_uint2inum _((unsigned long));
|
||||||
#define T_MATCH 0x23
|
#define T_MATCH 0x23
|
||||||
#define T_SYMBOL 0x24
|
#define T_SYMBOL 0x24
|
||||||
|
|
||||||
|
#define T_BLKTAG 0x3b
|
||||||
#define T_UNDEF 0x3c
|
#define T_UNDEF 0x3c
|
||||||
#define T_VARMAP 0x3d
|
#define T_VARMAP 0x3d
|
||||||
#define T_SCOPE 0x3e
|
#define T_SCOPE 0x3e
|
||||||
|
|
9
string.c
9
string.c
|
@ -367,7 +367,6 @@ str_independent(str)
|
||||||
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
|
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
|
||||||
if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return 1;
|
if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return 1;
|
||||||
if (TYPE(RSTRING(str)->orig) != T_STRING) rb_bug("non string str->orig");
|
if (TYPE(RSTRING(str)->orig) != T_STRING) rb_bug("non string str->orig");
|
||||||
RSTRING(str)->orig = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +383,7 @@ rb_str_modify(str)
|
||||||
}
|
}
|
||||||
ptr[RSTRING(str)->len] = 0;
|
ptr[RSTRING(str)->len] = 0;
|
||||||
RSTRING(str)->ptr = ptr;
|
RSTRING(str)->ptr = ptr;
|
||||||
|
RSTRING(str)->orig = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -1278,6 +1278,9 @@ str_gsub(argc, argv, str, bang)
|
||||||
if (str_independent(str)) {
|
if (str_independent(str)) {
|
||||||
free(RSTRING(str)->ptr);
|
free(RSTRING(str)->ptr);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
RSTRING(str)->orig = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NEWOBJ(dup, struct RString);
|
NEWOBJ(dup, struct RString);
|
||||||
|
@ -1320,9 +1323,9 @@ rb_str_replace_m(str, str2)
|
||||||
if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
|
if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
|
||||||
|
|
||||||
if (RSTRING(str2)->orig && !FL_TEST(str2, STR_NO_ORIG)) {
|
if (RSTRING(str2)->orig && !FL_TEST(str2, STR_NO_ORIG)) {
|
||||||
if (str_independent(str))
|
if (str_independent(str)) {
|
||||||
free(RSTRING(str)->ptr);
|
free(RSTRING(str)->ptr);
|
||||||
|
}
|
||||||
RSTRING(str)->len = RSTRING(str2)->len;
|
RSTRING(str)->len = RSTRING(str2)->len;
|
||||||
RSTRING(str)->ptr = RSTRING(str2)->ptr;
|
RSTRING(str)->ptr = RSTRING(str2)->ptr;
|
||||||
RSTRING(str)->orig = RSTRING(str2)->orig;
|
RSTRING(str)->orig = RSTRING(str2)->orig;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#define RUBY_VERSION "1.6.2"
|
#define RUBY_VERSION "1.6.2"
|
||||||
#define RUBY_RELEASE_DATE "2001-01-31"
|
#define RUBY_RELEASE_DATE "2001-02-02"
|
||||||
#define RUBY_VERSION_CODE 162
|
#define RUBY_VERSION_CODE 162
|
||||||
#define RUBY_RELEASE_CODE 20010131
|
#define RUBY_RELEASE_CODE 20010202
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue