blob: 8e60c0c0726106ad194f3e7f0e369aafa3fa68e4 [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 Rossum330aafb1997-12-15 17:27:35 +0000103 if(base == 10) {
Guido van Rossum39b0f891998-04-10 21:52:06 +0000104 if(((long)(result - c) / base != (long)temp)) /* overflow */
Guido van Rossum330aafb1997-12-15 17:27:35 +0000105 ovf = 1;
106 }
107 else {
108 if ((result - c) / base != temp) /* overflow */
109 ovf = 1;
110 }
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000111 str++;
112 }
113
114/* set pointer to point to the last character scanned */
115 if (ptr)
116 *ptr = str;
117 if (ovf)
118 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000119 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000120 errno = ERANGE;
121 }
122 return result;
123}
124
125long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000126PyOS_strtol(char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000127{
128 long result;
129 char sign;
130
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000131 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000132 str++;
133
134 sign = *str;
135 if (sign == '+' || sign == '-')
136 str++;
137
Guido van Rossumee2373b1997-05-07 23:51:07 +0000138 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000139
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;
145 }
146
147 if (sign == '-')
148 result = -result;
149
150 return result;
151}