diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-12-02 18:19:04 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-12-02 18:19:04 +0000 |
commit | 76915e433bd4342a6fb507eaafd77cd5dd77bea8 (patch) | |
tree | 00265034b9a87396f2690dbbf993f4556202ac73 | |
parent | 5b1722709e91fd3a2b110a04abe551c0f40a5414 (diff) |
* eval.c (backtrace): should ignore line 0 frame.
* sprintf.c (rb_f_sprintf): preceding ".." for negative
hexadecimal numbers should not appear if prec (e.g. %.4) is
specified.
* compar.c (cmp_eq,cmp_gt,cmp_ge,cmp_lt,cmp_le): "<=>" might
return nil. check using rb_cmpint().
* error.c (init_syserr): remove sys_nerr dependency.
* regex.c (re_match): avoid dereferencing if size == 0.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@3112 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | compar.c | 29 | ||||
-rw-r--r-- | configure.in | 30 | ||||
-rw-r--r-- | error.c | 150 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | gc.c | 2 | ||||
-rw-r--r-- | numeric.c | 1 | ||||
-rw-r--r-- | parse.y | 8 | ||||
-rw-r--r-- | regex.c | 1 | ||||
-rw-r--r-- | sprintf.c | 21 | ||||
-rw-r--r-- | util.c | 255 | ||||
-rw-r--r-- | util.h | 3 |
13 files changed, 335 insertions, 189 deletions
@@ -1,3 +1,7 @@ +Tue Dec 3 01:48:06 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * eval.c (backtrace): should ignore line 0 frame. + Sun Dec 1 22:43:29 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * win32/win32.c (win32_stat): empty path is invalid, and return @@ -37,10 +41,27 @@ Fri Nov 22 19:30:17 2002 Akinori MUSHA <knu@iDaemons.org> * instruby.rb: Install batch files on Windows. [Submitted by usa] +Fri Nov 22 22:55:01 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * sprintf.c (rb_f_sprintf): preceding ".." for negative + hexadecimal numbers should not appear if prec (e.g. %.4) is + specified. + Thu Nov 21 20:56:35 2002 Minero Aoki <aamine@loveruby.net> * lib/net/http.rb: should not overwrite Host: header. +Wed Nov 20 02:07:12 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * compar.c (cmp_eq,cmp_gt,cmp_ge,cmp_lt,cmp_le): "<=>" might + return nil. check using rb_cmpint(). + + * error.c (init_syserr): remove sys_nerr dependency. + +Tue Nov 19 22:37:23 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * regex.c (re_match): avoid dereferencing if size == 0. + Tue Nov 19 05:16:23 2002 Akinori MUSHA <knu@iDaemons.org> * instruby.rb: Do not install various working files under bin/. @@ -222,7 +222,6 @@ missing/strchr.c missing/strerror.c missing/strftime.c missing/strstr.c -missing/strtod.c missing/strtol.c missing/strtoul.c missing/vsnprintf.c @@ -21,9 +21,9 @@ cmp_eq(a) VALUE *a; { VALUE c = rb_funcall(a[0], cmp, 1, a[1]); - int t = NUM2INT(c); - if (t == 0) return Qtrue; + if (NIL_P(c)) return Qfalse; + if (rb_cmpint(c) == 0) return Qtrue; return Qfalse; } @@ -51,9 +51,9 @@ cmp_gt(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); - int t = NUM2INT(c); - if (t > 0) return Qtrue; + if (NIL_P(c)) return Qfalse; + if (rb_cmpint(c) > 0) return Qtrue; return Qfalse; } @@ -62,9 +62,9 @@ cmp_ge(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); - int t = NUM2INT(c); - if (t >= 0) return Qtrue; + if (NIL_P(c)) return Qfalse; + if (rb_cmpint(c) >= 0) return Qtrue; return Qfalse; } @@ -73,9 +73,9 @@ cmp_lt(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); - int t = NUM2INT(c); - if (t < 0) return Qtrue; + if (NIL_P(c)) return Qfalse; + if (rb_cmpint(c) < 0) return Qtrue; return Qfalse; } @@ -84,9 +84,9 @@ cmp_le(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); - int t = NUM2INT(c); - if (t <= 0) return Qtrue; + if (NIL_P(c)) return Qfalse; + if (rb_cmpint(c) <= 0) return Qtrue; return Qfalse; } @@ -94,13 +94,8 @@ static VALUE cmp_between(x, min, max) VALUE x, min, max; { - VALUE c = rb_funcall(x, cmp, 1, min); - long t = NUM2LONG(c); - if (t < 0) return Qfalse; - - c = rb_funcall(x, cmp, 1, max); - t = NUM2LONG(c); - if (t > 0) return Qfalse; + if (cmp_lt(x, min)) return Qfalse; + if (cmp_gt(x, max)) return Qfalse; return Qtrue; } diff --git a/configure.in b/configure.in index 0efeb9a896..465d0abf8f 100644 --- a/configure.in +++ b/configure.in @@ -402,36 +402,6 @@ fi AC_FUNC_GETPGRP AC_FUNC_SETPGRP -AC_CACHE_CHECK(for working strtod, rb_cv_func_strtod, -[AC_TRY_RUN([ -double strtod (); -int -main() -{ - { - /* Some versions of Linux strtod mis-parse strings with leading '+'. */ - char *string = " +69"; - char *term; - double value; - value = strtod(string, &term); - if (value != 69 || term != (string + 4)) - exit(1); - } - - { - /* Under Solaris 2.4, strtod returns the wrong value for the - terminating character under some conditions. */ - char *string = "NaN"; - char *term; - strtod(string, &term); - if (term != string && *(term - 1) == 0) - exit(1); - } - exit(0); -} -], rb_cv_func_strtod=yes, rb_cv_func_strtod=no, rb_cv_func_strtod=no)]) -test $rb_cv_func_strtod = no && LIBOBJS="$LIBOBJS strtod.o" - AC_C_BIGENDIAN AC_C_CONST AC_C_CHAR_UNSIGNED @@ -13,6 +13,7 @@ #include "ruby.h" #include "env.h" #include "version.h" +#include "st.h" #include <stdio.h> #ifdef HAVE_STDARG_PROTOTYPES @@ -412,101 +413,34 @@ exc_set_backtrace(exc, bt) return rb_iv_set(exc, "bt", check_backtrace(bt)); } -#ifdef __BEOS__ -typedef struct { - VALUE *list; - int n; -} syserr_list_entry; - -typedef struct { - int ix; - int n; -} syserr_index_entry; - -static VALUE syserr_error; -static VALUE syserr_list_b_general[16+1]; -static VALUE syserr_list_b_os0[2+1]; -static VALUE syserr_list_b_os1[5+1]; -static VALUE syserr_list_b_os2[2+1]; -static VALUE syserr_list_b_os3[3+1]; -static VALUE syserr_list_b_os4[1+1]; -static VALUE syserr_list_b_app[15+1]; -static VALUE syserr_list_b_interface[0+1]; -static VALUE syserr_list_b_media[8+1]; -static VALUE syserr_list_b_midi[0+1]; -static VALUE syserr_list_b_storage[15+1]; -static VALUE syserr_list_b_posix[38+1]; -static VALUE syserr_list_b_mail[8+1]; -static VALUE syserr_list_b_print[1+1]; -static VALUE syserr_list_b_device[14+1]; - -# define SYSERR_LIST_B(n) {(n), sizeof(n)/sizeof(VALUE)} -static const syserr_list_entry syserr_list[] = { - SYSERR_LIST_B(syserr_list_b_general), - SYSERR_LIST_B(syserr_list_b_os0), - SYSERR_LIST_B(syserr_list_b_os1), - SYSERR_LIST_B(syserr_list_b_os2), - SYSERR_LIST_B(syserr_list_b_os3), - SYSERR_LIST_B(syserr_list_b_os4), - SYSERR_LIST_B(syserr_list_b_app), - SYSERR_LIST_B(syserr_list_b_interface), - SYSERR_LIST_B(syserr_list_b_media), - SYSERR_LIST_B(syserr_list_b_midi), - SYSERR_LIST_B(syserr_list_b_storage), - SYSERR_LIST_B(syserr_list_b_posix), - SYSERR_LIST_B(syserr_list_b_mail), - SYSERR_LIST_B(syserr_list_b_print), - SYSERR_LIST_B(syserr_list_b_device), -}; -# undef SYSERR_LIST_B +static st_table *syserr_tbl; -static const syserr_index_entry syserr_index[]= { - {0, 1}, {1, 5}, {6, 1}, {7, 1}, {8, 1}, {9, 1}, {10, 1}, {11, 1}, - {12, 1}, {13, 1}, {14, 1}, {0, 0}, -}; -#else -static VALUE *syserr_list; -#endif +static VALUE +set_syserr(n, name) + int n; + const char *name; +{ + VALUE error; -#if !defined(NT) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(sys_nerr) -# if !defined(__APPLE__) || (__APPLE_CC__ < 1151) -extern int sys_nerr; -# endif -#endif + if (!st_lookup(syserr_tbl, n, &error)) { + error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);; + rb_define_const(error, "Errno", INT2NUM(n)); + st_add_direct(syserr_tbl, n, error); + } + return error; +} static VALUE -set_syserr(i, name) - int i; - const char *name; +get_syserr(int n) { -#ifdef __BEOS__ - VALUE *list; - int ix, offset; -#endif - VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError); - rb_define_const(error, "Errno", INT2NUM(i)); -#ifdef __BEOS__ - if (i == B_ERROR) { - syserr_error = error; - rb_global_variable(&syserr_error); - return error; - } - i -= B_GENERAL_ERROR_BASE; - ix = (i >> 12) & 0xf; - offset = (i >> 8) & 0xf; - if (offset < syserr_index[ix].n) { - ix = syserr_index[ix].ix; - if ((i & 0xff) < syserr_list[ix + offset].n) { - list = syserr_list[ix + offset].list; - list[i & 0xff] = error; - rb_global_variable(&list[i & 0xff]); - } - } -#else - if (i <= sys_nerr) { - syserr_list[i] = error; + VALUE error; + + if (!st_lookup(syserr_tbl, n, &error)) { + char name[6]; + + sprintf(name, "E%03d", n); + error = set_syserr(n, name); } -#endif return error; } @@ -672,26 +606,7 @@ rb_sys_fail(mesg) } errno = 0; -#ifdef __BEOS__ - ee = get_syserr(n); - if (!ee) { - char name[6]; - - sprintf(name, "E%03d", n); - ee = set_syserr(n, name); - } -#else - if (n > sys_nerr || !syserr_list[n]) { - char name[6]; - - sprintf(name, "E%03d", n); - ee = set_syserr(n, name); - } - else { - ee = syserr_list[n]; - } -#endif - ee = rb_exc_new2(ee, buf); + ee = rb_exc_new2(get_syserr(n), buf); rb_iv_set(ee, "errno", INT2NUM(n)); rb_exc_raise(ee); } @@ -713,26 +628,11 @@ rb_error_frozen(what) static void init_syserr() { -#ifdef __BEOS__ - int i, ix, offset; -#endif + syserr_tbl = st_init_numtable(); rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError); rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0); rb_mErrno = rb_define_module("Errno"); -#ifdef __BEOS__ - for (i = 0; syserr_index[i].n != 0; i++) { - ix = syserr_index[i].ix; - for (offset = 0; offset < syserr_index[i].n; offset++) { - MEMZERO(syserr_list[ix + offset].list, VALUE, syserr_list[ix + offset].n); - } - } - set_syserr(B_ERROR, "ERROR"); -#else - syserr_list = ALLOC_N(VALUE, sys_nerr+1); - MEMZERO(syserr_list, VALUE, sys_nerr+1); -#endif - #ifdef EPERM set_syserr(EPERM, "EPERM"); #endif @@ -4787,7 +4787,7 @@ backtrace(lev) } } } - while (frame && frame->file) { + while (frame && frame->file && frame->line) { if (frame->prev && frame->prev->last_func) { snprintf(buf, BUFSIZ, "%s:%d:in `%s'", frame->file, frame->line, @@ -922,7 +922,7 @@ obj_free(obj) break; #ifdef C_ALLOCA case NODE_ALLOCA: - RUBY_CRITICAL(free(RANY(obj)->as.node.u1.value)); + RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node)); break; #endif } @@ -1559,6 +1559,7 @@ Init_Numeric() rb_define_method(rb_cNumeric, "+@", num_uplus, 0); rb_define_method(rb_cNumeric, "-@", num_uminus, 0); + rb_define_method(rb_cNumeric, "==", num_equal, 1); rb_define_method(rb_cNumeric, "===", num_equal, 1); rb_define_method(rb_cNumeric, "eql?", num_eql, 1); rb_define_method(rb_cNumeric, "divmod", num_divmod, 1); @@ -2928,10 +2928,6 @@ arg_ambiguous() rb_warning("ambiguous first argument; make sure"); } -#if !defined(strtod) && !defined(HAVE_STDLIB_H) -double strtod (); -#endif - static int yylex() { @@ -4111,9 +4107,7 @@ str_extend(list, term, paren) c = nextc(); } } - else { - tokadd(c); - } + tokadd(c); break; } /* out of brace */ @@ -4140,6 +4140,7 @@ re_match(bufp, string_arg, size, pos, regs) case wordbound: if (AT_STRINGS_BEG(d)) { + if (AT_STRINGS_END(d)) goto fail; if (IS_A_LETTER(d)) break; else goto fail; } @@ -441,8 +441,13 @@ rb_f_sprintf(argc, argv) } s = nbuf; if (v < 0) { - strcpy(s, ".."); - s += 2; + if (base == 10) { + rb_warning("negative number for %%u specifier"); + } + else if (!(flags&FPREC)) { + strcpy(s, ".."); + s += 2; + } } sprintf(fbuf, "%%l%c", *p); sprintf(s, fbuf, v); @@ -494,8 +499,10 @@ rb_f_sprintf(argc, argv) remove_sign_bits(++s, base); val = rb_str_new(0, 3+strlen(s)); t = RSTRING(val)->ptr; - strcpy(t, ".."); - t += 2; + if (!(flags&FPREC)) { + strcpy(t, ".."); + t += 2; + } switch (base) { case 16: if (s[0] != 'f') strcpy(t++, "f"); break; @@ -520,7 +527,7 @@ rb_f_sprintf(argc, argv) } if (prec < len) prec = len; width -= prec; - if (!(flags&(FZERO|FMINUS)) && s[0] != '.') { + if (!(flags&(FZERO|FMINUS)) && v >= 0) { CHECK(width); while (width-->0) { buf[blen++] = ' '; @@ -537,7 +544,7 @@ rb_f_sprintf(argc, argv) if (!(flags & FMINUS)) { char c = ' '; - if (s[0] == '.') { + if (v < 0) { c = '.'; if ((flags & FPREC) && prec > len) { pos = blen; @@ -554,7 +561,7 @@ rb_f_sprintf(argc, argv) } CHECK(prec - len); while (len < prec--) { - buf[blen++] = s[0]=='.'?'.':'0'; + buf[blen++] = v < 0 ? '.' : '0'; } CHECK(len); strcpy(&buf[blen], s); @@ -11,6 +11,8 @@ **********************************************************************/ #include <stdio.h> +#include <ctype.h> +#include <errno.h> #ifdef NT #include "missing/file.h" @@ -634,3 +636,256 @@ ruby_strdup(str) return tmp; } + +/* copyright notice for strtod implementation -- + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + */ + +#define TRUE 1 +#define FALSE 0 + +static int maxExponent = 511; /* Largest possible base 10 exponent. Any + * exponent larger than this will already + * produce underflow or overflow, so there's + * no need to worry about additional digits. + */ +static double powersOf10[] = { /* Table giving binary powers of 10. Entry */ + 10.0, /* is 10^2^i. Used to convert decimal */ + 100.0, /* exponents into floating-point numbers. */ + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 +}; + +/* + *---------------------------------------------------------------------- + * + * strtod -- + * + * This procedure converts a floating-point number from an ASCII + * decimal representation to internal double-precision format. + * + * Results: + * The return value is the double-precision floating-point + * representation of the characters in string. If endPtr isn't + * NULL, then *endPtr is filled in with the address of the + * next character after the last one that was part of the + * floating-point number. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +double +ruby_strtod(string, endPtr) + const char *string; /* A decimal ASCII floating-point number, + * optionally preceded by white space. + * Must have form "-I.FE-X", where I is the + * integer part of the mantissa, F is the + * fractional part of the mantissa, and X + * is the exponent. Either of the signs + * may be "+", "-", or omitted. Either I + * or F may be omitted, or both. The decimal + * point isn't necessary unless F is present. + * The "E" may actually be an "e". E and X + * may both be omitted (but not just one). + */ + char **endPtr; /* If non-NULL, store terminating character's + * address here. */ +{ + int sign, expSign = FALSE; + double fraction, dblExp, *d; + register const char *p; + register int c; + int exp = 0; /* Exponent read from "EX" field. */ + int fracExp = 0; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + const char *pExp; /* Temporarily holds location of exponent + * in string. */ + + /* + * Strip off leading blanks and check for a sign. + */ + + errno = 0; + p = string; + while (ISSPACE(*p)) { + p += 1; + } + if (*p == '-') { + sign = TRUE; + p += 1; + } + else { + if (*p == '+') { + p += 1; + } + sign = FALSE; + } + + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + + decPt = -1; + for (mantSize = 0; ; mantSize += 1) { + c = *p; + if (!ISDIGIT(c)) { + if ((c != '.') || (decPt >= 0)) { + break; + } + decPt = mantSize; + } + p += 1; + } + + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) { + decPt = mantSize; + } + else { + mantSize -= 1; /* One of the digits was the point. */ + } + if (mantSize > 18) { + fracExp = decPt - 18; + mantSize = 18; + } + else { + fracExp = decPt - mantSize; + } + if (mantSize == 0) { + fraction = 0.0; + p = string; + goto done; + } + else { + int frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); + } + fraction = (1.0e9 * frac1) + frac2; + } + + /* + * Skim off the exponent. + */ + + p = pExp; + if ((*p == 'E') || (*p == 'e')) { + p += 1; + if (*p == '-') { + expSign = TRUE; + p += 1; + } + else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + while (ISDIGIT(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) { + exp = fracExp - exp; + } + else { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } + else { + expSign = FALSE; + } + if (exp > maxExponent) { + exp = maxExponent; + errno = ERANGE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction /= dblExp; + } + else { + fraction *= dblExp; + } + +done: + if (endPtr != NULL) { + *endPtr = (char *) p; + } + + if (sign) { + return -fraction; + } + return fraction; +} @@ -58,4 +58,7 @@ char *ruby_strdup _((const char*)); #undef strdup #define strdup(s) ruby_strdup((s)) +double ruby_strtod _((const char*, char **)); +#define strtod(s,e) ruby_strtod((s),(e)) + #endif /* UTIL_H */ |