Catch situations where currentframe() returns None. See SF patch #1447410, this is...
[python.git] / Python / mystrtoul.c
blob8e60c0c0726106ad194f3e7f0e369aafa3fa68e4
2 #include "Python.h"
4 #if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
5 #define _SGI_MP_SOURCE
6 #endif
8 /* 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
16 /* strtol and strtoul, renamed to avoid conflicts */
19 ** strtoul
20 ** This is a general purpose routine for converting
21 ** an ascii string to an integer in an arbitrary base.
22 ** Leading white space is ignored. If 'base' is zero
23 ** it looks for a leading 0, 0x or 0X to tell which
24 ** base. If these are absent it defaults to 10.
25 ** Base must be 0 or between 2 and 36 (inclusive).
26 ** If 'ptr' is non-NULL it will contain a pointer to
27 ** the end of the scan.
28 ** Errors due to bad pointers will probably result in
29 ** exceptions - we don't check for them.
32 #include <ctype.h>
33 #ifndef DONT_HAVE_ERRNO_H
34 #include <errno.h>
35 #endif
37 unsigned long
38 PyOS_strtoul(register char *str, char **ptr, int base)
40 register unsigned long result; /* return value of the function */
41 register int c; /* current input character */
42 register unsigned long temp; /* used in overflow testing */
43 int ovf; /* true if overflow occurred */
45 result = 0;
46 ovf = 0;
48 /* catch silly bases */
49 if (base != 0 && (base < 2 || base > 36))
51 if (ptr)
52 *ptr = str;
53 return 0;
56 /* skip leading white space */
57 while (*str && isspace(Py_CHARMASK(*str)))
58 str++;
60 /* check for leading 0 or 0x for auto-base or base 16 */
61 switch (base)
63 case 0: /* look for leading 0, 0x or 0X */
64 if (*str == '0')
66 str++;
67 if (*str == 'x' || *str == 'X')
69 str++;
70 base = 16;
72 else
73 base = 8;
75 else
76 base = 10;
77 break;
79 case 16: /* skip leading 0x or 0X */
80 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
81 str += 2;
82 break;
85 /* do the conversion */
86 while ((c = Py_CHARMASK(*str)) != '\0')
88 if (isdigit(c) && c - '0' < base)
89 c -= '0';
90 else
92 if (isupper(c))
93 c = tolower(c);
94 if (c >= 'a' && c <= 'z')
95 c -= 'a' - 10;
96 else /* non-"digit" character */
97 break;
98 if (c >= base) /* non-"digit" character */
99 break;
101 temp = result;
102 result = result * base + c;
103 if(base == 10) {
104 if(((long)(result - c) / base != (long)temp)) /* overflow */
105 ovf = 1;
107 else {
108 if ((result - c) / base != temp) /* overflow */
109 ovf = 1;
111 str++;
114 /* set pointer to point to the last character scanned */
115 if (ptr)
116 *ptr = str;
117 if (ovf)
119 result = (unsigned long) ~0L;
120 errno = ERANGE;
122 return result;
125 long
126 PyOS_strtol(char *str, char **ptr, int base)
128 long result;
129 char sign;
131 while (*str && isspace(Py_CHARMASK(*str)))
132 str++;
134 sign = *str;
135 if (sign == '+' || sign == '-')
136 str++;
138 result = (long) PyOS_strtoul(str, ptr, base);
140 /* Signal overflow if the result appears negative,
141 except for the largest negative integer */
142 if (result < 0 && !(sign == '-' && result == -result)) {
143 errno = ERANGE;
144 result = 0x7fffffff;
147 if (sign == '-')
148 result = -result;
150 return result;