blob: 6f8e9bd049a349da989b4ac35d5646ae06c10687 [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 Rossumbe0e9421993-12-24 10:32:00 +0000131 if ((result - c) / base != temp) /* overflow */
132 ovf = 1;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000133#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000134 str++;
135 }
136
137/* set pointer to point to the last character scanned */
138 if (ptr)
139 *ptr = str;
140 if (ovf)
141 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000142 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000143 errno = ERANGE;
144 }
145 return result;
146}
147
148long
Guido van Rossumee2373b1997-05-07 23:51:07 +0000149PyOS_strtol(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000150char * str;
151char ** ptr;
152int base;
153{
154 long result;
155 char sign;
156
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000157 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000158 str++;
159
160 sign = *str;
161 if (sign == '+' || sign == '-')
162 str++;
163
Guido van Rossumee2373b1997-05-07 23:51:07 +0000164 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000165
166 /* Signal overflow if the result appears negative,
167 except for the largest negative integer */
168 if (result < 0 && !(sign == '-' && result == -result)) {
169 errno = ERANGE;
170 result = 0x7fffffff;
171 }
172
173 if (sign == '-')
174 result = -result;
175
176 return result;
177}