blob: 29728e5682cb02ea5b98e374e09240831e84ad19 [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
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000047PyOS_strtoul(register char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +000048{
49 register unsigned long result; /* return value of the function */
50 register int c; /* current input character */
51 register unsigned long temp; /* used in overflow testing */
52 int ovf; /* true if overflow occurred */
53
54 result = 0;
55 ovf = 0;
56
57/* catch silly bases */
58 if (base != 0 && (base < 2 || base > 36))
59 {
60 if (ptr)
61 *ptr = str;
62 return 0;
63 }
64
65/* skip leading white space */
Guido van Rossum7f7f2741995-02-10 17:01:56 +000066 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +000067 str++;
68
69/* check for leading 0 or 0x for auto-base or base 16 */
70 switch (base)
71 {
72 case 0: /* look for leading 0, 0x or 0X */
73 if (*str == '0')
74 {
75 str++;
76 if (*str == 'x' || *str == 'X')
77 {
78 str++;
79 base = 16;
80 }
81 else
82 base = 8;
83 }
84 else
85 base = 10;
86 break;
87
88 case 16: /* skip leading 0x or 0X */
89 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
90 str += 2;
91 break;
92 }
93
94/* do the conversion */
Guido van Rossum80bb9651996-12-05 23:27:02 +000095 while ((c = Py_CHARMASK(*str)) != '\0')
Guido van Rossumbe0e9421993-12-24 10:32:00 +000096 {
97 if (isdigit(c) && c - '0' < base)
98 c -= '0';
99 else
100 {
101 if (isupper(c))
102 c = tolower(c);
103 if (c >= 'a' && c <= 'z')
104 c -= 'a' - 10;
105 else /* non-"digit" character */
106 break;
107 if (c >= base) /* non-"digit" character */
108 break;
109 }
110 temp = result;
111 result = result * base + c;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000112#ifndef MPW
Guido van Rossum330aafb1997-12-15 17:27:35 +0000113 if(base == 10) {
Guido van Rossum39b0f891998-04-10 21:52:06 +0000114 if(((long)(result - c) / base != (long)temp)) /* overflow */
Guido van Rossum330aafb1997-12-15 17:27:35 +0000115 ovf = 1;
116 }
117 else {
118 if ((result - c) / base != temp) /* overflow */
119 ovf = 1;
120 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000121#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000122 str++;
123 }
124
125/* set pointer to point to the last character scanned */
126 if (ptr)
127 *ptr = str;
128 if (ovf)
129 {
Guido van Rossum644a12b1997-04-09 19:24:53 +0000130 result = (unsigned long) ~0L;
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000131 errno = ERANGE;
132 }
133 return result;
134}
135
136long
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000137PyOS_strtol(char *str, char **ptr, int base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000138{
139 long result;
140 char sign;
141
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000142 while (*str && isspace(Py_CHARMASK(*str)))
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000143 str++;
144
145 sign = *str;
146 if (sign == '+' || sign == '-')
147 str++;
148
Guido van Rossumee2373b1997-05-07 23:51:07 +0000149 result = (long) PyOS_strtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000150
151 /* Signal overflow if the result appears negative,
152 except for the largest negative integer */
153 if (result < 0 && !(sign == '-' && result == -result)) {
154 errno = ERANGE;
155 result = 0x7fffffff;
156 }
157
158 if (sign == '-')
159 result = -result;
160
161 return result;
162}