blob: f8135e1761b29ad33b51110e4bb3528d794bf2f9 [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 Rossumb6775db1994-08-01 11:34:53 +000032#include "config.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000033
Guido van Rossum7f7f2741995-02-10 17:01:56 +000034/* Convert a possibly signed character to a nonnegative int */
35/* XXX This assumes characters are 8 bits wide */
36#ifdef __CHAR_UNSIGNED__
37#define Py_CHARMASK(c) (c)
38#else
39#define Py_CHARMASK(c) ((c) & 0xff)
40#endif
41
Guido van Rossumb6775db1994-08-01 11:34:53 +000042/* strtol and strtoul, renamed to avoid conflicts */
43
Guido van Rossumbe0e9421993-12-24 10:32:00 +000044/*
45** strtoul
46** This is a general purpose routine for converting
47** an ascii string to an integer in an arbitrary base.
48** Leading white space is ignored. If 'base' is zero
49** it looks for a leading 0, 0x or 0X to tell which
50** base. If these are absent it defaults to 10.
51** Base must be 0 or between 2 and 36 (inclusive).
52** If 'ptr' is non-NULL it will contain a pointer to
53** the end of the scan.
54** Errors due to bad pointers will probably result in
55** exceptions - we don't check for them.
56*/
57
58#include <ctype.h>
59#include <errno.h>
60
61unsigned long
Guido van Rossumee2373b1997-05-07 23:51:07 +000062PyOS_strtoul(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +000063register char * str;
64char ** ptr;
65int base;
66{
67 register unsigned long result; /* return value of the function */
68 register int c; /* current input character */
69 register unsigned long temp; /* used in overflow testing */
70 int ovf; /* true if overflow occurred */
71
72 result = 0;
73 ovf = 0;
74
75/* catch silly bases */
76 if (base != 0 && (base < 2 || base > 36))
77 {
78 if (ptr)
79 *ptr = str;
80 return 0;
81 }
82
83/* skip leading white space */
Guido van Rossum7f7f2741995-02-10 17:01:56 +000084 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +000085 str++;
86
87/* check for leading 0 or 0x for auto-base or base 16 */
88 switch (base)
89 {
90 case 0: /* look for leading 0, 0x or 0X */
91 if (*str == '0')
92 {
93 str++;
94 if (*str == 'x' || *str == 'X')
95 {
96 str++;
97 base = 16;
98 }
99 else
100 base = 8;
101 }
102 else
103 base = 10;
104 break;
105
106 case 16: /* skip leading 0x or 0X */
107 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
108 str += 2;
109 break;
110 }
111
112/* do the conversion */
Guido van Rossum80bb9651996-12-05 23:27:02 +0000113 while ((c = Py_CHARMASK(*str)) != '\0')
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000114 {
115 if (isdigit(c) && c - '0' < base)
116 c -= '0';
117 else
118 {
119 if (isupper(c))
120 c = tolower(c);
121 if (c >= 'a' && c <= 'z')
122 c -= 'a' - 10;
123 else /* non-"digit" character */
124 break;
125 if (c >= base) /* non-"digit" character */
126 break;
127 }
128 temp = result;
129 result = result * base + c;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000130#ifndef MPW
Guido van Rossum330aafb1997-12-15 17:27:35 +0000131 if(base == 10) {
Guido van Rossum39b0f891998-04-10 21:52:06 +0000132 if(((long)(result - c) / base != (long)temp)) /* overflow */
Guido van Rossum330aafb1997-12-15 17:27:35 +0000133 ovf = 1;
134 }
135 else {
136 if ((result - c) / base != temp) /* overflow */
137 ovf = 1;
138 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000139#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000140 str++;
141 }
142
143/* set pointer to point to the last character scanned */
144 if (ptr)
145 *ptr = str;
146 if (ovf)
147 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000148 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000149 errno = ERANGE;
150 }
151 return result;
152}
153
154long
Guido van Rossumee2373b1997-05-07 23:51:07 +0000155PyOS_strtol(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000156char * str;
157char ** ptr;
158int base;
159{
160 long result;
161 char sign;
162
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000163 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000164 str++;
165
166 sign = *str;
167 if (sign == '+' || sign == '-')
168 str++;
169
Guido van Rossumee2373b1997-05-07 23:51:07 +0000170 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000171
172 /* Signal overflow if the result appears negative,
173 except for the largest negative integer */
174 if (result < 0 && !(sign == '-' && result == -result)) {
175 errno = ERANGE;
176 result = 0x7fffffff;
177 }
178
179 if (sign == '-')
180 result = -result;
181
182 return result;
183}