diff --git a/ChangeLog b/ChangeLog index 100d46cf5c..b138cdc72b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +Fri Feb 1 19:10:04 2002 Nobuyoshi Nakada + + * intern.h: prototypes for new functions; rb_cstr_to_inum(), + rb_str_to_inum(), rb_cstr_to_dbl(), rb_str_to_dbl() + + * bignum.c (rb_cstr_to_inum): changed from rb_cstr2inum(), and + added argument badcheck to be consistent with parser. [new] + + * bignum.c (rb_str_to_inum): ditto. + + * bignum.c (rb_cstr2inum): wapper of rb_cstr_to_inum() now. + + * bignum.c (rb_str2inum): ditto. + + * object.c (rb_cstr_to_dbl): float number parser. [new] + + * object.c (rb_str_to_dbl): ditto. + + * object.c (rb_Float): use rb_cstr_to_dbl() for strict check. + + * object.c (rb_Integer): use rb_str_to_inum() for strict check. + + * string.c (rb_str_to_f): use rb_str_to_dbl() with less check. + + * string.c (rb_str_to_i): use rb_str_to_inum() with less check. + + * string.c (rb_str_hex): ditto. + + * string.c (rb_str_oct): ditto. + + * sprintf.c (rb_f_sprintf): ditto. + + * time.c (obj2long): ditto. + + * parse.y (yylex): use rb_cstr_to_inum() for strict check. + Fri Feb 1 17:46:39 2002 Nobuyoshi Nakada * regex.c (mbc_startpos): become macro. diff --git a/bignum.c b/bignum.c index f4add5f5f4..173c8fb968 100644 --- a/bignum.c +++ b/bignum.c @@ -186,21 +186,26 @@ rb_int2inum(n) } VALUE -rb_cstr2inum(str, base) +rb_cstr_to_inum(str, base, badcheck) const char *str; int base; + int badcheck; { const char *s = str; char *end; - int badcheck = (base==0)?1:0; - char sign = 1, c; + char sign = 1, c, nondigit = 0; BDIGIT_DBL num; long len, blen = 1; long i; VALUE z; BDIGIT *zds; - while (*str && ISSPACE(*str)) str++; + if (badcheck) { + while (ISSPACE(*str)) str++; + } + else { + while (ISSPACE(*str) || *str == '_') str++; + } if (str[0] == '+') { str++; @@ -213,7 +218,7 @@ rb_cstr2inum(str, base) if (badcheck) goto bad; return INT2FIX(0); } - if (base == 0) { + if (base <= 0) { if (str[0] == '0') { if (str[1] == 'x' || str[1] == 'X') { base = 16; @@ -225,6 +230,9 @@ rb_cstr2inum(str, base) base = 8; } } + else if (base < -1) { + base = -base; + } else { base = 10; } @@ -290,18 +298,27 @@ rb_cstr2inum(str, base) case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = c - '0'; + nondigit = 0; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - if (base != 16) c = base; - else c = c - 'a' + 10; - break; + c -= 'a' - 'A'; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - if (base != 16) c = base; - else c = c - 'A' + 10; + if (base != 16) { + nondigit = c; + c = base; + } + else { + c = c - 'A' + 10; + nondigit = 0; + } break; case '_': + if (badcheck) { + if (nondigit) goto bad; + nondigit = c; + } continue; default: c = base; @@ -334,9 +351,10 @@ rb_cstr2inum(str, base) } VALUE -rb_str2inum(str, base) +rb_str_to_inum(str, base, badcheck) VALUE str; int base; + int badcheck; { char *s; int len; @@ -351,10 +369,26 @@ rb_str2inum(str, base) p[len] = '\0'; s = p; } - if (base == 0 && len != strlen(s)) { + if (badcheck && len != strlen(s)) { rb_raise(rb_eArgError, "string for Integer contains null byte"); } - return rb_cstr2inum(s, base); + return rb_cstr_to_inum(s, base, badcheck); +} + +VALUE +rb_cstr2inum(str, base) + const char *str; + int base; +{ + return rb_cstr_to_inum(str, base, base==0); +} + +VALUE +rb_str2inum(str, base) + VALUE str; + int base; +{ + return rb_str_to_inum(str, base, base==0); } static char hexmap[] = "0123456789abcdef"; diff --git a/intern.h b/intern.h index f3c6b62355..d41086dfd0 100644 --- a/intern.h +++ b/intern.h @@ -61,6 +61,8 @@ VALUE rb_uint2big _((unsigned long)); VALUE rb_int2big _((long)); VALUE rb_uint2inum _((unsigned long)); VALUE rb_int2inum _((long)); +VALUE rb_cstr_to_inum _((const char*, int, int)); +VALUE rb_str_to_inum _((VALUE, int, int)); VALUE rb_cstr2inum _((const char*, int)); VALUE rb_str2inum _((VALUE, int)); VALUE rb_big2str _((VALUE, int)); @@ -263,6 +265,8 @@ VALUE rb_Integer _((VALUE)); VALUE rb_Float _((VALUE)); VALUE rb_String _((VALUE)); VALUE rb_Array _((VALUE)); +double rb_cstr_to_dbl _((const char *, int)); +double rb_str_to_dbl _((VALUE, int)); /* parse.y */ EXTERN int ruby_sourceline; EXTERN char *ruby_sourcefile; diff --git a/object.c b/object.c index f4558139e8..35517e963a 100644 --- a/object.c +++ b/object.c @@ -945,7 +945,7 @@ rb_Integer(val) return val; case T_STRING: - return rb_str2inum(val, 0); + return rb_str_to_inum(val, 0, Qtrue); case T_FIXNUM: return val; @@ -963,6 +963,90 @@ rb_f_integer(obj, arg) return rb_Integer(arg); } +double +rb_cstr_to_dbl(p, badcheck) + const char *p; + int badcheck; +{ + const char *q; + char *end; + double d; + + q = p; + if (badcheck) { + while (ISSPACE(*p)) p++; + } + else { + while (ISSPACE(*p) || *p == '_') p++; + } + d = strtod(p, &end); + if (p == end) { + if (badcheck) { + bad: + rb_invalid_str(q, "Float()"); + } + return d; + } + if (*end) { + char *buf = ALLOCA_N(char, strlen(p)); + char *n = buf; + + while (p < end) *n++ = *p++; + while (*p) { + if (*p == '_') { + /* remove underscores between digits */ + if (badcheck) { + if (n == buf || !ISDIGIT(n[-1])) goto bad; + ++p; + if (!ISDIGIT(*p)) goto bad; + } + else { + while (*++p == '_'); + continue; + } + } + *n++ = *p++; + } + *n = '\0'; + p = buf; + d = strtod(p, &end); + if (badcheck) { + if (p == end) goto bad; + while (*end && ISSPACE(*end)) end++; + if (*end) goto bad; + } + } + if (errno == ERANGE) { + errno = 0; + rb_raise(rb_eArgError, "Float %s out of range", q); + } + return d; +} + +double +rb_str_to_dbl(str, badcheck) + VALUE str; + int badcheck; +{ + char *s; + int len; + + StringValue(str); + s = RSTRING(str)->ptr; + len = RSTRING(str)->len; + if (s[len]) { /* no sentinel somehow */ + char *p = ALLOCA_N(char, len+1); + + MEMCPY(p, s, char, len); + p[len] = '\0'; + s = p; + } + if (badcheck && len != strlen(s)) { + rb_raise(rb_eArgError, "string for Float contains null byte"); + } + return rb_cstr_to_dbl(s, badcheck); +} + VALUE rb_Float(val) VALUE val; @@ -978,53 +1062,7 @@ rb_Float(val) return rb_float_new(rb_big2dbl(val)); case T_STRING: - { - char *q, *p, *end; - double d; - - q = p = StringValuePtr(val); - while (*p && ISSPACE(*p)) p++; - d = strtod(p, &end); - if (p == end) { - bad: - rb_invalid_str(q, "Float()"); - } - if (*end) { - if (*end == '_') { - char *buf = ALLOCA_N(char, strlen(p)); - char *n = buf, *last = p; - - while (p < end) *n++ = *p++; - while (*p) { - if (*p == '_' && (n > buf && ISDIGIT(n[-1]))) { - /* remove underscores between digits */ - last = ++p; - while (*p == '_') ++p; - if (!ISDIGIT(*p)) { - while (last < p) *n++ = *last++; - continue; - } - last = p; - } - *n++ = *p++; - } - while (*last && (*last == '_' || ISSPACE(*last))) - last++; - if (!*last) goto bad; - *n = '\0'; - p = buf; - d = strtod(p, &end); - if (p == end) goto bad; - } - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; - } - if (errno == ERANGE) { - errno = 0; - rb_raise(rb_eArgError, "Float %s out of range", p); - } - return rb_float_new(d); - } + return rb_float_new(rb_str_to_dbl(val, Qtrue)); case T_NIL: return rb_float_new(0.0); diff --git a/parse.y b/parse.y index 481927ec42..0081e9fa81 100644 --- a/parse.y +++ b/parse.y @@ -3345,7 +3345,7 @@ yylex() yyerror("hexadecimal number without hex-digits"); } else if (nondigit) goto trailing_uc; - yylval.val = rb_cstr2inum(tok(), 16); + yylval.val = rb_cstr_to_inum(tok(), 16, Qfalse); return tINTEGER; } if (c == 'b' || c == 'B') { @@ -3369,7 +3369,7 @@ yylex() yyerror("numeric literal without digits"); } else if (nondigit) goto trailing_uc; - yylval.val = rb_cstr2inum(tok(), 2); + yylval.val = rb_cstr_to_inum(tok(), 2, Qfalse); return tINTEGER; } if (c >= '0' && c <= '7' || c == '_') { @@ -3388,7 +3388,7 @@ yylex() pushback(c); tokfix(); if (nondigit) goto trailing_uc; - yylval.val = rb_cstr2inum(tok(), 8); + yylval.val = rb_cstr_to_inum(tok(), 8, Qfalse); return tINTEGER; } } @@ -3482,7 +3482,7 @@ yylex() yylval.val = rb_float_new(d); return tFLOAT; } - yylval.val = rb_cstr2inum(tok(), 10); + yylval.val = rb_cstr_to_inum(tok(), 10, Qfalse); return tINTEGER; } diff --git a/sprintf.c b/sprintf.c index fe53d6b27c..2355a65f9c 100644 --- a/sprintf.c +++ b/sprintf.c @@ -18,10 +18,6 @@ #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */ -#if !defined(atof) && !defined(HAVE_STDLIB_H) -double strtod(); -#endif - static void fmt_setup _((char*,int,int,int,int)); static char* @@ -397,7 +393,7 @@ rb_f_sprintf(argc, argv) bignum = 1; break; case T_STRING: - val = rb_str2inum(val, 0); + val = rb_str_to_inum(val, 0, Qtrue); goto bin_retry; case T_BIGNUM: bignum = 1; diff --git a/string.c b/string.c index 87411a5284..25fd851d08 100644 --- a/string.c +++ b/string.c @@ -1766,16 +1766,14 @@ rb_str_to_i(argc, argv, str) default: rb_raise(rb_eArgError, "illegal radix %d", base); } - return rb_str2inum(str, base); + return rb_str_to_inum(str, base, Qfalse); } static VALUE rb_str_to_f(str) VALUE str; { - double f = strtod(RSTRING(str)->ptr, 0); - - return rb_float_new(f); + return rb_float_new(rb_str_to_dbl(str, Qfalse)); } static VALUE @@ -2963,28 +2961,14 @@ static VALUE rb_str_hex(str) VALUE str; { - return rb_str2inum(str, 16); + return rb_str_to_inum(str, 16, Qfalse); } static VALUE rb_str_oct(str) VALUE str; { - int base = 8; - - if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0') { - switch (RSTRING(str)->ptr[1]) { - case 'x': - case 'X': - base = 16; - break; - case 'b': - case 'B': - base = 2; - break; - } - } - return rb_str2inum(str, base); + return rb_str_to_inum(str, -8, Qfalse); } static VALUE diff --git a/time.c b/time.c index c4c3da9bba..32b9f1118c 100644 --- a/time.c +++ b/time.c @@ -218,7 +218,7 @@ obj2long(obj) VALUE obj; { if (TYPE(obj) == T_STRING) { - obj = rb_str2inum(obj, 10); + obj = rb_str_to_inum(obj, 10, Qfalse); } return NUM2LONG(obj);