mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ruby.c (proc_options): unexpected SecurityError happens when -T4.
* regex.c (re_compile_pattern): * \1 .. \9 should be backreferences always. * regex.c (re_match): backreferences corresponding to unclosed/unmatched parentheses should fail always. * string.c (rb_str_cat): use rb_str_buf_cat() if possible. [new] * string.c (rb_str_append): ditto. * string.c (rb_str_buf_cat): remove unnecessary check (type, taint, modify) to gain performance. * string.c (rb_str_buf_append): ditto. * string.c (rb_str_buf_new): buffering string function. [new] * string.c (rb_str_buf_append): ditto. * string.c (rb_str_buf_cat): ditto. * time.c (make_time_t): local time adjustment revised. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1476 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4cd1cd7201
commit
abfaac7a6c
24 changed files with 925 additions and 423 deletions
78
ChangeLog
78
ChangeLog
|
@ -1,3 +1,38 @@
|
|||
Tue May 29 17:24:23 2001 K.Kosako <kosako@sofnec.co.jp>
|
||||
|
||||
* ruby.c (proc_options): unexpected SecurityError happens when -T4.
|
||||
|
||||
Tue May 29 18:46:04 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* regex.c (re_compile_pattern): * \1 .. \9 should be
|
||||
backreferences always.
|
||||
|
||||
* regex.c (re_match): backreferences corresponding to
|
||||
unclosed/unmatched parentheses should fail always.
|
||||
|
||||
Tue May 29 16:35:49 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* string.c (rb_str_cat): use rb_str_buf_cat() if possible. [new]
|
||||
|
||||
* string.c (rb_str_append): ditto.
|
||||
|
||||
* string.c (rb_str_buf_cat): remove unnecessary check (type,
|
||||
taint, modify) to gain performance.
|
||||
|
||||
* string.c (rb_str_buf_append): ditto.
|
||||
|
||||
* string.c (rb_str_buf_finish): removed.
|
||||
|
||||
Tue May 29 02:05:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* string.c (rb_str_buf_new): buffering string function. [new]
|
||||
|
||||
* string.c (rb_str_buf_append): ditto.
|
||||
|
||||
* string.c (rb_str_buf_cat): ditto.
|
||||
|
||||
* string.c (rb_str_buf_finish): ditto.
|
||||
|
||||
Mon May 28 23:20:43 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||
|
||||
* configure.in: remove unnecessary AC_CANONICAL_BUILD
|
||||
|
@ -21,6 +56,10 @@ Mon May 28 22:12:01 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
|||
* ext/extconf.rb.in: make the priority of the make rule of .c
|
||||
higher than .C .
|
||||
|
||||
Mon May 28 13:22:19 2001 Tanaka Akira <akr@m17n.org>
|
||||
|
||||
* time.c (make_time_t): local time adjustment revised.
|
||||
|
||||
Mon May 28 02:20:38 2001 Akinori MUSHA <knu@iDaemons.org>
|
||||
|
||||
* dir.c (glob_helper): teach has_magic() to handle flags and get
|
||||
|
@ -29,10 +68,38 @@ Mon May 28 02:20:38 2001 Akinori MUSHA <knu@iDaemons.org>
|
|||
* dir.c (fnmatch): fix a bug when FNM_PATHNAME and FNM_PERIOD are
|
||||
specified at the same time.
|
||||
|
||||
Sat May 26 09:55:26 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* parse.y: accomplish extended syntax described in [ruby-talk:14525]
|
||||
using tSPC token. [new, experimental]
|
||||
|
||||
Sat May 26 07:05:45 2001 Usaku Nakamura <usa@osb.att.ne.jp>
|
||||
|
||||
* MANIFEST: add win32/dir.h .
|
||||
|
||||
Fri May 25 20:03:51 2001 Pascal Rigaux <pixel@mandrakesoft.com>
|
||||
|
||||
* dln.c (dln_find_1): should exclude directories in executable
|
||||
file lookup.
|
||||
|
||||
Fri May 25 18:00:26 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* class.c (rb_obj_singleton_methods): list methods in extended
|
||||
modules if optional argument is true. [new]
|
||||
|
||||
Fri May 25 14:19:25 2001 K.Kosako <kosako@sofnec.co.jp>
|
||||
|
||||
* string.c (rb_str_replace): add taint status infection
|
||||
(OBJ_INFECT()).
|
||||
|
||||
* string.c (rb_str_crypt): ditto.
|
||||
|
||||
* string.c (rb_str_ljust): ditto.
|
||||
|
||||
* string.c (rb_str_rjust): ditto.
|
||||
|
||||
* string.c (rb_str_center): ditto.
|
||||
|
||||
Fri May 25 05:39:03 2001 Akinori MUSHA <knu@iDaemons.org>
|
||||
|
||||
* ext/sha1/sha1-ruby.c (sha1_hexdigest): fix buffer overflow. The
|
||||
|
@ -54,6 +121,17 @@ Fri May 25 00:53:41 2001 Akinori MUSHA <knu@iDaemons.org>
|
|||
* ext/dbm/extconf.rb: fix support for *BSD and set $CFLAGS
|
||||
properly.
|
||||
|
||||
Thu May 24 16:10:33 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* range.c (range_member): check based on "<=>" comparison. [new]
|
||||
|
||||
* range.c (range_check): add "succ" check if first end is not a
|
||||
numeric.
|
||||
|
||||
* range.c (range_eqq): comparison should based on "<=>".
|
||||
|
||||
* range.c (range_each): ditto.
|
||||
|
||||
Thu May 24 16:08:21 2001 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||
|
||||
* mkconfig.rb: autoconf 2.50 support.
|
||||
|
|
40
array.c
40
array.c
|
@ -739,26 +739,11 @@ inspect_join(ary, arg)
|
|||
return rb_ary_join(arg[0], arg[1]);
|
||||
}
|
||||
|
||||
static long
|
||||
str_cpy(str, idx, str2)
|
||||
VALUE str;
|
||||
long idx;
|
||||
VALUE str2;
|
||||
{
|
||||
long len = idx + RSTRING(str2)->len;
|
||||
|
||||
if (RSTRING(str)->len < len) {
|
||||
rb_str_resize(str, len);
|
||||
}
|
||||
memcpy(RSTRING(str)->ptr+idx, RSTRING(str2)->ptr, RSTRING(str2)->len);
|
||||
return len;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_ary_join(ary, sep)
|
||||
VALUE ary, sep;
|
||||
{
|
||||
long len, i, j;
|
||||
long len, i;
|
||||
int taint = 0;
|
||||
VALUE result, tmp;
|
||||
|
||||
|
@ -778,9 +763,8 @@ rb_ary_join(ary, sep)
|
|||
if (!NIL_P(sep) && TYPE(sep) == T_STRING) {
|
||||
len += RSTRING(sep)->len * RARRAY(ary)->len - 1;
|
||||
}
|
||||
result = rb_str_new(0, len);
|
||||
|
||||
for (i=0, j=0; i<RARRAY(ary)->len; i++) {
|
||||
result = rb_str_buf_new(len);
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
tmp = RARRAY(ary)->ptr[i];
|
||||
switch (TYPE(tmp)) {
|
||||
case T_STRING:
|
||||
|
@ -800,11 +784,11 @@ rb_ary_join(ary, sep)
|
|||
default:
|
||||
tmp = rb_obj_as_string(tmp);
|
||||
}
|
||||
if (i > 0 && !NIL_P(sep)) j = str_cpy(result, j, sep);
|
||||
j = str_cpy(result, j, tmp);
|
||||
if (i > 0 && !NIL_P(sep))
|
||||
rb_str_buf_append(result, sep);
|
||||
rb_str_buf_append(result, tmp);
|
||||
if (OBJ_TAINTED(tmp)) taint = 1;
|
||||
}
|
||||
rb_str_resize(result, j);
|
||||
|
||||
if (taint) OBJ_TAINT(result);
|
||||
return result;
|
||||
|
@ -909,16 +893,14 @@ inspect_ary(ary)
|
|||
long i = 0;
|
||||
VALUE s, str;
|
||||
|
||||
str = rb_str_new2("[");
|
||||
|
||||
str = rb_str_buf_new2("[");
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
s = rb_inspect(RARRAY(ary)->ptr[i]);
|
||||
tainted = OBJ_TAINTED(s);
|
||||
if (i > 0) rb_str_cat2(str, ", ");
|
||||
rb_str_append(str, s);
|
||||
if (OBJ_TAINTED(s)) tainted = 1;
|
||||
if (i > 0) rb_str_buf_cat2(str, ", ");
|
||||
rb_str_buf_append(str, s);
|
||||
}
|
||||
rb_str_cat(str, "]", 1);
|
||||
|
||||
rb_str_buf_cat2(str, "]");
|
||||
if (tainted) OBJ_TAINT(str);
|
||||
return str;
|
||||
}
|
||||
|
|
12
class.c
12
class.c
|
@ -484,19 +484,29 @@ rb_class_private_instance_methods(argc, argv, mod)
|
|||
}
|
||||
|
||||
VALUE
|
||||
rb_obj_singleton_methods(obj)
|
||||
rb_obj_singleton_methods(argc, argv, obj)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE obj;
|
||||
{
|
||||
VALUE all;
|
||||
VALUE ary;
|
||||
VALUE klass;
|
||||
VALUE *p, *q, *pend;
|
||||
|
||||
rb_scan_args(argc, argv, "01", &all);
|
||||
ary = rb_ary_new();
|
||||
klass = CLASS_OF(obj);
|
||||
while (klass && FL_TEST(klass, FL_SINGLETON)) {
|
||||
st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary);
|
||||
klass = RCLASS(klass)->super;
|
||||
}
|
||||
if (RTEST(all)) {
|
||||
while (klass && TYPE(klass) == T_ICLASS) {
|
||||
st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary);
|
||||
klass = RCLASS(klass)->super;
|
||||
}
|
||||
}
|
||||
p = q = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len;
|
||||
while (p < pend) {
|
||||
if (*p == Qnil) {
|
||||
|
|
15
dln.c
15
dln.c
|
@ -50,6 +50,10 @@ void *xrealloc();
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#else
|
||||
|
@ -1582,9 +1586,8 @@ dln_find_1(fname, path, exe_flag)
|
|||
register char *dp;
|
||||
register char *ep;
|
||||
register char *bp;
|
||||
#ifndef __MACOS__
|
||||
struct stat st;
|
||||
#else
|
||||
#ifdef __MACOS__
|
||||
const char* mac_fullpath;
|
||||
#endif
|
||||
|
||||
|
@ -1669,13 +1672,17 @@ dln_find_1(fname, path, exe_flag)
|
|||
if (stat(fbuf, &st) == 0) {
|
||||
if (exe_flag == 0) return fbuf;
|
||||
/* looking for executable */
|
||||
if (eaccess(fbuf, X_OK) == 0) return fbuf;
|
||||
if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
|
||||
return fbuf;
|
||||
}
|
||||
#else
|
||||
if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
|
||||
if (exe_flag == 0) return mac_fullpath;
|
||||
/* looking for executable */
|
||||
if (eaccess(mac_fullpath, X_OK) == 0) return mac_fullpath;
|
||||
if (stat(mac_fullpath, &st) == 0) {
|
||||
if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
|
||||
return mac_fullpath;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
|
||||
|
|
10
error.c
10
error.c
|
@ -359,12 +359,12 @@ exc_inspect(exc)
|
|||
return rb_str_dup(rb_class_path(klass));
|
||||
}
|
||||
|
||||
str = rb_str_new2("#<");
|
||||
str = rb_str_buf_new2("#<");
|
||||
klass = rb_class_path(klass);
|
||||
rb_str_append(str, klass);
|
||||
rb_str_cat(str, ": ", 2);
|
||||
rb_str_append(str, exc);
|
||||
rb_str_cat(str, ">", 1);
|
||||
rb_str_buf_append(str, klass);
|
||||
rb_str_buf_cat(str, ": ", 2);
|
||||
rb_str_buf_append(str, exc);
|
||||
rb_str_buf_cat(str, ">", 1);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
33
eval.c
33
eval.c
|
@ -15,6 +15,7 @@
|
|||
#include "ruby.h"
|
||||
#include "node.h"
|
||||
#include "env.h"
|
||||
#include "util.h"
|
||||
#include "rubysig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -1213,14 +1214,14 @@ compile_error(at)
|
|||
VALUE str;
|
||||
|
||||
ruby_nerrs = 0;
|
||||
str = rb_str_new2("compile error");
|
||||
str = rb_str_buf_new2("compile error");
|
||||
if (at) {
|
||||
rb_str_cat2(str, " in ");
|
||||
rb_str_cat2(str, at);
|
||||
rb_str_buf_cat2(str, " in ");
|
||||
rb_str_buf_cat2(str, at);
|
||||
}
|
||||
rb_str_cat(str, "\n", 1);
|
||||
rb_str_buf_cat(str, "\n", 1);
|
||||
if (!NIL_P(ruby_errinfo)) {
|
||||
rb_str_concat(str, ruby_errinfo);
|
||||
rb_str_append(str, ruby_errinfo);
|
||||
}
|
||||
rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str));
|
||||
}
|
||||
|
@ -2351,9 +2352,7 @@ rb_eval(self, n)
|
|||
case NODE_YIELD:
|
||||
if (node->nd_stts) {
|
||||
result = rb_eval(self, node->nd_stts);
|
||||
if (nd_type(node->nd_stts) == NODE_RESTARGS &&
|
||||
RARRAY(result)->len == 1)
|
||||
{
|
||||
if (nd_type(node->nd_stts) == NODE_RESTARGS && RARRAY(result)->len == 1) {
|
||||
result = RARRAY(result)->ptr[0];
|
||||
}
|
||||
}
|
||||
|
@ -6752,19 +6751,19 @@ method_inspect(method)
|
|||
const char *s;
|
||||
|
||||
Data_Get_Struct(method, struct METHOD, data);
|
||||
str = rb_str_new2("#<");
|
||||
str = rb_str_buf_new2("#<");
|
||||
s = rb_class2name(CLASS_OF(method));
|
||||
rb_str_cat2(str, s);
|
||||
rb_str_cat2(str, ": ");
|
||||
rb_str_buf_cat2(str, s);
|
||||
rb_str_buf_cat2(str, ": ");
|
||||
s = rb_class2name(data->oklass);
|
||||
rb_str_cat2(str, s);
|
||||
rb_str_cat2(str, "(");
|
||||
rb_str_buf_cat2(str, s);
|
||||
rb_str_buf_cat2(str, "(");
|
||||
s = rb_class2name(data->klass);
|
||||
rb_str_cat2(str, s);
|
||||
rb_str_cat2(str, ")#");
|
||||
rb_str_buf_cat2(str, s);
|
||||
rb_str_buf_cat2(str, ")#");
|
||||
s = rb_id2name(data->oid);
|
||||
rb_str_cat2(str, s);
|
||||
rb_str_cat2(str, ">");
|
||||
rb_str_buf_cat2(str, s);
|
||||
rb_str_buf_cat2(str, ">");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
16
file.c
16
file.c
|
@ -281,22 +281,22 @@ rb_stat_inspect(self)
|
|||
{"ctime", rb_stat_ctime},
|
||||
};
|
||||
|
||||
str = rb_str_new2("#<");
|
||||
rb_str_cat2(str, rb_class2name(CLASS_OF(self)));
|
||||
rb_str_cat2(str, " ");
|
||||
str = rb_str_buf_new2("#<");
|
||||
rb_str_buf_cat2(str, rb_class2name(CLASS_OF(self)));
|
||||
rb_str_buf_cat2(str, " ");
|
||||
|
||||
for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
|
||||
VALUE str2;
|
||||
|
||||
if (i > 0) {
|
||||
rb_str_cat2(str, ", ");
|
||||
rb_str_buf_cat2(str, ", ");
|
||||
}
|
||||
rb_str_cat2(str, member[i].name);
|
||||
rb_str_cat2(str, "=");
|
||||
rb_str_buf_cat2(str, member[i].name);
|
||||
rb_str_buf_cat2(str, "=");
|
||||
str2 = rb_inspect((*member[i].func)(self));
|
||||
rb_str_append(str, str2);
|
||||
}
|
||||
rb_str_cat2(str, ">");
|
||||
rb_str_buf_cat2(str, ">");
|
||||
OBJ_INFECT(str, self);
|
||||
|
||||
return str;
|
||||
|
@ -449,7 +449,7 @@ eaccess(path, mode)
|
|||
if (st.st_mode & mode) return 0;
|
||||
|
||||
return -1;
|
||||
#else /* !NT */
|
||||
#else
|
||||
return access(path, mode);
|
||||
#endif
|
||||
}
|
||||
|
|
26
hash.c
26
hash.c
|
@ -634,11 +634,11 @@ inspect_i(key, value, str)
|
|||
rb_str_cat2(str, ", ");
|
||||
}
|
||||
str2 = rb_inspect(key);
|
||||
rb_str_append(str, str2);
|
||||
rb_str_buf_append(str, str2);
|
||||
OBJ_INFECT(str, str2);
|
||||
rb_str_cat2(str, "=>");
|
||||
rb_str_buf_cat2(str, "=>");
|
||||
str2 = rb_inspect(value);
|
||||
rb_str_append(str, str2);
|
||||
rb_str_buf_append(str, str2);
|
||||
OBJ_INFECT(str, str2);
|
||||
|
||||
return ST_CONTINUE;
|
||||
|
@ -650,11 +650,11 @@ inspect_hash(hash)
|
|||
{
|
||||
VALUE str;
|
||||
|
||||
str = rb_str_new2("{");
|
||||
str = rb_str_buf_new2("{");
|
||||
st_foreach(RHASH(hash)->tbl, inspect_i, str);
|
||||
rb_str_cat2(str, "}");
|
||||
|
||||
rb_str_buf_cat2(str, "}");
|
||||
OBJ_INFECT(str, hash);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -1266,7 +1266,7 @@ static VALUE
|
|||
env_inspect()
|
||||
{
|
||||
char **env;
|
||||
VALUE str = rb_str_new2("{");
|
||||
VALUE str = rb_str_buf_new2("{");
|
||||
VALUE i;
|
||||
|
||||
env = environ;
|
||||
|
@ -1274,18 +1274,18 @@ env_inspect()
|
|||
char *s = strchr(*env, '=');
|
||||
|
||||
if (env != environ) {
|
||||
rb_str_cat2(str, ", ");
|
||||
rb_str_buf_cat2(str, ", ");
|
||||
}
|
||||
if (s) {
|
||||
rb_str_cat2(str, "\"");
|
||||
rb_str_cat(str, *env, s-*env);
|
||||
rb_str_cat2(str, "\"=>");
|
||||
rb_str_buf_cat2(str, "\"");
|
||||
rb_str_buf_cat(str, *env, s-*env);
|
||||
rb_str_buf_cat2(str, "\"=>");
|
||||
i = rb_inspect(rb_str_new2(s+1));
|
||||
rb_str_append(str, i);
|
||||
rb_str_buf_append(str, i);
|
||||
}
|
||||
env++;
|
||||
}
|
||||
rb_str_cat2(str, "}");
|
||||
rb_str_buf_cat2(str, "}");
|
||||
OBJ_TAINT(str);
|
||||
|
||||
return str;
|
||||
|
|
4
intern.h
4
intern.h
|
@ -91,7 +91,7 @@ VALUE rb_mod_ancestors _((VALUE));
|
|||
VALUE rb_class_instance_methods _((int, VALUE*, VALUE));
|
||||
VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
|
||||
VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
|
||||
VALUE rb_obj_singleton_methods _((VALUE));
|
||||
VALUE rb_obj_singleton_methods _((int, VALUE*, VALUE));
|
||||
void rb_define_method_id _((VALUE, ID, VALUE (*)(ANYARGS), int));
|
||||
void rb_frozen_class_p _((VALUE));
|
||||
void rb_undef _((VALUE, ID));
|
||||
|
@ -312,6 +312,8 @@ VALUE rb_str_new3 _((VALUE));
|
|||
VALUE rb_str_new4 _((VALUE));
|
||||
VALUE rb_tainted_str_new _((const char*, long));
|
||||
VALUE rb_tainted_str_new2 _((const char*));
|
||||
VALUE rb_str_buf_new _((long));
|
||||
VALUE rb_str_buf_new2 _((const char*));
|
||||
VALUE rb_obj_as_string _((VALUE));
|
||||
VALUE rb_str_dup _((VALUE));
|
||||
VALUE rb_str_plus _((VALUE, VALUE));
|
||||
|
|
2
io.c
2
io.c
|
@ -608,7 +608,7 @@ rb_io_gets_internal(argc, argv, io)
|
|||
VALUE rs;
|
||||
|
||||
if (argc == 0) {
|
||||
rs = rb_default_rs;
|
||||
rs = rb_rs;
|
||||
}
|
||||
else {
|
||||
rb_scan_args(argc, argv, "1", &rs);
|
||||
|
|
|
@ -106,7 +106,7 @@ w_byte(c, arg)
|
|||
struct dump_arg *arg;
|
||||
{
|
||||
if (arg->fp) putc(c, arg->fp);
|
||||
else rb_str_cat(arg->str, &c, 1);
|
||||
else rb_str_buf_cat(arg->str, &c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -540,7 +540,7 @@ marshal_dump(argc, argv)
|
|||
}
|
||||
else {
|
||||
arg.fp = 0;
|
||||
port = rb_str_new(0, 0);
|
||||
port = rb_str_buf_new(0);
|
||||
arg.str = port;
|
||||
}
|
||||
|
||||
|
|
4
object.c
4
object.c
|
@ -809,8 +809,6 @@ rb_obj_methods(obj)
|
|||
return rb_class_instance_methods(1, argv, CLASS_OF(obj));
|
||||
}
|
||||
|
||||
VALUE rb_obj_singleton_methods();
|
||||
|
||||
static VALUE
|
||||
rb_obj_protected_methods(obj)
|
||||
VALUE obj;
|
||||
|
@ -1179,7 +1177,7 @@ Init_Object()
|
|||
rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
|
||||
rb_define_method(rb_mKernel, "methods", rb_obj_methods, 0);
|
||||
rb_define_method(rb_mKernel, "public_methods", rb_obj_methods, 0);
|
||||
rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, 0);
|
||||
rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1);
|
||||
rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, 0);
|
||||
rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, 0);
|
||||
rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0);
|
||||
|
|
110
pack.c
110
pack.c
|
@ -331,7 +331,7 @@ pack_pack(ary, fmt)
|
|||
static char *nul10 = "\0\0\0\0\0\0\0\0\0\0";
|
||||
static char *spc10 = " ";
|
||||
char *p, *pend;
|
||||
VALUE res, from;
|
||||
VALUE res, from, associates = 0;
|
||||
char type;
|
||||
int items, len, idx;
|
||||
char *ptr;
|
||||
|
@ -343,7 +343,7 @@ pack_pack(ary, fmt)
|
|||
StringValue(fmt);
|
||||
p = RSTRING(fmt)->ptr;
|
||||
pend = p + RSTRING(fmt)->len;
|
||||
res = rb_str_new(0, 0);
|
||||
res = rb_str_buf_new(0);
|
||||
|
||||
items = RARRAY(ary)->len;
|
||||
idx = 0;
|
||||
|
@ -405,15 +405,15 @@ pack_pack(ary, fmt)
|
|||
case 'A':
|
||||
case 'Z':
|
||||
if (plen >= len)
|
||||
rb_str_cat(res, ptr, len);
|
||||
rb_str_buf_cat(res, ptr, len);
|
||||
else {
|
||||
rb_str_cat(res, ptr, plen);
|
||||
rb_str_buf_cat(res, ptr, plen);
|
||||
len -= plen;
|
||||
while (len >= 10) {
|
||||
rb_str_cat(res, (type == 'A')?spc10:nul10, 10);
|
||||
rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
|
||||
len -= 10;
|
||||
}
|
||||
rb_str_cat(res, (type == 'A')?spc10:nul10, len);
|
||||
rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -433,7 +433,7 @@ pack_pack(ary, fmt)
|
|||
byte >>= 1;
|
||||
else {
|
||||
char c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
|
@ -441,11 +441,9 @@ pack_pack(ary, fmt)
|
|||
char c;
|
||||
byte >>= 7 - (len & 7);
|
||||
c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
}
|
||||
len = RSTRING(res)->len;
|
||||
rb_str_resize(res, len+j);
|
||||
MEMZERO(RSTRING(res)->ptr+len, char, j);
|
||||
rb_str_buf_cat(res, 0, j);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -464,7 +462,7 @@ pack_pack(ary, fmt)
|
|||
byte <<= 1;
|
||||
else {
|
||||
char c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
|
@ -472,11 +470,9 @@ pack_pack(ary, fmt)
|
|||
char c;
|
||||
byte <<= 7 - (len & 7);
|
||||
c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
}
|
||||
len = RSTRING(res)->len;
|
||||
rb_str_resize(res, len+j);
|
||||
MEMZERO(RSTRING(res)->ptr+len, char, j);
|
||||
rb_str_buf_cat(res, 0, j);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -498,17 +494,15 @@ pack_pack(ary, fmt)
|
|||
byte >>= 4;
|
||||
else {
|
||||
char c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
if (len & 1) {
|
||||
char c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
}
|
||||
len = RSTRING(res)->len;
|
||||
rb_str_resize(res, len+j);
|
||||
MEMZERO(RSTRING(res)->ptr+len, char, j);
|
||||
rb_str_buf_cat(res, 0, j);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -530,17 +524,15 @@ pack_pack(ary, fmt)
|
|||
byte <<= 4;
|
||||
else {
|
||||
char c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
if (len & 1) {
|
||||
char c = byte & 0xff;
|
||||
rb_str_cat(res, &c, 1);
|
||||
rb_str_buf_cat(res, &c, 1);
|
||||
}
|
||||
len = RSTRING(res)->len;
|
||||
rb_str_resize(res, len+j);
|
||||
MEMZERO(RSTRING(res)->ptr+len, char, j);
|
||||
rb_str_buf_cat(res, 0, j);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -556,7 +548,7 @@ pack_pack(ary, fmt)
|
|||
else {
|
||||
c = NUM2INT(from);
|
||||
}
|
||||
rb_str_cat(res, &c, sizeof(char));
|
||||
rb_str_buf_cat(res, &c, sizeof(char));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -570,7 +562,7 @@ pack_pack(ary, fmt)
|
|||
else {
|
||||
s = NUM2INT(from);
|
||||
}
|
||||
rb_str_cat(res, OFF16(&s), NATINT_LEN(short,2));
|
||||
rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -584,7 +576,7 @@ pack_pack(ary, fmt)
|
|||
else {
|
||||
i = NUM2UINT(from);
|
||||
}
|
||||
rb_str_cat(res, (char*)&i, sizeof(int));
|
||||
rb_str_buf_cat(res, (char*)&i, sizeof(int));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -598,7 +590,7 @@ pack_pack(ary, fmt)
|
|||
else {
|
||||
l = NATINT_U32(from);
|
||||
}
|
||||
rb_str_cat(res, OFF32(&l), NATINT_LEN(long,4));
|
||||
rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -612,7 +604,7 @@ pack_pack(ary, fmt)
|
|||
s = NUM2INT(from);
|
||||
}
|
||||
s = htons(s);
|
||||
rb_str_cat(res, OFF16B(&s), NATINT_LEN(short,2));
|
||||
rb_str_buf_cat(res, OFF16B(&s), NATINT_LEN(short,2));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -626,7 +618,7 @@ pack_pack(ary, fmt)
|
|||
l = NATINT_U32(from);
|
||||
}
|
||||
l = htonl(l);
|
||||
rb_str_cat(res, OFF32B(&l), NATINT_LEN(long,4));
|
||||
rb_str_buf_cat(res, OFF32B(&l), NATINT_LEN(long,4));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -640,7 +632,7 @@ pack_pack(ary, fmt)
|
|||
s = NUM2INT(from);
|
||||
}
|
||||
s = htovs(s);
|
||||
rb_str_cat(res, OFF16(&s), NATINT_LEN(short,2));
|
||||
rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -654,7 +646,7 @@ pack_pack(ary, fmt)
|
|||
l = NATINT_U32(from);
|
||||
}
|
||||
l = htovl(l);
|
||||
rb_str_cat(res, OFF32(&l), NATINT_LEN(long,4));
|
||||
rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -674,7 +666,7 @@ pack_pack(ary, fmt)
|
|||
f = (float)NUM2INT(from);
|
||||
break;
|
||||
}
|
||||
rb_str_cat(res, (char*)&f, sizeof(float));
|
||||
rb_str_buf_cat(res, (char*)&f, sizeof(float));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -695,7 +687,7 @@ pack_pack(ary, fmt)
|
|||
break;
|
||||
}
|
||||
f = HTOVF(f,ftmp);
|
||||
rb_str_cat(res, (char*)&f, sizeof(float));
|
||||
rb_str_buf_cat(res, (char*)&f, sizeof(float));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -716,7 +708,7 @@ pack_pack(ary, fmt)
|
|||
break;
|
||||
}
|
||||
d = HTOVD(d,dtmp);
|
||||
rb_str_cat(res, (char*)&d, sizeof(double));
|
||||
rb_str_buf_cat(res, (char*)&d, sizeof(double));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -736,7 +728,7 @@ pack_pack(ary, fmt)
|
|||
d = (double)NUM2INT(from);
|
||||
break;
|
||||
}
|
||||
rb_str_cat(res, (char*)&d, sizeof(double));
|
||||
rb_str_buf_cat(res, (char*)&d, sizeof(double));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -757,7 +749,7 @@ pack_pack(ary, fmt)
|
|||
break;
|
||||
}
|
||||
f = HTONF(f,ftmp);
|
||||
rb_str_cat(res, (char*)&f, sizeof(float));
|
||||
rb_str_buf_cat(res, (char*)&f, sizeof(float));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -778,25 +770,26 @@ pack_pack(ary, fmt)
|
|||
break;
|
||||
}
|
||||
d = HTOND(d,dtmp);
|
||||
rb_str_cat(res, (char*)&d, sizeof(double));
|
||||
rb_str_buf_cat(res, (char*)&d, sizeof(double));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
grow:
|
||||
while (len >= 10) {
|
||||
rb_str_cat(res, nul10, 10);
|
||||
rb_str_buf_cat(res, nul10, 10);
|
||||
len -= 10;
|
||||
}
|
||||
rb_str_cat(res, nul10, len);
|
||||
rb_str_buf_cat(res, nul10, len);
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
shrink:
|
||||
if (RSTRING(res)->len < len)
|
||||
plen = RSTRING(res)->len;
|
||||
if (plen < len)
|
||||
rb_raise(rb_eArgError, "X outside of string");
|
||||
RSTRING(res)->len -= len;
|
||||
RSTRING(res)->ptr[RSTRING(res)->len] = '\0';
|
||||
RSTRING(res)->len = plen - len;
|
||||
RSTRING(res)->ptr[plen - len] = '\0';
|
||||
break;
|
||||
|
||||
case '@':
|
||||
|
@ -822,7 +815,7 @@ pack_pack(ary, fmt)
|
|||
l = NUM2ULONG(from);
|
||||
}
|
||||
le = uv_to_utf8(buf, l);
|
||||
rb_str_cat(res, (char*)buf, le);
|
||||
rb_str_buf_cat(res, (char*)buf, le);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -879,8 +872,11 @@ pack_pack(ary, fmt)
|
|||
StringValue(from);
|
||||
t = RSTRING(from)->ptr;
|
||||
}
|
||||
rb_str_associate(res, from);
|
||||
rb_str_cat(res, (char*)&t, sizeof(char*));
|
||||
if (!associates) {
|
||||
associates = rb_ary_new();
|
||||
}
|
||||
rb_ary_push(associates, from);
|
||||
rb_str_buf_cat(res, (char*)&t, sizeof(char*));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -891,13 +887,12 @@ pack_pack(ary, fmt)
|
|||
char c, *bufs, *bufe;
|
||||
|
||||
from = NEXTFROM;
|
||||
|
||||
if (TYPE(from) == T_BIGNUM) {
|
||||
VALUE big128 = rb_uint2big(128);
|
||||
while (TYPE(from) == T_BIGNUM) {
|
||||
from = rb_big_divmod(from, big128);
|
||||
c = NUM2INT(RARRAY(from)->ptr[1]) | 0x80; /* mod */
|
||||
rb_str_cat(buf, &c, sizeof(char));
|
||||
rb_str_buf_cat(buf, &c, sizeof(char));
|
||||
from = RARRAY(from)->ptr[0]; /* div */
|
||||
}
|
||||
}
|
||||
|
@ -909,7 +904,7 @@ pack_pack(ary, fmt)
|
|||
|
||||
while (ul) {
|
||||
c = ((ul & 0x7f) | 0x80);
|
||||
rb_str_cat(buf, &c, sizeof(char));
|
||||
rb_str_buf_cat(buf, &c, sizeof(char));
|
||||
ul >>= 7;
|
||||
}
|
||||
|
||||
|
@ -922,11 +917,11 @@ pack_pack(ary, fmt)
|
|||
*bufs++ = *bufe;
|
||||
*bufe-- = c;
|
||||
}
|
||||
rb_str_cat(res, RSTRING(buf)->ptr, RSTRING(buf)->len);
|
||||
rb_str_buf_cat(res, RSTRING(buf)->ptr, RSTRING(buf)->len);
|
||||
}
|
||||
else {
|
||||
c = 0;
|
||||
rb_str_cat(res, &c, sizeof(char));
|
||||
rb_str_buf_cat(res, &c, sizeof(char));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -936,6 +931,9 @@ pack_pack(ary, fmt)
|
|||
}
|
||||
}
|
||||
|
||||
if (associates) {
|
||||
rb_str_associate(res, associates);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -984,7 +982,7 @@ encodes(str, s, len, type)
|
|||
buff[i++] = padding;
|
||||
}
|
||||
buff[i++] = '\n';
|
||||
rb_str_cat(str, buff, i);
|
||||
rb_str_buf_cat(str, buff, i);
|
||||
}
|
||||
|
||||
static char hex_table[] = "0123456789ABCDEF";
|
||||
|
@ -1030,7 +1028,7 @@ qpencode(str, from, len)
|
|||
prev = '\n';
|
||||
}
|
||||
if (i > 1024 - 5) {
|
||||
rb_str_cat(str, buff, i);
|
||||
rb_str_buf_cat(str, buff, i);
|
||||
i = 0;
|
||||
}
|
||||
s++;
|
||||
|
@ -1040,7 +1038,7 @@ qpencode(str, from, len)
|
|||
buff[i++] = '\n';
|
||||
}
|
||||
if (i > 0) {
|
||||
rb_str_cat(str, buff, i);
|
||||
rb_str_buf_cat(str, buff, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
314
parse.y
314
parse.y
|
@ -51,6 +51,7 @@ static enum lex_state {
|
|||
EXPR_BEG, /* ignore newline, +/- is a sign. */
|
||||
EXPR_END, /* newline significant, +/- is a operator. */
|
||||
EXPR_ARG, /* newline significant, +/- is a operator. */
|
||||
EXPR_CMDARG, /* newline significant, +/- is a operator. */
|
||||
EXPR_MID, /* newline significant, +/- is a operator. */
|
||||
EXPR_FNAME, /* ignore newline, no reserved words. */
|
||||
EXPR_DOT, /* right after `.' or `::', no reserved words. */
|
||||
|
@ -63,32 +64,40 @@ typedef unsigned LONG_LONG stack_type;
|
|||
typedef unsigned long stack_type;
|
||||
#endif
|
||||
|
||||
static int cond_nest = 0;
|
||||
static stack_type cond_stack = 0;
|
||||
#define COND_PUSH do {\
|
||||
cond_nest++;\
|
||||
cond_stack = (cond_stack<<1)|1;\
|
||||
#define COND_PUSH(n) do {\
|
||||
cond_stack = (cond_stack<<1)|((n)&1);\
|
||||
} while(0)
|
||||
#define COND_POP do {\
|
||||
cond_nest--;\
|
||||
#define COND_POP() do {\
|
||||
cond_stack >>= 1;\
|
||||
} while (0)
|
||||
#define COND_P() (cond_nest > 0 && (cond_stack&1))
|
||||
#define COND_LEXPOP() do {\
|
||||
int last = COND_P();\
|
||||
cond_stack >>= 1;\
|
||||
if (last) cond_stack |= 1;\
|
||||
} while (0)
|
||||
#define COND_P() (cond_stack&1)
|
||||
|
||||
static stack_type cmdarg_stack = 0;
|
||||
#define CMDARG_PUSH do {\
|
||||
cmdarg_stack = (cmdarg_stack<<1)|1;\
|
||||
#define CMDARG_PUSH(n) do {\
|
||||
cmdarg_stack = (cmdarg_stack<<1)|((n)&1);\
|
||||
} while(0)
|
||||
#define CMDARG_POP do {\
|
||||
#define CMDARG_POP() do {\
|
||||
cmdarg_stack >>= 1;\
|
||||
} while (0)
|
||||
#define CMDARG_P() (cmdarg_stack && (cmdarg_stack&1))
|
||||
#define CMDARG_LEXPOP() do {\
|
||||
int last = CMDARG_P();\
|
||||
cmdarg_stack >>= 1;\
|
||||
if (last) cmdarg_stack |= 1;\
|
||||
} while (0)
|
||||
#define CMDARG_P() (cmdarg_stack&1)
|
||||
|
||||
static int class_nest = 0;
|
||||
static int in_single = 0;
|
||||
static int in_def = 0;
|
||||
static int compile_for_eval = 0;
|
||||
static ID cur_mid = 0;
|
||||
static ID last_id = 0;
|
||||
|
||||
static NODE *cond();
|
||||
static NODE *logop();
|
||||
|
@ -104,9 +113,11 @@ static NODE *block_append();
|
|||
static NODE *list_append();
|
||||
static NODE *list_concat();
|
||||
static NODE *arg_concat();
|
||||
static NODE *arg_prepend();
|
||||
static NODE *call_op();
|
||||
static int in_defined = 0;
|
||||
|
||||
static NODE *ret_args();
|
||||
static NODE *arg_blk_pass();
|
||||
static NODE *new_call();
|
||||
static NODE *new_fcall();
|
||||
|
@ -133,6 +144,7 @@ static int dyna_in_block();
|
|||
|
||||
static void top_local_init();
|
||||
static void top_local_setup();
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
|
@ -199,7 +211,7 @@ static void top_local_setup();
|
|||
%type <val> literal numeric
|
||||
%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> args ret_args when_args call_args paren_args opt_paren_args
|
||||
%type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
|
||||
%type <node> command_args aref_args opt_block_arg block_arg var_ref
|
||||
%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
|
||||
|
@ -228,9 +240,11 @@ static void top_local_setup();
|
|||
%token <id> tOP_ASGN /* +=, -= etc. */
|
||||
%token tASSOC /* => */
|
||||
%token tLPAREN /* ( */
|
||||
%token tLPAREN_ARG /* ( */
|
||||
%token tRPAREN /* ) */
|
||||
%token tLBRACK /* [ */
|
||||
%token tLBRACE /* { */
|
||||
%token tLBRACE_ARG /* { */
|
||||
%token tSTAR /* * */
|
||||
%token tAMPER /* & */
|
||||
%token tSYMBEG
|
||||
|
@ -420,19 +434,19 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
|
|||
}
|
||||
| expr
|
||||
|
||||
expr : kRETURN ret_args
|
||||
expr : kRETURN call_args
|
||||
{
|
||||
if (!compile_for_eval && !in_def && !in_single)
|
||||
yyerror("return appeared outside of method");
|
||||
$$ = NEW_RETURN($2);
|
||||
$$ = NEW_RETURN(ret_args($2));
|
||||
}
|
||||
| kBREAK ret_args
|
||||
| kBREAK call_args
|
||||
{
|
||||
$$ = NEW_BREAK($2);
|
||||
$$ = NEW_BREAK(ret_args($2));
|
||||
}
|
||||
| kNEXT ret_args
|
||||
| kNEXT call_args
|
||||
{
|
||||
$$ = NEW_NEXT($2);
|
||||
$$ = NEW_NEXT(ret_args($2));
|
||||
}
|
||||
| command_call
|
||||
| expr kAND expr
|
||||
|
@ -469,7 +483,7 @@ block_command : block_call
|
|||
$$ = new_call($1, $3, $4);
|
||||
}
|
||||
|
||||
command : operation command_args
|
||||
command : operation command_args
|
||||
{
|
||||
$$ = new_fcall($1, $2);
|
||||
fixpos($$, $2);
|
||||
|
@ -493,9 +507,9 @@ command : operation command_args
|
|||
$$ = new_super($2);
|
||||
fixpos($$, $2);
|
||||
}
|
||||
| kYIELD ret_args
|
||||
| kYIELD call_args
|
||||
{
|
||||
$$ = NEW_YIELD($2);
|
||||
$$ = NEW_YIELD(ret_args($2));
|
||||
fixpos($$, $2);
|
||||
}
|
||||
|
||||
|
@ -1001,9 +1015,90 @@ call_args : command
|
|||
}
|
||||
| block_arg
|
||||
|
||||
command_args : {CMDARG_PUSH;} call_args
|
||||
call_args2 : arg ',' args opt_block_arg
|
||||
{
|
||||
CMDARG_POP;
|
||||
$$ = arg_blk_pass(list_append(NEW_LIST($1),$3), $4);
|
||||
}
|
||||
| arg ',' tSTAR arg opt_block_arg
|
||||
{
|
||||
value_expr($1);
|
||||
value_expr($4);
|
||||
$$ = arg_concat(NEW_LIST($1), $4);
|
||||
$$ = arg_blk_pass($$, $5);
|
||||
}
|
||||
| arg ',' args ',' tSTAR arg opt_block_arg
|
||||
{
|
||||
value_expr($1);
|
||||
value_expr($6);
|
||||
$$ = arg_concat(list_append($1,$3), $6);
|
||||
$$ = arg_blk_pass($$, $7);
|
||||
}
|
||||
| assocs opt_block_arg
|
||||
{
|
||||
$$ = NEW_LIST(NEW_HASH($1));
|
||||
$$ = arg_blk_pass($$, $2);
|
||||
}
|
||||
| assocs ',' tSTAR arg opt_block_arg
|
||||
{
|
||||
value_expr($4);
|
||||
$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
|
||||
$$ = arg_blk_pass($$, $5);
|
||||
}
|
||||
| arg ',' assocs opt_block_arg
|
||||
{
|
||||
$$ = list_append(NEW_LIST($1), NEW_HASH($3));
|
||||
$$ = arg_blk_pass($$, $4);
|
||||
}
|
||||
| arg ',' args ',' assocs opt_block_arg
|
||||
{
|
||||
value_expr($1);
|
||||
value_expr($6);
|
||||
$$ = list_append(list_append($1,$3), NEW_HASH($5));
|
||||
$$ = arg_blk_pass($$, $6);
|
||||
}
|
||||
| arg ',' assocs ',' tSTAR arg opt_block_arg
|
||||
{
|
||||
value_expr($1);
|
||||
value_expr($6);
|
||||
$$ = arg_concat(list_append(NEW_LIST($1), NEW_HASH($3)), $6);
|
||||
$$ = arg_blk_pass($$, $7);
|
||||
}
|
||||
| arg ',' args ',' assocs ',' tSTAR arg opt_block_arg
|
||||
{
|
||||
value_expr($1);
|
||||
value_expr($8);
|
||||
$$ = arg_concat(list_append(list_append(NEW_LIST($1), $3), NEW_HASH($5)), $8);
|
||||
$$ = arg_blk_pass($$, $9);
|
||||
}
|
||||
| tSTAR arg opt_block_arg
|
||||
{
|
||||
value_expr($2);
|
||||
$$ = arg_blk_pass(NEW_RESTARGS($2), $3);
|
||||
}
|
||||
| block_arg
|
||||
|
||||
command_args : {
|
||||
$<num>$ = cmdarg_stack;
|
||||
CMDARG_PUSH(1);
|
||||
}
|
||||
open_args
|
||||
{
|
||||
/* CMDARG_POP() */
|
||||
cmdarg_stack = $<num>1;
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
open_args : call_args
|
||||
| tLPAREN_ARG ')'
|
||||
{
|
||||
rb_warning("%s (...) interpreted as method call",
|
||||
rb_id2name(last_id));
|
||||
$$ = 0;
|
||||
}
|
||||
| tLPAREN_ARG call_args2 ')'
|
||||
{
|
||||
rb_warning("%s (...) interpreted as method call",
|
||||
rb_id2name(last_id));
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
|
@ -1053,20 +1148,6 @@ mrhs_basic : args ',' arg
|
|||
$$ = $2;
|
||||
}
|
||||
|
||||
ret_args : call_args
|
||||
{
|
||||
$$ = $1;
|
||||
if ($1) {
|
||||
if (nd_type($1) == NODE_ARRAY &&
|
||||
$1->nd_next == 0) {
|
||||
$$ = $1->nd_head;
|
||||
}
|
||||
else if (nd_type($1) == NODE_BLOCK_PASS) {
|
||||
rb_compile_error("block argument should not be given");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
primary : literal
|
||||
{
|
||||
$$ = NEW_LIT($1);
|
||||
|
@ -1104,6 +1185,11 @@ primary : literal
|
|||
}
|
||||
fixpos($$, $2);
|
||||
}
|
||||
| tLPAREN_ARG expr ')'
|
||||
{
|
||||
rb_warning("%s (...) interpreted as command call", rb_id2name(last_id));
|
||||
$$ = $2;
|
||||
}
|
||||
| tLPAREN compstmt ')'
|
||||
{
|
||||
$$ = $2;
|
||||
|
@ -1140,10 +1226,10 @@ primary : literal
|
|||
yyerror("return appeared outside of method");
|
||||
$$ = NEW_RETURN(0);
|
||||
}
|
||||
| kYIELD '(' ret_args ')'
|
||||
| kYIELD '(' call_args ')'
|
||||
{
|
||||
value_expr($3);
|
||||
$$ = NEW_YIELD($3);
|
||||
$$ = NEW_YIELD(ret_args($3));
|
||||
}
|
||||
| kYIELD '(' ')'
|
||||
{
|
||||
|
@ -1191,7 +1277,7 @@ primary : literal
|
|||
$$ = NEW_UNLESS(cond($2), $4, $5);
|
||||
fixpos($$, $2);
|
||||
}
|
||||
| kWHILE {COND_PUSH;} expr do {COND_POP;}
|
||||
| kWHILE {COND_PUSH(1);} expr do {COND_POP();}
|
||||
compstmt
|
||||
kEND
|
||||
{
|
||||
|
@ -1199,7 +1285,7 @@ primary : literal
|
|||
$$ = NEW_WHILE(cond($3), $6, 1);
|
||||
fixpos($$, $3);
|
||||
}
|
||||
| kUNTIL {COND_PUSH;} expr do {COND_POP;}
|
||||
| kUNTIL {COND_PUSH(1);} expr do {COND_POP();}
|
||||
compstmt
|
||||
kEND
|
||||
{
|
||||
|
@ -1219,7 +1305,7 @@ primary : literal
|
|||
{
|
||||
$$ = $3;
|
||||
}
|
||||
| kFOR block_var kIN {COND_PUSH;} expr do {COND_POP;}
|
||||
| kFOR block_var kIN {COND_PUSH(1);} expr do {COND_POP();}
|
||||
compstmt
|
||||
kEND
|
||||
{
|
||||
|
@ -1407,6 +1493,16 @@ do_block : kDO_BLOCK
|
|||
fixpos($$, $3?$3:$4);
|
||||
dyna_pop($<vars>2);
|
||||
}
|
||||
| tLBRACE_ARG {$<vars>$ = dyna_push();}
|
||||
opt_block_var
|
||||
compstmt
|
||||
'}'
|
||||
{
|
||||
$$ = NEW_ITER($3, 0, $4);
|
||||
fixpos($$, $3?$3:$4);
|
||||
dyna_pop($<vars>2);
|
||||
}
|
||||
|
||||
|
||||
block_call : command do_block
|
||||
{
|
||||
|
@ -1913,6 +2009,7 @@ yyerror(msg)
|
|||
}
|
||||
|
||||
static int heredoc_end;
|
||||
static int command_start = Qtrue;
|
||||
|
||||
int ruby_in_compile = 0;
|
||||
int ruby__end__seen;
|
||||
|
@ -1958,9 +2055,9 @@ yycompile(f, line)
|
|||
ruby_debug_lines = 0;
|
||||
compile_for_eval = 0;
|
||||
ruby_in_compile = 0;
|
||||
cond_nest = 0;
|
||||
cond_stack = 0;
|
||||
cmdarg_stack = 0;
|
||||
command_start = 1;
|
||||
class_nest = 0;
|
||||
in_single = 0;
|
||||
in_def = 0;
|
||||
|
@ -2711,13 +2808,6 @@ here_document(term, indent)
|
|||
|
||||
lex_pbeg = lex_p = RSTRING(line)->ptr;
|
||||
lex_pend = lex_p + RSTRING(line)->len;
|
||||
#if 0
|
||||
if (indent) {
|
||||
while (*lex_p && *lex_p == '\t') {
|
||||
lex_p++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
retry:
|
||||
switch (parse_string(term, '\n', '\n')) {
|
||||
case tSTRING:
|
||||
|
@ -2791,13 +2881,18 @@ arg_ambiguous()
|
|||
double strtod ();
|
||||
#endif
|
||||
|
||||
#define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
|
||||
|
||||
static int
|
||||
yylex()
|
||||
{
|
||||
register int c;
|
||||
int space_seen = 0;
|
||||
int cmd_state;
|
||||
struct kwtable *kw;
|
||||
|
||||
cmd_state = command_start;
|
||||
command_start = Qfalse;
|
||||
retry:
|
||||
switch (c = nextc()) {
|
||||
case '\0': /* NUL */
|
||||
|
@ -2827,6 +2922,7 @@ yylex()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
command_start = Qtrue;
|
||||
lex_state = EXPR_BEG;
|
||||
return '\n';
|
||||
|
||||
|
@ -2846,7 +2942,7 @@ yylex()
|
|||
return tOP_ASGN;
|
||||
}
|
||||
pushback(c);
|
||||
if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
|
||||
if (IS_ARG() && space_seen && !ISSPACE(c)){
|
||||
rb_warning("`*' interpreted as argument prefix");
|
||||
c = tSTAR;
|
||||
}
|
||||
|
@ -2913,7 +3009,7 @@ yylex()
|
|||
c = nextc();
|
||||
if (c == '<' &&
|
||||
lex_state != EXPR_END && lex_state != EXPR_CLASS &&
|
||||
(lex_state != EXPR_ARG || space_seen)) {
|
||||
(!IS_ARG() || space_seen)) {
|
||||
int c2 = nextc();
|
||||
int indent = 0;
|
||||
if (c2 == '-') {
|
||||
|
@ -2980,7 +3076,7 @@ yylex()
|
|||
rb_compile_error("incomplete character syntax");
|
||||
return 0;
|
||||
}
|
||||
if (lex_state == EXPR_ARG && ISSPACE(c)){
|
||||
if (IS_ARG() && ISSPACE(c)){
|
||||
pushback(c);
|
||||
lex_state = EXPR_BEG;
|
||||
return '?';
|
||||
|
@ -3009,8 +3105,8 @@ yylex()
|
|||
return tOP_ASGN;
|
||||
}
|
||||
pushback(c);
|
||||
if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
|
||||
rb_warning("`&' interpreted as argument prefix");
|
||||
if (IS_ARG() && space_seen && !ISSPACE(c)){
|
||||
rb_warning("`&' interpeted as argument prefix");
|
||||
c = tAMPER;
|
||||
}
|
||||
else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
|
||||
|
@ -3054,8 +3150,8 @@ yylex()
|
|||
return tOP_ASGN;
|
||||
}
|
||||
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
|
||||
(lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
|
||||
if (lex_state == EXPR_ARG) arg_ambiguous();
|
||||
(IS_ARG() && space_seen && !ISSPACE(c))) {
|
||||
if (IS_ARG()) arg_ambiguous();
|
||||
lex_state = EXPR_BEG;
|
||||
pushback(c);
|
||||
if (ISDIGIT(c)) {
|
||||
|
@ -3083,8 +3179,8 @@ yylex()
|
|||
return tOP_ASGN;
|
||||
}
|
||||
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
|
||||
(lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
|
||||
if (lex_state == EXPR_ARG) arg_ambiguous();
|
||||
(IS_ARG() && space_seen && !ISSPACE(c))) {
|
||||
if (IS_ARG()) arg_ambiguous();
|
||||
lex_state = EXPR_BEG;
|
||||
pushback(c);
|
||||
if (ISDIGIT(c)) {
|
||||
|
@ -3276,13 +3372,9 @@ yylex()
|
|||
|
||||
case ']':
|
||||
case '}':
|
||||
lex_state = EXPR_END;
|
||||
return c;
|
||||
|
||||
case ')':
|
||||
if (cond_nest > 0) {
|
||||
cond_stack >>= 1;
|
||||
}
|
||||
COND_LEXPOP();
|
||||
CMDARG_LEXPOP();
|
||||
lex_state = EXPR_END;
|
||||
return c;
|
||||
|
||||
|
@ -3290,7 +3382,7 @@ yylex()
|
|||
c = nextc();
|
||||
if (c == ':') {
|
||||
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
|
||||
(lex_state == EXPR_ARG && space_seen)) {
|
||||
(IS_ARG() && space_seen)) {
|
||||
lex_state = EXPR_BEG;
|
||||
return tCOLON3;
|
||||
}
|
||||
|
@ -3315,7 +3407,7 @@ yylex()
|
|||
return tOP_ASGN;
|
||||
}
|
||||
pushback(c);
|
||||
if (lex_state == EXPR_ARG && space_seen) {
|
||||
if (IS_ARG() && space_seen) {
|
||||
if (!ISSPACE(c)) {
|
||||
arg_ambiguous();
|
||||
return parse_regx('/', '/');
|
||||
|
@ -3333,8 +3425,9 @@ yylex()
|
|||
pushback(c);
|
||||
return '^';
|
||||
|
||||
case ',':
|
||||
case ';':
|
||||
command_start = Qtrue;
|
||||
case ',':
|
||||
lex_state = EXPR_BEG;
|
||||
return c;
|
||||
|
||||
|
@ -3348,15 +3441,21 @@ yylex()
|
|||
return '~';
|
||||
|
||||
case '(':
|
||||
if (cond_nest > 0) {
|
||||
cond_stack = (cond_stack<<1)|0;
|
||||
}
|
||||
command_start = Qtrue;
|
||||
if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
|
||||
c = tLPAREN;
|
||||
}
|
||||
else if (lex_state == EXPR_ARG && space_seen) {
|
||||
rb_warning("%s (...) interpreted as method call", tok());
|
||||
else if (space_seen) {
|
||||
if (lex_state == EXPR_CMDARG) {
|
||||
c = tLPAREN_ARG;
|
||||
}
|
||||
else if (lex_state == EXPR_ARG) {
|
||||
rb_warning("%s (...) interpreted as method call", tok());
|
||||
c = tLPAREN_ARG;
|
||||
}
|
||||
}
|
||||
COND_PUSH(0);
|
||||
CMDARG_PUSH(0);
|
||||
lex_state = EXPR_BEG;
|
||||
return c;
|
||||
|
||||
|
@ -3375,15 +3474,23 @@ yylex()
|
|||
else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
|
||||
c = tLBRACK;
|
||||
}
|
||||
else if (lex_state == EXPR_ARG && space_seen) {
|
||||
else if (IS_ARG() && space_seen) {
|
||||
c = tLBRACK;
|
||||
}
|
||||
lex_state = EXPR_BEG;
|
||||
COND_PUSH(0);
|
||||
CMDARG_PUSH(0);
|
||||
return c;
|
||||
|
||||
case '{':
|
||||
if (lex_state != EXPR_END && lex_state != EXPR_ARG)
|
||||
c = tLBRACE;
|
||||
if (!IS_ARG()) {
|
||||
if (lex_state != EXPR_END)
|
||||
c = tLBRACE;
|
||||
if (space_seen && CMDARG_P())
|
||||
c = tLBRACE_ARG;
|
||||
}
|
||||
COND_PUSH(0);
|
||||
CMDARG_PUSH(0);
|
||||
lex_state = EXPR_BEG;
|
||||
return c;
|
||||
|
||||
|
@ -3446,7 +3553,7 @@ yylex()
|
|||
yylval.id = '%';
|
||||
return tOP_ASGN;
|
||||
}
|
||||
if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)) {
|
||||
if (IS_ARG() && space_seen && !ISSPACE(c)) {
|
||||
goto quotation;
|
||||
}
|
||||
lex_state = EXPR_BEG;
|
||||
|
@ -3608,7 +3715,8 @@ yylex()
|
|||
}
|
||||
if (kw->id[0] == kDO) {
|
||||
if (COND_P()) return kDO_COND;
|
||||
if (CMDARG_P()) return kDO_BLOCK;
|
||||
if (CMDARG_P() && state != EXPR_CMDARG && state != EXPR_ARG)
|
||||
return kDO_BLOCK;
|
||||
return kDO;
|
||||
}
|
||||
if (state == EXPR_BEG)
|
||||
|
@ -3626,12 +3734,8 @@ yylex()
|
|||
}
|
||||
else {
|
||||
if (lex_state == EXPR_FNAME) {
|
||||
#if 0
|
||||
if ((c = nextc()) == '=' && !peek('=') && !peek('~') && !peek('>')) {
|
||||
#else
|
||||
if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
|
||||
(!peek('=') || lex_p + 1 < lex_pend && lex_p[1] == '>')) {
|
||||
#endif
|
||||
result = tIDENTIFIER;
|
||||
tokadd(c);
|
||||
}
|
||||
|
@ -3648,15 +3752,19 @@ yylex()
|
|||
}
|
||||
if (lex_state == EXPR_BEG ||
|
||||
lex_state == EXPR_DOT ||
|
||||
lex_state == EXPR_ARG) {
|
||||
lex_state = EXPR_ARG;
|
||||
lex_state == EXPR_ARG ||
|
||||
lex_state == EXPR_CMDARG) {
|
||||
if (cmd_state)
|
||||
lex_state = EXPR_CMDARG;
|
||||
else
|
||||
lex_state = EXPR_ARG;
|
||||
}
|
||||
else {
|
||||
lex_state = EXPR_END;
|
||||
}
|
||||
}
|
||||
tokfix();
|
||||
yylval.id = rb_intern(tok());
|
||||
last_id = yylval.id = rb_intern(tok());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -4548,6 +4656,21 @@ logop(type, left, right)
|
|||
return rb_node_newnode(type, cond1(left, 1), cond1(right, 1), 0);
|
||||
}
|
||||
|
||||
static NODE *
|
||||
ret_args(node)
|
||||
NODE *node;
|
||||
{
|
||||
if (node) {
|
||||
if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) {
|
||||
node = node->nd_head;
|
||||
}
|
||||
else if (nd_type(node) == NODE_BLOCK_PASS) {
|
||||
rb_compile_error("block argument should not be given");
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static NODE *
|
||||
arg_blk_pass(node1, node2)
|
||||
NODE *node1;
|
||||
|
@ -4560,6 +4683,27 @@ arg_blk_pass(node1, node2)
|
|||
return node1;
|
||||
}
|
||||
|
||||
static NODE*
|
||||
arg_prepend(node1, node2)
|
||||
NODE *node1, *node2;
|
||||
{
|
||||
switch (nodetype(node2)) {
|
||||
case NODE_ARRAY:
|
||||
return list_concat(NEW_LIST(node1), node2);
|
||||
|
||||
case NODE_RESTARGS:
|
||||
return arg_concat(node1, node2->nd_head);
|
||||
|
||||
case NODE_BLOCK_PASS:
|
||||
node2->nd_body = arg_prepend(node1, node2->nd_body);
|
||||
return node2;
|
||||
|
||||
default:
|
||||
rb_bug("unknown nodetype(%d) for arg_prepend");
|
||||
}
|
||||
return 0; /* not reached */
|
||||
}
|
||||
|
||||
static NODE*
|
||||
new_call(r,m,a)
|
||||
NODE *r;
|
||||
|
|
95
range.c
95
range.c
|
@ -13,7 +13,7 @@
|
|||
#include "ruby.h"
|
||||
|
||||
VALUE rb_cRange;
|
||||
static ID id_cmp, id_beg, id_end, id_excl;
|
||||
static ID id_cmp, id_succ, id_beg, id_end, id_excl;
|
||||
|
||||
#define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
|
||||
#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v)?Qtrue:Qfalse)
|
||||
|
@ -23,6 +23,9 @@ range_check(args)
|
|||
VALUE *args;
|
||||
{
|
||||
rb_funcall(args[0], id_cmp, 1, args[1]);
|
||||
if (!FIXNUM_P(args[0]) && !rb_obj_is_kind_of(args[0], rb_cNumeric)) {
|
||||
rb_funcall(args[0], id_succ, 0, 0);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
@ -103,6 +106,49 @@ range_eq(range, obj)
|
|||
return Qtrue;
|
||||
}
|
||||
|
||||
static int
|
||||
r_eq(a,b)
|
||||
VALUE a, b;
|
||||
{
|
||||
VALUE r;
|
||||
|
||||
if (a == b) return Qtrue;
|
||||
|
||||
if (rb_funcall(a, id_cmp, 1, b) == INT2FIX(0))
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static int
|
||||
r_lt(a,b)
|
||||
VALUE a, b;
|
||||
{
|
||||
VALUE r = rb_funcall(a, id_cmp, 1, b);
|
||||
|
||||
if (NUM2LONG(r) < 0) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static int
|
||||
r_le(a,b)
|
||||
VALUE a, b;
|
||||
{
|
||||
VALUE r = rb_funcall(a, id_cmp, 1, b);
|
||||
|
||||
if (NUM2LONG(r) <= 0) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static int
|
||||
r_gt(a,b)
|
||||
VALUE a, b;
|
||||
{
|
||||
VALUE r = rb_funcall(a, id_cmp, 1, b);
|
||||
|
||||
if (NUM2LONG(r) > 0) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_eqq(range, obj)
|
||||
VALUE range, obj;
|
||||
|
@ -123,14 +169,12 @@ range_eqq(range, obj)
|
|||
}
|
||||
return Qfalse;
|
||||
}
|
||||
else if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj))) {
|
||||
else if (r_le(beg, obj)) {
|
||||
if (EXCL(range)) {
|
||||
if (RTEST(rb_funcall(end, rb_intern(">"), 1, obj)))
|
||||
return Qtrue;
|
||||
if (r_lt(obj, end)) return Qtrue;
|
||||
}
|
||||
else {
|
||||
if (RTEST(rb_funcall(end, rb_intern(">="), 1, obj)))
|
||||
return Qtrue;
|
||||
if (r_le(obj, end)) return Qtrue;
|
||||
}
|
||||
}
|
||||
return Qfalse;
|
||||
|
@ -169,22 +213,19 @@ range_each(range)
|
|||
}
|
||||
else { /* generic each */
|
||||
VALUE v = b;
|
||||
ID succ = rb_intern("succ");
|
||||
|
||||
if (EXCL(range)) {
|
||||
while (RTEST(rb_funcall(v, '<', 1, e))) {
|
||||
if (rb_equal(v, e)) break;
|
||||
while (r_lt(v, e)) {
|
||||
if (r_eq(v, e)) break;
|
||||
rb_yield(v);
|
||||
v = rb_funcall(v, succ, 0, 0);
|
||||
v = rb_funcall(v, id_succ, 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ID le = rb_intern("<=");
|
||||
|
||||
while (RTEST(rb_funcall(v, le, 1, e))) {
|
||||
while (r_le(v, e)) {
|
||||
rb_yield(v);
|
||||
if (rb_equal(v, e)) break;
|
||||
v = rb_funcall(v, succ, 0, 0);
|
||||
if (r_eq(v, e)) break;
|
||||
v = rb_funcall(v, id_succ, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,7 +365,7 @@ range_length(range)
|
|||
beg = rb_ivar_get(range, id_beg);
|
||||
end = rb_ivar_get(range, id_end);
|
||||
|
||||
if (RTEST(rb_funcall(beg, '>', 1, end))) {
|
||||
if (r_gt(beg, end)) {
|
||||
return INT2FIX(0);
|
||||
}
|
||||
if (FIXNUM_P(beg) && FIXNUM_P(end)) {
|
||||
|
@ -349,6 +390,25 @@ range_length(range)
|
|||
return size;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_member(range, val)
|
||||
VALUE range, val;
|
||||
{
|
||||
VALUE beg, end;
|
||||
|
||||
beg = rb_ivar_get(range, id_beg);
|
||||
end = rb_ivar_get(range, id_end);
|
||||
|
||||
if (r_lt(beg, val)) return Qtrue;
|
||||
if (EXCL(range)) {
|
||||
if (r_lt(val, end)) return Qtrue;
|
||||
}
|
||||
else {
|
||||
if (r_le(val, end)) return Qtrue;
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
void
|
||||
Init_Range()
|
||||
{
|
||||
|
@ -369,8 +429,11 @@ Init_Range()
|
|||
|
||||
rb_define_method(rb_cRange, "length", range_length, 0);
|
||||
rb_define_method(rb_cRange, "size", range_length, 0);
|
||||
rb_define_method(rb_cRange, "member?", range_member, 1);
|
||||
rb_define_method(rb_cRange, "include?", range_member, 1);
|
||||
|
||||
id_cmp = rb_intern("<=>");
|
||||
id_succ = rb_intern("succ");
|
||||
id_beg = rb_intern("begin");
|
||||
id_end = rb_intern("end");
|
||||
id_excl = rb_intern("excl");
|
||||
|
|
74
re.c
74
re.c
|
@ -224,51 +224,51 @@ rb_reg_expr_str(str, s, len)
|
|||
p++;
|
||||
}
|
||||
if (!need_escape) {
|
||||
rb_str_cat(str, s, len);
|
||||
rb_str_buf_cat(str, s, len);
|
||||
}
|
||||
else {
|
||||
p = s;
|
||||
while (p<pend) {
|
||||
if (*p == '/') {
|
||||
char c = '\\';
|
||||
rb_str_cat(str, &c, 1);
|
||||
rb_str_cat(str, p, 1);
|
||||
rb_str_buf_cat(str, &c, 1);
|
||||
rb_str_buf_cat(str, p, 1);
|
||||
}
|
||||
else if (ismbchar(*p)) {
|
||||
rb_str_cat(str, p, mbclen(*p));
|
||||
rb_str_buf_cat(str, p, mbclen(*p));
|
||||
p += mbclen(*p);
|
||||
continue;
|
||||
}
|
||||
else if (ISPRINT(*p)) {
|
||||
rb_str_cat(str, p, 1);
|
||||
rb_str_buf_cat(str, p, 1);
|
||||
}
|
||||
else {
|
||||
char b[8];
|
||||
switch (*p) {
|
||||
case '\r':
|
||||
rb_str_cat(str, "\\r", 2);
|
||||
rb_str_buf_cat(str, "\\r", 2);
|
||||
break;
|
||||
case '\n':
|
||||
rb_str_cat(str, "\\n", 2);
|
||||
rb_str_buf_cat(str, "\\n", 2);
|
||||
break;
|
||||
case '\t':
|
||||
rb_str_cat(str, "\\t", 2);
|
||||
rb_str_buf_cat(str, "\\t", 2);
|
||||
break;
|
||||
case '\f':
|
||||
rb_str_cat(str, "\\f", 2);
|
||||
rb_str_buf_cat(str, "\\f", 2);
|
||||
break;
|
||||
case 007:
|
||||
rb_str_cat(str, "\\a", 2);
|
||||
rb_str_buf_cat(str, "\\a", 2);
|
||||
break;
|
||||
case 013:
|
||||
rb_str_cat(str, "\\v", 2);
|
||||
rb_str_buf_cat(str, "\\v", 2);
|
||||
break;
|
||||
case 033:
|
||||
rb_str_cat(str, "\\e", 2);
|
||||
rb_str_buf_cat(str, "\\e", 2);
|
||||
break;
|
||||
default:
|
||||
sprintf(b, "\\%03o", *p & 0377);
|
||||
rb_str_cat(str, b, 4);
|
||||
rb_str_buf_cat(str, b, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -283,35 +283,35 @@ rb_reg_desc(s, len, re)
|
|||
int len;
|
||||
VALUE re;
|
||||
{
|
||||
VALUE str = rb_str_new2("/");
|
||||
VALUE str = rb_str_buf_new2("/");
|
||||
|
||||
rb_reg_expr_str(str, s, len);
|
||||
rb_str_cat2(str, "/");
|
||||
rb_str_buf_cat2(str, "/");
|
||||
if (re) {
|
||||
rb_reg_check(re);
|
||||
/* /p is obsolete; to be removed */
|
||||
if ((RREGEXP(re)->ptr->options & RE_OPTION_POSIXLINE) == RE_OPTION_POSIXLINE)
|
||||
rb_str_cat2(str, "p");
|
||||
rb_str_buf_cat2(str, "p");
|
||||
else if (RREGEXP(re)->ptr->options & RE_OPTION_MULTILINE)
|
||||
rb_str_cat2(str, "m");
|
||||
rb_str_buf_cat2(str, "m");
|
||||
if (RREGEXP(re)->ptr->options & RE_OPTION_IGNORECASE)
|
||||
rb_str_cat2(str, "i");
|
||||
rb_str_buf_cat2(str, "i");
|
||||
if (RREGEXP(re)->ptr->options & RE_OPTION_EXTENDED)
|
||||
rb_str_cat2(str, "x");
|
||||
rb_str_buf_cat2(str, "x");
|
||||
|
||||
if (FL_TEST(re, KCODE_FIXED)) {
|
||||
switch ((RBASIC(re)->flags & KCODE_MASK)) {
|
||||
case KCODE_NONE:
|
||||
rb_str_cat2(str, "n");
|
||||
rb_str_buf_cat2(str, "n");
|
||||
break;
|
||||
case KCODE_EUC:
|
||||
rb_str_cat2(str, "e");
|
||||
rb_str_buf_cat2(str, "e");
|
||||
break;
|
||||
case KCODE_SJIS:
|
||||
rb_str_cat2(str, "s");
|
||||
rb_str_buf_cat2(str, "s");
|
||||
break;
|
||||
case KCODE_UTF8:
|
||||
rb_str_cat2(str, "u");
|
||||
rb_str_buf_cat2(str, "u");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1171,8 +1171,13 @@ rb_reg_regsub(str, src, regs)
|
|||
}
|
||||
if (c != '\\' || s == e) continue;
|
||||
|
||||
if (!val) val = rb_str_new(p, ss-p);
|
||||
else rb_str_cat(val, p, ss-p);
|
||||
if (!val) {
|
||||
val = rb_str_buf_new(ss-p);
|
||||
rb_str_buf_cat(val, p, ss-p);
|
||||
}
|
||||
else {
|
||||
rb_str_buf_cat(val, p, ss-p);
|
||||
}
|
||||
|
||||
c = *s++;
|
||||
p = s;
|
||||
|
@ -1186,11 +1191,11 @@ rb_reg_regsub(str, src, regs)
|
|||
break;
|
||||
|
||||
case '`':
|
||||
rb_str_cat(val, RSTRING(src)->ptr, BEG(0));
|
||||
rb_str_buf_cat(val, RSTRING(src)->ptr, BEG(0));
|
||||
continue;
|
||||
|
||||
case '\'':
|
||||
rb_str_cat(val, RSTRING(src)->ptr+END(0), RSTRING(src)->len-END(0));
|
||||
rb_str_buf_cat(val, RSTRING(src)->ptr+END(0), RSTRING(src)->len-END(0));
|
||||
continue;
|
||||
|
||||
case '+':
|
||||
|
@ -1200,24 +1205,29 @@ rb_reg_regsub(str, src, regs)
|
|||
break;
|
||||
|
||||
case '\\':
|
||||
rb_str_cat(val, s-1, 1);
|
||||
rb_str_buf_cat(val, s-1, 1);
|
||||
continue;
|
||||
|
||||
default:
|
||||
rb_str_cat(val, s-2, 2);
|
||||
rb_str_buf_cat(val, s-2, 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (no >= 0) {
|
||||
if (no >= regs->num_regs) continue;
|
||||
if (BEG(no) == -1) continue;
|
||||
rb_str_cat(val, RSTRING(src)->ptr+BEG(no), END(no)-BEG(no));
|
||||
rb_str_buf_cat(val, RSTRING(src)->ptr+BEG(no), END(no)-BEG(no));
|
||||
}
|
||||
}
|
||||
|
||||
if (p < e) {
|
||||
if (!val) val = rb_str_new(p, e-p);
|
||||
else rb_str_cat(val, p, e-p);
|
||||
if (!val) {
|
||||
val = rb_str_buf_new(e-p);
|
||||
rb_str_buf_cat(val, p, e-p);
|
||||
}
|
||||
else {
|
||||
rb_str_buf_cat(val, p, e-p);
|
||||
}
|
||||
}
|
||||
if (!val) return str;
|
||||
|
||||
|
|
45
regex.c
45
regex.c
|
@ -370,6 +370,7 @@ enum regexpcode
|
|||
duplicate, /* Match a duplicate of something remembered.
|
||||
Followed by one byte containing the index of the memory
|
||||
register. */
|
||||
fail, /* always fails. */
|
||||
wordchar, /* Matches any word-constituent character. */
|
||||
notwordchar, /* Matches any char that is not a word-constituent. */
|
||||
wordbeg, /* Succeeds if at word beginning. */
|
||||
|
@ -2246,32 +2247,23 @@ re_compile_pattern(pattern, size, bufp)
|
|||
case '1': case '2': case '3':
|
||||
case '4': case '5': case '6':
|
||||
case '7': case '8': case '9':
|
||||
{
|
||||
const char *p_save;
|
||||
PATUNFETCH;
|
||||
p0 = p;
|
||||
|
||||
PATUNFETCH;
|
||||
p_save = p;
|
||||
had_mbchar = 0;
|
||||
c1 = 0;
|
||||
GET_UNSIGNED_NUMBER(c1);
|
||||
if (!ISDIGIT(c)) PATUNFETCH;
|
||||
|
||||
had_mbchar = 0;
|
||||
if (9 < c1 && c1 >= regnum) {
|
||||
/* need to get octal */
|
||||
c = scan_oct(p0, 3, &numlen) & 0xff;
|
||||
p = p0 + numlen;
|
||||
c1 = 0;
|
||||
GET_UNSIGNED_NUMBER(c1);
|
||||
if (!ISDIGIT(c)) PATUNFETCH;
|
||||
|
||||
if (c1 >= regnum) {
|
||||
/* need to get octal */
|
||||
p = p_save;
|
||||
c = scan_oct(p_save, 3, &numlen) & 0xff;
|
||||
p = p_save + numlen;
|
||||
c1 = 0;
|
||||
had_num_literal = 1;
|
||||
goto numeric_char;
|
||||
}
|
||||
had_num_literal = 1;
|
||||
goto numeric_char;
|
||||
}
|
||||
|
||||
/* Can't back reference to a subexpression if inside of it. */
|
||||
for (stackt = stackp - 2; stackt > stackb; stackt -= 5)
|
||||
if (*stackt == c1)
|
||||
goto normal_char;
|
||||
laststart = b;
|
||||
BUFPUSH(duplicate);
|
||||
BUFPUSH(c1);
|
||||
|
@ -3736,11 +3728,16 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
int regno = *p++; /* Get which register to match against */
|
||||
register unsigned char *d2, *dend2;
|
||||
|
||||
if (IS_ACTIVE(reg_info[regno])) break;
|
||||
#if 0
|
||||
/* Check if corresponding group is still open */
|
||||
if (IS_ACTIVE(reg_info[regno])) goto fail;
|
||||
|
||||
/* Where in input to try to start matching. */
|
||||
d2 = regstart[regno];
|
||||
if (REG_UNSET(d2)) break;
|
||||
#else
|
||||
d2 = IS_ACTIVE(reg_info[regno])?old_regstart[regno]:regstart[regno];
|
||||
#endif
|
||||
if (REG_UNSET(d2)) goto fail;
|
||||
|
||||
/* Where to stop matching; if both the place to start and
|
||||
the place to stop matching are in the same string, then
|
||||
|
@ -3748,7 +3745,7 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
the end of the first string. */
|
||||
|
||||
dend2 = regend[regno];
|
||||
if (REG_UNSET(dend2)) break;
|
||||
if (REG_UNSET(dend2)) goto fail;
|
||||
for (;;) {
|
||||
/* At end of register contents => success */
|
||||
if (d2 == dend2) break;
|
||||
|
|
10
ruby.c
10
ruby.c
|
@ -681,6 +681,11 @@ proc_options(argc, argv)
|
|||
ruby_show_copyright();
|
||||
}
|
||||
|
||||
if (rb_safe_level() >= 4) {
|
||||
OBJ_TAINT(rb_argv);
|
||||
OBJ_TAINT(rb_load_path);
|
||||
}
|
||||
|
||||
if (!e_script && argc == 0) { /* no more args */
|
||||
if (verbose) exit(0);
|
||||
script = "-";
|
||||
|
@ -726,6 +731,11 @@ proc_options(argc, argv)
|
|||
|
||||
process_sflag();
|
||||
xflag = 0;
|
||||
|
||||
if (rb_safe_level() >= 4) {
|
||||
FL_UNSET(rb_argv, FL_TAINT);
|
||||
FL_UNSET(rb_load_path, FL_TAINT);
|
||||
}
|
||||
}
|
||||
|
||||
extern int ruby__end__seen;
|
||||
|
|
1
ruby.h
1
ruby.h
|
@ -111,6 +111,7 @@ typedef unsigned long ID;
|
|||
|
||||
#define FIXNUM_FLAG 0x01
|
||||
#define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))
|
||||
#define LONG2FIX(i) INT2FIX(i)
|
||||
#define rb_fix_new(v) INT2FIX(v)
|
||||
VALUE rb_int2inum _((long));
|
||||
#define INT2NUM(v) rb_int2inum(v)
|
||||
|
|
188
string.c
188
string.c
|
@ -28,6 +28,7 @@
|
|||
VALUE rb_cString;
|
||||
|
||||
#define STR_NO_ORIG FL_USER2
|
||||
#define STR_ASSOC FL_USER3
|
||||
|
||||
VALUE rb_fs;
|
||||
|
||||
|
@ -132,6 +133,40 @@ rb_str_new4(orig)
|
|||
}
|
||||
}
|
||||
|
||||
#define STR_BUF_MIN_SIZE 128
|
||||
|
||||
VALUE
|
||||
rb_str_buf_new(capa)
|
||||
long capa;
|
||||
{
|
||||
NEWOBJ(str, struct RString);
|
||||
OBJSETUP(str, rb_cString, T_STRING);
|
||||
|
||||
FL_SET(str, STR_NO_ORIG);
|
||||
if (capa < STR_BUF_MIN_SIZE)
|
||||
capa = STR_BUF_MIN_SIZE;
|
||||
str->ptr = 0;
|
||||
str->len = 0;
|
||||
str->orig = LONG2FIX(capa);
|
||||
str->ptr = ALLOC_N(char, capa+1);
|
||||
str->ptr[0] = '\0';
|
||||
|
||||
return (VALUE)str;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_str_buf_new2(ptr)
|
||||
const char *ptr;
|
||||
{
|
||||
VALUE str;
|
||||
long len = strlen(ptr);
|
||||
|
||||
str = rb_str_buf_new(len + STR_BUF_MIN_SIZE);
|
||||
rb_str_cat(str, ptr, len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_str_to_str(str)
|
||||
VALUE str;
|
||||
|
@ -176,7 +211,7 @@ rb_str_associate(str, add)
|
|||
rb_str_modify(str);
|
||||
}
|
||||
RSTRING(str)->orig = rb_ary_new();
|
||||
FL_SET(str, STR_NO_ORIG);
|
||||
FL_SET(str, STR_NO_ORIG|STR_ASSOC);
|
||||
}
|
||||
rb_ary_push(RSTRING(str)->orig, add);
|
||||
}
|
||||
|
@ -185,7 +220,7 @@ VALUE
|
|||
rb_str_associated(str)
|
||||
VALUE str;
|
||||
{
|
||||
if (!FL_TEST(str, STR_NO_ORIG)) {
|
||||
if (!FL_TEST(str, STR_NO_ORIG|STR_ASSOC)) {
|
||||
return Qfalse;
|
||||
}
|
||||
return RSTRING(str)->orig;
|
||||
|
@ -442,28 +477,70 @@ rb_str_resize(str, len)
|
|||
return str;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_str_buf_cat(str, ptr, len)
|
||||
VALUE str;
|
||||
const char *ptr;
|
||||
long len;
|
||||
{
|
||||
long i, capa, total;
|
||||
|
||||
if (RSTRING(str)->orig == 0) {
|
||||
capa = RSTRING(str)->len;
|
||||
FL_SET(str, STR_NO_ORIG);
|
||||
}
|
||||
else {
|
||||
capa = FIX2LONG(RSTRING(str)->orig);
|
||||
}
|
||||
|
||||
total = RSTRING(str)->len+len;
|
||||
if (capa <= total) {
|
||||
while (total > capa) {
|
||||
capa = (capa + 1) * 2;
|
||||
}
|
||||
REALLOC_N(RSTRING(str)->ptr, char, capa+1);
|
||||
RSTRING(str)->orig = LONG2FIX(capa);
|
||||
}
|
||||
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
|
||||
RSTRING(str)->len = total;
|
||||
RSTRING(str)->ptr[total] = '\0'; /* sentinel */
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_str_buf_cat2(str, ptr)
|
||||
VALUE str;
|
||||
const char *ptr;
|
||||
{
|
||||
return rb_str_buf_cat(str, ptr, strlen(ptr));
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_str_cat(str, ptr, len)
|
||||
VALUE str;
|
||||
const char *ptr;
|
||||
long len;
|
||||
{
|
||||
if (len > 0) {
|
||||
int poffset = -1;
|
||||
long i, capa;
|
||||
|
||||
rb_str_modify(str);
|
||||
if (RSTRING(str)->ptr <= ptr &&
|
||||
ptr < RSTRING(str)->ptr + RSTRING(str)->len) {
|
||||
poffset = ptr - RSTRING(str)->ptr;
|
||||
rb_str_modify(str);
|
||||
if (len > 0) {
|
||||
if (RSTRING(str)->orig == 0 ||
|
||||
(FL_TEST(str, STR_NO_ORIG) && !FL_TEST(str, STR_ASSOC))) {
|
||||
return rb_str_buf_cat(str, ptr, len);
|
||||
}
|
||||
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len + len + 1);
|
||||
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+1);
|
||||
if (ptr) {
|
||||
if (poffset >= 0) ptr = RSTRING(str)->ptr + poffset;
|
||||
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
|
||||
}
|
||||
else {
|
||||
MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, len);
|
||||
}
|
||||
RSTRING(str)->len += len;
|
||||
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -476,14 +553,61 @@ rb_str_cat2(str, ptr)
|
|||
}
|
||||
|
||||
VALUE
|
||||
rb_str_append(str1, str2)
|
||||
VALUE str1, str2;
|
||||
rb_str_buf_append(str, str2)
|
||||
VALUE str, str2;
|
||||
{
|
||||
StringValue(str2);
|
||||
str1 = rb_str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
|
||||
OBJ_INFECT(str1, str2);
|
||||
long i, capa, len;
|
||||
|
||||
return str1;
|
||||
if (RSTRING(str)->orig == 0) {
|
||||
capa = RSTRING(str)->len;
|
||||
FL_SET(str, STR_NO_ORIG);
|
||||
}
|
||||
else {
|
||||
capa = FIX2LONG(RSTRING(str)->orig);
|
||||
}
|
||||
|
||||
len = RSTRING(str)->len+RSTRING(str2)->len;
|
||||
if (capa <= len) {
|
||||
while (len > capa) {
|
||||
capa = (capa + 1) * 2;
|
||||
}
|
||||
REALLOC_N(RSTRING(str)->ptr, char, capa+1);
|
||||
RSTRING(str)->orig = LONG2FIX(capa);
|
||||
}
|
||||
memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
|
||||
RSTRING(str2)->ptr, RSTRING(str2)->len);
|
||||
RSTRING(str)->len += RSTRING(str2)->len;
|
||||
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_str_append(str, str2)
|
||||
VALUE str, str2;
|
||||
{
|
||||
long i, capa, len;
|
||||
|
||||
StringValue(str2);
|
||||
rb_str_modify(str);
|
||||
len = RSTRING(str)->len+RSTRING(str2)->len;
|
||||
if (len > 0) {
|
||||
if (RSTRING(str)->orig == 0 ||
|
||||
(FL_TEST(str, STR_NO_ORIG) && !FL_TEST(str, STR_ASSOC))) {
|
||||
rb_str_buf_append(str, str2);
|
||||
OBJ_INFECT(str, str2);
|
||||
|
||||
return str;
|
||||
}
|
||||
REALLOC_N(RSTRING(str)->ptr, char, len+1);
|
||||
memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
|
||||
RSTRING(str2)->ptr, RSTRING(str2)->len);
|
||||
RSTRING(str)->len += RSTRING(str2)->len;
|
||||
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
|
||||
}
|
||||
OBJ_INFECT(str, str2);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -998,6 +1122,7 @@ rb_str_update(str, beg, len, val)
|
|||
}
|
||||
RSTRING(str)->len += RSTRING(val)->len - len;
|
||||
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
|
||||
OBJ_INFECT(str, val);
|
||||
}
|
||||
|
||||
static VALUE rb_str_sub_bang _((int, VALUE*, VALUE));
|
||||
|
@ -1518,7 +1643,7 @@ rb_str_inspect(str)
|
|||
VALUE str;
|
||||
{
|
||||
char *p, *pend;
|
||||
VALUE result = rb_str_new2("\"");
|
||||
VALUE result = rb_str_buf_new2("\"");
|
||||
char s[5];
|
||||
|
||||
p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
|
||||
|
@ -1526,51 +1651,51 @@ rb_str_inspect(str)
|
|||
char c = *p++;
|
||||
if (ismbchar(c) && p < pend) {
|
||||
int len = mbclen(c);
|
||||
rb_str_cat(result, p - 1, len);
|
||||
rb_str_buf_cat(result, p - 1, len);
|
||||
p += len - 1;
|
||||
}
|
||||
else if (c == '"'|| c == '\\') {
|
||||
s[0] = '\\'; s[1] = c;
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (ISPRINT(c)) {
|
||||
s[0] = c;
|
||||
rb_str_cat(result, s, 1);
|
||||
rb_str_buf_cat(result, s, 1);
|
||||
}
|
||||
else if (c == '\n') {
|
||||
s[0] = '\\'; s[1] = 'n';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (c == '\r') {
|
||||
s[0] = '\\'; s[1] = 'r';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (c == '\t') {
|
||||
s[0] = '\\'; s[1] = 't';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (c == '\f') {
|
||||
s[0] = '\\'; s[1] = 'f';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (c == '\013') {
|
||||
s[0] = '\\'; s[1] = 'v';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (c == '\007') {
|
||||
s[0] = '\\'; s[1] = 'a';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else if (c == 033) {
|
||||
s[0] = '\\'; s[1] = 'e';
|
||||
rb_str_cat(result, s, 2);
|
||||
rb_str_buf_cat(result, s, 2);
|
||||
}
|
||||
else {
|
||||
sprintf(s, "\\%03o", c & 0377);
|
||||
rb_str_cat2(result, s);
|
||||
rb_str_buf_cat2(result, s);
|
||||
}
|
||||
}
|
||||
rb_str_cat2(result, "\"");
|
||||
rb_str_buf_cat2(result, "\"");
|
||||
|
||||
OBJ_INFECT(result, str);
|
||||
return result;
|
||||
|
@ -2661,7 +2786,7 @@ rb_str_crypt(str, salt)
|
|||
StringValue(salt);
|
||||
if (RSTRING(salt)->len < 2)
|
||||
rb_raise(rb_eArgError, "salt too short(need >=2 bytes)");
|
||||
return rb_str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr));
|
||||
return rb_tainted_str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -2738,6 +2863,7 @@ rb_str_ljust(str, w)
|
|||
while (p < pend) {
|
||||
*p++ = ' ';
|
||||
}
|
||||
OBJ_INFECT(res, str);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2757,6 +2883,7 @@ rb_str_rjust(str, w)
|
|||
*p++ = ' ';
|
||||
}
|
||||
memcpy(pend, RSTRING(str)->ptr, RSTRING(str)->len);
|
||||
OBJ_INFECT(res, str);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2782,6 +2909,7 @@ rb_str_center(str, w)
|
|||
while (p < pend) {
|
||||
*p++ = ' ';
|
||||
}
|
||||
OBJ_INFECT(res, str);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
2
struct.c
2
struct.c
|
@ -358,7 +358,7 @@ inspect_struct(s)
|
|||
rb_bug("non-initialized struct");
|
||||
}
|
||||
|
||||
str = rb_str_new2("#<");
|
||||
str = rb_str_buf_new2("#<");
|
||||
rb_str_cat2(str, cname);
|
||||
rb_str_cat2(str, " ");
|
||||
for (i=0; i<RSTRUCT(s)->len; i++) {
|
||||
|
|
256
time.c
256
time.c
|
@ -314,7 +314,10 @@ make_time_t(tptr, utc_p)
|
|||
{
|
||||
time_t guess, guess_lo, guess_hi;
|
||||
struct tm *tm, tm_lo, tm_hi;
|
||||
int d;
|
||||
int d, have_guess;
|
||||
int find_dst;
|
||||
|
||||
find_dst = 1;
|
||||
|
||||
#ifdef NEGATIVE_TIME_T
|
||||
guess_lo = 1 << (8 * sizeof(time_t) - 1);
|
||||
|
@ -322,7 +325,7 @@ make_time_t(tptr, utc_p)
|
|||
guess_lo = 0;
|
||||
#endif
|
||||
guess_hi = ((time_t)-1) < ((time_t)0) ?
|
||||
(1U << (8 * sizeof(time_t) - 1)) - 1 :
|
||||
(1UL << (8 * sizeof(time_t) - 1)) - 1 :
|
||||
~(time_t)0;
|
||||
|
||||
tm = (utc_p ? gmtime : localtime)(&guess_lo);
|
||||
|
@ -339,62 +342,87 @@ make_time_t(tptr, utc_p)
|
|||
if (d == 0) return guess_hi;
|
||||
tm_hi = *tm;
|
||||
|
||||
while (guess_lo + 1 < guess_hi) { /* there is a gap between lo and hi. */
|
||||
unsigned long range;
|
||||
int a, b;
|
||||
/*
|
||||
Try precious guess by a linear interpolation at first.
|
||||
`a' and `b' is a coefficient of guess_lo and guess_hi.
|
||||
`range' is approximation of maximum error by the interpolation.
|
||||
(a + b)**2 should be less than 2**31 to avoid overflow.
|
||||
When these parameter is wrong, binary search is used.
|
||||
*/
|
||||
a = (tm_hi.tm_year - tptr->tm_year);
|
||||
b = (tptr->tm_year - tm_lo.tm_year);
|
||||
range = 366 * 24 * 3600;
|
||||
if (a + b < 46000 / 366) {
|
||||
/* 46000 is selected as `some big number less than sqrt(2**31)'. */
|
||||
/* The distinction between leap/non-leap year is not important here. */
|
||||
static int days[] = {
|
||||
0,
|
||||
0 + 31,
|
||||
0 + 31 + 29,
|
||||
0 + 31 + 29 + 31,
|
||||
0 + 31 + 29 + 31 + 30,
|
||||
0 + 31 + 29 + 31 + 30 + 31,
|
||||
0 + 31 + 29 + 31 + 30 + 31 + 30,
|
||||
0 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
|
||||
0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
|
||||
0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
|
||||
0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
|
||||
0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
|
||||
/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov */
|
||||
};
|
||||
a *= 366;
|
||||
b *= 366;
|
||||
d = days[tptr->tm_mon] + tptr->tm_mday;
|
||||
a += days[tm_hi.tm_mon] + tm_hi.tm_mday - d;
|
||||
b += d - (days[tm_lo.tm_mon] + tm_lo.tm_mday);
|
||||
range = 2 * 24 * 3600;
|
||||
}
|
||||
if (a + b <= 1) {
|
||||
range = 2;
|
||||
a *= 24 * 3600;
|
||||
b *= 24 * 3600;
|
||||
d = tptr->tm_hour * 3600 + tptr->tm_min * 60 + tptr->tm_sec;
|
||||
a += tm_hi.tm_hour * 3600 + tm_hi.tm_min * 60 + tm_hi.tm_sec - d;
|
||||
b += d - (tm_lo.tm_hour * 3600 + tm_lo.tm_min * 60 + tm_lo.tm_sec);
|
||||
}
|
||||
if (a <= 0) a = 1;
|
||||
if (b <= 0) b = 1;
|
||||
d = a + b;
|
||||
guess = guess_lo / d * a + guess_hi / d * b;
|
||||
/* Although `%' may not work with negative value,
|
||||
it doesn't cause serious problem because there is a fail safe. */
|
||||
guess += ((guess_lo % d) * a + (guess_hi % d) * b) / d;
|
||||
have_guess = 0;
|
||||
|
||||
fixguess:
|
||||
if (guess <= guess_lo || guess >= guess_hi) {
|
||||
while (guess_lo + 1 < guess_hi) {
|
||||
/* there is a gap between guess_lo and guess_hi. */
|
||||
unsigned long range = 0;
|
||||
if (!have_guess) {
|
||||
int a, b;
|
||||
/*
|
||||
Try precious guess by a linear interpolation at first.
|
||||
`a' and `b' is a coefficient of guess_lo and guess_hi as:
|
||||
|
||||
guess = (guess_lo * a + guess_hi * b) / (a + b)
|
||||
|
||||
However this causes overflow in most cases, following assignment
|
||||
is used instead:
|
||||
|
||||
guess = guess_lo / d * a + (guess_lo % d) * a / d
|
||||
+ guess_hi / d * b + (guess_hi % d) * b / d
|
||||
where d = a + b
|
||||
|
||||
To avoid overflow in this assignment, `d' is restricted to less than
|
||||
sqrt(2**31). By this restriction and other reasons, the guess is
|
||||
not accurate and some error is expected. `range' approximates
|
||||
the maximum error.
|
||||
|
||||
When these parameters are not suitable, i.e. guess is not within
|
||||
guess_lo and guess_hi, simple guess by binary search is used.
|
||||
*/
|
||||
range = 366 * 24 * 60 * 60;
|
||||
a = (tm_hi.tm_year - tptr->tm_year);
|
||||
b = (tptr->tm_year - tm_lo.tm_year);
|
||||
/* 46000 is selected as `some big number less than sqrt(2**31)'. */
|
||||
if (a + b <= 46000 / 12) {
|
||||
range = 31 * 24 * 60 * 60;
|
||||
a *= 12;
|
||||
b *= 12;
|
||||
a += tm_hi.tm_mon - tptr->tm_mon;
|
||||
b += tptr->tm_mon - tm_lo.tm_mon;
|
||||
if (a + b <= 46000 / 31) {
|
||||
range = 24 * 60 * 60;
|
||||
a *= 31;
|
||||
b *= 31;
|
||||
a += tm_hi.tm_mday - tptr->tm_mday;
|
||||
b += tptr->tm_mday - tm_lo.tm_mday;
|
||||
if (a + b <= 46000 / 24) {
|
||||
range = 60 * 60;
|
||||
a *= 24;
|
||||
b *= 24;
|
||||
a += tm_hi.tm_hour - tptr->tm_hour;
|
||||
b += tptr->tm_hour - tm_lo.tm_hour;
|
||||
if (a + b <= 46000 / 60) {
|
||||
range = 60;
|
||||
a *= 60;
|
||||
b *= 60;
|
||||
a += tm_hi.tm_min - tptr->tm_min;
|
||||
b += tptr->tm_min - tm_lo.tm_min;
|
||||
if (a + b <= 46000 / 60) {
|
||||
range = 1;
|
||||
a *= 60;
|
||||
b *= 60;
|
||||
a += tm_hi.tm_sec - tptr->tm_sec;
|
||||
b += tptr->tm_sec - tm_lo.tm_sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a <= 0) a = 1;
|
||||
if (b <= 0) b = 1;
|
||||
d = a + b;
|
||||
/*
|
||||
Although `/' and `%' may produce unexpected result with negative
|
||||
argument, it doesn't cause serious problem because there is a
|
||||
fail safe.
|
||||
*/
|
||||
guess = guess_lo / d * a + (guess_lo % d) * a / d
|
||||
+ guess_hi / d * b + (guess_hi % d) * b / d;
|
||||
have_guess = 1;
|
||||
}
|
||||
|
||||
if (guess <= guess_lo || guess_hi <= guess) {
|
||||
/* Precious guess is invalid. try binary search. */
|
||||
guess = guess_lo / 2 + guess_hi / 2;
|
||||
if (guess <= guess_lo)
|
||||
|
@ -406,53 +434,99 @@ make_time_t(tptr, utc_p)
|
|||
|
||||
tm = (utc_p ? gmtime : localtime)(&guess);
|
||||
if (!tm) goto error;
|
||||
have_guess = 0;
|
||||
|
||||
d = tmcmp(tptr, tm);
|
||||
if (d == 0) {
|
||||
if (!utc_p && !tm->tm_isdst) {
|
||||
/* When leaving DST, there may be two time corresponding to given
|
||||
argument. make_time_t returns DST in such cases. */
|
||||
/* xxx this assumes a difference in time as 3600 seconds. */
|
||||
time_t guess2 = guess - 3600;
|
||||
tm = localtime(&guess2);
|
||||
if (!tm) return guess;
|
||||
if (tmcmp(tptr, tm) == 0)
|
||||
return guess2;
|
||||
}
|
||||
return guess;
|
||||
}
|
||||
else if (d < 0) {
|
||||
if (d < 0) {
|
||||
guess_hi = guess;
|
||||
tm_hi = *tm;
|
||||
if (range && range < (unsigned long)(guess_hi - guess_lo)) {
|
||||
if (range) {
|
||||
guess = guess - range;
|
||||
range = 0;
|
||||
goto fixguess;
|
||||
if (guess_lo < guess && guess < guess_hi)
|
||||
have_guess = 1;
|
||||
}
|
||||
}
|
||||
else if (d > 0) {
|
||||
guess_lo = guess;
|
||||
tm_lo = *tm;
|
||||
if (range) {
|
||||
guess = guess + range;
|
||||
range = 0;
|
||||
if (guess_lo < guess && guess < guess_hi)
|
||||
have_guess = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
guess_lo = guess;
|
||||
tm_lo = *tm;
|
||||
if (range && range < (unsigned long)(guess_hi - guess_lo)) {
|
||||
guess = guess + range;
|
||||
range = 0;
|
||||
goto fixguess;
|
||||
if (!utc_p) {
|
||||
/* If localtime is nonmonotonic, another result may exist. */
|
||||
time_t guess2;
|
||||
if (find_dst) {
|
||||
guess2 = guess - 2 * 60 * 60;
|
||||
tm = localtime(&guess2);
|
||||
if (tm) {
|
||||
if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
|
||||
tptr->tm_min != tm->tm_min ||
|
||||
tptr->tm_sec != tm->tm_sec) {
|
||||
guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
|
||||
(tm->tm_min - tptr->tm_min) * 60 +
|
||||
(tm->tm_sec - tptr->tm_sec);
|
||||
if (tptr->tm_mday != tm->tm_mday)
|
||||
guess2 += 24 * 60 * 60;
|
||||
if (guess != guess2) {
|
||||
tm = localtime(&guess2);
|
||||
if (tmcmp(tptr, tm) == 0) {
|
||||
if (guess < guess2)
|
||||
return guess;
|
||||
else
|
||||
return guess2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
guess2 = guess + 2 * 60 * 60;
|
||||
tm = localtime(&guess2);
|
||||
if (tm) {
|
||||
if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
|
||||
tptr->tm_min != tm->tm_min ||
|
||||
tptr->tm_sec != tm->tm_sec) {
|
||||
guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
|
||||
(tm->tm_min - tptr->tm_min) * 60 +
|
||||
(tm->tm_sec - tptr->tm_sec);
|
||||
if (tptr->tm_mday != tm->tm_mday)
|
||||
guess2 -= 24 * 60 * 60;
|
||||
if (guess != guess2) {
|
||||
tm = localtime(&guess2);
|
||||
if (tmcmp(tptr, tm) == 0) {
|
||||
if (guess < guess2)
|
||||
return guess2;
|
||||
else
|
||||
return guess;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return guess;
|
||||
}
|
||||
}
|
||||
/* given time is not found. */
|
||||
if (guess_lo + 1 == guess_hi) {
|
||||
/* given argument is invalid: 04/29 at non-leap year for example. */
|
||||
return guess_hi;
|
||||
/* Given argument has no corresponding time_t. Let's outerpolation. */
|
||||
if (tm_lo.tm_year == tptr->tm_year && tm_lo.tm_mon == tptr->tm_mon) {
|
||||
return guess_lo +
|
||||
(tptr->tm_mday - tm_lo.tm_mday) * 24 * 60 * 60 +
|
||||
(tptr->tm_hour - tm_lo.tm_hour) * 60 * 60 +
|
||||
(tptr->tm_min - tm_lo.tm_min) * 60 +
|
||||
(tptr->tm_sec - tm_lo.tm_sec);
|
||||
}
|
||||
else {
|
||||
/* given argument is in a gap. When it enters DST, for example. */
|
||||
d = tptr->tm_sec - tm_lo.tm_sec;
|
||||
d += (tptr->tm_min - tm_lo.tm_min) * 60;
|
||||
d += (tptr->tm_hour - tm_lo.tm_hour) * 3600;
|
||||
if (d < 0)
|
||||
d += 24 * 3600;
|
||||
return guess_hi + d - 1;
|
||||
else if (tm_hi.tm_year == tptr->tm_year && tm_hi.tm_mon == tptr->tm_mon) {
|
||||
return guess_hi +
|
||||
(tptr->tm_mday - tm_hi.tm_mday) * 24 * 60 * 60 +
|
||||
(tptr->tm_hour - tm_hi.tm_hour) * 60 * 60 +
|
||||
(tptr->tm_min - tm_hi.tm_min) * 60 +
|
||||
(tptr->tm_sec - tm_hi.tm_sec);
|
||||
}
|
||||
|
||||
out_of_range:
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "env.h"
|
||||
#include "node.h"
|
||||
#include "st.h"
|
||||
#include "util.h"
|
||||
|
||||
static st_table *rb_global_tbl;
|
||||
st_table *rb_class_tbl;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define RUBY_VERSION "1.7.0"
|
||||
#define RUBY_RELEASE_DATE "2001-05-28"
|
||||
#define RUBY_VERSION_CODE 170
|
||||
#define RUBY_RELEASE_CODE 20010528
|
||||
#define RUBY_VERSION "1.7.1"
|
||||
#define RUBY_RELEASE_DATE "2001-05-30"
|
||||
#define RUBY_VERSION_CODE 171
|
||||
#define RUBY_RELEASE_CODE 20010530
|
||||
|
|
Loading…
Reference in a new issue