This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH] strtoll and strtoull in libiberty (fix: libstdc++/5611)
- From: Douglas Gregor <gregod at cs dot rpi dot edu>
- To: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Fri, 15 Mar 2002 14:48:12 -0500
- Subject: [PATCH] strtoll and strtoull in libiberty (fix: libstdc++/5611)
- Organization: Rensselaer Polytechnic Institute
- Reply-to: gregod at cs dot rpi dot edu
The attached patch (against the mainline) is a revised version of the one
posted in
http://gcc.gnu.org/ml/libstdc++/2002-02/msg00169.html
It fixes libstdc++/5611 and should also fix the unresolved symbol problems on
HP-UX reported here:
http://gcc.gnu.org/ml/gcc-patches/2002-02/msg01491.html
Tested on i386-unknown-freebsd3.4 (which needs strtoll/strtoull from
libiberty) and i686-pc-linux-gnu/glibc 2.2.4 (which doesn't need
strtoll/strotoull from libiberty); bootstrap ok, no new regressions.
Changelog entries:
in libiberty:
strtoll.c: New file
strtoull.c: Likewise
Makefile.in: Add strtoll and strtoull
configure.in: Likewise
in libstdc++-v3:
acconfig.h: Add _GLIBCPP_USE_LIBIBERTY_STRTOLL
acinclude.m4: Determine if libiberty is needed based on strtoll/strotoull
configure.in: Add GLIBCPP_NEED_LIBIBERTY
config/locale/generic/c_locale.cc: Add prototypes for strtoll/strotoull
when not supplied by native C library
src/Makefile.am: Link with libiberty when required
Doug Gregor
gregod@cs.rpi.edu
*** /dev/null Sun Nov 11 09:22:38 2001
--- libiberty/strtoll.c Thu Mar 14 11:26:11 2002
***************
*** 0 ****
--- 1,155 ----
+ /*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [rescinded 22 July 1999]
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ #ifdef HAVE_LIMITS_H
+ #include <limits.h>
+ #endif
+ #ifdef HAVE_SYS_PARAM_H
+ #include <sys/param.h>
+ #endif
+ #include <errno.h>
+ #ifdef NEED_DECLARATION_ERRNO
+ extern int errno;
+ #endif
+ #include "safe-ctype.h"
+
+ /* FIXME: It'd be nice to configure around these, but the include files are too
+ painful. These macros should at least be more portable than hardwired hex
+ constants. */
+
+ #ifndef ULONG_LONG_MAX
+ #define ULONG_LONG_MAX ((unsigned long long)(~0LL))
+ #endif
+
+ #ifndef LONG_LONG_MAX
+ #define LONG_LONG_MAX ((long long)(ULONG_LONG_MAX >> 1))
+ #endif
+
+ #ifndef LONG_LONG_MIN
+ #define LONG_LONG_MIN ((long long)(~LONG_LONG_MAX))
+ #endif
+
+ /*
+ * Convert a string to a long long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+ long long
+ strtoll (nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register 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;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ 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;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for long longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long long) LONG_LONG_MIN : LONG_LONG_MAX;
+ cutlim = cutoff % (unsigned long long) base;
+ cutoff /= (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 = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
+ errno = ERANGE;
+ }
+ else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+ }
*** /dev/null Sun Nov 11 09:22:38 2001
--- libiberty/strtoull.c Thu Mar 14 11:26:11 2002
***************
*** 0 ****
--- 1,126 ----
+ /*
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [rescinded 22 July 1999]
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ #ifdef HAVE_LIMITS_H
+ #include <limits.h>
+ #endif
+ #ifdef HAVE_SYS_PARAM_H
+ #include <sys/param.h>
+ #endif
+ #include <errno.h>
+ #ifdef NEED_DECLARATION_ERRNO
+ extern int errno;
+ #endif
+ #if 0
+ #include <stdlib.h>
+ #endif
+ #include "ansidecl.h"
+ #include "safe-ctype.h"
+
+ #ifndef ULONG_LONG_MAX
+ #define ULONG_LONG_MAX ((unsigned long long)(~0LL))
+ #endif
+
+ /*
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+ unsigned long long
+ strtoull (nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register 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 strtoll 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;
+ errno = ERANGE;
+ }
+ else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+ }
Index: libiberty/Makefile.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/Makefile.in,v
retrieving revision 1.74
diff -r1.74 Makefile.in
143c143
< strtod.c strtol.c strtoul.c \
---
> strtod.c strtol.c strtoll.c strtoul.c strtoull.c \
182c182
< strtoul.o \
---
> strtoul.o strtoll.o strtoull.o \
284c284,285
< strerror strncmp strrchr strstr strtol strtoul tmpnam vfprintf vprintf \
---
> strerror strncmp strrchr strstr strtol strtoul strtoll strtoull \
> stmpnam vfprintf vprintf \
466a468
> strtoll.o: config.h $(INCDIR)/safe-ctype.h
467a470
> strtoull.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h
Index: libiberty/configure.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/configure.in,v
retrieving revision 1.47
diff -r1.47 configure.in
173a174,175
> funcs="$funcs strtoll"
> funcs="$funcs strtoull"
194c196,197
< AC_CHECK_FUNCS(strtod strtol strtoul tmpnam vasprintf vfprintf vprintf)
---
> AC_CHECK_FUNCS(strtod strtol strtoul strtoll strtoull)
> AC_CHECK_FUNCS(tmpnam vasprintf vfprintf vprintf)
Index: libstdc++-v3/acconfig.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/acconfig.h,v
retrieving revision 1.25
diff -r1.25 acconfig.h
21a22,24
> // Use strtoll and strtoull from libiberty
> #undef _GLIBCPP_USE_LIBIBERTY_STRTOLL
>
Index: libstdc++-v3/acinclude.m4
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/acinclude.m4,v
retrieving revision 1.198
diff -r1.198 acinclude.m4
1581,1582c1581,1584
< AC_MSG_CHECKING([for enabled long long I/O support])
< # iostreams require strtoll, strtoull to compile
---
> AC_MSG_CHECKING([for native long long I/O support])
> # iostreams require strtoll, strtoull to compile. determine if we have
> # native versions, or if we need to use libiberty
> native_long_long=yes ;
1584c1586
< [char* tmp; strtoll("gnu", &tmp, 10);],,[enable_long_long=no])
---
> [char* tmp; strtoll("gnu", &tmp, 10);],,[native_long_long=no])
1586c1588,1593
< [char* tmp; strtoull("gnu", &tmp, 10);],,[enable_long_long=no])
---
> [char* tmp; strtoull("gnu", &tmp, 10);],,[native_long_long=no])
>
> if test x"$native_long_long" = xno; then
> AC_DEFINE(_GLIBCPP_USE_LIBIBERTY_STRTOLL)
> need_libiberty=yes;
> fi
1592c1599
< AC_MSG_RESULT($enable_long_long)
---
> AC_MSG_RESULT($native_long_long)
Index: libstdc++-v3/configure.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/configure.in,v
retrieving revision 1.84
diff -r1.84 configure.in
15a16
>
40a42
> need_libiberty=no
305a308,309
>
> AM_CONDITIONAL(GLIBCPP_NEED_LIBIBERTY, test "$need_libiberty" = yes)
Index: libstdc++-v3/config/locale/generic/c_locale.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/config/locale/generic/c_locale.cc,v
retrieving revision 1.1
diff -r1.1 c_locale.cc
79a80,84
> # ifdef _GLIBCPP_USE_LIBIBERTY_STRTOLL
> extern "C" long long strtoll(const char*, char**, int);
> extern "C" unsigned long long strtoull(const char*, char**, int);
> # endif
>
Index: libstdc++-v3/src/Makefile.am
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/Makefile.am,v
retrieving revision 1.104
diff -r1.104 Makefile.am
25c25
< AUTOMAKE_OPTIONS = 1.3 gnits
---
> AUTOMAKE_OPTIONS = 1.3 gnits
29a30,37
> if GLIBCPP_NEED_LIBIBERTY
> LIBIBERTY = -L../../libiberty -liberty
> else
> LIBIBERTY =
> endif
>
> LIBS = $(LIBIBERTY)
>
147a156
>