This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[RFA] Add new function strtoull()



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]