gcc/libiberty/strtol.c

166 lines
5.3 KiB
C
Raw Normal View History

1997-08-22 06:57:35 +08:00
/*-
* 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]
1997-08-22 06:57:35 +08:00
* 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.
*/
/*
@deftypefn Supplemental {long int} strtol (const char *@var{string}, @
char **@var{endptr}, int @var{base})
@deftypefnx Supplemental {unsigned long int} strtoul (const char *@var{string}, @
char **@var{endptr}, int @var{base})
The @code{strtol} function converts the string in @var{string} to a
long integer value according to the given @var{base}, which must be
between 2 and 36 inclusive, or be the special value 0. If @var{base}
is 0, @code{strtol} will look for the prefixes @code{0} and @code{0x}
to indicate bases 8 and 16, respectively, else default to base 10.
When the base is 16 (either explicitly or implicitly), a prefix of
@code{0x} is allowed. The handling of @var{endptr} is as that of
@code{strtod} above. The @code{strtoul} function is the same, except
that the converted value is unsigned.
@end deftypefn
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_LIMITS_H
1997-08-22 06:57:35 +08:00
#include <limits.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
1997-08-22 06:57:35 +08:00
#include <errno.h>
#ifdef NEED_DECLARATION_ERRNO
extern int errno;
#endif
safe-ctype.h: New file. include: * safe-ctype.h: New file. libiberty: * safe-ctype.c: New file. * Makefile.in (CFILES): Add safe-ctype.c. (REQUIRED_OFILES): Add safe-ctype.o. * argv.c: Define ISBLANK and use it, not isspace. * basename.c, cplus-dem.c, fnmatch.c, pexecute.c, strtod.c, strtol.c, strtoul.c: Include safe-ctype.h, not ctype.h. Use uppercase ctype macros. Don't test ISUPPER(c)/ISLOWER(c) before calling TOLOWER(c)/TOUPPER(c). gcc: * Makefile.in (HOST_RTL): Add safe-ctype.o. (safe-ctype.o): New rule. * system.h: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. * cpphash.h: Zap IStable and related macros. Define is_* in terms of safe-ctype.h macros. * cppinit.c: Delete the IStable and all related code. * tradcpp.c: Delete is_idchar, is_idstart, is_hor_space, and is_space arrays. Delete initialize_char_syntax. Change all references to the above arrays to use macros instead. * tradcpp.h: Define is_idchar, is_idstart, is_space, and is_nvspace in terms of safe_ctype.h's macros. * tradcif.y: is_idchar, is_idstart are macros not arrays. * config/i370/i370.c, config/winnt/dirent.c, config/winnt/fixinc-nt.c, config/winnt/ld.c: Use uppercase ctype macros. If we included ctype.h, include safe-ctype.h instead. * fixinc/fixfixes.c: Use uppercase ctype macros. Don't test ISLOWER(c) before calling TOUPPER(c). * fixinc/fixincl.c (extract_quoted_files): Simplify out some gunk. * fixinc/gnu-regex.c: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. Don't test ISUPPER(x) before calling TOLOWER(x). gcc/ch: * lex.c: Don't bother checking whether ISUPPER(c) before calling TOLOWER(c). Don't bother checking whether isascii(c) before testing ISSPACE(c); ISSPACE(c) includes '\n'. gcc/f: * Make-lang.in: Link f/fini with safe-ctype.o. * bad.c: Don't test ISUPPER(c) || ISLOWER(c) before calling TOUPPER(c). * com.c: Use TOUPPER, not ffesrc_toupper. * fini.c: Don't test ISALPHA(c) before calling TOUPPER(c)/TOLOWER(c). * intrin.c: Don't test IN_CTYPE_DOMAIN(c). * src.c: Delete ffesrc_toupper_ and ffesrc_tolower_ and their initializing code; use TOUPPER and TOLOWER instead of ffesrc_toupper and ffesrc_tolower. * src.h: Don't declare ffesrc_toupper_ or ffesrc_tolower_. Don't define ffesrc_toupper or ffesrc_tolower. gcc/java: * jvgenmain.c: Use ISPRINT not isascii. From-SVN: r38124
2000-12-08 11:00:26 +08:00
#include "safe-ctype.h"
1997-08-22 06:57:35 +08:00
/* 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_MAX
#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
#endif
#ifndef LONG_MAX
#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF */
#endif
#ifndef LONG_MIN
#define LONG_MIN ((long)(~LONG_MAX)) /* 0x80000000 */
#endif
/*
* Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
ternary.h: Don't use PARAMS anymore. include/ 2005-03-27 Gabriel Dos Reis <gdr@integreable-solutions.net> * ternary.h: Don't use PARAMS anymore. libiberty/ 2005-03-27 Gabriel Dos Reis <gdr@integrable-solutions.net> Convert libiberty to use ISO C prototype style 6/n. * strerror.c (init_error_tables, errno_max, strerror, strerrno, strtoerrno, main): Use ISO C prototype style. * strncasecmp.c (strncasecmp): Likewise. * strncmp.c (strncmp): Likewise. * strndup.c (strndup): Likewise. * strrchr.c (strrchr): Likewise. * strsignal.c (init_signal_tables, signo_max, strsignal, strsigno, strtosigno, psignal, main): Likewise. * strstr.c (strstr): Likewise. * strtod.c (strtod, atof): Likewise. * strtol.c (strtol): Likewise. * strtoul.c (strtoul): Likewise. * ternary.c (ternary_insert, ternary_cleanup, ternary_search, ternary_recursivesearch): Likewise. * tmpnam.c (tmpnam): Likewise. * unlink-if-ordinary.c (unlink_if_ordinary): Likewise. * vasprintf.c (int_vasprintf, vasprintf, checkit, main): Likewise. * vfork.c (vfork): Likewise. * vfprintf.c (vfprintf): Likewise. * vprintf.c (vprintf): Likewise. * vsnprintf.c (vsnprintf, checkit, main): Likewise. * vsprintf.c (vsprintf): Likewise. * waitpid.c (waitpid): Likewise. * xatexit.c (xatexit, xatexit_cleanup): Likewise. * xexit.c (xexit): Likewise. * xmalloc.c (xmalloc_set_program_name, xmalloc_failed, xmalloc, xcalloc, xrealloc): Likewise. * xmemdup.c (xmemdup): Likewise. * xstrdup.c (xstrdup): Likewise. * xstrerror.c (xstrerror): Likewise. * xstrndup.c (xstrndup): Likewise. From-SVN: r97122
2005-03-28 09:28:01 +08:00
strtol(const char *nptr, char **endptr, register int base)
1997-08-22 06:57:35 +08:00
{
register const char *s = nptr;
1997-08-22 06:57:35 +08:00
register unsigned long acc;
register int c;
register unsigned 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++;
safe-ctype.h: New file. include: * safe-ctype.h: New file. libiberty: * safe-ctype.c: New file. * Makefile.in (CFILES): Add safe-ctype.c. (REQUIRED_OFILES): Add safe-ctype.o. * argv.c: Define ISBLANK and use it, not isspace. * basename.c, cplus-dem.c, fnmatch.c, pexecute.c, strtod.c, strtol.c, strtoul.c: Include safe-ctype.h, not ctype.h. Use uppercase ctype macros. Don't test ISUPPER(c)/ISLOWER(c) before calling TOLOWER(c)/TOUPPER(c). gcc: * Makefile.in (HOST_RTL): Add safe-ctype.o. (safe-ctype.o): New rule. * system.h: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. * cpphash.h: Zap IStable and related macros. Define is_* in terms of safe-ctype.h macros. * cppinit.c: Delete the IStable and all related code. * tradcpp.c: Delete is_idchar, is_idstart, is_hor_space, and is_space arrays. Delete initialize_char_syntax. Change all references to the above arrays to use macros instead. * tradcpp.h: Define is_idchar, is_idstart, is_space, and is_nvspace in terms of safe_ctype.h's macros. * tradcif.y: is_idchar, is_idstart are macros not arrays. * config/i370/i370.c, config/winnt/dirent.c, config/winnt/fixinc-nt.c, config/winnt/ld.c: Use uppercase ctype macros. If we included ctype.h, include safe-ctype.h instead. * fixinc/fixfixes.c: Use uppercase ctype macros. Don't test ISLOWER(c) before calling TOUPPER(c). * fixinc/fixincl.c (extract_quoted_files): Simplify out some gunk. * fixinc/gnu-regex.c: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. Don't test ISUPPER(x) before calling TOLOWER(x). gcc/ch: * lex.c: Don't bother checking whether ISUPPER(c) before calling TOLOWER(c). Don't bother checking whether isascii(c) before testing ISSPACE(c); ISSPACE(c) includes '\n'. gcc/f: * Make-lang.in: Link f/fini with safe-ctype.o. * bad.c: Don't test ISUPPER(c) || ISLOWER(c) before calling TOUPPER(c). * com.c: Use TOUPPER, not ffesrc_toupper. * fini.c: Don't test ISALPHA(c) before calling TOUPPER(c)/TOLOWER(c). * intrin.c: Don't test IN_CTYPE_DOMAIN(c). * src.c: Delete ffesrc_toupper_ and ffesrc_tolower_ and their initializing code; use TOUPPER and TOLOWER instead of ffesrc_toupper and ffesrc_tolower. * src.h: Don't declare ffesrc_toupper_ or ffesrc_tolower_. Don't define ffesrc_toupper or ffesrc_tolower. gcc/java: * jvgenmain.c: Use ISPRINT not isascii. From-SVN: r38124
2000-12-08 11:00:26 +08:00
} while (ISSPACE(c));
1997-08-22 06:57:35 +08:00
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 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_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
safe-ctype.h: New file. include: * safe-ctype.h: New file. libiberty: * safe-ctype.c: New file. * Makefile.in (CFILES): Add safe-ctype.c. (REQUIRED_OFILES): Add safe-ctype.o. * argv.c: Define ISBLANK and use it, not isspace. * basename.c, cplus-dem.c, fnmatch.c, pexecute.c, strtod.c, strtol.c, strtoul.c: Include safe-ctype.h, not ctype.h. Use uppercase ctype macros. Don't test ISUPPER(c)/ISLOWER(c) before calling TOLOWER(c)/TOUPPER(c). gcc: * Makefile.in (HOST_RTL): Add safe-ctype.o. (safe-ctype.o): New rule. * system.h: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. * cpphash.h: Zap IStable and related macros. Define is_* in terms of safe-ctype.h macros. * cppinit.c: Delete the IStable and all related code. * tradcpp.c: Delete is_idchar, is_idstart, is_hor_space, and is_space arrays. Delete initialize_char_syntax. Change all references to the above arrays to use macros instead. * tradcpp.h: Define is_idchar, is_idstart, is_space, and is_nvspace in terms of safe_ctype.h's macros. * tradcif.y: is_idchar, is_idstart are macros not arrays. * config/i370/i370.c, config/winnt/dirent.c, config/winnt/fixinc-nt.c, config/winnt/ld.c: Use uppercase ctype macros. If we included ctype.h, include safe-ctype.h instead. * fixinc/fixfixes.c: Use uppercase ctype macros. Don't test ISLOWER(c) before calling TOUPPER(c). * fixinc/fixincl.c (extract_quoted_files): Simplify out some gunk. * fixinc/gnu-regex.c: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. Don't test ISUPPER(x) before calling TOLOWER(x). gcc/ch: * lex.c: Don't bother checking whether ISUPPER(c) before calling TOLOWER(c). Don't bother checking whether isascii(c) before testing ISSPACE(c); ISSPACE(c) includes '\n'. gcc/f: * Make-lang.in: Link f/fini with safe-ctype.o. * bad.c: Don't test ISUPPER(c) || ISLOWER(c) before calling TOUPPER(c). * com.c: Use TOUPPER, not ffesrc_toupper. * fini.c: Don't test ISALPHA(c) before calling TOUPPER(c)/TOLOWER(c). * intrin.c: Don't test IN_CTYPE_DOMAIN(c). * src.c: Delete ffesrc_toupper_ and ffesrc_tolower_ and their initializing code; use TOUPPER and TOLOWER instead of ffesrc_toupper and ffesrc_tolower. * src.h: Don't declare ffesrc_toupper_ or ffesrc_tolower_. Don't define ffesrc_toupper or ffesrc_tolower. gcc/java: * jvgenmain.c: Use ISPRINT not isascii. From-SVN: r38124
2000-12-08 11:00:26 +08:00
if (ISDIGIT(c))
1997-08-22 06:57:35 +08:00
c -= '0';
safe-ctype.h: New file. include: * safe-ctype.h: New file. libiberty: * safe-ctype.c: New file. * Makefile.in (CFILES): Add safe-ctype.c. (REQUIRED_OFILES): Add safe-ctype.o. * argv.c: Define ISBLANK and use it, not isspace. * basename.c, cplus-dem.c, fnmatch.c, pexecute.c, strtod.c, strtol.c, strtoul.c: Include safe-ctype.h, not ctype.h. Use uppercase ctype macros. Don't test ISUPPER(c)/ISLOWER(c) before calling TOLOWER(c)/TOUPPER(c). gcc: * Makefile.in (HOST_RTL): Add safe-ctype.o. (safe-ctype.o): New rule. * system.h: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. * cpphash.h: Zap IStable and related macros. Define is_* in terms of safe-ctype.h macros. * cppinit.c: Delete the IStable and all related code. * tradcpp.c: Delete is_idchar, is_idstart, is_hor_space, and is_space arrays. Delete initialize_char_syntax. Change all references to the above arrays to use macros instead. * tradcpp.h: Define is_idchar, is_idstart, is_space, and is_nvspace in terms of safe_ctype.h's macros. * tradcif.y: is_idchar, is_idstart are macros not arrays. * config/i370/i370.c, config/winnt/dirent.c, config/winnt/fixinc-nt.c, config/winnt/ld.c: Use uppercase ctype macros. If we included ctype.h, include safe-ctype.h instead. * fixinc/fixfixes.c: Use uppercase ctype macros. Don't test ISLOWER(c) before calling TOUPPER(c). * fixinc/fixincl.c (extract_quoted_files): Simplify out some gunk. * fixinc/gnu-regex.c: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. Don't test ISUPPER(x) before calling TOLOWER(x). gcc/ch: * lex.c: Don't bother checking whether ISUPPER(c) before calling TOLOWER(c). Don't bother checking whether isascii(c) before testing ISSPACE(c); ISSPACE(c) includes '\n'. gcc/f: * Make-lang.in: Link f/fini with safe-ctype.o. * bad.c: Don't test ISUPPER(c) || ISLOWER(c) before calling TOUPPER(c). * com.c: Use TOUPPER, not ffesrc_toupper. * fini.c: Don't test ISALPHA(c) before calling TOUPPER(c)/TOLOWER(c). * intrin.c: Don't test IN_CTYPE_DOMAIN(c). * src.c: Delete ffesrc_toupper_ and ffesrc_tolower_ and their initializing code; use TOUPPER and TOLOWER instead of ffesrc_toupper and ffesrc_tolower. * src.h: Don't declare ffesrc_toupper_ or ffesrc_tolower_. Don't define ffesrc_toupper or ffesrc_tolower. gcc/java: * jvgenmain.c: Use ISPRINT not isascii. From-SVN: r38124
2000-12-08 11:00:26 +08:00
else if (ISALPHA(c))
c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10;
1997-08-22 06:57:35 +08:00
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
1997-08-22 06:57:35 +08:00
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}