blob: 272f827c8cf482a4d505b0f43b14750355e7fc9a [file] [log] [blame]
Guido van Rossumbe0e9421993-12-24 10:32:00 +00001
Guido van Rossum1924a061998-12-18 22:02:37 +00002#include "Python.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +00003
Guido van Rossume32d1531998-07-07 21:32:53 +00004#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
5#define _SGI_MP_SOURCE
6#endif
7
Guido van Rossum7f7f2741995-02-10 17:01:56 +00008/* Convert a possibly signed character to a nonnegative int */
9/* XXX This assumes characters are 8 bits wide */
10#ifdef __CHAR_UNSIGNED__
11#define Py_CHARMASK(c) (c)
12#else
13#define Py_CHARMASK(c) ((c) & 0xff)
14#endif
15
Guido van Rossumb6775db1994-08-01 11:34:53 +000016/* strtol and strtoul, renamed to avoid conflicts */
17
Tim Petersb713ec22006-05-23 18:45:30 +000018
19#include <ctype.h>
20#ifndef DONT_HAVE_ERRNO_H
21#include <errno.h>
22#endif
23
24/* Static overflow check values for bases 2 through 36.
25 * smallmax[base] is the largest unsigned long i such that
26 * i * base doesn't overflow unsigned long.
27 */
28static unsigned long smallmax[] = {
29 0, /* bases 0 and 1 are invalid */
30 0,
31 ULONG_MAX / 2,
32 ULONG_MAX / 3,
33 ULONG_MAX / 4,
34 ULONG_MAX / 5,
35 ULONG_MAX / 6,
36 ULONG_MAX / 7,
37 ULONG_MAX / 8,
38 ULONG_MAX / 9,
39 ULONG_MAX / 10,
40 ULONG_MAX / 11,
41 ULONG_MAX / 12,
42 ULONG_MAX / 13,
43 ULONG_MAX / 14,
44 ULONG_MAX / 15,
45 ULONG_MAX / 16,
46 ULONG_MAX / 17,
47 ULONG_MAX / 18,
48 ULONG_MAX / 19,
49 ULONG_MAX / 20,
50 ULONG_MAX / 21,
51 ULONG_MAX / 22,
52 ULONG_MAX / 23,
53 ULONG_MAX / 24,
54 ULONG_MAX / 25,
55 ULONG_MAX / 26,
56 ULONG_MAX / 27,
57 ULONG_MAX / 28,
58 ULONG_MAX / 29,
59 ULONG_MAX / 30,
60 ULONG_MAX / 31,
61 ULONG_MAX / 32,
62 ULONG_MAX / 33,
63 ULONG_MAX / 34,
64 ULONG_MAX / 35,
65 ULONG_MAX / 36,
66};
67
68/* maximum digits that can't ever overflow for bases 2 through 36,
69 * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
70 * Note that this is pessimistic if sizeof(long) > 4.
71 */
72static int digitlimit[] = {
73 0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
74 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
75 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
76 6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
77
78/* char-to-digit conversion for bases 2-36; all non-digits are 37 */
79static int digitlookup[] = {
80 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
81 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
82 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
83 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 37, 37, 37, 37, 37, 37,
84 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
85 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
86 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
87 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
88 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
89 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
90 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
91 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
92 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
93 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
94 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
95 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
96 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
97 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
98 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
99 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
100 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
101 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
102 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
103 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37
104};
105
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000106/*
107** strtoul
108** This is a general purpose routine for converting
109** an ascii string to an integer in an arbitrary base.
110** Leading white space is ignored. If 'base' is zero
111** it looks for a leading 0, 0x or 0X to tell which
112** base. If these are absent it defaults to 10.
113** Base must be 0 or between 2 and 36 (inclusive).
114** If 'ptr' is non-NULL it will contain a pointer to
115** the end of the scan.
116** Errors due to bad pointers will probably result in
117** exceptions - we don't check for them.
118*/
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000119unsigned long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000120PyOS_strtoul(register char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000121{
Tim Petersb713ec22006-05-23 18:45:30 +0000122 register unsigned long result = 0; /* return value of the function */
123 register int c; /* current input character */
124 register int ovlimit; /* required digits to overflow */
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000125
Tim Petersb713ec22006-05-23 18:45:30 +0000126 /* skip leading white space */
127 while (*str && isspace(Py_CHARMASK(*str)))
128 ++str;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000129
Tim Petersb713ec22006-05-23 18:45:30 +0000130 /* check for leading 0 or 0x for auto-base or base 16 */
131 switch (base) {
132 case 0: /* look for leading 0, 0x or 0X */
133 if (*str == '0') {
134 ++str;
135 if (*str == 'x' || *str == 'X') {
136 ++str;
137 base = 16;
138 }
139 else
140 base = 8;
141 }
142 else
143 base = 10;
144 break;
145
146 case 16: /* skip leading 0x or 0X */
147 if (*str == '0') {
148 ++str;
149 if (*str == 'x' || *str == 'X')
150 ++str;
151 }
152 break;
153 }
154
155 /* catch silly bases */
156 if (base < 2 || base > 36) {
157 if (ptr)
158 *ptr = str;
159 return 0;
160 }
161
162 /* skip leading zeroes */
163 while (*str == '0')
164 ++str;
165
166 /* base is guaranteed to be in [2, 36] at this point */
167 ovlimit = digitlimit[base];
168
169 /* do the conversion until non-digit character encountered */
170 while ((c = digitlookup[Py_CHARMASK(*str)]) < base) {
171 if (ovlimit > 0) /* no overflow check required */
172 result = result * base + c;
173 else { /* requires overflow check */
174 register unsigned long temp_result;
175
176 if (ovlimit < 0) /* guaranteed overflow */
177 goto overflowed;
178
179 /* there could be an overflow */
180 /* check overflow just from shifting */
181 if (result > smallmax[base])
182 goto overflowed;
183
184 result *= base;
185
186 /* check overflow from the digit's value */
187 temp_result = result + c;
188 if (temp_result < result)
189 goto overflowed;
190
191 result = temp_result;
192 }
193
194 ++str;
195 --ovlimit;
196 }
197
198 /* set pointer to point to the last character scanned */
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000199 if (ptr)
Tim Petersb713ec22006-05-23 18:45:30 +0000200 *ptr = str;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000201
Tim Petersb713ec22006-05-23 18:45:30 +0000202 return result;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000203
Tim Petersb713ec22006-05-23 18:45:30 +0000204overflowed:
205 if (ptr) {
206 /* spool through remaining digit characters */
207 while (digitlookup[Py_CHARMASK(*str)] < base)
208 ++str;
209 *ptr = str;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000210 }
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000211 errno = ERANGE;
Tim Petersb713ec22006-05-23 18:45:30 +0000212 return (unsigned long)-1;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000213}
214
215long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000216PyOS_strtol(char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000217{
218 long result;
219 char sign;
Tim Petersb713ec22006-05-23 18:45:30 +0000220
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000221 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000222 str++;
Tim Petersb713ec22006-05-23 18:45:30 +0000223
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000224 sign = *str;
225 if (sign == '+' || sign == '-')
226 str++;
Tim Petersb713ec22006-05-23 18:45:30 +0000227
Guido van Rossumee2373b1997-05-07 23:51:07 +0000228 result = (long) PyOS_strtoul(str, ptr, base);
Tim Petersb713ec22006-05-23 18:45:30 +0000229
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000230 /* Signal overflow if the result appears negative,
231 except for the largest negative integer */
232 if (result < 0 && !(sign == '-' && result == -result)) {
233 errno = ERANGE;
234 result = 0x7fffffff;
235 }
Tim Petersb713ec22006-05-23 18:45:30 +0000236
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000237 if (sign == '-')
238 result = -result;
Tim Petersb713ec22006-05-23 18:45:30 +0000239
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000240 return result;
241}