summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-01-02 06:24:27 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-01-02 06:24:27 +0000
commit0352d32f05b42bb31fe98e0fa3582ef4e4689e79 (patch)
tree9f6bc245a678bd5c4d451053ab221395692c4d30
parentaac5220c666dcb84db1c39247aaf0fd394869b89 (diff)
* util.c (ruby_strtoul): locale independent strtoul is implemented to
avoid "i".to_i(36) cause 0 under tr_TR locale. This is newly implemented, not a copy of missing/strtoul.c. * include/ruby/ruby.h (ruby_strtoul): declared. (STRTOUL): defined to use ruby_strtoul. * bignum.c, pack.c, ext/socket/socket.c: use STRTOUL. * configure.in (strtoul): don't check. * missing/strtoul.c: removed. * include/ruby/missing.h (strtoul): removed. * common.mk (strtoul.o): removed. * LEGAL (missing/strtoul.c): removed. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog21
-rw-r--r--LEGAL16
-rw-r--r--bignum.c3
-rw-r--r--common.mk1
-rw-r--r--configure.in2
-rw-r--r--ext/socket/socket.c4
-rw-r--r--include/ruby/missing.h4
-rw-r--r--include/ruby/ruby.h3
-rw-r--r--missing/strtoul.c184
-rw-r--r--pack.c4
-rw-r--r--util.c111
11 files changed, 142 insertions, 211 deletions
diff --git a/ChangeLog b/ChangeLog
index 1393b5fdb9..22fb6a3bf7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+Wed Jan 2 15:23:15 2008 Tanaka Akira <akr@fsij.org>
+
+ * util.c (ruby_strtoul): locale independent strtoul is implemented to
+ avoid "i".to_i(36) cause 0 under tr_TR locale.
+ This is newly implemented, not a copy of missing/strtoul.c.
+
+ * include/ruby/ruby.h (ruby_strtoul): declared.
+ (STRTOUL): defined to use ruby_strtoul.
+
+ * bignum.c, pack.c, ext/socket/socket.c: use STRTOUL.
+
+ * configure.in (strtoul): don't check.
+
+ * missing/strtoul.c: removed.
+
+ * include/ruby/missing.h (strtoul): removed.
+
+ * common.mk (strtoul.o): removed.
+
+ * LEGAL (missing/strtoul.c): removed.
+
Wed Jan 2 14:41:08 2008 Tanaka Akira <akr@fsij.org>
* common.mk (strcasecmp.o): removed.
diff --git a/LEGAL b/LEGAL
index f882dbd442..b12bf66bfa 100644
--- a/LEGAL
+++ b/LEGAL
@@ -157,22 +157,6 @@ ext/digest/sha1/sha1.[ch]:
These files are all under public domain.
-missing/strtoul.c:
-
- This file will not be used on most platforms depending on how the
- configure script results. In any case you must not receive any fee
- with the file itself.
-
- Copyright 1988 Regents of the University of California
-
- 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.
-
missing/erf.c:
missing/crypt.c:
missing/vsnprintf.c:
diff --git a/bignum.c b/bignum.c
index 160e0f0f6a..64a0344274 100644
--- a/bignum.c
+++ b/bignum.c
@@ -11,6 +11,7 @@
**********************************************************************/
#include "ruby/ruby.h"
+#include "ruby/util.h"
#include <math.h>
#include <float.h>
@@ -483,7 +484,7 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
len *= strlen(str)*sizeof(char);
if (len <= (sizeof(long)*CHAR_BIT)) {
- unsigned long val = strtoul(str, &end, base);
+ unsigned long val = STRTOUL(str, &end, base);
if (str < end && *end == '_') goto bigparse;
if (badcheck) {
diff --git a/common.mk b/common.mk
index 27cbcdc5f2..ea739d96fa 100644
--- a/common.mk
+++ b/common.mk
@@ -394,7 +394,6 @@ strftime.$(OBJEXT): {$(VPATH)}strftime.c
strstr.$(OBJEXT): {$(VPATH)}strstr.c
strtod.$(OBJEXT): {$(VPATH)}strtod.c
strtol.$(OBJEXT): {$(VPATH)}strtol.c
-strtoul.$(OBJEXT): {$(VPATH)}strtoul.c
nt.$(OBJEXT): {$(VPATH)}nt.c
x68.$(OBJEXT): {$(VPATH)}x68.c
os2.$(OBJEXT): {$(VPATH)}os2.c
diff --git a/configure.in b/configure.in
index a3018d6660..1ab21a7354 100644
--- a/configure.in
+++ b/configure.in
@@ -633,7 +633,7 @@ powerpc-darwin*)
esac
AC_FUNC_MEMCMP
AC_REPLACE_FUNCS(dup2 memmove strerror strftime\
- strchr strstr strtoul crypt flock vsnprintf\
+ strchr strstr crypt flock vsnprintf\
isnan finite isinf hypot acosh erf strlcpy strlcat)
AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall chroot fsync getcwd eaccess\
truncate chsize times utimes utimensat fcntl lockf lstat\
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index c7b2c928b6..01294b218f 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -817,7 +817,7 @@ str_isnumber(const char *p)
if (!p || *p == '\0')
return 0;
ep = NULL;
- (void)strtoul(p, &ep, 10);
+ (void)STRTOUL(p, &ep, 10);
if (ep && *ep == '\0')
return 1;
else
@@ -3165,7 +3165,7 @@ sock_s_getservbyname(int argc, VALUE *argv)
char *s = RSTRING_PTR(service);
char *end;
- port = strtoul(s, &end, 0);
+ port = STRTOUL(s, &end, 0);
if (*end != '\0') {
rb_raise(rb_eSocket, "no such service %s/%s", s, RSTRING_PTR(proto));
}
diff --git a/include/ruby/missing.h b/include/ruby/missing.h
index 68cd844080..db32057779 100644
--- a/include/ruby/missing.h
+++ b/include/ruby/missing.h
@@ -133,10 +133,6 @@ extern long strtol(const char *, char **, int);
#endif
*/
-#ifndef HAVE_STRTOUL
-extern unsigned long strtoul(const char *, char **, int);
-#endif
-
#ifndef HAVE_VSNPRINTF
# include <stdarg.h>
extern int snprintf(char *, size_t n, char const *, ...);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 8ce623dfe3..c5184f7ca6 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -986,4 +986,7 @@ int rb_remove_event_hook(rb_event_hook_func_t func);
#define STRCASECMP(s1, s2) (st_strcasecmp(s1, s2))
#define STRNCASECMP(s1, s2, n) (st_strncasecmp(s1, s2, n))
+unsigned long ruby_strtoul(const char *str, char **endptr, int base);
+#define STRTOUL(str, endptr, base) (ruby_strtoul(str, endptr, base))
+
#endif /* RUBY_H */
diff --git a/missing/strtoul.c b/missing/strtoul.c
deleted file mode 100644
index 4f09f899a1..0000000000
--- a/missing/strtoul.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * strtoul.c --
- *
- * Source code for the "strtoul" library procedure.
- *
- * Copyright 1988 Regents of the University of California
- * 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.
- */
-
-#include <ctype.h>
-
-/*
- * The table below is used to convert from ASCII digits to a
- * numerical equivalent. It maps from '0' through 'z' to integers
- * (100 for non-digit characters).
- */
-
-static const char cvtIn[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
- 100, 100, 100, 100, 100, 100, 100, /* punctuation */
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35,
- 100, 100, 100, 100, 100, 100, /* punctuation */
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35};
-
-/*
- *----------------------------------------------------------------------
- *
- * strtoul --
- *
- * Convert an ASCII string into an integer.
- *
- * Results:
- * The return value is the integer equivalent of string. If endPtr
- * is non-NULL, then *endPtr is filled in with the character
- * after the last one that was part of the integer. If string
- * doesn't contain a valid integer value, then zero is returned
- * and *endPtr is set to string.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-unsigned long int
-strtoul(
- const char *string, /* String of ASCII digits, possibly
- * preceded by white space. For bases
- * greater than 10, either lower- or
- * upper-case digits may be used.
- */
- char **endPtr, /* Where to store address of terminating
- * character, or NULL. */
- int base) /* Base for conversion. Must be less
- * than 37. If 0, then the base is chosen
- * from the leading characters of string:
- * "0x" means hex, "0" means octal, anything
- * else means decimal.
- */
-{
- register const char *p;
- register unsigned long int result = 0;
- register unsigned digit;
- int anyDigits = 0;
-
- /*
- * Skip any leading blanks.
- */
-
- p = string;
- while (isspace(*p)) {
- p += 1;
- }
-
- /*
- * If no base was provided, pick one from the leading characters
- * of the string.
- */
-
- if (base == 0)
- {
- if (*p == '0') {
- p += 1;
- if (*p == 'x') {
- p += 1;
- base = 16;
- } else {
-
- /*
- * Must set anyDigits here, otherwise "0" produces a
- * "no digits" error.
- */
-
- anyDigits = 1;
- base = 8;
- }
- }
- else base = 10;
- } else if (base == 16) {
-
- /*
- * Skip a leading "0x" from hex numbers.
- */
-
- if ((p[0] == '0') && (p[1] == 'x')) {
- p += 2;
- }
- }
-
- /*
- * Sorry this code is so messy, but speed seems important. Do
- * different things for base 8, 10, 16, and other.
- */
-
- if (base == 8) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > 7) {
- break;
- }
- result = (result << 3) + digit;
- anyDigits = 1;
- }
- } else if (base == 10) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > 9) {
- break;
- }
- result = (10*result) + digit;
- anyDigits = 1;
- }
- } else if (base == 16) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > ('z' - '0')) {
- break;
- }
- digit = cvtIn[digit];
- if (digit > 15) {
- break;
- }
- result = (result << 4) + digit;
- anyDigits = 1;
- }
- } else {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > ('z' - '0')) {
- break;
- }
- digit = cvtIn[digit];
- if (digit >= base) {
- break;
- }
- result = result*base + digit;
- anyDigits = 1;
- }
- }
-
- /*
- * See if there were any digits at all.
- */
-
- if (!anyDigits) {
- p = string;
- }
-
- if (endPtr != 0) {
- *endPtr = (char *)p;
- }
-
- return result;
-}
diff --git a/pack.c b/pack.c
index 0df3c567ed..5d15a41027 100644
--- a/pack.c
+++ b/pack.c
@@ -492,7 +492,7 @@ pack_pack(VALUE ary, VALUE fmt)
p++;
}
else if (ISDIGIT(*p)) {
- len = strtoul(p, (char**)&p, 10);
+ len = STRTOUL(p, (char**)&p, 10);
}
else {
len = 1;
@@ -1351,7 +1351,7 @@ pack_unpack(VALUE str, VALUE fmt)
p++;
}
else if (ISDIGIT(*p)) {
- len = strtoul(p, (char**)&p, 10);
+ len = STRTOUL(p, (char**)&p, 10);
}
else {
len = (type != '@');
diff --git a/util.c b/util.c
index 992fb831c6..21a2719aa5 100644
--- a/util.c
+++ b/util.c
@@ -63,6 +63,117 @@ ruby_scan_hex(const char *start, int len, int *retlen)
return retval;
}
+static unsigned long
+scan_digits(const char *str, int base, size_t *retlen, int *overflow)
+{
+ static char table[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /*0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*1*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*2*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*3*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
+ /*4*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+ /*5*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
+ /*6*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+ /*7*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
+ /*8*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*9*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*a*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*b*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*c*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*d*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*e*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ /*f*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ };
+
+ const char *start = str;
+ unsigned long ret = 0, x;
+ unsigned long MUL_OVERFLOW = (~(unsigned long)0) / base;
+ int c;
+ *overflow = 0;
+
+ while ((c = (unsigned char)*str++) != '\0') {
+ int d = table[c];
+ if (d == -1 || base <= d) {
+ *retlen = (str-1) - start;
+ return ret;
+ }
+ if (MUL_OVERFLOW < ret)
+ *overflow = 1;
+ ret *= base;
+ x = ret;
+ ret += d;
+ if (ret < x)
+ *overflow = 1;
+ }
+ *retlen = (str-1) - start;
+ return ret;
+}
+
+unsigned long
+ruby_strtoul(const char *str, char **endptr, int base)
+{
+ int c, b, overflow;
+ int sign = 0;
+ size_t len;
+ unsigned long ret;
+
+ if (base == 1 || 36 < base) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ while ((c = *str) && ISSPACE(c))
+ str++;
+
+ if (c == '+') {
+ sign = 1;
+ str++;
+ }
+ else if (c == '-') {
+ sign = -1;
+ str++;
+ }
+
+ if (str[0] == '0') {
+ if (base == 0 || base == 16) {
+ if (str[1] == 'x' || str[1] == 'X') {
+ b = 16;
+ str += 2;
+ }
+ else {
+ b = base == 0 ? 8 : 16;
+ str++;
+ }
+ }
+ else {
+ b = base;
+ str++;
+ }
+ }
+ else {
+ b = base == 0 ? 10 : base;
+ }
+
+ ret = scan_digits(str, b, &len, &overflow);
+
+ if (endptr)
+ *endptr = (char*)(str+len);
+
+ if (overflow) {
+ errno = ERANGE;
+ return ULONG_MAX;
+ }
+
+ if (sign < 0) {
+ ret = -(long)ret;
+ return ret;
+ }
+ else {
+ return ret;
+ }
+}
+
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H