blob: f785c51e31a207ca31bff6bd239c7d581bdc8c2e [file] [log] [blame]
Guido van Rossumbe0e9421993-12-24 10:32:00 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossumbe0e9421993-12-24 10:32:00 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossumbe0e9421993-12-24 10:32:00 +00009******************************************************************/
10
Guido van Rossum1924a061998-12-18 22:02:37 +000011#include "Python.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000012
Guido van Rossume32d1531998-07-07 21:32:53 +000013#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
14#define _SGI_MP_SOURCE
15#endif
16
Guido van Rossum7f7f2741995-02-10 17:01:56 +000017/* Convert a possibly signed character to a nonnegative int */
18/* XXX This assumes characters are 8 bits wide */
19#ifdef __CHAR_UNSIGNED__
20#define Py_CHARMASK(c) (c)
21#else
22#define Py_CHARMASK(c) ((c) & 0xff)
23#endif
24
Guido van Rossumb6775db1994-08-01 11:34:53 +000025/* strtol and strtoul, renamed to avoid conflicts */
26
Guido van Rossumbe0e9421993-12-24 10:32:00 +000027/*
28** strtoul
29** This is a general purpose routine for converting
30** an ascii string to an integer in an arbitrary base.
31** Leading white space is ignored. If 'base' is zero
32** it looks for a leading 0, 0x or 0X to tell which
33** base. If these are absent it defaults to 10.
34** Base must be 0 or between 2 and 36 (inclusive).
35** If 'ptr' is non-NULL it will contain a pointer to
36** the end of the scan.
37** Errors due to bad pointers will probably result in
38** exceptions - we don't check for them.
39*/
40
41#include <ctype.h>
Guido van Rossum2571cc81999-04-07 16:07:23 +000042#ifndef DONT_HAVE_ERRNO_H
Guido van Rossumbe0e9421993-12-24 10:32:00 +000043#include <errno.h>
Guido van Rossum2571cc81999-04-07 16:07:23 +000044#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +000045
46unsigned long
Guido van Rossumee2373b1997-05-07 23:51:07 +000047PyOS_strtoul(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +000048register char * str;
49char ** ptr;
50int base;
51{
52 register unsigned long result; /* return value of the function */
53 register int c; /* current input character */
54 register unsigned long temp; /* used in overflow testing */
55 int ovf; /* true if overflow occurred */
56
57 result = 0;
58 ovf = 0;
59
60/* catch silly bases */
61 if (base != 0 && (base < 2 || base > 36))
62 {
63 if (ptr)
64 *ptr = str;
65 return 0;
66 }
67
68/* skip leading white space */
Guido van Rossum7f7f2741995-02-10 17:01:56 +000069 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +000070 str++;
71
72/* check for leading 0 or 0x for auto-base or base 16 */
73 switch (base)
74 {
75 case 0: /* look for leading 0, 0x or 0X */
76 if (*str == '0')
77 {
78 str++;
79 if (*str == 'x' || *str == 'X')
80 {
81 str++;
82 base = 16;
83 }
84 else
85 base = 8;
86 }
87 else
88 base = 10;
89 break;
90
91 case 16: /* skip leading 0x or 0X */
92 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
93 str += 2;
94 break;
95 }
96
97/* do the conversion */
Guido van Rossum80bb9651996-12-05 23:27:02 +000098 while ((c = Py_CHARMASK(*str)) != '\0')
Guido van Rossumbe0e9421993-12-24 10:32:00 +000099 {
100 if (isdigit(c) && c - '0' < base)
101 c -= '0';
102 else
103 {
104 if (isupper(c))
105 c = tolower(c);
106 if (c >= 'a' && c <= 'z')
107 c -= 'a' - 10;
108 else /* non-"digit" character */
109 break;
110 if (c >= base) /* non-"digit" character */
111 break;
112 }
113 temp = result;
114 result = result * base + c;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000115#ifndef MPW
Guido van Rossum330aafb1997-12-15 17:27:35 +0000116 if(base == 10) {
Guido van Rossum39b0f891998-04-10 21:52:06 +0000117 if(((long)(result - c) / base != (long)temp)) /* overflow */
Guido van Rossum330aafb1997-12-15 17:27:35 +0000118 ovf = 1;
119 }
120 else {
121 if ((result - c) / base != temp) /* overflow */
122 ovf = 1;
123 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000124#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000125 str++;
126 }
127
128/* set pointer to point to the last character scanned */
129 if (ptr)
130 *ptr = str;
131 if (ovf)
132 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000133 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000134 errno = ERANGE;
135 }
136 return result;
137}
138
139long
Guido van Rossumee2373b1997-05-07 23:51:07 +0000140PyOS_strtol(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000141char * str;
142char ** ptr;
143int base;
144{
145 long result;
146 char sign;
147
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000148 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000149 str++;
150
151 sign = *str;
152 if (sign == '+' || sign == '-')
153 str++;
154
Guido van Rossumee2373b1997-05-07 23:51:07 +0000155 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000156
157 /* Signal overflow if the result appears negative,
158 except for the largest negative integer */
159 if (result < 0 && !(sign == '-' && result == -result)) {
160 errno = ERANGE;
161 result = 0x7fffffff;
162 }
163
164 if (sign == '-')
165 result = -result;
166
167 return result;
168}