Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* Convert string representation of a number into an integer value.  | 
2  |  |  | 
3  |  |    Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2025 Free Software  | 
4  |  |    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 file is free software: you can redistribute it and/or modify  | 
10  |  |    it under the terms of the GNU Lesser General Public License as  | 
11  |  |    published by the Free Software Foundation, either version 3 of the  | 
12  |  |    License, or (at your option) any later version.  | 
13  |  |  | 
14  |  |    This file 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 Lesser General Public License for more details.  | 
18  |  |  | 
19  |  |    You should have received a copy of the GNU Lesser General Public License  | 
20  |  |    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */  | 
21  |  |  | 
22  |  | #ifdef _LIBC  | 
23  |  | # define USE_NUMBER_GROUPING  | 
24  |  | #else  | 
25  |  | # include <config.h>  | 
26  |  | #endif  | 
27  |  |  | 
28  |  | #include <ctype.h>  | 
29  |  | #include <errno.h>  | 
30  |  | #ifndef __set_errno  | 
31  | 1.08k  | # define __set_errno(Val) errno = (Val)  | 
32  |  | #endif  | 
33  |  |  | 
34  |  | #include <limits.h>  | 
35  |  | #include <stddef.h>  | 
36  |  | #include <stdlib.h>  | 
37  |  | #include <string.h>  | 
38  |  |  | 
39  |  | #ifdef USE_NUMBER_GROUPING  | 
40  |  | # include "../locale/localeinfo.h"  | 
41  |  | #endif  | 
42  |  |  | 
43  |  | /* Nonzero if we are defining 'strtoul' or 'strtoull', operating on  | 
44  |  |    unsigned integers.  */  | 
45  |  | #ifndef UNSIGNED  | 
46  |  | # define UNSIGNED 0  | 
47  |  | # define INT LONG int  | 
48  |  | #else  | 
49  |  | # define INT unsigned LONG int  | 
50  |  | #endif  | 
51  |  |  | 
52  |  | /* Determine the name.  */  | 
53  |  | #ifdef USE_IN_EXTENDED_LOCALE_MODEL  | 
54  |  | # undef strtol  | 
55  |  | # if UNSIGNED  | 
56  |  | #  ifdef USE_WIDE_CHAR  | 
57  |  | #   ifdef QUAD  | 
58  |  | #    define strtol __wcstoull_l  | 
59  |  | #   else  | 
60  |  | #    define strtol __wcstoul_l  | 
61  |  | #   endif  | 
62  |  | #  else  | 
63  |  | #   ifdef QUAD  | 
64  |  | #    define strtol __strtoull_l  | 
65  |  | #   else  | 
66  |  | #    define strtol __strtoul_l  | 
67  |  | #   endif  | 
68  |  | #  endif  | 
69  |  | # else  | 
70  |  | #  ifdef USE_WIDE_CHAR  | 
71  |  | #   ifdef QUAD  | 
72  |  | #    define strtol __wcstoll_l  | 
73  |  | #   else  | 
74  |  | #    define strtol __wcstol_l  | 
75  |  | #   endif  | 
76  |  | #  else  | 
77  |  | #   ifdef QUAD  | 
78  |  | #    define strtol __strtoll_l  | 
79  |  | #   else  | 
80  |  | #    define strtol __strtol_l  | 
81  |  | #   endif  | 
82  |  | #  endif  | 
83  |  | # endif  | 
84  |  | #else  | 
85  |  | # if UNSIGNED  | 
86  |  | #  undef strtol  | 
87  |  | #  ifdef USE_WIDE_CHAR  | 
88  |  | #   ifdef QUAD  | 
89  |  | #    define strtol wcstoull  | 
90  |  | #   else  | 
91  |  | #    define strtol wcstoul  | 
92  |  | #   endif  | 
93  |  | #  else  | 
94  |  | #   ifdef QUAD  | 
95  |  | #    define strtol strtoull  | 
96  |  | #   else  | 
97  |  | #    define strtol strtoul  | 
98  |  | #   endif  | 
99  |  | #  endif  | 
100  |  | # else  | 
101  |  | #  ifdef USE_WIDE_CHAR  | 
102  |  | #   undef strtol  | 
103  |  | #   ifdef QUAD  | 
104  |  | #    define strtol wcstoll  | 
105  |  | #   else  | 
106  |  | #    define strtol wcstol  | 
107  |  | #   endif  | 
108  |  | #  else  | 
109  |  | #   ifdef QUAD  | 
110  |  | #    undef strtol  | 
111  |  | #    define strtol strtoll  | 
112  |  | #   endif  | 
113  |  | #  endif  | 
114  |  | # endif  | 
115  |  | #endif  | 
116  |  |  | 
117  |  | /* If QUAD is defined, we are defining 'strtoll' or 'strtoull',  | 
118  |  |    operating on 'long long int's.  */  | 
119  |  | #ifdef QUAD  | 
120  |  | # define LONG long long  | 
121  | 1.83k  | # define STRTOL_LONG_MIN LLONG_MIN  | 
122  | 8.51k  | # define STRTOL_LONG_MAX LLONG_MAX  | 
123  | 47.9k  | # define STRTOL_ULONG_MAX ULLONG_MAX  | 
124  |  | # if __GNUC__ == 2 && __GNUC_MINOR__ < 7  | 
125  |  |    /* Work around gcc bug with using this constant.  */  | 
126  |  |    static const unsigned long long int maxquad = ULLONG_MAX;  | 
127  |  | #  undef STRTOL_ULONG_MAX  | 
128  |  | #  define STRTOL_ULONG_MAX maxquad  | 
129  |  | # endif  | 
130  |  | #else  | 
131  |  | # define LONG long  | 
132  | 0  | # define STRTOL_LONG_MIN LONG_MIN  | 
133  | 0  | # define STRTOL_LONG_MAX LONG_MAX  | 
134  | 0  | # define STRTOL_ULONG_MAX ULONG_MAX  | 
135  |  | #endif  | 
136  |  |  | 
137  |  |  | 
138  |  | #ifdef USE_NUMBER_GROUPING  | 
139  |  | # define GROUP_PARAM_PROTO , int group  | 
140  |  | #else  | 
141  |  | # define GROUP_PARAM_PROTO  | 
142  |  | #endif  | 
143  |  |  | 
144  |  | /* We use this code also for the extended locale handling where the  | 
145  |  |    function gets as an additional argument the locale which has to be  | 
146  |  |    used.  To access the values we have to redefine the _NL_CURRENT  | 
147  |  |    macro.  */  | 
148  |  | #ifdef USE_IN_EXTENDED_LOCALE_MODEL  | 
149  |  | # undef _NL_CURRENT  | 
150  |  | # define _NL_CURRENT(category, item) \  | 
151  |  |   (current->values[_NL_ITEM_INDEX (item)].string)  | 
152  |  | # define LOCALE_PARAM , loc  | 
153  |  | # define LOCALE_PARAM_PROTO , __locale_t loc  | 
154  |  | #else  | 
155  |  | # define LOCALE_PARAM  | 
156  |  | # define LOCALE_PARAM_PROTO  | 
157  |  | #endif  | 
158  |  |  | 
159  |  | #ifdef USE_WIDE_CHAR  | 
160  |  | # include <wchar.h>  | 
161  |  | # include <wctype.h>  | 
162  |  | # define L_(Ch) L##Ch  | 
163  |  | # define UCHAR_TYPE wint_t  | 
164  |  | # define STRING_TYPE wchar_t  | 
165  |  | # ifdef USE_IN_EXTENDED_LOCALE_MODEL  | 
166  |  | #  define ISSPACE(Ch) __iswspace_l ((Ch), loc)  | 
167  |  | #  define ISALPHA(Ch) __iswalpha_l ((Ch), loc)  | 
168  |  | #  define TOUPPER(Ch) __towupper_l ((Ch), loc)  | 
169  |  | # else  | 
170  |  | #  define ISSPACE(Ch) iswspace (Ch)  | 
171  |  | #  define ISALPHA(Ch) iswalpha (Ch)  | 
172  |  | #  define TOUPPER(Ch) towupper (Ch)  | 
173  |  | # endif  | 
174  |  | #else  | 
175  | 377k  | # define L_(Ch) Ch  | 
176  |  | # define UCHAR_TYPE unsigned char  | 
177  |  | # define STRING_TYPE char  | 
178  |  | # ifdef USE_IN_EXTENDED_LOCALE_MODEL  | 
179  |  | #  define ISSPACE(Ch) __isspace_l ((unsigned char) (Ch), loc)  | 
180  |  | #  define ISALPHA(Ch) __isalpha_l ((unsigned char) (Ch), loc)  | 
181  |  | #  define TOUPPER(Ch) __toupper_l ((unsigned char) (Ch), loc)  | 
182  |  | # else  | 
183  |  | #  define ISSPACE(Ch) isspace ((unsigned char) (Ch))  | 
184  | 14.3k  | #  define ISALPHA(Ch) isalpha ((unsigned char) (Ch))  | 
185  | 5.98k  | #  define TOUPPER(Ch) toupper ((unsigned char) (Ch))  | 
186  |  | # endif  | 
187  |  | #endif  | 
188  |  |  | 
189  |  | #ifdef USE_NUMBER_GROUPING  | 
190  |  | # define INTERNAL(X) INTERNAL1(X)  | 
191  |  | # define INTERNAL1(X) __##X##_internal  | 
192  |  | # define WEAKNAME(X) WEAKNAME1(X)  | 
193  |  | #else  | 
194  |  | # define INTERNAL(X) X  | 
195  |  | #endif  | 
196  |  |  | 
197  |  | #ifdef USE_NUMBER_GROUPING  | 
198  |  | /* This file defines a function to check for correct grouping.  */  | 
199  |  | # include "grouping.h"  | 
200  |  | #endif  | 
201  |  |  | 
202  |  |  | 
203  |  |  | 
204  |  | /* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE.  | 
205  |  |    If BASE is 0 the base is determined by the presence of a leading  | 
206  |  |    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.  | 
207  |  |    If BASE is < 2 or > 36, it is reset to 10.  | 
208  |  |    If ENDPTR is not NULL, a pointer to the character after the last  | 
209  |  |    one converted is stored in *ENDPTR.  */  | 
210  |  |  | 
211  |  | INT  | 
212  |  | INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,  | 
213  |  |                    int base GROUP_PARAM_PROTO LOCALE_PARAM_PROTO)  | 
214  | 24.1k  | { | 
215  | 24.1k  |   int negative;  | 
216  | 24.1k  |   register unsigned LONG int cutoff;  | 
217  | 24.1k  |   register unsigned int cutlim;  | 
218  | 24.1k  |   register unsigned LONG int i;  | 
219  | 24.1k  |   register const STRING_TYPE *s;  | 
220  | 24.1k  |   register UCHAR_TYPE c;  | 
221  | 24.1k  |   const STRING_TYPE *save, *end;  | 
222  | 24.1k  |   int overflow;  | 
223  |  |  | 
224  |  | #ifdef USE_NUMBER_GROUPING  | 
225  |  | # ifdef USE_IN_EXTENDED_LOCALE_MODEL  | 
226  |  |   struct locale_data *current = loc->__locales[LC_NUMERIC];  | 
227  |  | # endif  | 
228  |  |   /* The thousands character of the current locale.  */  | 
229  |  |   wchar_t thousands = L'\0';  | 
230  |  |   /* The numeric grouping specification of the current locale,  | 
231  |  |      in the format described in <locale.h>.  */  | 
232  |  |   const char *grouping;  | 
233  |  |  | 
234  |  |   if (group)  | 
235  |  |     { | 
236  |  |       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);  | 
237  |  |       if (*grouping <= 0 || *grouping == CHAR_MAX)  | 
238  |  |         grouping = NULL;  | 
239  |  |       else  | 
240  |  |         { | 
241  |  |           /* Figure out the thousands separator character.  */  | 
242  |  | # if defined _LIBC || defined _HAVE_BTOWC  | 
243  |  |           thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));  | 
244  |  |           if (thousands == WEOF)  | 
245  |  |             thousands = L'\0';  | 
246  |  | # endif  | 
247  |  |           if (thousands == L'\0')  | 
248  |  |             grouping = NULL;  | 
249  |  |         }  | 
250  |  |     }  | 
251  |  |   else  | 
252  |  |     grouping = NULL;  | 
253  |  | #endif  | 
254  |  |  | 
255  | 24.1k  |   if (base < 0 || base == 1 || base > 36)  | 
256  | 0  |     { | 
257  | 0  |       __set_errno (EINVAL);  | 
258  | 0  |       return 0;  | 
259  | 0  |     }  | 
260  |  |  | 
261  | 24.1k  |   save = s = nptr;  | 
262  |  |  | 
263  |  |   /* Skip white space.  */  | 
264  | 24.1k  |   while (ISSPACE (*s))  | 
265  | 573  |     ++s;  | 
266  | 24.1k  |   if (*s == L_('\0')) | 
267  | 236  |     goto noconv;  | 
268  |  |  | 
269  |  |   /* Check for a sign.  */  | 
270  | 23.9k  |   if (*s == L_('-')) | 
271  | 1.78k  |     { | 
272  | 1.78k  |       negative = 1;  | 
273  | 1.78k  |       ++s;  | 
274  | 1.78k  |     }  | 
275  | 22.1k  |   else if (*s == L_('+')) | 
276  | 231  |     { | 
277  | 231  |       negative = 0;  | 
278  | 231  |       ++s;  | 
279  | 231  |     }  | 
280  | 21.9k  |   else  | 
281  | 21.9k  |     negative = 0;  | 
282  |  |  | 
283  |  |   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */  | 
284  | 23.9k  |   if (*s == L_('0')) | 
285  | 1.44k  |     { | 
286  | 1.44k  |       if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) | 
287  | 0  |         { | 
288  | 0  |           s += 2;  | 
289  | 0  |           base = 16;  | 
290  | 0  |         }  | 
291  | 1.44k  |       else if ((base == 0 || base == 2) && TOUPPER (s[1]) == L_('B')) | 
292  | 0  |         { | 
293  | 0  |           s += 2;  | 
294  | 0  |           base = 2;  | 
295  | 0  |         }  | 
296  | 1.44k  |       else if (base == 0)  | 
297  | 0  |         base = 8;  | 
298  | 1.44k  |     }  | 
299  | 22.5k  |   else if (base == 0)  | 
300  | 0  |     base = 10;  | 
301  |  |  | 
302  |  |   /* Save the pointer so we can check later if anything happened.  */  | 
303  | 23.9k  |   save = s;  | 
304  |  |  | 
305  |  | #ifdef USE_NUMBER_GROUPING  | 
306  |  |   if (group)  | 
307  |  |     { | 
308  |  |       /* Find the end of the digit string and check its grouping.  */  | 
309  |  |       end = s;  | 
310  |  |       for (c = *end; c != L_('\0'); c = *++end) | 
311  |  |         if ((wchar_t) c != thousands  | 
312  |  |             && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) | 
313  |  |             && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) | 
314  |  |           break;  | 
315  |  |       if (*s == thousands)  | 
316  |  |         end = s;  | 
317  |  |       else  | 
318  |  |         end = correctly_grouped_prefix (s, end, thousands, grouping);  | 
319  |  |     }  | 
320  |  |   else  | 
321  |  | #endif  | 
322  | 23.9k  |     end = NULL;  | 
323  |  |  | 
324  | 23.9k  |   cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;  | 
325  | 23.9k  |   cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;  | 
326  |  |  | 
327  | 23.9k  |   overflow = 0;  | 
328  | 23.9k  |   i = 0;  | 
329  | 66.7k  |   for (c = *s; c != L_('\0'); c = *++s) | 
330  | 57.1k  |     { | 
331  | 57.1k  |       if (s == end)  | 
332  | 0  |         break;  | 
333  | 57.1k  |       if (c >= L_('0') && c <= L_('9')) | 
334  | 42.7k  |         c -= L_('0'); | 
335  | 14.3k  |       else if (ISALPHA (c))  | 
336  | 5.98k  |         c = TOUPPER (c) - L_('A') + 10; | 
337  | 8.39k  |       else  | 
338  | 8.39k  |         break;  | 
339  | 48.7k  |       if ((int) c >= base)  | 
340  | 5.98k  |         break;  | 
341  |  |       /* Check for overflow.  */  | 
342  | 42.7k  |       if (i > cutoff || (i == cutoff && c > cutlim))  | 
343  | 1.25k  |         overflow = 1;  | 
344  | 41.4k  |       else  | 
345  | 41.4k  |         { | 
346  | 41.4k  |           i *= (unsigned LONG int) base;  | 
347  | 41.4k  |           i += c;  | 
348  | 41.4k  |         }  | 
349  | 42.7k  |     }  | 
350  |  |  | 
351  |  |   /* Check if anything actually happened.  */  | 
352  | 23.9k  |   if (s == save)  | 
353  | 15.2k  |     goto noconv;  | 
354  |  |  | 
355  |  |   /* Store in ENDPTR the address of one character  | 
356  |  |      past the last character we converted.  */  | 
357  | 8.71k  |   if (endptr != NULL)  | 
358  | 0  |     *endptr = (STRING_TYPE *) s;  | 
359  |  |  | 
360  | 8.71k  | #if !UNSIGNED  | 
361  |  |   /* Check for a value that is within the range of  | 
362  |  |      'unsigned LONG int', but outside the range of 'LONG int'.  */  | 
363  | 8.71k  |   if (overflow == 0  | 
364  | 8.71k  |       && i > (negative  | 
365  | 8.17k  |               ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1  | 
366  | 8.17k  |               : (unsigned LONG int) STRTOL_LONG_MAX))  | 
367  | 546  |     overflow = 1;  | 
368  | 8.71k  | #endif  | 
369  |  |  | 
370  | 8.71k  |   if (overflow)  | 
371  | 1.08k  |     { | 
372  | 1.08k  |       __set_errno (ERANGE);  | 
373  |  | #if UNSIGNED  | 
374  |  |       return STRTOL_ULONG_MAX;  | 
375  |  | #else  | 
376  | 1.08k  |       return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;  | 
377  | 1.08k  | #endif  | 
378  | 1.08k  |     }  | 
379  |  |  | 
380  |  |   /* Return the result of the appropriate sign.  */  | 
381  | 7.62k  |   return negative ? -i : i;  | 
382  |  |  | 
383  | 15.4k  | noconv:  | 
384  |  |   /* We must handle a special case here: the base is 0 or 16 and the  | 
385  |  |      first two characters are '0' and 'x', but the rest are no  | 
386  |  |      hexadecimal digits.  Likewise when the base is 0 or 2 and the  | 
387  |  |      first two characters are '0' and 'b', but the rest are no binary  | 
388  |  |      digits.  This is no error case.  We return 0 and ENDPTR points to  | 
389  |  |      the 'x' or 'b'.  */  | 
390  | 15.4k  |   if (endptr != NULL)  | 
391  | 0  |     { | 
392  | 0  |       if (save - nptr >= 2  | 
393  | 0  |           && (TOUPPER (save[-1]) == L_('X') || TOUPPER (save[-1]) == L_('B')) | 
394  | 0  |           && save[-2] == L_('0')) | 
395  | 0  |         *endptr = (STRING_TYPE *) &save[-1];  | 
396  | 0  |       else  | 
397  |  |         /*  There was no number to convert.  */  | 
398  | 0  |         *endptr = (STRING_TYPE *) nptr;  | 
399  | 0  |     }  | 
400  |  |  | 
401  | 15.4k  |   return 0L;  | 
402  | 8.71k  | } Unexecuted instantiation: rpl_strtol Line  | Count  | Source  |  214  | 24.1k  | { |  215  | 24.1k  |   int negative;  |  216  | 24.1k  |   register unsigned LONG int cutoff;  |  217  | 24.1k  |   register unsigned int cutlim;  |  218  | 24.1k  |   register unsigned LONG int i;  |  219  | 24.1k  |   register const STRING_TYPE *s;  |  220  | 24.1k  |   register UCHAR_TYPE c;  |  221  | 24.1k  |   const STRING_TYPE *save, *end;  |  222  | 24.1k  |   int overflow;  |  223  |  |  |  224  |  | #ifdef USE_NUMBER_GROUPING  |  225  |  | # ifdef USE_IN_EXTENDED_LOCALE_MODEL  |  226  |  |   struct locale_data *current = loc->__locales[LC_NUMERIC];  |  227  |  | # endif  |  228  |  |   /* The thousands character of the current locale.  */  |  229  |  |   wchar_t thousands = L'\0';  |  230  |  |   /* The numeric grouping specification of the current locale,  |  231  |  |      in the format described in <locale.h>.  */  |  232  |  |   const char *grouping;  |  233  |  |  |  234  |  |   if (group)  |  235  |  |     { |  236  |  |       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);  |  237  |  |       if (*grouping <= 0 || *grouping == CHAR_MAX)  |  238  |  |         grouping = NULL;  |  239  |  |       else  |  240  |  |         { |  241  |  |           /* Figure out the thousands separator character.  */  |  242  |  | # if defined _LIBC || defined _HAVE_BTOWC  |  243  |  |           thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));  |  244  |  |           if (thousands == WEOF)  |  245  |  |             thousands = L'\0';  |  246  |  | # endif  |  247  |  |           if (thousands == L'\0')  |  248  |  |             grouping = NULL;  |  249  |  |         }  |  250  |  |     }  |  251  |  |   else  |  252  |  |     grouping = NULL;  |  253  |  | #endif  |  254  |  |  |  255  | 24.1k  |   if (base < 0 || base == 1 || base > 36)  |  256  | 0  |     { |  257  | 0  |       __set_errno (EINVAL);  |  258  | 0  |       return 0;  |  259  | 0  |     }  |  260  |  |  |  261  | 24.1k  |   save = s = nptr;  |  262  |  |  |  263  |  |   /* Skip white space.  */  |  264  | 24.1k  |   while (ISSPACE (*s))  |  265  | 573  |     ++s;  |  266  | 24.1k  |   if (*s == L_('\0')) |  267  | 236  |     goto noconv;  |  268  |  |  |  269  |  |   /* Check for a sign.  */  |  270  | 23.9k  |   if (*s == L_('-')) |  271  | 1.78k  |     { |  272  | 1.78k  |       negative = 1;  |  273  | 1.78k  |       ++s;  |  274  | 1.78k  |     }  |  275  | 22.1k  |   else if (*s == L_('+')) |  276  | 231  |     { |  277  | 231  |       negative = 0;  |  278  | 231  |       ++s;  |  279  | 231  |     }  |  280  | 21.9k  |   else  |  281  | 21.9k  |     negative = 0;  |  282  |  |  |  283  |  |   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */  |  284  | 23.9k  |   if (*s == L_('0')) |  285  | 1.44k  |     { |  286  | 1.44k  |       if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) |  287  | 0  |         { |  288  | 0  |           s += 2;  |  289  | 0  |           base = 16;  |  290  | 0  |         }  |  291  | 1.44k  |       else if ((base == 0 || base == 2) && TOUPPER (s[1]) == L_('B')) |  292  | 0  |         { |  293  | 0  |           s += 2;  |  294  | 0  |           base = 2;  |  295  | 0  |         }  |  296  | 1.44k  |       else if (base == 0)  |  297  | 0  |         base = 8;  |  298  | 1.44k  |     }  |  299  | 22.5k  |   else if (base == 0)  |  300  | 0  |     base = 10;  |  301  |  |  |  302  |  |   /* Save the pointer so we can check later if anything happened.  */  |  303  | 23.9k  |   save = s;  |  304  |  |  |  305  |  | #ifdef USE_NUMBER_GROUPING  |  306  |  |   if (group)  |  307  |  |     { |  308  |  |       /* Find the end of the digit string and check its grouping.  */  |  309  |  |       end = s;  |  310  |  |       for (c = *end; c != L_('\0'); c = *++end) |  311  |  |         if ((wchar_t) c != thousands  |  312  |  |             && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) |  313  |  |             && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) |  314  |  |           break;  |  315  |  |       if (*s == thousands)  |  316  |  |         end = s;  |  317  |  |       else  |  318  |  |         end = correctly_grouped_prefix (s, end, thousands, grouping);  |  319  |  |     }  |  320  |  |   else  |  321  |  | #endif  |  322  | 23.9k  |     end = NULL;  |  323  |  |  |  324  | 23.9k  |   cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;  |  325  | 23.9k  |   cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;  |  326  |  |  |  327  | 23.9k  |   overflow = 0;  |  328  | 23.9k  |   i = 0;  |  329  | 66.7k  |   for (c = *s; c != L_('\0'); c = *++s) |  330  | 57.1k  |     { |  331  | 57.1k  |       if (s == end)  |  332  | 0  |         break;  |  333  | 57.1k  |       if (c >= L_('0') && c <= L_('9')) |  334  | 42.7k  |         c -= L_('0'); |  335  | 14.3k  |       else if (ISALPHA (c))  |  336  | 5.98k  |         c = TOUPPER (c) - L_('A') + 10; |  337  | 8.39k  |       else  |  338  | 8.39k  |         break;  |  339  | 48.7k  |       if ((int) c >= base)  |  340  | 5.98k  |         break;  |  341  |  |       /* Check for overflow.  */  |  342  | 42.7k  |       if (i > cutoff || (i == cutoff && c > cutlim))  |  343  | 1.25k  |         overflow = 1;  |  344  | 41.4k  |       else  |  345  | 41.4k  |         { |  346  | 41.4k  |           i *= (unsigned LONG int) base;  |  347  | 41.4k  |           i += c;  |  348  | 41.4k  |         }  |  349  | 42.7k  |     }  |  350  |  |  |  351  |  |   /* Check if anything actually happened.  */  |  352  | 23.9k  |   if (s == save)  |  353  | 15.2k  |     goto noconv;  |  354  |  |  |  355  |  |   /* Store in ENDPTR the address of one character  |  356  |  |      past the last character we converted.  */  |  357  | 8.71k  |   if (endptr != NULL)  |  358  | 0  |     *endptr = (STRING_TYPE *) s;  |  359  |  |  |  360  | 8.71k  | #if !UNSIGNED  |  361  |  |   /* Check for a value that is within the range of  |  362  |  |      'unsigned LONG int', but outside the range of 'LONG int'.  */  |  363  | 8.71k  |   if (overflow == 0  |  364  | 8.71k  |       && i > (negative  |  365  | 8.17k  |               ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1  |  366  | 8.17k  |               : (unsigned LONG int) STRTOL_LONG_MAX))  |  367  | 546  |     overflow = 1;  |  368  | 8.71k  | #endif  |  369  |  |  |  370  | 8.71k  |   if (overflow)  |  371  | 1.08k  |     { |  372  | 1.08k  |       __set_errno (ERANGE);  |  373  |  | #if UNSIGNED  |  374  |  |       return STRTOL_ULONG_MAX;  |  375  |  | #else  |  376  | 1.08k  |       return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;  |  377  | 1.08k  | #endif  |  378  | 1.08k  |     }  |  379  |  |  |  380  |  |   /* Return the result of the appropriate sign.  */  |  381  | 7.62k  |   return negative ? -i : i;  |  382  |  |  |  383  | 15.4k  | noconv:  |  384  |  |   /* We must handle a special case here: the base is 0 or 16 and the  |  385  |  |      first two characters are '0' and 'x', but the rest are no  |  386  |  |      hexadecimal digits.  Likewise when the base is 0 or 2 and the  |  387  |  |      first two characters are '0' and 'b', but the rest are no binary  |  388  |  |      digits.  This is no error case.  We return 0 and ENDPTR points to  |  389  |  |      the 'x' or 'b'.  */  |  390  | 15.4k  |   if (endptr != NULL)  |  391  | 0  |     { |  392  | 0  |       if (save - nptr >= 2  |  393  | 0  |           && (TOUPPER (save[-1]) == L_('X') || TOUPPER (save[-1]) == L_('B')) |  394  | 0  |           && save[-2] == L_('0')) |  395  | 0  |         *endptr = (STRING_TYPE *) &save[-1];  |  396  | 0  |       else  |  397  |  |         /*  There was no number to convert.  */  |  398  | 0  |         *endptr = (STRING_TYPE *) nptr;  |  399  | 0  |     }  |  400  |  |  |  401  | 15.4k  |   return 0L;  |  402  | 8.71k  | }  |  
  | 
403  |  |  | 
404  |  | #ifdef USE_NUMBER_GROUPING  | 
405  |  | /* External user entry point.  */  | 
406  |  |  | 
407  |  | INT  | 
408  |  | # ifdef weak_function  | 
409  |  | weak_function  | 
410  |  | # endif  | 
411  |  | strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,  | 
412  |  |         int base LOCALE_PARAM_PROTO)  | 
413  |  | { | 
414  |  |   return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);  | 
415  |  | }  | 
416  |  | #endif  |