blob: e7c0a570bf5343ef87bb3c3aba12993a88fa5e90 [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
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossumb6775db1994-08-01 11:34:53 +000025#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
Guido van Rossum5c2306c1995-01-17 16:31:21 +000029#include "rename2.h"
30
Guido van Rossumb6775db1994-08-01 11:34:53 +000031/* strtol and strtoul, renamed to avoid conflicts */
32
Guido van Rossumbe0e9421993-12-24 10:32:00 +000033/*
34** strtoul
35** This is a general purpose routine for converting
36** an ascii string to an integer in an arbitrary base.
37** Leading white space is ignored. If 'base' is zero
38** it looks for a leading 0, 0x or 0X to tell which
39** base. If these are absent it defaults to 10.
40** Base must be 0 or between 2 and 36 (inclusive).
41** If 'ptr' is non-NULL it will contain a pointer to
42** the end of the scan.
43** Errors due to bad pointers will probably result in
44** exceptions - we don't check for them.
45*/
46
47#include <ctype.h>
48#include <errno.h>
49
50unsigned long
Guido van Rossumb6775db1994-08-01 11:34:53 +000051mystrtoul(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +000052register char * str;
53char ** ptr;
54int base;
55{
56 register unsigned long result; /* return value of the function */
57 register int c; /* current input character */
58 register unsigned long temp; /* used in overflow testing */
59 int ovf; /* true if overflow occurred */
60
61 result = 0;
62 ovf = 0;
63
64/* catch silly bases */
65 if (base != 0 && (base < 2 || base > 36))
66 {
67 if (ptr)
68 *ptr = str;
69 return 0;
70 }
71
72/* skip leading white space */
73 while (*str && isspace(*str))
74 str++;
75
76/* check for leading 0 or 0x for auto-base or base 16 */
77 switch (base)
78 {
79 case 0: /* look for leading 0, 0x or 0X */
80 if (*str == '0')
81 {
82 str++;
83 if (*str == 'x' || *str == 'X')
84 {
85 str++;
86 base = 16;
87 }
88 else
89 base = 8;
90 }
91 else
92 base = 10;
93 break;
94
95 case 16: /* skip leading 0x or 0X */
96 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
97 str += 2;
98 break;
99 }
100
101/* do the conversion */
102 while (c = *str)
103 {
104 if (isdigit(c) && c - '0' < base)
105 c -= '0';
106 else
107 {
108 if (isupper(c))
109 c = tolower(c);
110 if (c >= 'a' && c <= 'z')
111 c -= 'a' - 10;
112 else /* non-"digit" character */
113 break;
114 if (c >= base) /* non-"digit" character */
115 break;
116 }
117 temp = result;
118 result = result * base + c;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000119#ifndef MPW
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000120 if ((result - c) / base != temp) /* overflow */
121 ovf = 1;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000122#endif
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000123 str++;
124 }
125
126/* set pointer to point to the last character scanned */
127 if (ptr)
128 *ptr = str;
129 if (ovf)
130 {
131 result = ~0;
132 errno = ERANGE;
133 }
134 return result;
135}
136
137long
Guido van Rossumb6775db1994-08-01 11:34:53 +0000138mystrtol(str, ptr, base)
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000139char * str;
140char ** ptr;
141int base;
142{
143 long result;
144 char sign;
145
146 while (*str && isspace(*str))
147 str++;
148
149 sign = *str;
150 if (sign == '+' || sign == '-')
151 str++;
152
Guido van Rossumb6775db1994-08-01 11:34:53 +0000153 result = (long) mystrtoul(str, ptr, base);
Guido van Rossumbe0e9421993-12-24 10:32:00 +0000154
155 /* Signal overflow if the result appears negative,
156 except for the largest negative integer */
157 if (result < 0 && !(sign == '-' && result == -result)) {
158 errno = ERANGE;
159 result = 0x7fffffff;
160 }
161
162 if (sign == '-')
163 result = -result;
164
165 return result;
166}