[gforth] / gforth / engine / strtol.c  

gforth: gforth/engine/strtol.c


1 : anton 1.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 : anton 1.2 not, write to the Free Software Foundation, Inc.,
17 :     59 Temple Place, Suite 330, Boston, MA 02111, USA. */
18 : anton 1.1
19 :     #include "ansidecl.h"
20 :     #include <ctype.h>
21 :     #include <limits.h>
22 :     #include <stddef.h>
23 :     #include <stdlib.h>
24 :     /* errno.h is needed on SunOS 4.1.2 */
25 :     #include <errno.h>
26 :    
27 :     #ifndef UNSIGNED
28 :     #define UNSIGNED 0
29 :     #endif
30 :    
31 :     /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
32 :     If BASE is 0 the base is determined by the presence of a leading
33 :     zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
34 :     If BASE is < 2 or > 36, it is reset to 10.
35 :     If ENDPTR is not NULL, a pointer to the character after the last
36 :     one converted is stored in *ENDPTR. */
37 :     #if UNSIGNED
38 :     unsigned long int
39 :     #define strtol strtoul
40 :     #else
41 :     long int
42 :     #endif
43 :     DEFUN(strtol, (nptr, endptr, base),
44 :     CONST char *nptr AND char **endptr AND int base)
45 :     {
46 :     int negative;
47 :     register unsigned long int cutoff;
48 :     register unsigned int cutlim;
49 :     register unsigned long int i;
50 :     register CONST char *s;
51 :     register unsigned char c;
52 :     CONST char *save;
53 :     int overflow;
54 :    
55 :     if (base < 0 || base == 1 || base > 36)
56 :     base = 10;
57 :    
58 :     s = nptr;
59 :    
60 :     /* Skip white space. */
61 :     while (isspace(*s))
62 :     ++s;
63 :     if (*s == '\0')
64 :     goto noconv;
65 :    
66 :     /* Check for a sign. */
67 :     if (*s == '-')
68 :     {
69 :     negative = 1;
70 :     ++s;
71 :     }
72 :     else if (*s == '+')
73 :     {
74 :     negative = 0;
75 :     ++s;
76 :     }
77 :     else
78 :     negative = 0;
79 :    
80 :     if (base == 16 && s[0] == '0' && toupper(s[1]) == 'X')
81 :     s += 2;
82 :    
83 :     /* If BASE is zero, figure it out ourselves. */
84 :     if (base == 0)
85 :     if (*s == '0')
86 :     {
87 :     if (toupper(s[1]) == 'X')
88 :     {
89 :     s += 2;
90 :     base = 16;
91 :     }
92 :     else
93 :     base = 8;
94 :     }
95 :     else
96 :     base = 10;
97 :    
98 :     /* Save the pointer so we can check later if anything happened. */
99 :     save = s;
100 :    
101 :     cutoff = ULONG_MAX / (unsigned long int) base;
102 :     cutlim = ULONG_MAX % (unsigned long int) base;
103 :    
104 :     overflow = 0;
105 :     i = 0;
106 :     for (c = *s; c != '\0'; c = *++s)
107 :     {
108 :     if (isdigit(c))
109 :     c -= '0';
110 :     else if (isalpha(c))
111 :     c = toupper(c) - 'A' + 10;
112 :     else
113 :     break;
114 :     if (c >= base)
115 :     break;
116 :     /* Check for overflow. */
117 :     if (i > cutoff || (i == cutoff && c > cutlim))
118 :     overflow = 1;
119 :     else
120 :     {
121 :     i *= (unsigned long int) base;
122 :     i += c;
123 :     }
124 :     }
125 :    
126 :     /* Check if anything actually happened. */
127 :     if (s == save)
128 :     goto noconv;
129 :    
130 :     /* Store in ENDPTR the address of one character
131 :     past the last character we converted. */
132 :     if (endptr != NULL)
133 :     *endptr = (char *) s;
134 :    
135 :     #if !UNSIGNED
136 :     /* Check for a value that is within the range of
137 :     `unsigned long int', but outside the range of `long int'. */
138 :     if (i > (negative ?
139 :     - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
140 :     overflow = 1;
141 :     #endif
142 :    
143 :     if (overflow)
144 :     {
145 :     errno = ERANGE;
146 :     #if UNSIGNED
147 :     return ULONG_MAX;
148 :     #else
149 :     return negative ? LONG_MIN : LONG_MAX;
150 :     #endif
151 :     }
152 :    
153 :     /* Return the result of the appropriate sign. */
154 :     return (negative ? - i : i);
155 :    
156 :     noconv:
157 :     /* There was no number to convert. */
158 :     if (endptr != NULL)
159 :     *endptr = (char *) nptr;
160 :     return 0L;
161 :     }

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help