This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
[RFA] Add new function strtoull()
- To: <newlib at sources dot redhat dot com>
- Subject: [RFA] Add new function strtoull()
- From: "John R. Moore" <jmoore at redhat dot com>
- Date: Thu, 19 Apr 2001 11:53:43 -0700 (PDT)
For 64-bit architectures, gdbtk needs a function exactly
like strtoul(), but that extends "unsigned long" to
be "unsigned long long". I'm proposing strtoull to be added
to newlib/libc/stdlib/strtoul.c since it mimics strtoul.
The following code has been tested using gcc-2.97 on linux-2.4.2 kernel:
2001-04-19 John R. Moore <jmoore@redhat.com>
* newlib/libc/stdlib/strtoul.c: Added new strtoull() and
_strtoull_r.
Index: newlib/libc/stdlib/strtoul.c
===================================================================
RCS file: /cvs/cvsfiles/devo/newlib/libc/stdlib/strtoul.c,v
retrieving revision 1.13
diff -p -u -r1.13 strtoul.c
--- newlib/libc/stdlib/strtoul.c 2000/04/17 17:11:23 1.13
+++ newlib/libc/stdlib/strtoul.c 2001/04/19 18:49:43
@@ -204,3 +204,83 @@ _DEFUN (strtoul, (s, ptr, base),
}
#endif
+
+/*
+ * Convert a string to an unsigned long long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long long
+_DEFUN (_strtoull_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST char *nptr _AND
+ char **endptr _AND
+ int base)
+{
+ register const char *s = nptr;
+ register unsigned long long acc;
+ register int c;
+ register unsigned long long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base;
+ cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_LONG_MAX;
+ rptr->_errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+}
+
+#ifndef _REENT_ONLY
+
+unsigned long long
+_DEFUN (strtoull, (s, ptr, base),
+ _CONST char *s _AND
+ char **ptr _AND
+ int base)
+{
+ return _strtoull_r (_REENT, s, ptr, base);
+}
+
+#endif