blob: db98d2b31a50db71a60ede594bfa78e1b11d8166 [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
Guido van Rossumbe0e9421993-12-24 10:32:00 +000018/*
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.
30*/
31
32#include <ctype.h>
Guido van Rossum2571cc81999-04-07 16:07:23 +000033#ifndef DONT_HAVE_ERRNO_H
Guido van Rossumbe0e9421993-12-24 10:32:00 +000034#include <errno.h>
Guido van Rossum2571cc81999-04-07 16:07:23 +000035#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +000036
37unsigned long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000038PyOS_strtoul(register char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +000039{
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 */
44
45 result = 0;
46 ovf = 0;
47
48/* catch silly bases */
49 if (base != 0 && (base < 2 || base > 36))
50 {
51 if (ptr)
52 *ptr = str;
53 return 0;
54 }
55
56/* skip leading white space */
Guido van Rossum7f7f2741995-02-10 17:01:56 +000057 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +000058 str++;
59
60/* check for leading 0 or 0x for auto-base or base 16 */
61 switch (base)
62 {
63 case 0: /* look for leading 0, 0x or 0X */
64 if (*str == '0')
65 {
66 str++;
67 if (*str == 'x' || *str == 'X')
68 {
69 str++;
70 base = 16;
71 }
72 else
73 base = 8;
74 }
75 else
76 base = 10;
77 break;
78
79 case 16: /* skip leading 0x or 0X */
80 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
81 str += 2;
82 break;
83 }
84
85/* do the conversion */
Guido van Rossum80bb9651996-12-05 23:27:02 +000086 while ((c = Py_CHARMASK(*str)) != '\0')
Guido van Rossumbe0e9421993-12-24 10:32:00 +000087 {
88 if (isdigit(c) && c - '0' < base)
89 c -= '0';
90 else
91 {
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;
100 }
101 temp = result;
102 result = result * base + c;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000103#ifndef MPW
Guido van Rossum330aafb1997-12-15 17:27:35 +0000104 if(base == 10) {
Guido van Rossum39b0f891998-04-10 21:52:06 +0000105 if(((long)(result - c) / base != (long)temp)) /* overflow */
Guido van Rossum330aafb1997-12-15 17:27:35 +0000106 ovf = 1;
107 }
108 else {
109 if ((result - c) / base != temp) /* overflow */
110 ovf = 1;
111 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000112#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000113 str++;
114 }
115
116/* set pointer to point to the last character scanned */
117 if (ptr)
118 *ptr = str;
119 if (ovf)
120 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000121 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000122 errno = ERANGE;
123 }
124 return result;
125}
126
127long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000128PyOS_strtol(char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000129{
130 long result;
131 char sign;
132
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000133 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000134 str++;
135
136 sign = *str;
137 if (sign == '+' || sign == '-')
138 str++;
139
Guido van Rossumee2373b1997-05-07 23:51:07 +0000140 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000141
142 /* Signal overflow if the result appears negative,
143 except for the largest negative integer */
144 if (result < 0 && !(sign == '-' && result == -result)) {
145 errno = ERANGE;
146 result = 0x7fffffff;
147 }
148
149 if (sign == '-')
150 result = -result;
151
152 return result;
153}