source: branches/libc-0.6/src/binutils/libiberty/strtol.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 5.3 KB
Line 
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. [rescinded 22 July 1999]
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32
33@deftypefn Supplemental {long int} strtol (const char *@var{string}, char **@var{endptr}, int @var{base})
34@deftypefnx Supplemental {unsigned long int} strtoul (const char *@var{string}, char **@var{endptr}, int @var{base})
35
36The @code{strtol} function converts the string in @var{string} to a
37long integer value according to the given @var{base}, which must be
38between 2 and 36 inclusive, or be the special value 0. If @var{base}
39is 0, @code{strtol} will look for the prefixes @code{0} and @code{0x}
40to indicate bases 8 and 16, respectively, else default to base 10.
41When the base is 16 (either explicitly or implicitly), a prefix of
42@code{0x} is allowed. The handling of @var{endptr} is as that of
43@code{strtod} above. The @code{strtoul} function is the same, except
44that the converted value is unsigned.
45
46@end deftypefn
47
48*/
49
50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
53#ifdef HAVE_LIMITS_H
54#include <limits.h>
55#endif
56#ifdef HAVE_SYS_PARAM_H
57#include <sys/param.h>
58#endif
59#include <errno.h>
60#ifdef NEED_DECLARATION_ERRNO
61extern int errno;
62#endif
63#include "safe-ctype.h"
64
65/* FIXME: It'd be nice to configure around these, but the include files are too
66 painful. These macros should at least be more portable than hardwired hex
67 constants. */
68
69#ifndef ULONG_MAX
70#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
71#endif
72
73#ifndef LONG_MAX
74#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF */
75#endif
76
77#ifndef LONG_MIN
78#define LONG_MIN ((long)(~LONG_MAX)) /* 0x80000000 */
79#endif
80
81/*
82 * Convert a string to a long integer.
83 *
84 * Ignores `locale' stuff. Assumes that the upper and lower case
85 * alphabets and digits are each contiguous.
86 */
87long
88strtol(nptr, endptr, base)
89 const char *nptr;
90 char **endptr;
91 register int base;
92{
93 register const char *s = nptr;
94 register unsigned long acc;
95 register int c;
96 register unsigned long cutoff;
97 register int neg = 0, any, cutlim;
98
99 /*
100 * Skip white space and pick up leading +/- sign if any.
101 * If base is 0, allow 0x for hex and 0 for octal, else
102 * assume decimal; if base is already 16, allow 0x.
103 */
104 do {
105 c = *s++;
106 } while (ISSPACE(c));
107 if (c == '-') {
108 neg = 1;
109 c = *s++;
110 } else if (c == '+')
111 c = *s++;
112 if ((base == 0 || base == 16) &&
113 c == '0' && (*s == 'x' || *s == 'X')) {
114 c = s[1];
115 s += 2;
116 base = 16;
117 }
118 if (base == 0)
119 base = c == '0' ? 8 : 10;
120
121 /*
122 * Compute the cutoff value between legal numbers and illegal
123 * numbers. That is the largest legal value, divided by the
124 * base. An input number that is greater than this value, if
125 * followed by a legal input character, is too big. One that
126 * is equal to this value may be valid or not; the limit
127 * between valid and invalid numbers is then based on the last
128 * digit. For instance, if the range for longs is
129 * [-2147483648..2147483647] and the input base is 10,
130 * cutoff will be set to 214748364 and cutlim to either
131 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
132 * a value > 214748364, or equal but the next digit is > 7 (or 8),
133 * the number is too big, and we will return a range error.
134 *
135 * Set any if any `digits' consumed; make it negative to indicate
136 * overflow.
137 */
138 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
139 cutlim = cutoff % (unsigned long)base;
140 cutoff /= (unsigned long)base;
141 for (acc = 0, any = 0;; c = *s++) {
142 if (ISDIGIT(c))
143 c -= '0';
144 else if (ISALPHA(c))
145 c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10;
146 else
147 break;
148 if (c >= base)
149 break;
150 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
151 any = -1;
152 else {
153 any = 1;
154 acc *= base;
155 acc += c;
156 }
157 }
158 if (any < 0) {
159 acc = neg ? LONG_MIN : LONG_MAX;
160 errno = ERANGE;
161 } else if (neg)
162 acc = -acc;
163 if (endptr != 0)
164 *endptr = (char *) (any ? s - 1 : nptr);
165 return (acc);
166}
Note: See TracBrowser for help on using the repository browser.