summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-02-01 10:23:22 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-02-01 10:23:22 +0000
commitc2269d5b4f60829a523f3479492267ef99e1c5fb (patch)
tree1b0a0b035dbca831b168c86d833de524b5cf7848
parentd9b49e39b2f3380cb6c4bb68a175a230c4702b58 (diff)
* 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
-rw-r--r--ChangeLog36
-rw-r--r--bignum.c60
-rw-r--r--intern.h4
-rw-r--r--object.c134
-rw-r--r--parse.y8
-rw-r--r--sprintf.c6
-rw-r--r--string.c24
-rw-r--r--time.c2
8 files changed, 183 insertions, 91 deletions
diff --git a/ChangeLog b/ChangeLog
index 100d46c..b138cdc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* regex.c (mbc_startpos): become macro.
diff --git a/bignum.c b/bignum.c
index f4add5f..173c8fb 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 f3c6b62..d41086d 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 f455813..35517e9 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 481927e..0081e9f 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 fe53d6b..2355a65 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 87411a5..25fd851 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 c4c3da9..32b9f11 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);