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