Annotation of gforth/strtol.c, revision 1.2
1.1 anton 1: /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
2: This file is part of the GNU C Library.
3:
4: The GNU C Library is free software; you can redistribute it and/or
5: modify it under the terms of the GNU Library General Public License as
6: published by the Free Software Foundation; either version 2 of the
7: License, or (at your option) any later version.
8:
9: The GNU C Library is distributed in the hope that it will be useful,
10: but WITHOUT ANY WARRANTY; without even the implied warranty of
11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12: Library General Public License for more details.
13:
14: You should have received a copy of the GNU Library General Public
15: License along with the GNU C Library; see the file COPYING.LIB. If
16: not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17: Cambridge, MA 02139, USA. */
18:
1.2 ! anton 19: #include "ansidecl.h"
1.1 anton 20: #include <ctype.h>
21: #include <limits.h>
22: #include <stddef.h>
23: #include <stdlib.h>
24:
25:
26: #ifndef UNSIGNED
27: #define UNSIGNED 0
28: #endif
29:
30: /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
31: If BASE is 0 the base is determined by the presence of a leading
32: zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
33: If BASE is < 2 or > 36, it is reset to 10.
34: If ENDPTR is not NULL, a pointer to the character after the last
35: one converted is stored in *ENDPTR. */
36: #if UNSIGNED
37: unsigned long int
38: #define strtol strtoul
39: #else
40: long int
41: #endif
42: DEFUN(strtol, (nptr, endptr, base),
43: CONST char *nptr AND char **endptr AND int base)
44: {
45: int negative;
46: register unsigned long int cutoff;
47: register unsigned int cutlim;
48: register unsigned long int i;
49: register CONST char *s;
50: register unsigned char c;
51: CONST char *save;
52: int overflow;
53:
54: if (base < 0 || base == 1 || base > 36)
55: base = 10;
56:
57: s = nptr;
58:
59: /* Skip white space. */
60: while (isspace(*s))
61: ++s;
62: if (*s == '\0')
63: goto noconv;
64:
65: /* Check for a sign. */
66: if (*s == '-')
67: {
68: negative = 1;
69: ++s;
70: }
71: else if (*s == '+')
72: {
73: negative = 0;
74: ++s;
75: }
76: else
77: negative = 0;
78:
79: if (base == 16 && s[0] == '0' && toupper(s[1]) == 'X')
80: s += 2;
81:
82: /* If BASE is zero, figure it out ourselves. */
83: if (base == 0)
84: if (*s == '0')
85: {
86: if (toupper(s[1]) == 'X')
87: {
88: s += 2;
89: base = 16;
90: }
91: else
92: base = 8;
93: }
94: else
95: base = 10;
96:
97: /* Save the pointer so we can check later if anything happened. */
98: save = s;
99:
100: cutoff = ULONG_MAX / (unsigned long int) base;
101: cutlim = ULONG_MAX % (unsigned long int) base;
102:
103: overflow = 0;
104: i = 0;
105: for (c = *s; c != '\0'; c = *++s)
106: {
107: if (isdigit(c))
108: c -= '0';
109: else if (isalpha(c))
110: c = toupper(c) - 'A' + 10;
111: else
112: break;
113: if (c >= base)
114: break;
115: /* Check for overflow. */
116: if (i > cutoff || (i == cutoff && c > cutlim))
117: overflow = 1;
118: else
119: {
120: i *= (unsigned long int) base;
121: i += c;
122: }
123: }
124:
125: /* Check if anything actually happened. */
126: if (s == save)
127: goto noconv;
128:
129: /* Store in ENDPTR the address of one character
130: past the last character we converted. */
131: if (endptr != NULL)
132: *endptr = (char *) s;
133:
134: #if !UNSIGNED
135: /* Check for a value that is within the range of
136: `unsigned long int', but outside the range of `long int'. */
137: if (i > (negative ?
138: - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
139: overflow = 1;
140: #endif
141:
142: if (overflow)
143: {
144: errno = ERANGE;
145: #if UNSIGNED
146: return ULONG_MAX;
147: #else
148: return negative ? LONG_MIN : LONG_MAX;
149: #endif
150: }
151:
152: /* Return the result of the appropriate sign. */
153: return (negative ? - i : i);
154:
155: noconv:
156: /* There was no number to convert. */
157: if (endptr != NULL)
158: *endptr = (char *) nptr;
159: return 0L;
160: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>