summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-12-02 18:19:04 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-12-02 18:19:04 +0000
commit76915e433bd4342a6fb507eaafd77cd5dd77bea8 (patch)
tree00265034b9a87396f2690dbbf993f4556202ac73
parent5b1722709e91fd3a2b110a04abe551c0f40a5414 (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--ChangeLog21
-rw-r--r--MANIFEST1
-rw-r--r--compar.c29
-rw-r--r--configure.in30
-rw-r--r--error.c150
-rw-r--r--eval.c2
-rw-r--r--gc.c2
-rw-r--r--numeric.c1
-rw-r--r--parse.y8
-rw-r--r--regex.c1
-rw-r--r--sprintf.c21
-rw-r--r--util.c255
-rw-r--r--util.h3
13 files changed, 335 insertions, 189 deletions
diff --git a/ChangeLog b/ChangeLog
index de3c2d28ed..9cca25f39e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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/.
diff --git a/MANIFEST b/MANIFEST
index 3c57e578fa..04ab6d3ca8 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -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
diff --git a/compar.c b/compar.c
index 3cebc30a80..4cd169ca73 100644
--- a/compar.c
+++ b/compar.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
diff --git a/error.c b/error.c
index 7e9e4a91ba..df9bcccdf8 100644
--- a/error.c
+++ b/error.c
@@ -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
diff --git a/eval.c b/eval.c
index 3a2b9d1c96..d8a9dc1a1f 100644
--- a/eval.c
+++ b/eval.c
@@ -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,
diff --git a/gc.c b/gc.c
index a1ebacc88e..2d97a7622a 100644
--- a/gc.c
+++ b/gc.c
@@ -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
}
diff --git a/numeric.c b/numeric.c
index e82772eb78..912f9dd30b 100644
--- a/numeric.c
+++ b/numeric.c
@@ -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);
diff --git a/parse.y b/parse.y
index a04fcadd9d..c977eaa0ef 100644
--- a/parse.y
+++ b/parse.y
@@ -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 */
diff --git a/regex.c b/regex.c
index d19ff0126a..5a8b5de277 100644
--- a/regex.c
+++ b/regex.c
@@ -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;
}
diff --git a/sprintf.c b/sprintf.c
index 4a7f8f6090..9019234b58 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -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);
diff --git a/util.c b/util.c
index d9f268ea56..2a5a6d82c8 100644
--- a/util.c
+++ b/util.c
@@ -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;
+}
diff --git a/util.h b/util.h
index e3a774df94..b08a75961c 100644
--- a/util.h
+++ b/util.h
@@ -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 */