* stdlib/strtol.c [_LIBC]: Define STDC_HEADERS.
[platform/upstream/linaro-glibc.git] / stdlib / strtol.c
1 /* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
2
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #ifdef _LIBC
25 # define USE_NUMBER_GROUPING
26 # define STDC_HEADERS
27 #endif
28
29 #include <ctype.h>
30 #include <errno.h>
31 #include <limits.h>
32
33 #ifdef STDC_HEADERS
34 # include <stddef.h>
35 # include <stdlib.h>
36 #else
37 # ifndef NULL
38 #  define NULL 0
39 # endif
40 #endif
41
42 #ifdef USE_NUMBER_GROUPING
43 # include "../locale/localeinfo.h"
44 #endif
45
46 /* Nonzero if we are defining `strtoul' or `strtouq', operating on
47    unsigned integers.  */
48 #ifndef UNSIGNED
49 # define UNSIGNED 0
50 # define INT LONG int
51 #else
52 # define strtol strtoul
53 # define INT unsigned LONG int
54 #endif
55
56 /* If QUAD is defined, we are defining `strtoq' or `strtouq',
57    operating on `long long int's.  */
58 #ifdef QUAD
59 # if UNSIGNED
60 #  define strtoul strtouq
61 # else
62 #  define strtol strtoq
63 # endif
64 # define LONG long long
65 # undef LONG_MIN
66 # define LONG_MIN LONG_LONG_MIN
67 # undef LONG_MAX
68 # define LONG_MAX LONG_LONG_MAX
69 # undef ULONG_MAX
70 # define ULONG_MAX ULONG_LONG_MAX
71 # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
72    /* Work around gcc bug with using this constant.  */
73    static const unsigned long long int maxquad = ULONG_LONG_MAX;
74 #  undef ULONG_MAX
75 #  define ULONG_MAX maxquad
76 # endif
77 #else
78 # define LONG long
79 #endif
80
81 #ifdef __STDC__
82 # define INTERNAL(x) INTERNAL1(x)
83 # define INTERNAL1(x) __##x##_internal
84 #else
85 # define INTERNAL(x) __/**/x/**/_internal
86 #endif
87
88 #ifdef USE_NUMBER_GROUPING
89 /* This file defines a function to check for correct grouping.  */
90 # include "grouping.h"
91 #endif
92
93
94 /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
95    If BASE is 0 the base is determined by the presence of a leading
96    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
97    If BASE is < 2 or > 36, it is reset to 10.
98    If ENDPTR is not NULL, a pointer to the character after the last
99    one converted is stored in *ENDPTR.  */
100
101 INT
102 INTERNAL (strtol) (nptr, endptr, base, group)
103      const char *nptr;
104      char **endptr;
105      int base;
106      int group;
107 {
108   int negative;
109   register unsigned LONG int cutoff;
110   register unsigned int cutlim;
111   register unsigned LONG int i;
112   register const char *s;
113   register unsigned char c;
114   const char *save, *end;
115   int overflow;
116
117 #ifdef USE_NUMBER_GROUPING
118   /* The thousands character of the current locale.  */
119   wchar_t thousands;
120   /* The numeric grouping specification of the current locale,
121      in the format described in <locale.h>.  */
122   const char *grouping;
123
124   if (group)
125     {
126       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
127       if (*grouping <= 0 || *grouping == CHAR_MAX)
128         grouping = NULL;
129       else
130         {
131           /* Figure out the thousands separator character.  */
132           if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
133                       strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
134             thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
135           if (thousands == L'\0')
136             grouping = NULL;
137         }
138     }
139   else
140     grouping = NULL;
141 #endif
142
143   if (base < 0 || base == 1 || base > 36)
144     base = 10;
145
146   s = nptr;
147
148   /* Skip white space.  */
149   while (isspace (*s))
150     ++s;
151   if (*s == '\0')
152     goto noconv;
153
154   /* Check for a sign.  */
155   if (*s == '-')
156     {
157       negative = 1;
158       ++s;
159     }
160   else if (*s == '+')
161     {
162       negative = 0;
163       ++s;
164     }
165   else
166     negative = 0;
167
168   if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
169     s += 2;
170
171   /* If BASE is zero, figure it out ourselves.  */
172   if (base == 0)
173     if (*s == '0')
174       {
175         if (toupper (s[1]) == 'X')
176           {
177             s += 2;
178             base = 16;
179           }
180         else
181           base = 8;
182       }
183     else
184       base = 10;
185
186   /* Save the pointer so we can check later if anything happened.  */
187   save = s;
188
189 #ifdef USE_NUMBER_GROUPING
190   if (group)
191     {
192       /* Find the end of the digit string and check its grouping.  */
193       end = s;
194       for (c = *end; c != '\0'; c = *++end)
195         if (c != thousands && !isdigit (c) &&
196             (!isalpha (c) || toupper (c) - 'A' + 10 >= base))
197           break;
198       if (*s == thousands)
199         end = s;
200       else
201         end = correctly_grouped_prefix (s, end, thousands, grouping);
202     }
203   else
204 #endif
205     end = NULL;
206
207   cutoff = ULONG_MAX / (unsigned LONG int) base;
208   cutlim = ULONG_MAX % (unsigned LONG int) base;
209
210   overflow = 0;
211   i = 0;
212   for (c = *s; c != '\0'; c = *++s)
213     {
214       if (s == end)
215         break;
216       if (isdigit (c))
217         c -= '0';
218       else if (isalpha (c))
219         c = toupper (c) - 'A' + 10;
220       else
221         break;
222       if (c >= base)
223         break;
224       /* Check for overflow.  */
225       if (i > cutoff || (i == cutoff && c > cutlim))
226         overflow = 1;
227       else
228         {
229           i *= (unsigned LONG int) base;
230           i += c;
231         }
232     }
233
234   /* Check if anything actually happened.  */
235   if (s == save)
236     goto noconv;
237
238   /* Store in ENDPTR the address of one character
239      past the last character we converted.  */
240   if (endptr != NULL)
241     *endptr = (char *) s;
242
243 #if !UNSIGNED
244   /* Check for a value that is within the range of
245      `unsigned LONG int', but outside the range of `LONG int'.  */
246   if (i > (negative ?
247            -(unsigned LONG int) LONG_MIN : (unsigned LONG int) LONG_MAX))
248     overflow = 1;
249 #endif
250
251   if (overflow)
252     {
253       errno = ERANGE;
254 #if UNSIGNED
255       return ULONG_MAX;
256 #else
257       return negative ? LONG_MIN : LONG_MAX;
258 #endif
259     }
260
261   /* Return the result of the appropriate sign.  */
262   return (negative ? -i : i);
263
264 noconv:
265   /* There was no number to convert.  */
266   if (endptr != NULL)
267     *endptr = (char *) nptr;
268   return 0L;
269 }
270 \f
271 /* External user entry point.  */
272
273 #ifdef weak_symbol
274 weak_symbol (strtol)
275 #endif
276
277 INT
278 strtol (nptr, endptr, base)
279      const char *nptr;
280      char **endptr;
281      int base;
282 {
283   return INTERNAL (strtol) (nptr, endptr, base, 0);
284 }