source: trunk/grep/lib/strtol.c@ 2731

Last change on this file since 2731 was 2557, checked in by bird, 19 years ago

grep 2.5.1a

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