Fix CFLAGS/LDFLAGS syntax
[platform/upstream/lrzsz.git] / lib / strtol.c
1 /* Copyright (C) 1991, 92, 94, 95, 96 Free Software Foundation, Inc.
2
3 NOTE: The canonical source of this file is maintained with the GNU C Library.
4 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.  */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #ifdef _LIBC
26 # define USE_NUMBER_GROUPING
27 # define STDC_HEADERS
28 # define HAVE_LIMITS_H
29 #endif
30
31 #include <ctype.h>
32 #include <errno.h>
33 #ifndef errno
34 extern int errno;
35 #endif
36
37 #ifdef HAVE_LIMITS_H
38 # include <limits.h>
39 #endif
40
41 #ifdef STDC_HEADERS
42 # include <stddef.h>
43 # include <stdlib.h>
44 #else
45 # ifndef NULL
46 #  define NULL 0
47 # endif
48 #endif
49
50 #ifdef USE_NUMBER_GROUPING
51 # include "../locale/localeinfo.h"
52 #endif
53
54 /* Nonzero if we are defining `strtoul' or `strtouq', operating on
55    unsigned integers.  */
56 #ifndef UNSIGNED
57 # define UNSIGNED 0
58 # define INT LONG int
59 #else
60 # define INT unsigned LONG int
61 #endif
62
63 /* Determine the name.  */
64 #if UNSIGNED
65 # ifdef USE_WIDE_CHAR
66 #  ifdef QUAD
67 #   define strtol wcstouq
68 #  else
69 #   define strtol wcstoul
70 #  endif
71 # else
72 #  ifdef QUAD
73 #   define strtol strtouq
74 #  else
75 #   define strtol strtoul
76 #  endif
77 # endif
78 #else
79 # ifdef USE_WIDE_CHAR
80 #  ifdef QUAD
81 #   define strtol wcstoq
82 #  else
83 #   define strtol wcstol
84 #  endif
85 # else
86 #  ifdef QUAD
87 #   define strtol strtoq
88 #  endif
89 # endif
90 #endif
91
92 /* If QUAD is defined, we are defining `strtoq' or `strtouq',
93    operating on `long long int's.  */
94 #ifdef QUAD
95 # define LONG long long
96 # undef LONG_MIN
97 # define LONG_MIN LONG_LONG_MIN
98 # undef LONG_MAX
99 # define LONG_MAX LONG_LONG_MAX
100 # undef ULONG_MAX
101 # define ULONG_MAX ULONG_LONG_MAX
102 # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
103    /* Work around gcc bug with using this constant.  */
104    static const unsigned long long int maxquad = ULONG_LONG_MAX;
105 #  undef ULONG_MAX
106 #  define ULONG_MAX maxquad
107 # endif
108 #else
109 # define LONG long
110
111 #ifndef ULONG_MAX
112 # define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
113 #endif
114 #ifndef LONG_MAX
115 # define LONG_MAX ((long int) (ULONG_MAX >> 1))
116 #endif
117 #endif
118
119 #ifdef USE_WIDE_CHAR
120 # include <wchar.h>
121 # include <wctype.h>
122 # define L_(ch) L##ch
123 # define UCHAR_TYPE wint_t
124 # define STRING_TYPE wchar_t
125 # define ISSPACE(ch) iswspace (ch)
126 # define ISALPHA(ch) iswalpha (ch)
127 # define TOUPPER(ch) towupper (ch)
128 #else
129 # define L_(ch) ch
130 # define UCHAR_TYPE unsigned char
131 # define STRING_TYPE char
132 # define ISSPACE(ch) isspace (ch)
133 # define ISALPHA(ch) isalpha (ch)
134 # define TOUPPER(ch) toupper (ch)
135 #endif
136
137 #ifdef __STDC__
138 # define INTERNAL(x) INTERNAL1(x)
139 # define INTERNAL1(x) __##x##_internal
140 # define WEAKNAME(x) WEAKNAME1(x)
141 # define WEAKNAME1(x) __##x
142 #else
143 # define INTERNAL(x) __/**/x/**/_internal
144 # define WEAKNAME(x) __/**/x
145 #endif
146
147 #ifdef USE_NUMBER_GROUPING
148 /* This file defines a function to check for correct grouping.  */
149 # include "grouping.h"
150 #endif
151
152
153 /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
154    If BASE is 0 the base is determined by the presence of a leading
155    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
156    If BASE is < 2 or > 36, it is reset to 10.
157    If ENDPTR is not NULL, a pointer to the character after the last
158    one converted is stored in *ENDPTR.  */
159
160 INT
161 INTERNAL (strtol) (nptr, endptr, base, group)
162      const STRING_TYPE *nptr;
163      STRING_TYPE **endptr;
164      int base;
165      int group;
166 {
167   int negative;
168   register unsigned LONG int cutoff;
169   register unsigned int cutlim;
170   register unsigned LONG int i;
171   register const STRING_TYPE *s;
172   register UCHAR_TYPE c;
173   const STRING_TYPE *save, *end;
174   int overflow;
175
176 #ifdef USE_NUMBER_GROUPING
177   /* The thousands character of the current locale.  */
178   wchar_t thousands;
179   /* The numeric grouping specification of the current locale,
180      in the format described in <locale.h>.  */
181   const char *grouping;
182
183   if (group)
184     {
185       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
186       if (*grouping <= 0 || *grouping == CHAR_MAX)
187         grouping = NULL;
188       else
189         {
190           /* Figure out the thousands separator character.  */
191           if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
192                       strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
193             thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
194           if (thousands == L'\0')
195             grouping = NULL;
196         }
197     }
198   else
199     grouping = NULL;
200 #endif
201
202   if (base < 0 || base == 1 || base > 36)
203     base = 10;
204
205   save = s = nptr;
206
207   /* Skip white space.  */
208   while (ISSPACE (*s))
209     ++s;
210   if (*s == L_('\0'))
211     goto noconv;
212
213   /* Check for a sign.  */
214   if (*s == L_('-'))
215     {
216       negative = 1;
217       ++s;
218     }
219   else if (*s == L_('+'))
220     {
221       negative = 0;
222       ++s;
223     }
224   else
225     negative = 0;
226
227   if (base == 16 && s[0] == L_('0') && TOUPPER (s[1]) == L_('X'))
228     s += 2;
229
230   /* If BASE is zero, figure it out ourselves.  */
231   if (base == 0)
232     if (*s == L_('0'))
233       {
234         if (TOUPPER (s[1]) == L_('X'))
235           {
236             s += 2;
237             base = 16;
238           }
239         else
240           base = 8;
241       }
242     else
243       base = 10;
244
245   /* Save the pointer so we can check later if anything happened.  */
246   save = s;
247
248 #ifdef USE_NUMBER_GROUPING
249   if (group)
250     {
251       /* Find the end of the digit string and check its grouping.  */
252       end = s;
253       for (c = *end; c != L_('\0'); c = *++end)
254         if (c != thousands && (c < L_('0') || c > L_('9'))
255             && (!ISALPHA (c) || TOUPPER (c) - L_('A') + 10 >= base))
256           break;
257       if (*s == thousands)
258         end = s;
259       else
260         end = correctly_grouped_prefix (s, end, thousands, grouping);
261     }
262   else
263 #endif
264     end = NULL;
265
266   cutoff = ULONG_MAX / (unsigned LONG int) base;
267   cutlim = ULONG_MAX % (unsigned LONG int) base;
268
269   overflow = 0;
270   i = 0;
271   for (c = *s; c != L_('\0'); c = *++s)
272     {
273       if (s == end)
274         break;
275       if (c >= L_('0') && c <= L_('9'))
276         c -= L_('0');
277       else if (ISALPHA (c))
278         c = TOUPPER (c) - L_('A') + 10;
279       else
280         break;
281       if (c >= base)
282         break;
283       /* Check for overflow.  */
284       if (i > cutoff || (i == cutoff && c > cutlim))
285         overflow = 1;
286       else
287         {
288           i *= (unsigned LONG int) base;
289           i += c;
290         }
291     }
292
293   /* Check if anything actually happened.  */
294   if (s == save)
295     goto noconv;
296
297   /* Store in ENDPTR the address of one character
298      past the last character we converted.  */
299   if (endptr != NULL)
300     *endptr = (STRING_TYPE *) s;
301
302 #if !UNSIGNED
303   /* Check for a value that is within the range of
304      `unsigned LONG int', but outside the range of `LONG int'.  */
305   if (overflow == 0
306       && i > (negative
307               ? -((unsigned LONG int) (LONG_MIN + 1)) + 1
308               : (unsigned LONG int) LONG_MAX))
309     overflow = 1;
310 #endif
311
312   if (overflow)
313     {
314       errno = ERANGE;
315 #if UNSIGNED
316       return ULONG_MAX;
317 #else
318       return negative ? LONG_MIN : LONG_MAX;
319 #endif
320     }
321
322   /* Return the result of the appropriate sign.  */
323   return (negative ? -i : i);
324
325 noconv:
326   /* We must handle a special case here: the base is 0 or 16 and the
327      first two characters and '0' and 'x', but the rest are no
328      hexadecimal digits.  This is no error case.  We return 0 and
329      ENDPTR points to the `x`.  */
330   if (endptr != NULL)
331     if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
332         && save[-2] == L_('0'))
333       *endptr = (STRING_TYPE *) &save[-1];
334     else
335       /*  There was no number to convert.  */
336       *endptr = (STRING_TYPE *) nptr;
337
338   return 0L;
339 }
340 \f
341 /* External user entry point.  */
342
343 #undef __P
344 #if defined (__STDC__) && __STDC__
345 #define __P(args) args
346 #else
347 #define __P(args) ()
348 #endif
349
350 /* Prototype.  */
351 INT strtol __P ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
352                             int base));
353
354
355 INT
356 strtol (nptr, endptr, base)
357      const STRING_TYPE *nptr;
358      STRING_TYPE **endptr;
359      int base;
360 {
361   return INTERNAL (strtol) (nptr, endptr, base, 0);
362 }