mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* random.c: replace with Mersenne Twister RNG.
* eval.c (jump_tag_but_local_jump): preserve retval in LocalJumpError exceptions. * parse.y (command): no more check for "super outside of method". * eval.c (rb_mod_define_method): should set last_class and last_func in the block->frame. * eval.c (error_handle): should handle TAG_THROW as well. * parse.y (yylex): new decimal notation '0d4567'. * parse.y (yylex): new octal notation '0o777'. * parse.y (string_content): every string_content node should return string only. use NODE_EVSTR to coercing. * eval.c (rb_eval): NODE_EVSTR support. * re.c (rb_reg_quote): avoid unnecessary string allocation. * string.c (get_pat): quote metachracters before compiling a string into a regex. * string.c (rb_str_split_m): special treatment of strings of size 1, but AWK emulation. now uses get_pat(). * string.c (rb_str_match_m): quote metacharacters. * string.c (rb_str_match2): ditto. * ext/socket/socket.c (sock_addrinfo): make all 3 versions of getaddrinfo happy. [ruby-core:00184] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1d132e648d
commit
7194b66fb2
14 changed files with 462 additions and 207 deletions
52
ChangeLog
52
ChangeLog
|
@ -1,3 +1,7 @@
|
|||
Fri Jul 26 14:31:06 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* random.c: replace with Mersenne Twister RNG.
|
||||
|
||||
Fri Jul 26 12:14:48 2002 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* parse.y (yylex): modify to accept a code like "m (a){...}".
|
||||
|
@ -22,6 +26,24 @@ Thu Jul 25 09:05:02 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
|
|||
|
||||
* misc/ruby-mode.el (ruby-move-to-block): skips RD style comments.
|
||||
|
||||
Wed Jul 24 09:47:42 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (jump_tag_but_local_jump): preserve retval in
|
||||
LocalJumpError exceptions.
|
||||
|
||||
* parse.y (command): no more check for "super outside of method".
|
||||
|
||||
* eval.c (rb_mod_define_method): should set last_class and
|
||||
last_func in the block->frame.
|
||||
|
||||
Mon Jul 22 17:23:00 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (error_handle): should handle TAG_THROW as well.
|
||||
|
||||
Fri Jul 19 10:52:32 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* parse.y (yylex): new decimal notation '0d4567'.
|
||||
|
||||
Thu Jul 18 11:52:02 2002 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* lib/net/ftp.rb (set_socket): new method.
|
||||
|
@ -30,6 +52,17 @@ Thu Jul 18 06:51:24 2002 Minero Aoki <aamine@loveruby.net>
|
|||
|
||||
* parse.y (yylex): fix typo.
|
||||
|
||||
Wed Jul 17 18:41:28 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* parse.y (yylex): new octal notation '0o777'.
|
||||
|
||||
Mon Jul 15 18:36:42 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* parse.y (string_content): every string_content node should
|
||||
return string only. use NODE_EVSTR to coercing.
|
||||
|
||||
* eval.c (rb_eval): NODE_EVSTR support.
|
||||
|
||||
Mon Jul 15 10:35:35 2002 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* parse.y (heredoc_identifier): fix typo.
|
||||
|
@ -61,6 +94,20 @@ Fri Jul 12 00:02:50 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
|
|||
* ext/stringio/stringio.c (strio_gets_internal): fixed for record
|
||||
separator longer than 1.
|
||||
|
||||
Thu Jul 11 17:59:20 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* re.c (rb_reg_quote): avoid unnecessary string allocation.
|
||||
|
||||
* string.c (get_pat): quote metachracters before compiling a
|
||||
string into a regex.
|
||||
|
||||
* string.c (rb_str_split_m): special treatment of strings of size
|
||||
1, but AWK emulation. now uses get_pat().
|
||||
|
||||
* string.c (rb_str_match_m): quote metacharacters.
|
||||
|
||||
* string.c (rb_str_match2): ditto.
|
||||
|
||||
Thu Jul 11 12:59:23 2002 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* lib/resolv.rb: untaint strings read from /etc/hosts and
|
||||
|
@ -256,6 +303,11 @@ Sun Jun 23 00:19:10 2002 Tadayoshi Funaba <tadf@dotrb.org>
|
|||
* lib/date.rb, lib/date/format.rb, sample/cal.rb, sample/goodfriday.rb:
|
||||
updated to the new version (based on date2 3.3).
|
||||
|
||||
Sat Jun 22 14:41:33 2002 Guy Decoux <ts@moulon.inra.fr>
|
||||
|
||||
* ext/socket/socket.c (sock_addrinfo): make all 3 versions of
|
||||
getaddrinfo happy. [ruby-core:00184]
|
||||
|
||||
Fri Jun 21 18:49:58 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* parse.y (yylex): __END__ should not be effective within
|
||||
|
|
47
LEGAL
47
LEGAL
|
@ -83,6 +83,53 @@ win32/win32.[ch]:
|
|||
You may distribute under the terms of either the GNU General Public
|
||||
License or the Artistic License, as specified in the perl README file.
|
||||
|
||||
random.c
|
||||
|
||||
This file is under the new-style BSD license.
|
||||
|
||||
A C-program for MT19937, with initialization improved 2002/2/10.
|
||||
Coded by Takuji Nishimura and Makoto Matsumoto.
|
||||
This is a faster version by taking Shawn Cokus's optimization,
|
||||
Matthe Bellew's simplification, Isaku Wada's real version.
|
||||
|
||||
Before using, initialize the state by using init_genrand(seed)
|
||||
or init_by_array(init_key, key_length).
|
||||
|
||||
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of its contributors may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Any feedback is very welcome.
|
||||
http://www.math.keio.ac.jp/matumoto/emt.html
|
||||
email: matumoto@math.keio.ac.jp
|
||||
|
||||
st.[ch]:
|
||||
x68/*:
|
||||
missing/alloca.c:
|
||||
|
|
1
ToDo
1
ToDo
|
@ -78,6 +78,7 @@ Standard Libraries
|
|||
- Hash::new{default}
|
||||
- hash etc. should handle self referenceing array/hash
|
||||
- Array#select(n1,n2...) works like Array#indexes(n1,n2...)
|
||||
- use Mersenne Twister RNG for random.
|
||||
* String#scanf(?)
|
||||
* Object#fmt(?)
|
||||
* Time::strptime
|
||||
|
|
10
bignum.c
10
bignum.c
|
@ -1675,14 +1675,10 @@ rb_big_abs(x)
|
|||
return x;
|
||||
}
|
||||
|
||||
/* !!!warnig!!!!
|
||||
this is not really a random number!!
|
||||
*/
|
||||
|
||||
VALUE
|
||||
rb_big_rand(max, rand)
|
||||
rb_big_rand(max, rand_buf)
|
||||
VALUE max;
|
||||
double rand;
|
||||
double *rand_buf;
|
||||
{
|
||||
VALUE v;
|
||||
long len;
|
||||
|
@ -1690,7 +1686,7 @@ rb_big_rand(max, rand)
|
|||
len = RBIGNUM(max)->len;
|
||||
v = bignew(len,1);
|
||||
while (len--) {
|
||||
BDIGITS(v)[len] = ((BDIGIT)~0) * rand;
|
||||
BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
|
||||
}
|
||||
|
||||
return rb_big_modulo((VALUE)v, max);
|
||||
|
|
32
eval.c
32
eval.c
|
@ -1141,6 +1141,17 @@ error_handle(ex)
|
|||
fprintf(stderr, ": retry outside of rescue clause\n");
|
||||
ex = 1;
|
||||
break;
|
||||
case TAG_THROW:
|
||||
if (prot_tag && prot_tag->frame && prot_tag->frame->file) {
|
||||
fprintf(stderr, "%s:%d: uncaught throw\n",
|
||||
prot_tag->frame->file, prot_tag->frame->line);
|
||||
}
|
||||
else {
|
||||
error_pos();
|
||||
fprintf(stderr, ": unexpected throw\n");
|
||||
}
|
||||
ex = 1;
|
||||
break;
|
||||
case TAG_RAISE:
|
||||
case TAG_FATAL:
|
||||
if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
|
||||
|
@ -1354,17 +1365,21 @@ static void
|
|||
jump_tag_but_local_jump(state)
|
||||
int state;
|
||||
{
|
||||
VALUE val;
|
||||
|
||||
if (prot_tag) val = prot_tag->retval;
|
||||
else val = Qnil;
|
||||
switch (state) {
|
||||
case 0:
|
||||
break;
|
||||
case TAG_RETURN:
|
||||
localjump_error("unexpected return", Qnil);
|
||||
localjump_error("unexpected return", val);
|
||||
break;
|
||||
case TAG_NEXT:
|
||||
localjump_error("unexpected next", Qnil);
|
||||
localjump_error("unexpected next", val);
|
||||
break;
|
||||
case TAG_BREAK:
|
||||
localjump_error("unexpected break", Qnil);
|
||||
localjump_error("unexpected break", val);
|
||||
break;
|
||||
case TAG_REDO:
|
||||
localjump_error("unexpected redo", Qnil);
|
||||
|
@ -1412,7 +1427,6 @@ rb_eval_cmd(cmd, arg, tcheck)
|
|||
if ((state = EXEC_TAG()) == 0) {
|
||||
val = eval(ruby_top_self, cmd, Qnil, 0, 0);
|
||||
}
|
||||
|
||||
if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
|
||||
scope_dup(saved_scope);
|
||||
ruby_scope = saved_scope;
|
||||
|
@ -3059,6 +3073,10 @@ rb_eval(self, n)
|
|||
result = rb_str_new3(node->nd_lit);
|
||||
break;
|
||||
|
||||
case NODE_EVSTR:
|
||||
result = rb_obj_as_string(rb_eval(self, node->nd_body));
|
||||
break;
|
||||
|
||||
case NODE_DSTR:
|
||||
case NODE_DXSTR:
|
||||
case NODE_DREGX:
|
||||
|
@ -7102,6 +7120,12 @@ rb_mod_define_method(argc, argv, mod)
|
|||
node = NEW_DMETHOD(method_unbind(body));
|
||||
}
|
||||
else if (RDATA(body)->dmark == (RUBY_DATA_FUNC)blk_mark) {
|
||||
struct BLOCK *block;
|
||||
|
||||
body = bind_clone(body);
|
||||
Data_Get_Struct(body, struct BLOCK, block);
|
||||
block->frame.last_func = id;
|
||||
block->frame.last_class = mod;
|
||||
node = NEW_BMETHOD(body);
|
||||
}
|
||||
else {
|
||||
|
|
2
gc.c
2
gc.c
|
@ -651,7 +651,6 @@ rb_gc_mark_children(ptr)
|
|||
case NODE_ARRAY:
|
||||
case NODE_DSTR:
|
||||
case NODE_DXSTR:
|
||||
case NODE_EVSTR:
|
||||
case NODE_DREGX:
|
||||
case NODE_DREGX_ONCE:
|
||||
case NODE_FBODY:
|
||||
|
@ -697,6 +696,7 @@ rb_gc_mark_children(ptr)
|
|||
case NODE_MODULE:
|
||||
case NODE_COLON3:
|
||||
case NODE_OPT_N:
|
||||
case NODE_EVSTR:
|
||||
rb_gc_mark((VALUE)obj->as.node.u2.node);
|
||||
break;
|
||||
|
||||
|
|
2
intern.h
2
intern.h
|
@ -89,7 +89,7 @@ VALUE rb_big_and _((VALUE, VALUE));
|
|||
VALUE rb_big_or _((VALUE, VALUE));
|
||||
VALUE rb_big_xor _((VALUE, VALUE));
|
||||
VALUE rb_big_lshift _((VALUE, VALUE));
|
||||
VALUE rb_big_rand _((VALUE, double));
|
||||
VALUE rb_big_rand _((VALUE, double*));
|
||||
/* class.c */
|
||||
VALUE rb_class_boot _((VALUE));
|
||||
VALUE rb_class_new _((VALUE));
|
||||
|
|
2
node.h
2
node.h
|
@ -294,7 +294,7 @@ typedef struct RNode {
|
|||
#define NEW_DSTR(s) rb_node_newnode(NODE_DSTR,s,0,0)
|
||||
#define NEW_XSTR(s) rb_node_newnode(NODE_XSTR,s,0,0)
|
||||
#define NEW_DXSTR(s) rb_node_newnode(NODE_DXSTR,s,0,0)
|
||||
#define NEW_EVSTR(s,l) rb_node_newnode(NODE_EVSTR,rb_str_new(s,l),0,0)
|
||||
#define NEW_EVSTR(n) rb_node_newnode(NODE_EVSTR,0,(n),0)
|
||||
#define NEW_CALL(r,m,a) rb_node_newnode(NODE_CALL,r,m,a)
|
||||
#define NEW_FCALL(m,a) rb_node_newnode(NODE_FCALL,0,m,a)
|
||||
#define NEW_VCALL(m) rb_node_newnode(NODE_VCALL,0,m,0)
|
||||
|
|
|
@ -861,6 +861,7 @@ rb_num2long(val)
|
|||
case T_BIGNUM:
|
||||
return rb_big2long(val);
|
||||
|
||||
#if 0
|
||||
case T_STRING:
|
||||
rb_raise(rb_eTypeError, "no implicit conversion to integer from string");
|
||||
return Qnil; /* not reached */
|
||||
|
@ -869,7 +870,7 @@ rb_num2long(val)
|
|||
case T_FALSE:
|
||||
rb_raise(rb_eTypeError, "no implicit conversion to integer from boolean");
|
||||
return Qnil; /* not reached */
|
||||
|
||||
#endif
|
||||
default:
|
||||
val = rb_to_int(val);
|
||||
return NUM2LONG(val);
|
||||
|
|
78
parse.y
78
parse.y
|
@ -369,22 +369,16 @@ stmts : none
|
|||
|
||||
stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
|
||||
{
|
||||
if (in_def || in_single)
|
||||
yyerror("alias within method");
|
||||
$$ = NEW_ALIAS($2, $4);
|
||||
}
|
||||
| kALIAS tGVAR tGVAR
|
||||
{
|
||||
if (in_def || in_single)
|
||||
yyerror("alias within method");
|
||||
$$ = NEW_VALIAS($2, $3);
|
||||
}
|
||||
| kALIAS tGVAR tBACK_REF
|
||||
{
|
||||
char buf[3];
|
||||
|
||||
if (in_def || in_single)
|
||||
yyerror("alias within method");
|
||||
sprintf(buf, "$%c", $3->nd_nth);
|
||||
$$ = NEW_VALIAS($2, rb_intern(buf));
|
||||
}
|
||||
|
@ -395,8 +389,6 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
|
|||
}
|
||||
| kUNDEF undef_list
|
||||
{
|
||||
if (in_def || in_single)
|
||||
yyerror("undef within method");
|
||||
$$ = $2;
|
||||
}
|
||||
| stmt kIF_MOD expr_value
|
||||
|
@ -632,8 +624,6 @@ command : operation command_args
|
|||
}
|
||||
| kSUPER command_args
|
||||
{
|
||||
if (!compile_for_eval && !in_def && !in_single)
|
||||
yyerror("super called outside of method");
|
||||
$$ = new_super($2);
|
||||
fixpos($$, $2);
|
||||
}
|
||||
|
@ -1490,8 +1480,6 @@ primary : literal
|
|||
}
|
||||
| kDEF fname
|
||||
{
|
||||
if (in_def || in_single)
|
||||
yyerror("nested method definition");
|
||||
$<id>$ = cur_mid;
|
||||
cur_mid = $2;
|
||||
in_def++;
|
||||
|
@ -1658,16 +1646,10 @@ method_call : operation paren_args
|
|||
}
|
||||
| kSUPER paren_args
|
||||
{
|
||||
if (!compile_for_eval && !in_def &&
|
||||
!in_single && !in_defined)
|
||||
yyerror("super called outside of method");
|
||||
$$ = new_super($2);
|
||||
}
|
||||
| kSUPER
|
||||
{
|
||||
if (!compile_for_eval && !in_def &&
|
||||
!in_single && !in_defined)
|
||||
yyerror("super called outside of method");
|
||||
$$ = NEW_ZSUPER();
|
||||
}
|
||||
;
|
||||
|
@ -1936,7 +1918,7 @@ string_content : tSTRING_CONTENT {$$ = NEW_STR($1);}
|
|||
{
|
||||
lex_strnest = $<num>1;
|
||||
lex_strterm = $<node>2;
|
||||
$$ = $3;
|
||||
$$ = NEW_EVSTR($3);
|
||||
}
|
||||
| tSTRING_DBEG term_push
|
||||
{
|
||||
|
@ -1954,6 +1936,7 @@ string_content : tSTRING_CONTENT {$$ = NEW_STR($1);}
|
|||
$$ = $$->nd_next;
|
||||
rb_gc_force_recycle((VALUE)$4);
|
||||
}
|
||||
$$ = NEW_EVSTR($$);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -3570,7 +3553,7 @@ yylex()
|
|||
pushback(c);
|
||||
tokfix();
|
||||
if (toklen() == start) {
|
||||
yyerror("hexadecimal number without hex-digits");
|
||||
yyerror("numeric literal without digits");
|
||||
}
|
||||
else if (nondigit) goto trailing_uc;
|
||||
yylval.val = rb_cstr_to_inum(tok(), 16, Qfalse);
|
||||
|
@ -3600,8 +3583,44 @@ yylex()
|
|||
yylval.val = rb_cstr_to_inum(tok(), 2, Qfalse);
|
||||
return tINTEGER;
|
||||
}
|
||||
if (c >= '0' && c <= '7' || c == '_') {
|
||||
if (c == 'd' || c == 'D') {
|
||||
/* decimal */
|
||||
c = nextc();
|
||||
if (ISDIGIT(c)) {
|
||||
do {
|
||||
if (c == '_') {
|
||||
if (nondigit) break;
|
||||
nondigit = c;
|
||||
continue;
|
||||
}
|
||||
if (!ISDIGIT(c)) break;
|
||||
nondigit = 0;
|
||||
tokadd(c);
|
||||
} while (c = nextc());
|
||||
}
|
||||
pushback(c);
|
||||
tokfix();
|
||||
if (toklen() == start) {
|
||||
yyerror("numeric literal without digits");
|
||||
}
|
||||
else if (nondigit) goto trailing_uc;
|
||||
yylval.val = rb_cstr_to_inum(tok(), 10, Qfalse);
|
||||
return tINTEGER;
|
||||
}
|
||||
if (c == '_') {
|
||||
/* 0_0 */
|
||||
goto octal_number;
|
||||
}
|
||||
if (c == 'o' || c == 'O') {
|
||||
/* prefixed octal */
|
||||
c = nextc();
|
||||
if (c == '_') {
|
||||
yyerror("numeric literal without digits");
|
||||
}
|
||||
}
|
||||
if (c >= '0' && c <= '7') {
|
||||
/* octal */
|
||||
octal_number:
|
||||
do {
|
||||
if (c == '_') {
|
||||
if (nondigit) break;
|
||||
|
@ -4299,24 +4318,26 @@ block_append(head, tail)
|
|||
return head;
|
||||
}
|
||||
|
||||
/* append item to the list */
|
||||
static NODE*
|
||||
list_append(head, tail)
|
||||
NODE *head, *tail;
|
||||
list_append(list, item)
|
||||
NODE *list, *item;
|
||||
{
|
||||
NODE *last;
|
||||
|
||||
if (head == 0) return NEW_LIST(tail);
|
||||
if (list == 0) return NEW_LIST(item);
|
||||
|
||||
last = head;
|
||||
last = list;
|
||||
while (last->nd_next) {
|
||||
last = last->nd_next;
|
||||
}
|
||||
|
||||
last->nd_next = NEW_LIST(tail);
|
||||
head->nd_alen += 1;
|
||||
return head;
|
||||
last->nd_next = NEW_LIST(item);
|
||||
list->nd_alen += 1;
|
||||
return list;
|
||||
}
|
||||
|
||||
/* concat two lists */
|
||||
static NODE*
|
||||
list_concat(head, tail)
|
||||
NODE *head, *tail;
|
||||
|
@ -4439,6 +4460,7 @@ literal_append(head, tail)
|
|||
}
|
||||
}
|
||||
|
||||
/* concat two string literals */
|
||||
static NODE *
|
||||
literal_concat(head, tail)
|
||||
NODE *head, *tail;
|
||||
|
|
235
random.c
235
random.c
|
@ -10,6 +10,131 @@
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
This is based on trimmed version of MT19937. To get the original version,
|
||||
contact <http://www.math.keio.ac.jp/~matumoto/emt.html>.
|
||||
|
||||
The original copyright notice follows.
|
||||
|
||||
A C-program for MT19937, with initialization improved 2002/2/10.
|
||||
Coded by Takuji Nishimura and Makoto Matsumoto.
|
||||
This is a faster version by taking Shawn Cokus's optimization,
|
||||
Matthe Bellew's simplification, Isaku Wada's real version.
|
||||
|
||||
Before using, initialize the state by using init_genrand(seed)
|
||||
or init_by_array(init_key, key_length).
|
||||
|
||||
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of its contributors may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Any feedback is very welcome.
|
||||
http://www.math.keio.ac.jp/matumoto/emt.html
|
||||
email: matumoto@math.keio.ac.jp
|
||||
*/
|
||||
|
||||
/* Period parameters */
|
||||
#define N 624
|
||||
#define M 397
|
||||
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
|
||||
#define UMASK 0x80000000UL /* most significant w-r bits */
|
||||
#define LMASK 0x7fffffffUL /* least significant r bits */
|
||||
#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
|
||||
#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
|
||||
|
||||
static unsigned long state[N]; /* the array for the state vector */
|
||||
static int left = 1;
|
||||
static int initf = 0;
|
||||
static unsigned long *next;
|
||||
|
||||
/* initializes state[N] with a seed */
|
||||
static void
|
||||
init_genrand(s)
|
||||
unsigned long s;
|
||||
{
|
||||
int j;
|
||||
state[0]= s & 0xffffffffUL;
|
||||
for (j=1; j<N; j++) {
|
||||
state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
|
||||
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||
/* In the previous versions, MSBs of the seed affect */
|
||||
/* only MSBs of the array state[]. */
|
||||
/* 2002/01/09 modified by Makoto Matsumoto */
|
||||
state[j] &= 0xffffffffUL; /* for >32 bit machines */
|
||||
}
|
||||
left = 1; initf = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
next_state()
|
||||
{
|
||||
unsigned long *p=state;
|
||||
int j;
|
||||
|
||||
/* if init_genrand() has not been called, */
|
||||
/* a default initial seed is used */
|
||||
if (initf==0) init_genrand(5489UL);
|
||||
|
||||
left = N;
|
||||
next = state;
|
||||
|
||||
for (j=N-M+1; --j; p++)
|
||||
*p = p[M] ^ TWIST(p[0], p[1]);
|
||||
|
||||
for (j=M; --j; p++)
|
||||
*p = p[M-N] ^ TWIST(p[0], p[1]);
|
||||
|
||||
*p = p[M-N] ^ TWIST(p[0], state[0]);
|
||||
}
|
||||
|
||||
/* generates a random number on [0,1)-real-interval */
|
||||
static double
|
||||
genrand_real()
|
||||
{
|
||||
unsigned long y;
|
||||
|
||||
if (--left == 0) next_state();
|
||||
y = *next++;
|
||||
|
||||
/* Tempering */
|
||||
y ^= (y >> 11);
|
||||
y ^= (y << 7) & 0x9d2c5680UL;
|
||||
y ^= (y << 15) & 0xefc60000UL;
|
||||
y ^= (y >> 18);
|
||||
|
||||
return (double)y * (1.0/4294967296.0);
|
||||
/* divided by 2^32 */
|
||||
}
|
||||
|
||||
/* These real versions are due to Isaku Wada, 2002/01/09 added */
|
||||
|
||||
#include "ruby.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
|
@ -27,84 +152,33 @@ struct timeval {
|
|||
#endif
|
||||
#endif /* NT */
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prefer to use drand48, otherwise use random, or rand as a last resort.
|
||||
*/
|
||||
#ifdef HAVE_DRAND48
|
||||
|
||||
#ifndef HAVE_DRAND48_DECL
|
||||
double drand48 _((void));
|
||||
void srand48 _((long));
|
||||
#endif
|
||||
|
||||
#define SRANDOM(s) srand48((long)(s))
|
||||
#define RANDOM_NUMBER drand48()
|
||||
|
||||
#else /* not HAVE_DRAND48 */
|
||||
|
||||
/*
|
||||
* The largest number returned by the random number generator is
|
||||
* RANDOM_MAX. If we're using `rand' it's RAND_MAX, but if we're
|
||||
* using `random' it's 2^31-1.
|
||||
*/
|
||||
#ifndef RANDOM_MAX
|
||||
# ifndef HAVE_RANDOM
|
||||
# define RANDOM_MAX RAND_MAX
|
||||
# else
|
||||
# define RANDOM_MAX 2147483647.0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RANDOM
|
||||
|
||||
#define RANDOM random
|
||||
#define SRANDOM srandom
|
||||
|
||||
#else /* HAVE_RANDOM */
|
||||
|
||||
#define RANDOM rand
|
||||
#define SRANDOM srand
|
||||
|
||||
#endif /* HAVE_RANDOM */
|
||||
|
||||
/* 0 <= RANDOM_NUMBER < 1 */
|
||||
#define RANDOM_NUMBER (((double)RANDOM())/((double)RANDOM_MAX+1))
|
||||
|
||||
#endif /* not HAVE_DRAND48 */
|
||||
|
||||
static int first = 1;
|
||||
#ifdef HAVE_INITSTATE
|
||||
static char state[256];
|
||||
#endif
|
||||
|
||||
static int
|
||||
rand_init(seed)
|
||||
long seed;
|
||||
unsigned long seed;
|
||||
{
|
||||
int old;
|
||||
static unsigned int saved_seed;
|
||||
static unsigned long saved_seed;
|
||||
unsigned long old;
|
||||
|
||||
#ifdef HAVE_INITSTATE
|
||||
if (first == 1) {
|
||||
initstate(1, state, sizeof state);
|
||||
}
|
||||
else {
|
||||
setstate(state);
|
||||
}
|
||||
#endif
|
||||
first = 0;
|
||||
|
||||
SRANDOM(seed);
|
||||
init_genrand(seed);
|
||||
old = saved_seed;
|
||||
saved_seed = seed;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
random_seed()
|
||||
{
|
||||
static int n = 0;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
return tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_f_srand(argc, argv, obj)
|
||||
int argc;
|
||||
|
@ -112,18 +186,14 @@ rb_f_srand(argc, argv, obj)
|
|||
VALUE obj;
|
||||
{
|
||||
VALUE sd;
|
||||
unsigned int seed, old;
|
||||
unsigned long seed, old;
|
||||
|
||||
rb_secure(4);
|
||||
if (rb_scan_args(argc, argv, "01", &sd) == 0) {
|
||||
static int n = 0;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++;
|
||||
seed = random_seed();
|
||||
}
|
||||
else {
|
||||
seed = NUM2UINT(sd);
|
||||
seed = NUM2ULONG(sd);
|
||||
}
|
||||
old = rand_init(seed);
|
||||
|
||||
|
@ -141,10 +211,7 @@ rb_f_rand(argc, argv, obj)
|
|||
|
||||
rb_scan_args(argc, argv, "01", &vmax);
|
||||
if (first) {
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
rand_init(tv.tv_sec ^ tv.tv_usec ^ getpid());
|
||||
rand_init(random_seed());
|
||||
}
|
||||
switch (TYPE(vmax)) {
|
||||
case T_FLOAT:
|
||||
|
@ -155,7 +222,15 @@ rb_f_rand(argc, argv, obj)
|
|||
vmax = rb_dbl2big(RFLOAT(vmax)->value);
|
||||
/* fall through */
|
||||
case T_BIGNUM:
|
||||
return rb_big_rand(vmax, RANDOM_NUMBER);
|
||||
{
|
||||
long len = RBIGNUM(vmax)->len;
|
||||
double *buf = ALLOCA_N(double, len);
|
||||
|
||||
while (len--) {
|
||||
buf[len] = genrand_real();
|
||||
}
|
||||
return rb_big_rand(vmax, buf);
|
||||
}
|
||||
case T_NIL:
|
||||
max = 0;
|
||||
break;
|
||||
|
@ -165,11 +240,11 @@ rb_f_rand(argc, argv, obj)
|
|||
}
|
||||
|
||||
if (max == 0) {
|
||||
return rb_float_new(RANDOM_NUMBER);
|
||||
return rb_float_new(genrand_real());
|
||||
}
|
||||
val = max*RANDOM_NUMBER;
|
||||
if (max < 0) max = -max;
|
||||
val = max*genrand_real();
|
||||
|
||||
if (val < 0) val = -val;
|
||||
return LONG2NUM(val);
|
||||
}
|
||||
|
||||
|
|
60
re.c
60
re.c
|
@ -1170,26 +1170,39 @@ rb_reg_initialize_m(argc, argv, self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_reg_s_quote(argc, argv)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE
|
||||
rb_reg_quote(str)
|
||||
VALUE str;
|
||||
{
|
||||
VALUE str, kcode;
|
||||
int kcode_saved = reg_kcode;
|
||||
char *s, *send, *t;
|
||||
VALUE tmp;
|
||||
int c;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &str, &kcode);
|
||||
if (!NIL_P(kcode)) {
|
||||
rb_set_kcode(StringValuePtr(kcode));
|
||||
curr_kcode = reg_kcode;
|
||||
reg_kcode = kcode_saved;
|
||||
}
|
||||
StringValue(str);
|
||||
s = RSTRING(str)->ptr;
|
||||
send = s + RSTRING(str)->len;
|
||||
for (; s < send; s++) {
|
||||
c = *s;
|
||||
if (ismbchar(c)) {
|
||||
int n = mbclen(c);
|
||||
|
||||
while (n-- && s < send)
|
||||
s++;
|
||||
s--;
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case '\t': case '\f': case '\r': case '\n':
|
||||
case '[': case ']': case '{': case '}':
|
||||
case '(': case ')': case '|': case '-':
|
||||
case '*': case '.': case '\\':
|
||||
case '?': case '+': case '^': case '$':
|
||||
case ' ': case '#':
|
||||
goto meta_found;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
|
||||
meta_found:
|
||||
tmp = rb_str_new(0, RSTRING(str)->len*2);
|
||||
t = RSTRING(tmp)->ptr;
|
||||
|
||||
|
@ -1230,12 +1243,31 @@ rb_reg_s_quote(argc, argv)
|
|||
}
|
||||
*t++ = c;
|
||||
}
|
||||
kcode_reset_option();
|
||||
rb_str_resize(tmp, t - RSTRING(tmp)->ptr);
|
||||
OBJ_INFECT(tmp, str);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_reg_s_quote(argc, argv)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
{
|
||||
VALUE str, kcode;
|
||||
int kcode_saved = reg_kcode;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &str, &kcode);
|
||||
if (!NIL_P(kcode)) {
|
||||
rb_set_kcode(StringValuePtr(kcode));
|
||||
curr_kcode = reg_kcode;
|
||||
reg_kcode = kcode_saved;
|
||||
}
|
||||
StringValue(str);
|
||||
str = rb_reg_quote(str);
|
||||
kcode_reset_option();
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
rb_kcode()
|
||||
{
|
||||
|
|
1
re.h
1
re.h
|
@ -33,6 +33,7 @@ int rb_reg_search _((VALUE, VALUE, int, int));
|
|||
VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *));
|
||||
int rb_reg_adjust_startpos _((VALUE, VALUE, int, int));
|
||||
void rb_match_busy _((VALUE));
|
||||
VALUE rb_reg_quote _((VALUE));
|
||||
|
||||
EXTERN int ruby_ignorecase;
|
||||
|
||||
|
|
144
string.c
144
string.c
|
@ -889,16 +889,44 @@ rb_str_index_m(argc, argv, str)
|
|||
return INT2NUM(pos);
|
||||
}
|
||||
|
||||
static long
|
||||
rb_str_rindex(str, sub, pos)
|
||||
VALUE str, sub;
|
||||
long pos;
|
||||
{
|
||||
long len = RSTRING(sub)->len;
|
||||
char *s, *sbeg, *t;
|
||||
|
||||
/* substring longer than string */
|
||||
if (RSTRING(str)->len < len) return -1;
|
||||
if (RSTRING(str)->len - pos < len) {
|
||||
pos = RSTRING(str)->len - len;
|
||||
}
|
||||
sbeg = RSTRING(str)->ptr;
|
||||
s = RSTRING(str)->ptr + pos;
|
||||
t = RSTRING(sub)->ptr;
|
||||
if (len) {
|
||||
while (sbeg <= s) {
|
||||
if (rb_memcmp(s, t, len) == 0) {
|
||||
return s - RSTRING(str)->ptr;
|
||||
}
|
||||
s--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_str_rindex(argc, argv, str)
|
||||
rb_str_rindex_m(argc, argv, str)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE str;
|
||||
{
|
||||
VALUE sub;
|
||||
VALUE position;
|
||||
int pos, len;
|
||||
char *s, *sbeg, *t;
|
||||
int pos;
|
||||
|
||||
if (rb_scan_args(argc, argv, "11", &sub, &position) == 2) {
|
||||
pos = NUM2INT(position);
|
||||
|
@ -927,26 +955,8 @@ rb_str_rindex(argc, argv, str)
|
|||
break;
|
||||
|
||||
case T_STRING:
|
||||
len = RSTRING(sub)->len;
|
||||
/* substring longer than string */
|
||||
if (RSTRING(str)->len < len) return Qnil;
|
||||
if (RSTRING(str)->len - pos < len) {
|
||||
pos = RSTRING(str)->len - len;
|
||||
}
|
||||
sbeg = RSTRING(str)->ptr;
|
||||
s = RSTRING(str)->ptr + pos;
|
||||
t = RSTRING(sub)->ptr;
|
||||
if (len) {
|
||||
while (sbeg <= s) {
|
||||
if (rb_memcmp(s, t, len) == 0) {
|
||||
return INT2NUM(s - RSTRING(str)->ptr);
|
||||
}
|
||||
s--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return INT2NUM(pos);
|
||||
}
|
||||
pos = rb_str_rindex(str, sub, pos);
|
||||
if (pos >= 0) return INT2NUM(pos);
|
||||
break;
|
||||
|
||||
case T_FIXNUM:
|
||||
|
@ -996,7 +1006,7 @@ rb_str_match2(str)
|
|||
VALUE str;
|
||||
{
|
||||
StringValue(str);
|
||||
return rb_reg_match2(rb_reg_regcomp(str));
|
||||
return rb_reg_match2(rb_reg_regcomp(rb_reg_quote(str)));
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1007,7 +1017,7 @@ rb_str_match_m(str, re)
|
|||
|
||||
if (!NIL_P(str2)) {
|
||||
StringValue(re);
|
||||
re = rb_reg_regcomp(re);
|
||||
re = rb_reg_regcomp(rb_reg_quote(re));
|
||||
}
|
||||
return rb_funcall(re, rb_intern("match"), 1, str);
|
||||
}
|
||||
|
@ -1397,19 +1407,29 @@ static VALUE
|
|||
get_pat(pat)
|
||||
VALUE pat;
|
||||
{
|
||||
VALUE val;
|
||||
|
||||
switch (TYPE(pat)) {
|
||||
case T_REGEXP:
|
||||
break;
|
||||
return pat;
|
||||
|
||||
case T_STRING:
|
||||
pat = rb_reg_regcomp(pat);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* type failed */
|
||||
Check_Type(pat, T_REGEXP);
|
||||
val = rb_check_convert_type(pat, T_STRING, "String", "to_str");
|
||||
if (NIL_P(val)) {
|
||||
Check_Type(pat, T_REGEXP);
|
||||
}
|
||||
pat = val;
|
||||
}
|
||||
return pat;
|
||||
val = rb_reg_quote(pat);
|
||||
#if RUBY_VERSION_CODE < 180
|
||||
if (val != pat) {
|
||||
rb_warn("string pattern instead of regexp; metacharacters no longer effective");
|
||||
}
|
||||
#endif
|
||||
return rb_reg_regcomp(val);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -2449,7 +2469,7 @@ rb_str_split_m(argc, argv, str)
|
|||
{
|
||||
VALUE spat;
|
||||
VALUE limit;
|
||||
int char_sep = -1;
|
||||
int awk_split = Qfalse;
|
||||
long beg, end, i = 0;
|
||||
int lim = 0;
|
||||
VALUE result, tmp;
|
||||
|
@ -2466,67 +2486,51 @@ rb_str_split_m(argc, argv, str)
|
|||
spat = rb_fs;
|
||||
goto fs_set;
|
||||
}
|
||||
char_sep = ' ';
|
||||
awk_split = Qtrue;
|
||||
}
|
||||
else {
|
||||
fs_set:
|
||||
switch (TYPE(spat)) {
|
||||
case T_STRING:
|
||||
if (RSTRING(spat)->len == 1) {
|
||||
char_sep = (unsigned char)RSTRING(spat)->ptr[0];
|
||||
if (TYPE(spat) == T_STRING && RSTRING(spat)->len == 1) {
|
||||
if (RSTRING(spat)->ptr[0] == ' ') {
|
||||
awk_split = Qtrue;
|
||||
}
|
||||
else {
|
||||
spat = rb_reg_regcomp(spat);
|
||||
spat = rb_reg_regcomp(rb_reg_quote(spat));
|
||||
}
|
||||
break;
|
||||
case T_REGEXP:
|
||||
break;
|
||||
default:
|
||||
rb_raise(rb_eArgError, "bad separator");
|
||||
}
|
||||
else {
|
||||
spat = get_pat(spat);
|
||||
}
|
||||
}
|
||||
|
||||
result = rb_ary_new();
|
||||
beg = 0;
|
||||
if (char_sep >= 0) {
|
||||
if (awk_split) {
|
||||
char *ptr = RSTRING(str)->ptr;
|
||||
long len = RSTRING(str)->len;
|
||||
char *eptr = ptr + len;
|
||||
int skip = 1;
|
||||
|
||||
if (char_sep == ' ') { /* AWK emulation */
|
||||
int skip = 1;
|
||||
|
||||
for (end = beg = 0; ptr<eptr; ptr++) {
|
||||
if (skip) {
|
||||
if (ISSPACE(*ptr)) {
|
||||
beg++;
|
||||
}
|
||||
else {
|
||||
end = beg+1;
|
||||
skip = 0;
|
||||
}
|
||||
for (end = beg = 0; ptr<eptr; ptr++) {
|
||||
if (skip) {
|
||||
if (ISSPACE(*ptr)) {
|
||||
beg++;
|
||||
}
|
||||
else {
|
||||
if (ISSPACE(*ptr)) {
|
||||
rb_ary_push(result, rb_str_substr(str, beg, end-beg));
|
||||
skip = 1;
|
||||
beg = end + 1;
|
||||
if (!NIL_P(limit) && lim <= ++i) break;
|
||||
}
|
||||
else {
|
||||
end++;
|
||||
}
|
||||
end = beg+1;
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (end = beg = 0; ptr<eptr; ptr++) {
|
||||
if (*ptr == (char)char_sep) {
|
||||
else {
|
||||
if (ISSPACE(*ptr)) {
|
||||
rb_ary_push(result, rb_str_substr(str, beg, end-beg));
|
||||
skip = 1;
|
||||
beg = end + 1;
|
||||
if (!NIL_P(limit) && lim <= ++i) break;
|
||||
}
|
||||
end++;
|
||||
else {
|
||||
end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3178,7 +3182,7 @@ Init_String()
|
|||
rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
|
||||
rb_define_method(rb_cString, "upto", rb_str_upto_m, 1);
|
||||
rb_define_method(rb_cString, "index", rb_str_index_m, -1);
|
||||
rb_define_method(rb_cString, "rindex", rb_str_rindex, -1);
|
||||
rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1);
|
||||
rb_define_method(rb_cString, "replace", rb_str_replace, 1);
|
||||
|
||||
rb_define_method(rb_cString, "to_i", rb_str_to_i, -1);
|
||||
|
|
Loading…
Reference in a new issue