1
0
Fork 0
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:
matz 2002-07-26 06:12:39 +00:00
parent 1d132e648d
commit 7194b66fb2
14 changed files with 462 additions and 207 deletions

View file

@ -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
View file

@ -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
View file

@ -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

View file

@ -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
View file

@ -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
View file

@ -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;

View file

@ -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
View file

@ -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)

View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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);