summaryrefslogtreecommitdiff
path: root/util.c
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 /util.c
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
Diffstat (limited to 'util.c')
-rw-r--r--util.c111
1 files changed, 111 insertions, 0 deletions
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