Annotation of embedaddon/lrzsz/lib/strtol.c, revision 1.1.1.1
1.1 misho 1: /* Copyright (C) 1991, 92, 94, 95, 96 Free Software Foundation, Inc.
2:
3: NOTE: The canonical source of this file is maintained with the GNU C Library.
4: Bugs can be reported to bug-glibc@prep.ai.mit.edu.
5:
6: This program is free software; you can redistribute it and/or modify it
7: under the terms of the GNU General Public License as published by the
8: Free Software Foundation; either version 2, or (at your option) any
9: later version.
10:
11: This program is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with this program; if not, write to the Free Software
18: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19: USA. */
20:
21: #ifdef HAVE_CONFIG_H
22: # include <config.h>
23: #endif
24:
25: #ifdef _LIBC
26: # define USE_NUMBER_GROUPING
27: # define STDC_HEADERS
28: # define HAVE_LIMITS_H
29: #endif
30:
31: #include <ctype.h>
32: #include <errno.h>
33: #ifndef errno
34: extern int errno;
35: #endif
36:
37: #ifdef HAVE_LIMITS_H
38: # include <limits.h>
39: #endif
40:
41: #ifdef STDC_HEADERS
42: # include <stddef.h>
43: # include <stdlib.h>
44: #else
45: # ifndef NULL
46: # define NULL 0
47: # endif
48: #endif
49:
50: #ifdef USE_NUMBER_GROUPING
51: # include "../locale/localeinfo.h"
52: #endif
53:
54: /* Nonzero if we are defining `strtoul' or `strtouq', operating on
55: unsigned integers. */
56: #ifndef UNSIGNED
57: # define UNSIGNED 0
58: # define INT LONG int
59: #else
60: # define INT unsigned LONG int
61: #endif
62:
63: /* Determine the name. */
64: #if UNSIGNED
65: # ifdef USE_WIDE_CHAR
66: # ifdef QUAD
67: # define strtol wcstouq
68: # else
69: # define strtol wcstoul
70: # endif
71: # else
72: # ifdef QUAD
73: # define strtol strtouq
74: # else
75: # define strtol strtoul
76: # endif
77: # endif
78: #else
79: # ifdef USE_WIDE_CHAR
80: # ifdef QUAD
81: # define strtol wcstoq
82: # else
83: # define strtol wcstol
84: # endif
85: # else
86: # ifdef QUAD
87: # define strtol strtoq
88: # endif
89: # endif
90: #endif
91:
92: /* If QUAD is defined, we are defining `strtoq' or `strtouq',
93: operating on `long long int's. */
94: #ifdef QUAD
95: # define LONG long long
96: # undef LONG_MIN
97: # define LONG_MIN LONG_LONG_MIN
98: # undef LONG_MAX
99: # define LONG_MAX LONG_LONG_MAX
100: # undef ULONG_MAX
101: # define ULONG_MAX ULONG_LONG_MAX
102: # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
103: /* Work around gcc bug with using this constant. */
104: static const unsigned long long int maxquad = ULONG_LONG_MAX;
105: # undef ULONG_MAX
106: # define ULONG_MAX maxquad
107: # endif
108: #else
109: # define LONG long
110:
111: #ifndef ULONG_MAX
112: # define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
113: #endif
114: #ifndef LONG_MAX
115: # define LONG_MAX ((long int) (ULONG_MAX >> 1))
116: #endif
117: #endif
118:
119: #ifdef USE_WIDE_CHAR
120: # include <wchar.h>
121: # include <wctype.h>
122: # define L_(ch) L##ch
123: # define UCHAR_TYPE wint_t
124: # define STRING_TYPE wchar_t
125: # define ISSPACE(ch) iswspace (ch)
126: # define ISALPHA(ch) iswalpha (ch)
127: # define TOUPPER(ch) towupper (ch)
128: #else
129: # define L_(ch) ch
130: # define UCHAR_TYPE unsigned char
131: # define STRING_TYPE char
132: # define ISSPACE(ch) isspace (ch)
133: # define ISALPHA(ch) isalpha (ch)
134: # define TOUPPER(ch) toupper (ch)
135: #endif
136:
137: #ifdef __STDC__
138: # define INTERNAL(x) INTERNAL1(x)
139: # define INTERNAL1(x) __##x##_internal
140: # define WEAKNAME(x) WEAKNAME1(x)
141: # define WEAKNAME1(x) __##x
142: #else
143: # define INTERNAL(x) __/**/x/**/_internal
144: # define WEAKNAME(x) __/**/x
145: #endif
146:
147: #ifdef USE_NUMBER_GROUPING
148: /* This file defines a function to check for correct grouping. */
149: # include "grouping.h"
150: #endif
151:
152:
153: /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
154: If BASE is 0 the base is determined by the presence of a leading
155: zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
156: If BASE is < 2 or > 36, it is reset to 10.
157: If ENDPTR is not NULL, a pointer to the character after the last
158: one converted is stored in *ENDPTR. */
159:
160: INT
161: INTERNAL (strtol) (nptr, endptr, base, group)
162: const STRING_TYPE *nptr;
163: STRING_TYPE **endptr;
164: int base;
165: int group;
166: {
167: int negative;
168: register unsigned LONG int cutoff;
169: register unsigned int cutlim;
170: register unsigned LONG int i;
171: register const STRING_TYPE *s;
172: register UCHAR_TYPE c;
173: const STRING_TYPE *save, *end;
174: int overflow;
175:
176: #ifdef USE_NUMBER_GROUPING
177: /* The thousands character of the current locale. */
178: wchar_t thousands;
179: /* The numeric grouping specification of the current locale,
180: in the format described in <locale.h>. */
181: const char *grouping;
182:
183: if (group)
184: {
185: grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
186: if (*grouping <= 0 || *grouping == CHAR_MAX)
187: grouping = NULL;
188: else
189: {
190: /* Figure out the thousands separator character. */
191: if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
192: strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
193: thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
194: if (thousands == L'\0')
195: grouping = NULL;
196: }
197: }
198: else
199: grouping = NULL;
200: #endif
201:
202: if (base < 0 || base == 1 || base > 36)
203: base = 10;
204:
205: save = s = nptr;
206:
207: /* Skip white space. */
208: while (ISSPACE (*s))
209: ++s;
210: if (*s == L_('\0'))
211: goto noconv;
212:
213: /* Check for a sign. */
214: if (*s == L_('-'))
215: {
216: negative = 1;
217: ++s;
218: }
219: else if (*s == L_('+'))
220: {
221: negative = 0;
222: ++s;
223: }
224: else
225: negative = 0;
226:
227: if (base == 16 && s[0] == L_('0') && TOUPPER (s[1]) == L_('X'))
228: s += 2;
229:
230: /* If BASE is zero, figure it out ourselves. */
231: if (base == 0)
232: if (*s == L_('0'))
233: {
234: if (TOUPPER (s[1]) == L_('X'))
235: {
236: s += 2;
237: base = 16;
238: }
239: else
240: base = 8;
241: }
242: else
243: base = 10;
244:
245: /* Save the pointer so we can check later if anything happened. */
246: save = s;
247:
248: #ifdef USE_NUMBER_GROUPING
249: if (group)
250: {
251: /* Find the end of the digit string and check its grouping. */
252: end = s;
253: for (c = *end; c != L_('\0'); c = *++end)
254: if (c != thousands && (c < L_('0') || c > L_('9'))
255: && (!ISALPHA (c) || TOUPPER (c) - L_('A') + 10 >= base))
256: break;
257: if (*s == thousands)
258: end = s;
259: else
260: end = correctly_grouped_prefix (s, end, thousands, grouping);
261: }
262: else
263: #endif
264: end = NULL;
265:
266: cutoff = ULONG_MAX / (unsigned LONG int) base;
267: cutlim = ULONG_MAX % (unsigned LONG int) base;
268:
269: overflow = 0;
270: i = 0;
271: for (c = *s; c != L_('\0'); c = *++s)
272: {
273: if (s == end)
274: break;
275: if (c >= L_('0') && c <= L_('9'))
276: c -= L_('0');
277: else if (ISALPHA (c))
278: c = TOUPPER (c) - L_('A') + 10;
279: else
280: break;
281: if (c >= base)
282: break;
283: /* Check for overflow. */
284: if (i > cutoff || (i == cutoff && c > cutlim))
285: overflow = 1;
286: else
287: {
288: i *= (unsigned LONG int) base;
289: i += c;
290: }
291: }
292:
293: /* Check if anything actually happened. */
294: if (s == save)
295: goto noconv;
296:
297: /* Store in ENDPTR the address of one character
298: past the last character we converted. */
299: if (endptr != NULL)
300: *endptr = (STRING_TYPE *) s;
301:
302: #if !UNSIGNED
303: /* Check for a value that is within the range of
304: `unsigned LONG int', but outside the range of `LONG int'. */
305: if (overflow == 0
306: && i > (negative
307: ? -((unsigned LONG int) (LONG_MIN + 1)) + 1
308: : (unsigned LONG int) LONG_MAX))
309: overflow = 1;
310: #endif
311:
312: if (overflow)
313: {
314: errno = ERANGE;
315: #if UNSIGNED
316: return ULONG_MAX;
317: #else
318: return negative ? LONG_MIN : LONG_MAX;
319: #endif
320: }
321:
322: /* Return the result of the appropriate sign. */
323: return (negative ? -i : i);
324:
325: noconv:
326: /* We must handle a special case here: the base is 0 or 16 and the
327: first two characters and '0' and 'x', but the rest are no
328: hexadecimal digits. This is no error case. We return 0 and
329: ENDPTR points to the `x`. */
330: if (endptr != NULL)
331: if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
332: && save[-2] == L_('0'))
333: *endptr = (STRING_TYPE *) &save[-1];
334: else
335: /* There was no number to convert. */
336: *endptr = (STRING_TYPE *) nptr;
337:
338: return 0L;
339: }
340:
341: /* External user entry point. */
342:
343: #undef __P
344: #if defined (__STDC__) && __STDC__
345: #define __P(args) args
346: #else
347: #define __P(args) ()
348: #endif
349:
350: /* Prototype. */
351: INT strtol __P ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
352: int base));
353:
354:
355: INT
356: strtol (nptr, endptr, base)
357: const STRING_TYPE *nptr;
358: STRING_TYPE **endptr;
359: int base;
360: {
361: return INTERNAL (strtol) (nptr, endptr, base, 0);
362: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>