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