* 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.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2041 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2002-02-01 10:23:22 +00:00
parent d9b49e39b2
commit c2269d5b4f
8 changed files with 183 additions and 91 deletions

View File

@ -1,3 +1,39 @@
Fri Feb 1 19:10:04 2002 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* 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 <nobu.nakada@nifty.ne.jp> Fri Feb 1 17:46:39 2002 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* regex.c (mbc_startpos): become macro. * regex.c (mbc_startpos): become macro.

View File

@ -186,21 +186,26 @@ rb_int2inum(n)
} }
VALUE VALUE
rb_cstr2inum(str, base) rb_cstr_to_inum(str, base, badcheck)
const char *str; const char *str;
int base; int base;
int badcheck;
{ {
const char *s = str; const char *s = str;
char *end; char *end;
int badcheck = (base==0)?1:0; char sign = 1, c, nondigit = 0;
char sign = 1, c;
BDIGIT_DBL num; BDIGIT_DBL num;
long len, blen = 1; long len, blen = 1;
long i; long i;
VALUE z; VALUE z;
BDIGIT *zds; BDIGIT *zds;
while (*str && ISSPACE(*str)) str++; if (badcheck) {
while (ISSPACE(*str)) str++;
}
else {
while (ISSPACE(*str) || *str == '_') str++;
}
if (str[0] == '+') { if (str[0] == '+') {
str++; str++;
@ -213,7 +218,7 @@ rb_cstr2inum(str, base)
if (badcheck) goto bad; if (badcheck) goto bad;
return INT2FIX(0); return INT2FIX(0);
} }
if (base == 0) { if (base <= 0) {
if (str[0] == '0') { if (str[0] == '0') {
if (str[1] == 'x' || str[1] == 'X') { if (str[1] == 'x' || str[1] == 'X') {
base = 16; base = 16;
@ -225,6 +230,9 @@ rb_cstr2inum(str, base)
base = 8; base = 8;
} }
} }
else if (base < -1) {
base = -base;
}
else { else {
base = 10; base = 10;
} }
@ -290,18 +298,27 @@ rb_cstr2inum(str, base)
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '5': case '6': case '7':
c = c - '0'; c = c - '0';
nondigit = 0;
break; break;
case 'a': case 'b': case 'c': case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f': case 'd': case 'e': case 'f':
if (base != 16) c = base; c -= 'a' - 'A';
else c = c - 'a' + 10;
break;
case 'A': case 'B': case 'C': case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F': case 'D': case 'E': case 'F':
if (base != 16) c = base; if (base != 16) {
else c = c - 'A' + 10; nondigit = c;
c = base;
}
else {
c = c - 'A' + 10;
nondigit = 0;
}
break; break;
case '_': case '_':
if (badcheck) {
if (nondigit) goto bad;
nondigit = c;
}
continue; continue;
default: default:
c = base; c = base;
@ -334,9 +351,10 @@ rb_cstr2inum(str, base)
} }
VALUE VALUE
rb_str2inum(str, base) rb_str_to_inum(str, base, badcheck)
VALUE str; VALUE str;
int base; int base;
int badcheck;
{ {
char *s; char *s;
int len; int len;
@ -351,10 +369,26 @@ rb_str2inum(str, base)
p[len] = '\0'; p[len] = '\0';
s = p; s = p;
} }
if (base == 0 && len != strlen(s)) { if (badcheck && len != strlen(s)) {
rb_raise(rb_eArgError, "string for Integer contains null byte"); 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"; static char hexmap[] = "0123456789abcdef";

View File

@ -61,6 +61,8 @@ VALUE rb_uint2big _((unsigned long));
VALUE rb_int2big _((long)); VALUE rb_int2big _((long));
VALUE rb_uint2inum _((unsigned long)); VALUE rb_uint2inum _((unsigned long));
VALUE rb_int2inum _((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_cstr2inum _((const char*, int));
VALUE rb_str2inum _((VALUE, int)); VALUE rb_str2inum _((VALUE, int));
VALUE rb_big2str _((VALUE, int)); VALUE rb_big2str _((VALUE, int));
@ -263,6 +265,8 @@ VALUE rb_Integer _((VALUE));
VALUE rb_Float _((VALUE)); VALUE rb_Float _((VALUE));
VALUE rb_String _((VALUE)); VALUE rb_String _((VALUE));
VALUE rb_Array _((VALUE)); VALUE rb_Array _((VALUE));
double rb_cstr_to_dbl _((const char *, int));
double rb_str_to_dbl _((VALUE, int));
/* parse.y */ /* parse.y */
EXTERN int ruby_sourceline; EXTERN int ruby_sourceline;
EXTERN char *ruby_sourcefile; EXTERN char *ruby_sourcefile;

134
object.c
View File

@ -945,7 +945,7 @@ rb_Integer(val)
return val; return val;
case T_STRING: case T_STRING:
return rb_str2inum(val, 0); return rb_str_to_inum(val, 0, Qtrue);
case T_FIXNUM: case T_FIXNUM:
return val; return val;
@ -963,6 +963,90 @@ rb_f_integer(obj, arg)
return rb_Integer(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 VALUE
rb_Float(val) rb_Float(val)
VALUE val; VALUE val;
@ -978,53 +1062,7 @@ rb_Float(val)
return rb_float_new(rb_big2dbl(val)); return rb_float_new(rb_big2dbl(val));
case T_STRING: case T_STRING:
{ return rb_float_new(rb_str_to_dbl(val, Qtrue));
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);
}
case T_NIL: case T_NIL:
return rb_float_new(0.0); return rb_float_new(0.0);

View File

@ -3345,7 +3345,7 @@ yylex()
yyerror("hexadecimal number without hex-digits"); yyerror("hexadecimal number without hex-digits");
} }
else if (nondigit) goto trailing_uc; else if (nondigit) goto trailing_uc;
yylval.val = rb_cstr2inum(tok(), 16); yylval.val = rb_cstr_to_inum(tok(), 16, Qfalse);
return tINTEGER; return tINTEGER;
} }
if (c == 'b' || c == 'B') { if (c == 'b' || c == 'B') {
@ -3369,7 +3369,7 @@ yylex()
yyerror("numeric literal without digits"); yyerror("numeric literal without digits");
} }
else if (nondigit) goto trailing_uc; else if (nondigit) goto trailing_uc;
yylval.val = rb_cstr2inum(tok(), 2); yylval.val = rb_cstr_to_inum(tok(), 2, Qfalse);
return tINTEGER; return tINTEGER;
} }
if (c >= '0' && c <= '7' || c == '_') { if (c >= '0' && c <= '7' || c == '_') {
@ -3388,7 +3388,7 @@ yylex()
pushback(c); pushback(c);
tokfix(); tokfix();
if (nondigit) goto trailing_uc; if (nondigit) goto trailing_uc;
yylval.val = rb_cstr2inum(tok(), 8); yylval.val = rb_cstr_to_inum(tok(), 8, Qfalse);
return tINTEGER; return tINTEGER;
} }
} }
@ -3482,7 +3482,7 @@ yylex()
yylval.val = rb_float_new(d); yylval.val = rb_float_new(d);
return tFLOAT; return tFLOAT;
} }
yylval.val = rb_cstr2inum(tok(), 10); yylval.val = rb_cstr_to_inum(tok(), 10, Qfalse);
return tINTEGER; return tINTEGER;
} }

