blob: b5ea751068be2c514a179d2869683f7abbeb9d71 [file] [log] [blame]
Guido van Rossumbe0e9421993-12-24 10:32:00 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumbe0e9421993-12-24 10:32:00 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumbe0e9421993-12-24 10:32:00 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumbe0e9421993-12-24 10:32:00 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumbe0e9421993-12-24 10:32:00 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumbe0e9421993-12-24 10:32:00 +000029
30******************************************************************/
31
Guido van Rossum1924a061998-12-18 22:02:37 +000032#include "Python.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000033
Guido van Rossume32d1531998-07-07 21:32:53 +000034#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
35#define _SGI_MP_SOURCE
36#endif
37
Guido van Rossum7f7f2741995-02-10 17:01:56 +000038/* Convert a possibly signed character to a nonnegative int */
39/* XXX This assumes characters are 8 bits wide */
40#ifdef __CHAR_UNSIGNED__
41#define Py_CHARMASK(c) (c)
42#else
43#define Py_CHARMASK(c) ((c) & 0xff)
44#endif
45
Guido van Rossumb6775db1994-08-01 11:34:53 +000046/* strtol and strtoul, renamed to avoid conflicts */
47
Guido van Rossumbe0e9421993-12-24 10:32:00 +000048/*
49** strtoul
50** This is a general purpose routine for converting
51** an ascii string to an integer in an arbitrary base.
52** Leading white space is ignored. If 'base' is zero
53** it looks for a leading 0, 0x or 0X to tell which
54** base. If these are absent it defaults to 10.
55** Base must be 0 or between 2 and 36 (inclusive).
56** If 'ptr' is non-NULL it will contain a pointer to
57** the end of the scan.
58** Errors due to bad pointers will probably result in
59** exceptions - we don't check for them.
60*/
61
62#include <ctype.h>
63#include <errno.h>
64
65unsigned long
Guido van Rossumee2373b1997-05-07 23:51:07 +000066PyOS_strtoul(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +000067register char * str;
68char ** ptr;
69int base;
70{
71 register unsigned long result; /* return value of the function */
72 register int c; /* current input character */
73 register unsigned long temp; /* used in overflow testing */
74 int ovf; /* true if overflow occurred */
75
76 result = 0;
77 ovf = 0;
78
79/* catch silly bases */
80 if (base != 0 && (base < 2 || base > 36))
81 {
82 if (ptr)
83 *ptr = str;
84 return 0;
85 }
86
87/* skip leading white space */
Guido van Rossum7f7f2741995-02-10 17:01:56 +000088 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +000089 str++;
90
91/* check for leading 0 or 0x for auto-base or base 16 */
92 switch (base)
93 {
94 case 0: /* look for leading 0, 0x or 0X */
95 if (*str == '0')
96 {
97 str++;
98 if (*str == 'x' || *str == 'X')
99 {
100 str++;
101 base = 16;
102 }
103 else
104 base = 8;
105 }
106 else
107 base = 10;
108 break;
109
110 case 16: /* skip leading 0x or 0X */
111 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
112 str += 2;
113 break;
114 }
115
116/* do the conversion */
Guido van Rossum80bb9651996-12-05 23:27:02 +0000117 while ((c = Py_CHARMASK(*str)) != '\0')
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000118 {
119 if (isdigit(c) && c - '0' < base)
120 c -= '0';
121 else
122 {
123 if (isupper(c))
124 c = tolower(c);
125 if (c >= 'a' && c <= 'z')
126 c -= 'a' - 10;
127 else /* non-"digit" character */
128 break;
129 if (c >= base) /* non-"digit" character */
130 break;
131 }
132 temp = result;
133 result = result * base + c;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000134#ifndef MPW
Guido van Rossum330aafb1997-12-15 17:27:35 +0000135 if(base == 10) {
Guido van Rossum39b0f891998-04-10 21:52:06 +0000136 if(((long)(result - c) / base != (long)temp)) /* overflow */
Guido van Rossum330aafb1997-12-15 17:27:35 +0000137 ovf = 1;
138 }
139 else {
140 if ((result - c) / base != temp) /* overflow */
141 ovf = 1;
142 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000143#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000144 str++;
145 }
146
147/* set pointer to point to the last character scanned */
148 if (ptr)
149 *ptr = str;
150 if (ovf)
151 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000152 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000153 errno = ERANGE;
154 }
155 return result;
156}
157
158long
Guido van Rossumee2373b1997-05-07 23:51:07 +0000159PyOS_strtol(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000160char * str;
161char ** ptr;
162int base;
163{
164 long result;
165 char sign;
166
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000167 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000168 str++;
169
170 sign = *str;
171 if (sign == '+' || sign == '-')
172 str++;
173
Guido van Rossumee2373b1997-05-07 23:51:07 +0000174 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000175
176 /* Signal overflow if the result appears negative,
177 except for the largest negative integer */
178 if (result < 0 && !(sign == '-' && result == -result)) {
179 errno = ERANGE;
180 result = 0x7fffffff;
181 }
182
183 if (sign == '-')
184 result = -result;
185
186 return result;
187}