diff options
-rw-r--r-- | ChangeLog | 52 | ||||
-rw-r--r-- | LEGAL | 47 | ||||
-rw-r--r-- | ToDo | 1 | ||||
-rw-r--r-- | bignum.c | 10 | ||||
-rw-r--r-- | eval.c | 32 | ||||
-rw-r--r-- | gc.c | 2 | ||||
-rw-r--r-- | intern.h | 2 | ||||
-rw-r--r-- | node.h | 2 | ||||
-rw-r--r-- | numeric.c | 3 | ||||
-rw-r--r-- | parse.y | 78 | ||||
-rw-r--r-- | random.c | 235 | ||||
-rw-r--r-- | re.c | 60 | ||||
-rw-r--r-- | re.h | 1 | ||||
-rw-r--r-- | string.c | 144 |
14 files changed, 462 insertions, 207 deletions
@@ -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 @@ -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: @@ -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 @@ -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); @@ -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 { @@ -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; @@ -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)); @@ -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); @@ -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; @@ -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); } @@ -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() { @@ -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; @@ -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); |