This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
Re: [RFA] Add new function strtoull()
- To: "John R. Moore" <jmoore at redhat dot com>
- Subject: Re: [RFA] Add new function strtoull()
- From: "J. Johnston" <jjohnstn at cygnus dot com>
- Date: Thu, 19 Apr 2001 17:36:22 -0400
- CC: newlib at sources dot redhat dot com
- Organization: Red Hat Inc.
- References: <Pine.LNX.4.33.0104191130060.10922-100000@bosch.cygnus.com>
"John R. Moore" wrote:
>
> 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.
>
Thanks John. I am going to make a change though. The code should sit
in its own file to prevent excessive code bloat to an application that
needs strtoul.
-- Jeff J.
> 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