mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
5b1722709e
commit
76915e433b
13 changed files with 336 additions and 190 deletions
21
ChangeLog
21
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/.
|
||||
|
|
1
MANIFEST
1
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
|
||||
|
|
29
compar.c
29
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;
|
||||
}
|
||||
|
||||
|
|
30
configure.in
30
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
|
||||
|
|
152
error.c
152
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 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
|
||||
|
||||
#if !defined(NT) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(sys_nerr)
|
||||
# if !defined(__APPLE__) || (__APPLE_CC__ < 1151)
|
||||
extern int sys_nerr;
|
||||
# endif
|
||||
#endif
|
||||
static st_table *syserr_tbl;
|
||||
|
||||
static VALUE
|
||||
set_syserr(i, name)
|
||||
int i;
|
||||
set_syserr(n, name)
|
||||
int n;
|
||||
const char *name;
|
||||
{
|
||||
#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)) {
|
||||
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
|
||||
get_syserr(int n)
|
||||
{
|
||||
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
|
||||
|
|
2
eval.c
2
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,
|
||||
|
|
2
gc.c
2
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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
8
parse.y
8
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 */
|
||||
|
|
1
regex.c
1
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;
|
||||
}
|
||||
|
|
21
sprintf.c
21
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);
|
||||
|
|
255
util.c
255
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;
|
||||
}
|
||||
|
|
3
util.h
3
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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue