summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog52
-rw-r--r--LEGAL47
-rw-r--r--ToDo1
-rw-r--r--bignum.c10
-rw-r--r--eval.c32
-rw-r--r--gc.c2
-rw-r--r--intern.h2
-rw-r--r--node.h2
-rw-r--r--numeric.c3
-rw-r--r--parse.y78
-rw-r--r--random.c235
-rw-r--r--re.c60
-rw-r--r--re.h1
-rw-r--r--string.c144
14 files changed, 462 insertions, 207 deletions
diff --git a/ChangeLog b/ChangeLog
index e7dbef55dc..1f0d6557e1 100644
--- a/ChangeLog
+++ b/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
diff --git a/LEGAL b/LEGAL
index dba950076b..8a87bfa668 100644
--- a/LEGAL
+++ b/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:
diff --git a/ToDo b/ToDo
index d34bedbaf1..3d5e79436b 100644
--- a/ToDo
+++ b/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
diff --git a/bignum.c b/bignum.c
index ddb1636d69..fbf293de83 100644
--- a/bignum.c
+++ b/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);
diff --git a/eval.c b/eval.c
index 236d48adbe..30aa9fca90 100644
--- a/eval.c
+++ b/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 {
diff --git a/gc.c b/gc.c
index 21a4c2e1cb..9a17078e11 100644
--- a/gc.c
+++ b/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;
diff --git a/intern.h b/intern.h
index eef7235c70..7c9308e3f1 100644
--- a/intern.h
+++ b/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));
diff --git a/node.h b/node.h
index 722df09771..8d3e347c57 100644
--- a/node.h
+++ b/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)
diff --git a/numeric.c b/numeric.c
index 6722ab0c99..bb2ed583b1 100644
--- a/numeric.c
+++ b/numeric.c
@@ -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);
diff --git a/parse.y b/parse.y
index 2ca171f332..17c885957f 100644
--- a/parse.y
+++ b/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;
diff --git a/random.c b/random.c
index 3fdac4a5c4..6b6d5d7045 100644
--- a/random.c
+++ b/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);
}
diff --git a/re.c b/re.c
index 0cb048be27..90999a9572 100644
--- a/re.c
+++ b/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()
{
diff --git a/re.h b/re.h
index 47c5f424ad..0e43f922df 100644
--- a/re.h
+++ b/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;
diff --git a/string.c b/string.c
index cba8d340c5..e687fcc533 100644
--- a/string.c
+++ b/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;
+ }
+ val = rb_reg_quote(pat);
+#if RUBY_VERSION_CODE < 180
+ if (val != pat) {
+ rb_warn("string pattern instead of regexp; metacharacters no longer effective");
}
- return pat;
+#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);