View File

@ -18,10 +18,6 @@
#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */ #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 void fmt_setup _((char*,int,int,int,int));
static char* static char*
@ -397,7 +393,7 @@ rb_f_sprintf(argc, argv)
bignum = 1; bignum = 1;
break; break;
case T_STRING: case T_STRING:
val = rb_str2inum(val, 0); val = rb_str_to_inum(val, 0, Qtrue);
goto bin_retry; goto bin_retry;
case T_BIGNUM: case T_BIGNUM:
bignum = 1; bignum = 1;

View File

@ -1766,16 +1766,14 @@ rb_str_to_i(argc, argv, str)
default: default:
rb_raise(rb_eArgError, "illegal radix %d", base); rb_raise(rb_eArgError, "illegal radix %d", base);
} }
return rb_str2inum(str, base); return rb_str_to_inum(str, base, Qfalse);
} }
static VALUE static VALUE
rb_str_to_f(str) rb_str_to_f(str)
VALUE str; VALUE str;
{ {
double f = strtod(RSTRING(str)->ptr, 0); return rb_float_new(rb_str_to_dbl(str, Qfalse));
return rb_float_new(f);
} }
static VALUE static VALUE
@ -2963,28 +2961,14 @@ static VALUE
rb_str_hex(str) rb_str_hex(str)
VALUE str; VALUE str;
{ {
return rb_str2inum(str, 16); return rb_str_to_inum(str, 16, Qfalse);
} }
static VALUE static VALUE
rb_str_oct(str) rb_str_oct(str)
VALUE str; VALUE str;
{ {
int base = 8; return rb_str_to_inum(str, -8, Qfalse);
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);
} }
static VALUE static VALUE

2
time.c
View File

@ -218,7 +218,7 @@ obj2long(obj)
VALUE obj; VALUE obj;
{ {
if (TYPE(obj) == T_STRING) { if (TYPE(obj) == T_STRING) {
obj = rb_str2inum(obj, 10); obj = rb_str_to_inum(obj, 10, Qfalse);
} }
return NUM2LONG(obj); return NUM2LONG(obj);