source: trunk/libs/newlib/src/newlib/libc/stdlib/wcstoimax.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: 4.3 KB
Line 
1/*-
2 * Copyright (c) 1992, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Copyright (c) 2011 The FreeBSD Foundation
6 * All rights reserved.
7 * Portions of this software were developed by David Chisnall
8 * under sponsorship from the FreeBSD Foundation.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36#if 0
37#if defined(LIBC_SCCS) && !defined(lint)
38static char sccsid[] = "from @(#)strtol.c       8.1 (Berkeley) 6/4/93";
39#endif /* LIBC_SCCS and not lint */
40__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
41#endif
42__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoimax.c 314436 2017-02-28 23:42:47Z imp $");
43
44#include <errno.h>
45#include <inttypes.h>
46#include <stdlib.h>
47#include <wchar.h>
48#include <wctype.h>
49#include <reent.h>
50#include <stdint.h>
51#include "../locale/setlocale.h"
52
53/*
54 * Convert a wide character string to an intmax_t integer.
55 */
56
57/*
58 *Reentrant version of wcstoimax.
59 */
60static intmax_t
61_wcstoimax_l(struct _reent *rptr, const wchar_t * __restrict nptr,
62             wchar_t ** __restrict endptr, int base, locale_t loc)
63{
64        const wchar_t *s = nptr;
65        uintmax_t acc;
66        wchar_t c;
67        uintmax_t cutoff;
68        int neg = 0, any, cutlim;
69
70        /*
71         * See strtoimax for comments as to the logic used.
72         */
73        do {
74                c = *s++;
75        } while (iswspace_l(c, loc));
76        if (c == L'-') {
77                neg = 1;
78                c = *s++;
79        } else {
80                neg = 0;
81                if (c == L'+')
82                        c = *s++;
83        }
84        if ((base == 0 || base == 16) &&
85            c == L'0' && (*s == L'x' || *s == L'X')) {
86                c = s[1];
87                s += 2;
88                base = 16;
89        }
90        if (base == 0)
91                base = c == L'0' ? 8 : 10;
92        acc = any = 0;
93        if (base < 2 || base > 36)
94                goto noconv;
95
96        cutoff = neg ? -(uintmax_t)INTMAX_MIN : INTMAX_MAX;
97        cutlim = cutoff % base;
98        cutoff /= base;
99        for ( ; ; c = *s++) {
100#ifdef notyet
101                if (iswdigit_l(c, loc))
102                        c = digittoint_l(c, loc);
103                else
104#endif
105                if (c >= L'0' && c <= L'9')
106                        c -= L'0';
107                else if (c >= L'A' && c <= L'Z')
108                        c -= L'A' - 10;
109                else if (c >= 'a' && c <= 'z')
110                        c -= L'a' - 10;
111                else
112                        break;
113                if (c >= base)
114                        break;
115                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
116                        any = -1;
117                else {
118                        any = 1;
119                        acc *= base;
120                        acc += c;
121                }
122        }
123        if (any < 0) {
124                acc = neg ? INTMAX_MIN : INTMAX_MAX;
125                rptr->_errno = ERANGE;
126        } else if (!any) {
127noconv:
128                rptr->_errno = EINVAL;
129        } else if (neg)
130                acc = -acc;
131        if (endptr != NULL)
132                *endptr = (wchar_t *)(any ? s - 1 : nptr);
133        return (acc);
134}
135
136intmax_t
137_wcstoimax_r(struct _reent *rptr, const wchar_t *__restrict nptr,
138             wchar_t **__restrict endptr, int base)
139{
140        return _wcstoimax_l(rptr, nptr, endptr, base, __get_current_locale());
141}
142
143#ifndef _REENT_ONLY
144
145intmax_t
146wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
147            int base, locale_t loc)
148{
149        return _wcstoimax_l(_REENT, nptr, endptr, base, loc);
150}
151
152intmax_t
153wcstoimax(const wchar_t* __restrict nptr, wchar_t** __restrict endptr, int base)
154{
155        return _wcstoimax_l(_REENT, nptr, endptr, base, __get_current_locale());
156}
157
158#endif
Note: See TracBrowser for help on using the repository browser.