/src/Python-3.8.3/Python/mystrtoul.c
Line  | Count  | Source  | 
1  |  |  | 
2  |  | #include "Python.h"  | 
3  |  |  | 
4  |  | #if defined(__sgi) && !defined(_SGI_MP_SOURCE)  | 
5  |  | #define _SGI_MP_SOURCE  | 
6  |  | #endif  | 
7  |  |  | 
8  |  | /* strtol and strtoul, renamed to avoid conflicts */  | 
9  |  |  | 
10  |  |  | 
11  |  | #include <ctype.h>  | 
12  |  | #ifdef HAVE_ERRNO_H  | 
13  |  | #include <errno.h>  | 
14  |  | #endif  | 
15  |  |  | 
16  |  | /* Static overflow check values for bases 2 through 36.  | 
17  |  |  * smallmax[base] is the largest unsigned long i such that  | 
18  |  |  * i * base doesn't overflow unsigned long.  | 
19  |  |  */  | 
20  |  | static const unsigned long smallmax[] = { | 
21  |  |     0, /* bases 0 and 1 are invalid */  | 
22  |  |     0,  | 
23  |  |     ULONG_MAX / 2,  | 
24  |  |     ULONG_MAX / 3,  | 
25  |  |     ULONG_MAX / 4,  | 
26  |  |     ULONG_MAX / 5,  | 
27  |  |     ULONG_MAX / 6,  | 
28  |  |     ULONG_MAX / 7,  | 
29  |  |     ULONG_MAX / 8,  | 
30  |  |     ULONG_MAX / 9,  | 
31  |  |     ULONG_MAX / 10,  | 
32  |  |     ULONG_MAX / 11,  | 
33  |  |     ULONG_MAX / 12,  | 
34  |  |     ULONG_MAX / 13,  | 
35  |  |     ULONG_MAX / 14,  | 
36  |  |     ULONG_MAX / 15,  | 
37  |  |     ULONG_MAX / 16,  | 
38  |  |     ULONG_MAX / 17,  | 
39  |  |     ULONG_MAX / 18,  | 
40  |  |     ULONG_MAX / 19,  | 
41  |  |     ULONG_MAX / 20,  | 
42  |  |     ULONG_MAX / 21,  | 
43  |  |     ULONG_MAX / 22,  | 
44  |  |     ULONG_MAX / 23,  | 
45  |  |     ULONG_MAX / 24,  | 
46  |  |     ULONG_MAX / 25,  | 
47  |  |     ULONG_MAX / 26,  | 
48  |  |     ULONG_MAX / 27,  | 
49  |  |     ULONG_MAX / 28,  | 
50  |  |     ULONG_MAX / 29,  | 
51  |  |     ULONG_MAX / 30,  | 
52  |  |     ULONG_MAX / 31,  | 
53  |  |     ULONG_MAX / 32,  | 
54  |  |     ULONG_MAX / 33,  | 
55  |  |     ULONG_MAX / 34,  | 
56  |  |     ULONG_MAX / 35,  | 
57  |  |     ULONG_MAX / 36,  | 
58  |  | };  | 
59  |  |  | 
60  |  | /* maximum digits that can't ever overflow for bases 2 through 36,  | 
61  |  |  * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].  | 
62  |  |  * Note that this is pessimistic if sizeof(long) > 4.  | 
63  |  |  */  | 
64  |  | #if SIZEOF_LONG == 4  | 
65  |  | static const int digitlimit[] = { | 
66  |  |     0,  0, 32, 20, 16, 13, 12, 11, 10, 10,  /*  0 -  9 */  | 
67  |  |     9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  /* 10 - 19 */  | 
68  |  |     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  /* 20 - 29 */  | 
69  |  |     6,  6,  6,  6,  6,  6,  6};             /* 30 - 36 */  | 
70  |  | #elif SIZEOF_LONG == 8  | 
71  |  | /* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */  | 
72  |  | static const int digitlimit[] = { | 
73  |  |          0,   0, 64, 40, 32, 27, 24, 22, 21, 20,  /*  0 -  9 */  | 
74  |  |     19,  18, 17, 17, 16, 16, 16, 15, 15, 15,  /* 10 - 19 */  | 
75  |  |     14,  14, 14, 14, 13, 13, 13, 13, 13, 13,  /* 20 - 29 */  | 
76  |  |     13,  12, 12, 12, 12, 12, 12};             /* 30 - 36 */  | 
77  |  | #else  | 
78  |  | #error "Need table for SIZEOF_LONG"  | 
79  |  | #endif  | 
80  |  |  | 
81  |  | /*  | 
82  |  | **      strtoul  | 
83  |  | **              This is a general purpose routine for converting  | 
84  |  | **              an ascii string to an integer in an arbitrary base.  | 
85  |  | **              Leading white space is ignored.  If 'base' is zero  | 
86  |  | **              it looks for a leading 0b, 0o or 0x to tell which  | 
87  |  | **              base.  If these are absent it defaults to 10.  | 
88  |  | **              Base must be 0 or between 2 and 36 (inclusive).  | 
89  |  | **              If 'ptr' is non-NULL it will contain a pointer to  | 
90  |  | **              the end of the scan.  | 
91  |  | **              Errors due to bad pointers will probably result in  | 
92  |  | **              exceptions - we don't check for them.  | 
93  |  | */  | 
94  |  | unsigned long  | 
95  |  | PyOS_strtoul(const char *str, char **ptr, int base)  | 
96  | 30  | { | 
97  | 30  |     unsigned long result = 0; /* return value of the function */  | 
98  | 30  |     int c;             /* current input character */  | 
99  | 30  |     int ovlimit;       /* required digits to overflow */  | 
100  |  |  | 
101  |  |     /* skip leading white space */  | 
102  | 30  |     while (*str && Py_ISSPACE(Py_CHARMASK(*str)))  | 
103  | 0  |         ++str;  | 
104  |  |  | 
105  |  |     /* check for leading 0b, 0o or 0x for auto-base or base 16 */  | 
106  | 30  |     switch (base) { | 
107  | 30  |     case 0:             /* look for leading 0b, 0o or 0x */  | 
108  | 30  |         if (*str == '0') { | 
109  | 14  |             ++str;  | 
110  | 14  |             if (*str == 'x' || *str == 'X') { | 
111  |  |                 /* there must be at least one digit after 0x */  | 
112  | 0  |                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) { | 
113  | 0  |                     if (ptr)  | 
114  | 0  |                         *ptr = (char *)str;  | 
115  | 0  |                     return 0;  | 
116  | 0  |                 }  | 
117  | 0  |                 ++str;  | 
118  | 0  |                 base = 16;  | 
119  | 14  |             } else if (*str == 'o' || *str == 'O') { | 
120  |  |                 /* there must be at least one digit after 0o */  | 
121  | 0  |                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) { | 
122  | 0  |                     if (ptr)  | 
123  | 0  |                         *ptr = (char *)str;  | 
124  | 0  |                     return 0;  | 
125  | 0  |                 }  | 
126  | 0  |                 ++str;  | 
127  | 0  |                 base = 8;  | 
128  | 14  |             } else if (*str == 'b' || *str == 'B') { | 
129  |  |                 /* there must be at least one digit after 0b */  | 
130  | 0  |                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) { | 
131  | 0  |                     if (ptr)  | 
132  | 0  |                         *ptr = (char *)str;  | 
133  | 0  |                     return 0;  | 
134  | 0  |                 }  | 
135  | 0  |                 ++str;  | 
136  | 0  |                 base = 2;  | 
137  | 14  |             } else { | 
138  |  |                 /* skip all zeroes... */  | 
139  | 14  |                 while (*str == '0')  | 
140  | 0  |                     ++str;  | 
141  | 14  |                 while (Py_ISSPACE(Py_CHARMASK(*str)))  | 
142  | 0  |                     ++str;  | 
143  | 14  |                 if (ptr)  | 
144  | 14  |                     *ptr = (char *)str;  | 
145  | 14  |                 return 0;  | 
146  | 14  |             }  | 
147  | 14  |         }  | 
148  | 16  |         else  | 
149  | 16  |             base = 10;  | 
150  | 16  |         break;  | 
151  |  |  | 
152  |  |     /* even with explicit base, skip leading 0? prefix */  | 
153  | 16  |     case 16:  | 
154  | 0  |         if (*str == '0') { | 
155  | 0  |             ++str;  | 
156  | 0  |             if (*str == 'x' || *str == 'X') { | 
157  |  |                 /* there must be at least one digit after 0x */  | 
158  | 0  |                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) { | 
159  | 0  |                     if (ptr)  | 
160  | 0  |                         *ptr = (char *)str;  | 
161  | 0  |                     return 0;  | 
162  | 0  |                 }  | 
163  | 0  |                 ++str;  | 
164  | 0  |             }  | 
165  | 0  |         }  | 
166  | 0  |         break;  | 
167  | 0  |     case 8:  | 
168  | 0  |         if (*str == '0') { | 
169  | 0  |             ++str;  | 
170  | 0  |             if (*str == 'o' || *str == 'O') { | 
171  |  |                 /* there must be at least one digit after 0o */  | 
172  | 0  |                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) { | 
173  | 0  |                     if (ptr)  | 
174  | 0  |                         *ptr = (char *)str;  | 
175  | 0  |                     return 0;  | 
176  | 0  |                 }  | 
177  | 0  |                 ++str;  | 
178  | 0  |             }  | 
179  | 0  |         }  | 
180  | 0  |         break;  | 
181  | 0  |     case 2:  | 
182  | 0  |         if(*str == '0') { | 
183  | 0  |             ++str;  | 
184  | 0  |             if (*str == 'b' || *str == 'B') { | 
185  |  |                 /* there must be at least one digit after 0b */  | 
186  | 0  |                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) { | 
187  | 0  |                     if (ptr)  | 
188  | 0  |                         *ptr = (char *)str;  | 
189  | 0  |                     return 0;  | 
190  | 0  |                 }  | 
191  | 0  |                 ++str;  | 
192  | 0  |             }  | 
193  | 0  |         }  | 
194  | 0  |         break;  | 
195  | 30  |     }  | 
196  |  |  | 
197  |  |     /* catch silly bases */  | 
198  | 16  |     if (base < 2 || base > 36) { | 
199  | 0  |         if (ptr)  | 
200  | 0  |             *ptr = (char *)str;  | 
201  | 0  |         return 0;  | 
202  | 0  |     }  | 
203  |  |  | 
204  |  |     /* skip leading zeroes */  | 
205  | 16  |     while (*str == '0')  | 
206  | 0  |         ++str;  | 
207  |  |  | 
208  |  |     /* base is guaranteed to be in [2, 36] at this point */  | 
209  | 16  |     ovlimit = digitlimit[base];  | 
210  |  |  | 
211  |  |     /* do the conversion until non-digit character encountered */  | 
212  | 44  |     while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) { | 
213  | 28  |         if (ovlimit > 0) /* no overflow check required */  | 
214  | 28  |             result = result * base + c;  | 
215  | 0  |         else { /* requires overflow check */ | 
216  | 0  |             unsigned long temp_result;  | 
217  |  | 
  | 
218  | 0  |             if (ovlimit < 0) /* guaranteed overflow */  | 
219  | 0  |                 goto overflowed;  | 
220  |  |  | 
221  |  |             /* there could be an overflow */  | 
222  |  |             /* check overflow just from shifting */  | 
223  | 0  |             if (result > smallmax[base])  | 
224  | 0  |                 goto overflowed;  | 
225  |  |  | 
226  | 0  |             result *= base;  | 
227  |  |  | 
228  |  |             /* check overflow from the digit's value */  | 
229  | 0  |             temp_result = result + c;  | 
230  | 0  |             if (temp_result < result)  | 
231  | 0  |                 goto overflowed;  | 
232  |  |  | 
233  | 0  |             result = temp_result;  | 
234  | 0  |         }  | 
235  |  |  | 
236  | 28  |         ++str;  | 
237  | 28  |         --ovlimit;  | 
238  | 28  |     }  | 
239  |  |  | 
240  |  |     /* set pointer to point to the last character scanned */  | 
241  | 16  |     if (ptr)  | 
242  | 16  |         *ptr = (char *)str;  | 
243  |  |  | 
244  | 16  |     return result;  | 
245  |  |  | 
246  | 0  | overflowed:  | 
247  | 0  |     if (ptr) { | 
248  |  |         /* spool through remaining digit characters */  | 
249  | 0  |         while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)  | 
250  | 0  |             ++str;  | 
251  | 0  |         *ptr = (char *)str;  | 
252  | 0  |     }  | 
253  | 0  |     errno = ERANGE;  | 
254  | 0  |     return (unsigned long)-1;  | 
255  | 16  | }  | 
256  |  |  | 
257  |  | /* Checking for overflow in PyOS_strtol is a PITA; see comments  | 
258  |  |  * about PY_ABS_LONG_MIN in longobject.c.  | 
259  |  |  */  | 
260  | 0  | #define PY_ABS_LONG_MIN         (0-(unsigned long)LONG_MIN)  | 
261  |  |  | 
262  |  | long  | 
263  |  | PyOS_strtol(const char *str, char **ptr, int base)  | 
264  | 16  | { | 
265  | 16  |     long result;  | 
266  | 16  |     unsigned long uresult;  | 
267  | 16  |     char sign;  | 
268  |  |  | 
269  | 16  |     while (*str && Py_ISSPACE(Py_CHARMASK(*str)))  | 
270  | 0  |         str++;  | 
271  |  |  | 
272  | 16  |     sign = *str;  | 
273  | 16  |     if (sign == '+' || sign == '-')  | 
274  | 0  |         str++;  | 
275  |  |  | 
276  | 16  |     uresult = PyOS_strtoul(str, ptr, base);  | 
277  |  |  | 
278  | 16  |     if (uresult <= (unsigned long)LONG_MAX) { | 
279  | 16  |         result = (long)uresult;  | 
280  | 16  |         if (sign == '-')  | 
281  | 0  |             result = -result;  | 
282  | 16  |     }  | 
283  | 0  |     else if (sign == '-' && uresult == PY_ABS_LONG_MIN) { | 
284  | 0  |         result = LONG_MIN;  | 
285  | 0  |     }  | 
286  | 0  |     else { | 
287  | 0  |         errno = ERANGE;  | 
288  |  |         result = LONG_MAX;  | 
289  | 0  |     }  | 
290  | 16  |     return result;  | 
291  | 16  | }  |