source: trunk/libs/newlib/src/newlib/libc/stdlib/strtol.c @ 577

Last change on this file since 577 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 8.0 KB
Line 
1/*
2FUNCTION
3   <<strtol>>, <<strtol_l>>---string to long
4
5INDEX
6        strtol
7
8INDEX
9        strtol_l
10
11INDEX
12        _strtol_r
13
14SYNOPSIS
15        #include <stdlib.h>
16        long strtol(const char *restrict <[s]>, char **restrict <[ptr]>,
17                    int <[base]>);
18
19        #include <stdlib.h>
20        long strtol_l(const char *restrict <[s]>, char **restrict <[ptr]>,
21                      int <[base]>, locale_t <[locale]>);
22
23        long _strtol_r(void *<[reent]>, const char *restrict <[s]>,
24                       char **restrict <[ptr]>,int <[base]>);
25
26DESCRIPTION
27The function <<strtol>> converts the string <<*<[s]>>> to
28a <<long>>. First, it breaks down the string into three parts:
29leading whitespace, which is ignored; a subject string consisting
30of characters resembling an integer in the radix specified by <[base]>;
31and a trailing portion consisting of zero or more unparseable characters,
32and always including the terminating null character. Then, it attempts
33to convert the subject string into a <<long>> and returns the
34result.
35
36If the value of <[base]> is 0, the subject string is expected to look
37like a normal C integer constant: an optional sign, a possible `<<0x>>'
38indicating a hexadecimal base, and a number. If <[base]> is between
392 and 36, the expected form of the subject is a sequence of letters
40and digits representing an integer in the radix specified by <[base]>,
41with an optional plus or minus sign. The letters <<a>>--<<z>> (or,
42equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35;
43only letters whose ascribed values are less than <[base]> are
44permitted. If <[base]> is 16, a leading <<0x>> is permitted.
45
46The subject sequence is the longest initial sequence of the input
47string that has the expected form, starting with the first
48non-whitespace character.  If the string is empty or consists entirely
49of whitespace, or if the first non-whitespace character is not a
50permissible letter or digit, the subject string is empty.
51
52If the subject string is acceptable, and the value of <[base]> is zero,
53<<strtol>> attempts to determine the radix from the input string. A
54string with a leading <<0x>> is treated as a hexadecimal value; a string with
55a leading 0 and no <<x>> is treated as octal; all other strings are
56treated as decimal. If <[base]> is between 2 and 36, it is used as the
57conversion radix, as described above. If the subject string begins with
58a minus sign, the value is negated. Finally, a pointer to the first
59character past the converted subject string is stored in <[ptr]>, if
60<[ptr]> is not <<NULL>>.
61
62If the subject string is empty (or not in acceptable form), no conversion
63is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
64not <<NULL>>).
65
66<<strtol_l>> is like <<strtol>> but performs the conversion based on the
67locale specified by the locale object locale.  If <[locale]> is
68LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is undefined.
69
70The alternate function <<_strtol_r>> is a reentrant version.  The
71extra argument <[reent]> is a pointer to a reentrancy structure.
72
73RETURNS
74<<strtol>>, <<strtol_l>> return the converted value, if any. If no
75conversion was made, 0 is returned.
76
77<<strtol>>, <<strtol_l>> return <<LONG_MAX>> or <<LONG_MIN>> if the
78magnitude of the converted value is too large, and sets <<errno>>
79to <<ERANGE>>.
80
81PORTABILITY
82<<strtol>> is ANSI.
83<<strtol_l>> is a GNU extension.
84
85No supporting OS subroutines are required.
86*/
87
88/*-
89 * Copyright (c) 1990 The Regents of the University of California.
90 * All rights reserved.
91 *
92 * Redistribution and use in source and binary forms, with or without
93 * modification, are permitted provided that the following conditions
94 * are met:
95 * 1. Redistributions of source code must retain the above copyright
96 *    notice, this list of conditions and the following disclaimer.
97 * 2. Redistributions in binary form must reproduce the above copyright
98 *    notice, this list of conditions and the following disclaimer in the
99 *    documentation and/or other materials provided with the distribution.
100 * 3. All advertising materials mentioning features or use of this software
101 *    must display the following acknowledgement:
102 *      This product includes software developed by the University of
103 *      California, Berkeley and its contributors.
104 * 4. Neither the name of the University nor the names of its contributors
105 *    may be used to endorse or promote products derived from this software
106 *    without specific prior written permission.
107 *
108 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
109 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
110 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
111 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
112 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
113 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
114 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
115 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
116 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
117 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
118 * SUCH DAMAGE.
119 */
120
121#define _GNU_SOURCE
122#include <_ansi.h>
123#include <limits.h>
124#include <ctype.h>
125#include <errno.h>
126#include <stdlib.h>
127#include <reent.h>
128#include "../locale/setlocale.h"
129
130/*
131 * Convert a string to a long integer.
132 */
133static long
134_strtol_l (struct _reent *rptr, const char *__restrict nptr,
135           char **__restrict endptr, int base, locale_t loc)
136{
137        register const unsigned char *s = (const unsigned char *)nptr;
138        register unsigned long acc;
139        register int c;
140        register unsigned long cutoff;
141        register int neg = 0, any, cutlim;
142
143        /*
144         * Skip white space and pick up leading +/- sign if any.
145         * If base is 0, allow 0x for hex and 0 for octal, else
146         * assume decimal; if base is already 16, allow 0x.
147         */
148        do {
149                c = *s++;
150        } while (isspace_l(c, loc));
151        if (c == '-') {
152                neg = 1;
153                c = *s++;
154        } else if (c == '+')
155                c = *s++;
156        if ((base == 0 || base == 16) &&
157            c == '0' && (*s == 'x' || *s == 'X')) {
158                c = s[1];
159                s += 2;
160                base = 16;
161        }
162        if (base == 0)
163                base = c == '0' ? 8 : 10;
164
165        /*
166         * Compute the cutoff value between legal numbers and illegal
167         * numbers.  That is the largest legal value, divided by the
168         * base.  An input number that is greater than this value, if
169         * followed by a legal input character, is too big.  One that
170         * is equal to this value may be valid or not; the limit
171         * between valid and invalid numbers is then based on the last
172         * digit.  For instance, if the range for longs is
173         * [-2147483648..2147483647] and the input base is 10,
174         * cutoff will be set to 214748364 and cutlim to either
175         * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
176         * a value > 214748364, or equal but the next digit is > 7 (or 8),
177         * the number is too big, and we will return a range error.
178         *
179         * Set any if any `digits' consumed; make it negative to indicate
180         * overflow.
181         */
182        cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
183        cutlim = cutoff % (unsigned long)base;
184        cutoff /= (unsigned long)base;
185        for (acc = 0, any = 0;; c = *s++) {
186                if (c >= '0' && c <= '9')
187                        c -= '0';
188                else if (c >= 'A' && c <= 'Z')
189                        c -= 'A' - 10;
190                else if (c >= 'a' && c <= 'z')
191                        c -= 'a' - 10;
192                else
193                        break;
194                if (c >= base)
195                        break;
196               if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
197                        any = -1;
198                else {
199                        any = 1;
200                        acc *= base;
201                        acc += c;
202                }
203        }
204        if (any < 0) {
205                acc = neg ? LONG_MIN : LONG_MAX;
206                rptr->_errno = ERANGE;
207        } else if (neg)
208                acc = -acc;
209        if (endptr != 0)
210                *endptr = (char *) (any ? (char *)s - 1 : nptr);
211        return (acc);
212}
213
214long
215_strtol_r (struct _reent *rptr,
216        const char *__restrict nptr,
217        char **__restrict endptr,
218        int base)
219{
220        return _strtol_l (rptr, nptr, endptr, base, __get_current_locale ());
221}
222
223#ifndef _REENT_ONLY
224
225long
226strtol_l (const char *__restrict s, char **__restrict ptr, int base,
227          locale_t loc)
228{
229        return _strtol_l (_REENT, s, ptr, base, loc);
230}
231
232long
233strtol (const char *__restrict s,
234        char **__restrict ptr,
235        int base)
236{
237        return _strtol_l (_REENT, s, ptr, base, __get_current_locale ());
238}
239
240#endif
Note: See TracBrowser for help on using the repository browser.