xref: /netbsd-src/external/gpl2/xcvs/dist/lib/strtol.c (revision 5a6c14c844c4c665da5632061aebde7bb2cb5766)
1 /* Convert string representation of a number into an integer value.
2 
3    Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005
4    Free Software Foundation, Inc.
5 
6    NOTE: The canonical source of this file is maintained with the GNU C
7    Library.  Bugs can be reported to bug-glibc@gnu.org.
8 
9    This program is free software; you can redistribute it and/or modify it
10    under the terms of the GNU General Public License as published by the
11    Free Software Foundation; either version 2, or (at your option) any
12    later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
22 #include <sys/cdefs.h>
23 __RCSID("$NetBSD: strtol.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #ifdef _LIBC
31 # define USE_NUMBER_GROUPING
32 #endif
33 
34 #include <ctype.h>
35 #include <errno.h>
36 #ifndef errno
37 extern int errno;
38 #endif
39 #ifndef __set_errno
40 # define __set_errno(Val) errno = (Val)
41 #endif
42 
43 #include <limits.h>
44 #include <stddef.h>
45 #include <stdlib.h>
46 #include <string.h>
47 
48 #ifdef USE_NUMBER_GROUPING
49 # include "../locale/localeinfo.h"
50 #endif
51 
52 /* Nonzero if we are defining `strtoul' or `strtoull', operating on
53    unsigned integers.  */
54 #ifndef UNSIGNED
55 # define UNSIGNED 0
56 # define INT LONG int
57 #else
58 # define INT unsigned LONG int
59 #endif
60 
61 /* Determine the name.  */
62 #ifdef USE_IN_EXTENDED_LOCALE_MODEL
63 # if UNSIGNED
64 #  ifdef USE_WIDE_CHAR
65 #   ifdef QUAD
66 #    define strtol __wcstoull_l
67 #   else
68 #    define strtol __wcstoul_l
69 #   endif
70 #  else
71 #   ifdef QUAD
72 #    define strtol __strtoull_l
73 #   else
74 #    define strtol __strtoul_l
75 #   endif
76 #  endif
77 # else
78 #  ifdef USE_WIDE_CHAR
79 #   ifdef QUAD
80 #    define strtol __wcstoll_l
81 #   else
82 #    define strtol __wcstol_l
83 #   endif
84 #  else
85 #   ifdef QUAD
86 #    define strtol __strtoll_l
87 #   else
88 #    define strtol __strtol_l
89 #   endif
90 #  endif
91 # endif
92 #else
93 # if UNSIGNED
94 #  ifdef USE_WIDE_CHAR
95 #   ifdef QUAD
96 #    define strtol wcstoull
97 #   else
98 #    define strtol wcstoul
99 #   endif
100 #  else
101 #   ifdef QUAD
102 #    define strtol strtoull
103 #   else
104 #    define strtol strtoul
105 #   endif
106 #  endif
107 # else
108 #  ifdef USE_WIDE_CHAR
109 #   ifdef QUAD
110 #    define strtol wcstoll
111 #   else
112 #    define strtol wcstol
113 #   endif
114 #  else
115 #   ifdef QUAD
116 #    define strtol strtoll
117 #   endif
118 #  endif
119 # endif
120 #endif
121 
122 /* If QUAD is defined, we are defining `strtoll' or `strtoull',
123    operating on `long long int's.  */
124 #ifdef QUAD
125 # define LONG long long
126 # define STRTOL_LONG_MIN LONG_LONG_MIN
127 # define STRTOL_LONG_MAX LONG_LONG_MAX
128 # define STRTOL_ULONG_MAX ULONG_LONG_MAX
129 
130 /* The extra casts in the following macros work around compiler bugs,
131    e.g., in Cray C 5.0.3.0.  */
132 
133 /* True if negative values of the signed integer type T use two's
134    complement, ones' complement, or signed magnitude representation,
135    respectively.  Much GNU code assumes two's complement, but some
136    people like to be portable to all possible C hosts.  */
137 # define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
138 # define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
139 # define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
140 
141 /* True if the arithmetic type T is signed.  */
142 # define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
143 
144 /* The maximum and minimum values for the integer type T.  These
145    macros have undefined behavior if T is signed and has padding bits.
146    If this is a problem for you, please let us know how to fix it for
147    your host.  */
148 # define TYPE_MINIMUM(t) \
149    ((t) (! TYPE_SIGNED (t) \
150 	 ? (t) 0 \
151 	 : TYPE_SIGNED_MAGNITUDE (t) \
152 	 ? ~ (t) 0 \
153 	 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
154 # define TYPE_MAXIMUM(t) \
155    ((t) (! TYPE_SIGNED (t) \
156 	 ? (t) -1 \
157 	 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
158 
159 # ifndef ULONG_LONG_MAX
160 #  define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long)
161 # endif
162 # ifndef LONG_LONG_MAX
163 #  define LONG_LONG_MAX TYPE_MAXIMUM (long long int)
164 # endif
165 # ifndef LONG_LONG_MIN
166 #  define LONG_LONG_MIN TYPE_MINIMUM (long long int)
167 # endif
168 
169 # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
170    /* Work around gcc bug with using this constant.  */
171    static const unsigned long long int maxquad = ULONG_LONG_MAX;
172 #  undef STRTOL_ULONG_MAX
173 #  define STRTOL_ULONG_MAX maxquad
174 # endif
175 #else
176 # define LONG long
177 # define STRTOL_LONG_MIN LONG_MIN
178 # define STRTOL_LONG_MAX LONG_MAX
179 # define STRTOL_ULONG_MAX ULONG_MAX
180 #endif
181 
182 
183 /* We use this code also for the extended locale handling where the
184    function gets as an additional argument the locale which has to be
185    used.  To access the values we have to redefine the _NL_CURRENT
186    macro.  */
187 #ifdef USE_IN_EXTENDED_LOCALE_MODEL
188 # undef _NL_CURRENT
189 # define _NL_CURRENT(category, item) \
190   (current->values[_NL_ITEM_INDEX (item)].string)
191 # define LOCALE_PARAM , loc
192 # define LOCALE_PARAM_PROTO , __locale_t loc
193 #else
194 # define LOCALE_PARAM
195 # define LOCALE_PARAM_PROTO
196 #endif
197 
198 #if defined _LIBC || defined HAVE_WCHAR_H
199 # include <wchar.h>
200 #endif
201 
202 #ifdef USE_WIDE_CHAR
203 # include <wctype.h>
204 # define L_(Ch) L##Ch
205 # define UCHAR_TYPE wint_t
206 # define STRING_TYPE wchar_t
207 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
208 #  define ISSPACE(Ch) __iswspace_l ((Ch), loc)
209 #  define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
210 #  define TOUPPER(Ch) __towupper_l ((Ch), loc)
211 # else
212 #  define ISSPACE(Ch) iswspace (Ch)
213 #  define ISALPHA(Ch) iswalpha (Ch)
214 #  define TOUPPER(Ch) towupper (Ch)
215 # endif
216 #else
217 # if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
218 #  define IN_CTYPE_DOMAIN(c) 1
219 # else
220 #  define IN_CTYPE_DOMAIN(c) isascii(c)
221 # endif
222 # define L_(Ch) Ch
223 # define UCHAR_TYPE unsigned char
224 # define STRING_TYPE char
225 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
226 #  define ISSPACE(Ch) __isspace_l ((Ch), loc)
227 #  define ISALPHA(Ch) __isalpha_l ((Ch), loc)
228 #  define TOUPPER(Ch) __toupper_l ((Ch), loc)
229 # else
230 #  define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
231 #  define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
232 #  define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
233 # endif
234 #endif
235 
236 #define INTERNAL(X) INTERNAL1(X)
237 #define INTERNAL1(X) __##X##_internal
238 #define WEAKNAME(X) WEAKNAME1(X)
239 
240 #ifdef USE_NUMBER_GROUPING
241 /* This file defines a function to check for correct grouping.  */
242 # include "grouping.h"
243 #endif
244 
245 
246 
247 /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
248    If BASE is 0 the base is determined by the presence of a leading
249    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
250    If BASE is < 2 or > 36, it is reset to 10.
251    If ENDPTR is not NULL, a pointer to the character after the last
252    one converted is stored in *ENDPTR.  */
253 
254 INT
INTERNAL(strtol)255 INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
256 		   int base, int group LOCALE_PARAM_PROTO)
257 {
258   int negative;
259   register unsigned LONG int cutoff;
260   register unsigned int cutlim;
261   register unsigned LONG int i;
262   register const STRING_TYPE *s;
263   register UCHAR_TYPE c;
264   const STRING_TYPE *save, *end;
265   int overflow;
266 
267 #ifdef USE_NUMBER_GROUPING
268 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
269   struct locale_data *current = loc->__locales[LC_NUMERIC];
270 # endif
271   /* The thousands character of the current locale.  */
272   wchar_t thousands = L'\0';
273   /* The numeric grouping specification of the current locale,
274      in the format described in <locale.h>.  */
275   const char *grouping;
276 
277   if (group)
278     {
279       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
280       if (*grouping <= 0 || *grouping == CHAR_MAX)
281 	grouping = NULL;
282       else
283 	{
284 	  /* Figure out the thousands separator character.  */
285 # if defined _LIBC || defined _HAVE_BTOWC
286 	  thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
287 	  if (thousands == WEOF)
288 	    thousands = L'\0';
289 # endif
290 	  if (thousands == L'\0')
291 	    grouping = NULL;
292 	}
293     }
294   else
295     grouping = NULL;
296 #endif
297 
298   if (base < 0 || base == 1 || base > 36)
299     {
300       __set_errno (EINVAL);
301       return 0;
302     }
303 
304   save = s = nptr;
305 
306   /* Skip white space.  */
307   while (ISSPACE (*s))
308     ++s;
309   if (*s == L_('\0'))
310     goto noconv;
311 
312   /* Check for a sign.  */
313   if (*s == L_('-'))
314     {
315       negative = 1;
316       ++s;
317     }
318   else if (*s == L_('+'))
319     {
320       negative = 0;
321       ++s;
322     }
323   else
324     negative = 0;
325 
326   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
327   if (*s == L_('0'))
328     {
329       if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
330 	{
331 	  s += 2;
332 	  base = 16;
333 	}
334       else if (base == 0)
335 	base = 8;
336     }
337   else if (base == 0)
338     base = 10;
339 
340   /* Save the pointer so we can check later if anything happened.  */
341   save = s;
342 
343 #ifdef USE_NUMBER_GROUPING
344   if (group)
345     {
346       /* Find the end of the digit string and check its grouping.  */
347       end = s;
348       for (c = *end; c != L_('\0'); c = *++end)
349 	if ((wchar_t) c != thousands
350 	    && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
351 	    && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
352 	  break;
353       if (*s == thousands)
354 	end = s;
355       else
356 	end = correctly_grouped_prefix (s, end, thousands, grouping);
357     }
358   else
359 #endif
360     end = NULL;
361 
362   cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
363   cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
364 
365   overflow = 0;
366   i = 0;
367   for (c = *s; c != L_('\0'); c = *++s)
368     {
369       if (s == end)
370 	break;
371       if (c >= L_('0') && c <= L_('9'))
372 	c -= L_('0');
373       else if (ISALPHA (c))
374 	c = TOUPPER (c) - L_('A') + 10;
375       else
376 	break;
377       if ((int) c >= base)
378 	break;
379       /* Check for overflow.  */
380       if (i > cutoff || (i == cutoff && c > cutlim))
381 	overflow = 1;
382       else
383 	{
384 	  i *= (unsigned LONG int) base;
385 	  i += c;
386 	}
387     }
388 
389   /* Check if anything actually happened.  */
390   if (s == save)
391     goto noconv;
392 
393   /* Store in ENDPTR the address of one character
394      past the last character we converted.  */
395   if (endptr != NULL)
396     *endptr = (STRING_TYPE *) s;
397 
398 #if !UNSIGNED
399   /* Check for a value that is within the range of
400      `unsigned LONG int', but outside the range of `LONG int'.  */
401   if (overflow == 0
402       && i > (negative
403 	      ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
404 	      : (unsigned LONG int) STRTOL_LONG_MAX))
405     overflow = 1;
406 #endif
407 
408   if (overflow)
409     {
410       __set_errno (ERANGE);
411 #if UNSIGNED
412       return STRTOL_ULONG_MAX;
413 #else
414       return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
415 #endif
416     }
417 
418   /* Return the result of the appropriate sign.  */
419   return negative ? -i : i;
420 
421 noconv:
422   /* We must handle a special case here: the base is 0 or 16 and the
423      first two characters are '0' and 'x', but the rest are no
424      hexadecimal digits.  This is no error case.  We return 0 and
425      ENDPTR points to the `x`.  */
426   if (endptr != NULL)
427     {
428       if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
429 	  && save[-2] == L_('0'))
430 	*endptr = (STRING_TYPE *) &save[-1];
431       else
432 	/*  There was no number to convert.  */
433 	*endptr = (STRING_TYPE *) nptr;
434     }
435 
436   return 0L;
437 }
438 
439 /* External user entry point.  */
440 
441 
442 INT
443 #ifdef weak_function
444 weak_function
445 #endif
strtol(const STRING_TYPE * nptr,STRING_TYPE ** endptr,int base LOCALE_PARAM_PROTO)446 strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,
447 	int base LOCALE_PARAM_PROTO)
448 {
449   return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
450 }
451