Add %b and %B support to the scanf/wscanf and strto*/wcsto* families.
Coming to C23 via WG14 N2630.
This one is a little interesting, because it actually changes existing
behavior. Previously "0b101" would be parsed as "0", "b", "101" by these
functions. I'm led to believe that glibc plans to actually have separate
versions of these functions for C23 and pre-C23, so callers can have the
behavior they (implicitly) specify by virtue of which -std= they compile
with. Android has never really done anything like that, and I'm pretty
sure app developers have more than enough to worry about with API levels
without having to deal with the cartesian product of API level and C
standard.
Therefore, my plan A is "if you're running on Android >= U, you get C23
behavior". My plan B in the (I think unlikely) event that that actually
causes trouble for anyone is "if you're _targeting_ Android >= U, you
get C23 behavior". I don't think we'd actually want to have two versions
of each of these functions under any circumstances --- that seems by far
the most confusing option.
Test: treehugger
Change-Id: I0bbb30315d3fabd306905ad1484361f5d8745935
diff --git a/libc/Android.bp b/libc/Android.bp
index b7cb59d..f064047 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -35,7 +35,7 @@
"stdio/stdio.cpp",
"stdio/stdio_ext.cpp",
"stdio/vfscanf.cpp",
- "stdio/vfwscanf.c",
+ "stdio/vfwscanf.cpp",
]
// off64_t/time64_t support on LP32.
@@ -500,13 +500,7 @@
"upstream-openbsd/lib/libc/locale/mbstowcs.c",
"upstream-openbsd/lib/libc/locale/mbtowc.c",
"upstream-openbsd/lib/libc/locale/wcscoll.c",
- "upstream-openbsd/lib/libc/locale/wcstoimax.c",
- "upstream-openbsd/lib/libc/locale/wcstol.c",
- "upstream-openbsd/lib/libc/locale/wcstoll.c",
"upstream-openbsd/lib/libc/locale/wcstombs.c",
- "upstream-openbsd/lib/libc/locale/wcstoul.c",
- "upstream-openbsd/lib/libc/locale/wcstoull.c",
- "upstream-openbsd/lib/libc/locale/wcstoumax.c",
"upstream-openbsd/lib/libc/locale/wcsxfrm.c",
"upstream-openbsd/lib/libc/locale/wctob.c",
"upstream-openbsd/lib/libc/locale/wctomb.c",
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index 77f1d92..ec72b09 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -32,11 +32,13 @@
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
+#include <wchar.h>
-template <typename T, T Min, T Max> T StrToI(const char* nptr, char** endptr, int base) {
+template <typename T, T Min, T Max, typename CharT>
+T StrToI(const CharT* nptr, CharT** endptr, int base) {
// Ensure that base is between 2 and 36 inclusive, or the special value of 0.
if (base < 0 || base == 1 || base > 36) {
- if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(nptr);
errno = EINVAL;
return 0;
}
@@ -44,7 +46,7 @@
// Skip white space and pick up leading +/- sign if any.
// If base is 0, allow 0x for hex and 0 for octal, else
// assume decimal; if base is already 16, allow 0x.
- const char* s = nptr;
+ const CharT* s = nptr;
int c;
do {
c = *s++;
@@ -62,6 +64,11 @@
s += 2;
base = 16;
}
+ if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B') && isdigit(s[1])) {
+ c = s[1];
+ s += 2;
+ base = 2;
+ }
if (base == 0) base = (c == '0') ? 8 : 10;
// We always work in the negative space because the most negative value has a
@@ -91,7 +98,7 @@
acc -= c;
}
}
- if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(any ? s - 1 : nptr);
if (!neg) {
if (acc == Min) {
errno = ERANGE;
@@ -103,14 +110,15 @@
return acc;
}
-template <typename T, T Max> T StrToU(const char* nptr, char** endptr, int base) {
+template <typename T, T Max, typename CharT>
+T StrToU(const CharT* nptr, CharT** endptr, int base) {
if (base < 0 || base == 1 || base > 36) {
- if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(nptr);
errno = EINVAL;
return 0;
}
- const char* s = nptr;
+ const CharT* s = nptr;
int c;
do {
c = *s++;
@@ -128,6 +136,11 @@
s += 2;
base = 16;
}
+ if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B') && isdigit(s[1])) {
+ c = s[1];
+ s += 2;
+ base = 2;
+ }
if (base == 0) base = (c == '0') ? 8 : 10;
T cutoff = Max / static_cast<T>(base);
@@ -155,7 +168,7 @@
}
}
if (neg && any > 0) acc = -acc;
- if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
+ if (endptr != nullptr) *endptr = const_cast<CharT*>(any ? s - 1 : nptr);
return acc;
}
@@ -172,30 +185,54 @@
}
intmax_t strtoimax(const char* s, char** end, int base) {
- return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX>(s, end, base);
+ return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX, char>(s, end, base);
+}
+
+intmax_t wcstoimax(const wchar_t* s, wchar_t** end, int base) {
+ return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX, wchar_t>(s, end, base);
}
long strtol(const char* s, char** end, int base) {
- return StrToI<long, LONG_MIN, LONG_MAX>(s, end, base);
+ return StrToI<long, LONG_MIN, LONG_MAX, char>(s, end, base);
+}
+
+long wcstol(const wchar_t* s, wchar_t** end, int base) {
+ return StrToI<long, LONG_MIN, LONG_MAX, wchar_t>(s, end, base);
}
long long strtoll(const char* s, char** end, int base) {
- return StrToI<long long, LLONG_MIN, LLONG_MAX>(s, end, base);
+ return StrToI<long long, LLONG_MIN, LLONG_MAX, char>(s, end, base);
+}
+
+long long wcstoll(const wchar_t* s, wchar_t** end, int base) {
+ return StrToI<long long, LLONG_MIN, LLONG_MAX, wchar_t>(s, end, base);
}
// Public API since L, but not in any header.
__strong_alias(strtoq, strtoll);
unsigned long strtoul(const char* s, char** end, int base) {
- return StrToU<unsigned long, ULONG_MAX>(s, end, base);
+ return StrToU<unsigned long, ULONG_MAX, char>(s, end, base);
+}
+
+unsigned long wcstoul(const wchar_t* s, wchar_t** end, int base) {
+ return StrToU<unsigned long, ULONG_MAX, wchar_t>(s, end, base);
}
unsigned long long strtoull(const char* s, char** end, int base) {
- return StrToU<unsigned long long, ULLONG_MAX>(s, end, base);
+ return StrToU<unsigned long long, ULLONG_MAX, char>(s, end, base);
+}
+
+unsigned long long wcstoull(const wchar_t* s, wchar_t** end, int base) {
+ return StrToU<unsigned long long, ULLONG_MAX, wchar_t>(s, end, base);
}
uintmax_t strtoumax(const char* s, char** end, int base) {
- return StrToU<uintmax_t, UINTMAX_MAX>(s, end, base);
+ return StrToU<uintmax_t, UINTMAX_MAX, char>(s, end, base);
+}
+
+uintmax_t wcstoumax(const wchar_t* s, wchar_t** end, int base) {
+ return StrToU<uintmax_t, UINTMAX_MAX, wchar_t>(s, end, base);
}
// Public API since L, but not in any header.
diff --git a/libc/stdio/vfscanf.cpp b/libc/stdio/vfscanf.cpp
index 424c4ef..d05a3a6 100644
--- a/libc/stdio/vfscanf.cpp
+++ b/libc/stdio/vfscanf.cpp
@@ -69,7 +69,8 @@
#define HAVESIGN 0x04000 // Sign detected
#define NDIGITS 0x08000 // No digits detected
#define PFXOK 0x10000 // "0x" prefix is (still) legal
-#define NZDIGITS 0x20000 // No zero digits detected
+#define PFBOK 0x20000 // "0b" prefix is (still) legal
+#define NZDIGITS 0x40000 // No zero digits detected
// Conversion types.
#define CT_CHAR 0 // %c conversion
@@ -101,9 +102,6 @@
void* allocation = nullptr; // Allocated but unassigned result for %mc/%ms/%m[.
size_t capacity = 0; // Number of char/wchar_t units allocated in `allocation`.
- /* `basefix' is used to avoid `if' tests in the integer scanner */
- static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
-
_SET_ORIENTATION(fp, -1);
nassigned = 0;
@@ -188,6 +186,12 @@
* Conversions.
* Those marked `compat' are for 4.[123]BSD compatibility.
*/
+ case 'b':
+ c = CT_INT;
+ base = 2;
+ flags |= PFBOK; /* enable 0b prefixing */
+ break;
+
case 'D': /* compat */
flags |= LONG;
__BIONIC_FALLTHROUGH;
@@ -558,7 +562,7 @@
* digits (zero or nonzero) have been
* scanned (only signs), we will have
* base==0. In that case, we should set
- * it to 8 and enable 0x prefixing.
+ * it to 8 and enable 0b/0x prefixing.
* Also, if we have not scanned zero digits
* before this, do not turn off prefixing
* (someone else will turn it off if we
@@ -567,15 +571,24 @@
case '0':
if (base == 0) {
base = 8;
- flags |= PFXOK;
+ flags |= PFBOK | PFXOK;
}
- if (flags & NZDIGITS)
+ if (flags & NZDIGITS) {
flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
- else
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ } else {
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
+ }
goto ok;
-
- /* 1 through 7 always legal */
+ case 'B':
+ case 'b':
+ // Is this 'b' or 'B' potentially part of an "0b" prefix?
+ if ((flags & PFBOK) && p == buf + 1 + !!(flags & HAVESIGN)) {
+ base = 2;
+ flags &= ~PFBOK;
+ goto ok;
+ }
+ // No? Fall through and see if it's a hex digit instead then...
+ __BIONIC_FALLTHROUGH;
case '1':
case '2':
case '3':
@@ -583,34 +596,21 @@
case '5':
case '6':
case '7':
- base = basefix[base];
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* digits 8 and 9 ok iff decimal or hex */
case '8':
case '9':
- base = basefix[base];
- if (base <= 8) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* letters ok iff hex */
case 'A':
- case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
- case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
- /* no need to fix base here */
- if (base <= 10) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ if (base == 0) base = 10;
+ if (base != 16 && (c - '0') >= base) break; /* not legal here */
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
goto ok;
/* sign ok only as first character */
@@ -653,17 +653,16 @@
break; /* EOF */
}
/*
- * If we had only a sign, it is no good; push
- * back the sign. If the number ends in `x',
- * it was [sign] '0' 'x', so push back the x
- * and treat it as [sign] '0'.
+ * If we had only a sign, it is no good; push back the sign.
+ * If the number was `[-+]0[BbXx]`, push back and treat it
+ * as `[-+]0`.
*/
if (flags & NDIGITS) {
if (p > buf) (void)ungetc(*(u_char*)--p, fp);
goto match_failure;
}
c = ((u_char*)p)[-1];
- if (c == 'x' || c == 'X') {
+ if ((base == 2 && (c == 'b' || c == 'B')) || c == 'x' || c == 'X') {
--p;
(void)ungetc(c, fp);
}
diff --git a/libc/stdio/vfwscanf.c b/libc/stdio/vfwscanf.cpp
similarity index 91%
rename from libc/stdio/vfwscanf.c
rename to libc/stdio/vfwscanf.cpp
index 71cd49b..06f706a 100644
--- a/libc/stdio/vfwscanf.c
+++ b/libc/stdio/vfwscanf.cpp
@@ -42,6 +42,8 @@
#include <wctype.h>
#include "local.h"
+#include <platform/bionic/macros.h>
+
#define BUF 513 /* Maximum length of numeric string. */
/*
@@ -65,15 +67,16 @@
* SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
* SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
*/
-#define SIGNOK 0x01000 /* +/- is (still) legal */
+#define SIGNOK 0x01000 /* +/- is (still) legal */
#define HAVESIGN 0x02000 /* sign detected */
-#define NDIGITS 0x04000 /* no digits detected */
+#define NDIGITS 0x04000 /* no digits detected */
-#define DPTOK 0x08000 /* (float) decimal point is still legal */
-#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */
+#define DPTOK 0x08000 /* (float) decimal point is still legal */
+#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */
-#define PFXOK 0x08000 /* 0x prefix is (still) legal */
-#define NZDIGITS 0x10000 /* no zero digits detected */
+#define PFBOK 0x20000 /* 0x prefix is (still) legal */
+#define PFXOK 0x40000 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x80000 /* no zero digits detected */
/*
* Conversion types.
@@ -147,9 +150,6 @@
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
mbstate_t mbs;
- /* `basefix' is used to avoid `if' tests in the integer scanner */
- static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
-
_SET_ORIENTATION(fp, 1);
nassigned = 0;
@@ -239,9 +239,15 @@
* Conversions.
* Those marked `compat' are for 4.[123]BSD compatibility.
*/
+ case 'b':
+ c = CT_INT;
+ base = 2;
+ flags |= PFBOK; /* enable 0b prefixing */
+ break;
+
case 'D': /* compat */
flags |= LONG;
- /* FALLTHROUGH */
+ __BIONIC_FALLTHROUGH;
case 'd':
c = CT_INT;
base = 10;
@@ -254,7 +260,7 @@
case 'O': /* compat */
flags |= LONG;
- /* FALLTHROUGH */
+ __BIONIC_FALLTHROUGH;
case 'o':
c = CT_INT;
flags |= UNSIGNED;
@@ -468,7 +474,7 @@
* digits (zero or nonzero) have been
* scanned (only signs), we will have
* base==0. In that case, we should set
- * it to 8 and enable 0x prefixing.
+ * it to 8 and enable 0b/0x prefixing.
* Also, if we have not scanned zero digits
* before this, do not turn off prefixing
* (someone else will turn it off if we
@@ -477,15 +483,26 @@
case '0':
if (base == 0) {
base = 8;
- flags |= PFXOK;
+ flags |= PFBOK | PFXOK;
}
- if (flags & NZDIGITS)
+ if (flags & NZDIGITS) {
flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
- else
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ } else {
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
+ }
goto ok;
/* 1 through 7 always legal */
+ case 'B':
+ case 'b':
+ // Is this 'b' potentially part of an "0b" prefix?
+ if ((flags & PFBOK) && p == buf + 1 + !!(flags & HAVESIGN)) {
+ base = 2;
+ flags &= ~PFBOK;
+ goto ok;
+ }
+ // No? Fall through and see if it's a hex digit instead then...
+ __BIONIC_FALLTHROUGH;
case '1':
case '2':
case '3':
@@ -493,34 +510,21 @@
case '5':
case '6':
case '7':
- base = basefix[base];
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* digits 8 and 9 ok iff decimal or hex */
case '8':
case '9':
- base = basefix[base];
- if (base <= 8) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* letters ok iff hex */
case 'A':
- case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
- case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
- /* no need to fix base here */
- if (base <= 10) break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ if (base == 0) base = 10;
+ if (base != 16 && (int)(c - '0') >= base) break; /* not legal here */
+ flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
goto ok;
/* sign ok only as first character */
@@ -560,17 +564,16 @@
*p++ = (wchar_t)c;
}
/*
- * If we had only a sign, it is no good; push
- * back the sign. If the number ends in `x',
- * it was [sign] '0' 'x', so push back the x
- * and treat it as [sign] '0'.
+ * If we had only a sign, it is no good; push back the sign.
+ * If the number was `[-+]0[BbXx]`, push back and treat it
+ * as `[-+]0`.
*/
if (flags & NDIGITS) {
if (p > buf) __ungetwc(*--p, fp);
goto match_failure;
}
c = p[-1];
- if (c == 'x' || c == 'X') {
+ if ((base == 2 && (c == 'b' || c == 'B')) || c == 'x' || c == 'X') {
--p;
__ungetwc(c, fp);
}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
deleted file mode 100644
index 1b60a3a..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* $OpenBSD: _wcstol.h,v 1.3 2015/10/01 02:32:07 guenther Exp $ */
-/* $NetBSD: _wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
-
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original version ID:
- * @(#)strtol.c 8.1 (Berkeley) 6/4/93
- * NetBSD: wcstol.c,v 1.1 2001/09/27 16:30:36 yamt Exp
- * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstol.c,v 1.2 2001/09/21 16:11:41 yamt Exp
- */
-
-/*
- * function template for wcstol, wcstoll and wcstoimax.
- *
- * parameters:
- * FUNCNAME : function name
- * int_type : return type
- * MIN_VALUE : lower limit of the return type
- * MAX_VALUE : upper limit of the return type
- */
-
-int_type
-FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
-{
- const wchar_t *s;
- int_type acc, cutoff;
- wint_t wc;
- int i;
- int neg, any, cutlim;
-
- /* check base value */
- if (base && (base < 2 || base > 36)) {
- errno = EINVAL;
- return 0;
- }
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- wc = (wchar_t) *s++;
- } while (iswspace(wc));
- if (wc == L'-') {
- neg = 1;
- wc = *s++;
- } else {
- neg = 0;
- if (wc == L'+')
- wc = *s++;
- }
- if ((base == 0 || base == 16) &&
- wc == L'0' && (*s == L'x' || *s == L'X')) {
- wc = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = wc == L'0' ? 8 : 10;
-
- /*
- * See strtol for comments as to the logic used.
- */
- cutoff = neg ? MIN_VALUE : MAX_VALUE;
- cutlim = (int)(cutoff % base);
- cutoff /= base;
- if (neg) {
- if (cutlim > 0) {
- cutlim -= base;
- cutoff += 1;
- }
- cutlim = -cutlim;
- }
- for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
- i = wctoint(wc);
- if (i == -1)
- break;
- if (i >= base)
- break;
- if (any < 0)
- continue;
- if (neg) {
- if (acc < cutoff || (acc == cutoff && i > cutlim)) {
- any = -1;
- acc = MIN_VALUE;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= base;
- acc -= i;
- }
- } else {
- if (acc > cutoff || (acc == cutoff && i > cutlim)) {
- any = -1;
- acc = MAX_VALUE;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= base;
- acc += i;
- }
- }
- }
- if (endptr != 0)
- *endptr = (wchar_t *)(any ? s - 1 : nptr);
- return (acc);
-}
-DEF_STRONG(FUNCNAME);
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
deleted file mode 100644
index 159b22b..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* $OpenBSD: _wcstoul.h,v 1.3 2015/10/01 02:32:07 guenther Exp $ */
-/* $NetBSD: _wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
-
-/*
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original version ID:
- * @(#)strtoul.c 8.1 (Berkeley) 6/4/93
- * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstoul.c,v 1.2 2001/09/21 16:11:41 yamt Exp
- * NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp
- */
-
-/*
- * function template for wcstoul, wcstoull and wcstoumax.
- *
- * parameters:
- * FUNCNAME : function name
- * uint_type : return type
- * MAX_VALUE : upper limit of the return type
- */
-
-uint_type
-FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
-{
- const wchar_t *s;
- uint_type acc, cutoff;
- wint_t wc;
- int i;
- int neg, any, cutlim;
-
- if (base && (base < 2 || base > 36)) {
- errno = EINVAL;
- return 0;
- }
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- wc = (wchar_t) *s++;
- } while (iswspace(wc));
- if (wc == L'-') {
- neg = 1;
- wc = *s++;
- } else {
- neg = 0;
- if (wc == L'+')
- wc = *s++;
- }
- if ((base == 0 || base == 16) &&
- wc == L'0' && (*s == L'x' || *s == L'X')) {
- wc = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = wc == L'0' ? 8 : 10;
-
- /*
- * See strtoul for comments as to the logic used.
- */
- cutoff = MAX_VALUE / (uint_type)base;
- cutlim = (int)(MAX_VALUE % (uint_type)base);
- for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
- i = wctoint(wc);
- if (i == (wint_t)-1)
- break;
- if (i >= base)
- break;
- if (any < 0)
- continue;
- if (acc > cutoff || (acc == cutoff && i > cutlim)) {
- any = -1;
- acc = MAX_VALUE;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= (uint_type)base;
- acc += i;
- }
- }
- if (neg && any > 0)
- acc = -acc;
- if (endptr != 0)
- *endptr = (wchar_t *)(any ? s - 1 : nptr);
- return (acc);
-}
-DEF_STRONG(FUNCNAME);
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
deleted file mode 100644
index d46a7c7..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* $OpenBSD: wcstoimax.c,v 1.1 2009/01/13 18:13:51 kettenis Exp $ */
-/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoimax
-typedef intmax_t int_type;
-#define MIN_VALUE INTMAX_MIN
-#define MAX_VALUE INTMAX_MAX
-
-#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstol.c b/libc/upstream-openbsd/lib/libc/locale/wcstol.c
deleted file mode 100644
index 03395a0..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstol.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $OpenBSD: wcstol.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstol
-typedef long int_type;
-#define MIN_VALUE LONG_MIN
-#define MAX_VALUE LONG_MAX
-
-#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoll.c b/libc/upstream-openbsd/lib/libc/locale/wcstoll.c
deleted file mode 100644
index 926db70..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoll.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $OpenBSD: wcstoll.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstoll.c,v 1.1 2003/03/11 09:21:23 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoll
-typedef long long int int_type;
-#define MIN_VALUE LLONG_MIN
-#define MAX_VALUE LLONG_MAX
-
-#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoul.c b/libc/upstream-openbsd/lib/libc/locale/wcstoul.c
deleted file mode 100644
index e863862..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoul.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $OpenBSD: wcstoul.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoul
-typedef unsigned long uint_type;
-#define MAX_VALUE ULONG_MAX
-
-#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoull.c b/libc/upstream-openbsd/lib/libc/locale/wcstoull.c
deleted file mode 100644
index 6671c37..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoull.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $OpenBSD: wcstoull.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */
-/* $NetBSD: wcstoull.c,v 1.1 2003/03/11 09:21:24 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoull
-typedef unsigned long long int uint_type;
-#define MAX_VALUE ULLONG_MAX
-
-#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
deleted file mode 100644
index ccd4713..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $OpenBSD: wcstoumax.c,v 1.1 2009/01/13 18:13:51 kettenis Exp $ */
-/* $NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $ */
-
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "wctoint.h"
-
-#define FUNCNAME wcstoumax
-typedef uintmax_t uint_type;
-#define MAX_VALUE UINTMAX_MAX
-
-#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wctoint.h b/libc/upstream-openbsd/lib/libc/locale/wctoint.h
deleted file mode 100644
index ea50c5a..0000000
--- a/libc/upstream-openbsd/lib/libc/locale/wctoint.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $OpenBSD: wctoint.h,v 1.2 2015/09/13 11:38:08 guenther Exp $ */
-/* $NetBSD: __wctoint.h,v 1.1 2001/09/28 11:25:37 yamt Exp $ */
-
-/*-
- * Copyright (c)2001 Citrus Project,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/__wctoint.h,v 1.1 2001/09/21 13:52:32 yamt Exp $
- */
-
-
-inline static int
-wctoint(wchar_t wc)
-{
- int n;
-
- switch (wc) {
- case L'0': n = 0; break;
- case L'1': n = 1; break;
- case L'2': n = 2; break;
- case L'3': n = 3; break;
- case L'4': n = 4; break;
- case L'5': n = 5; break;
- case L'6': n = 6; break;
- case L'7': n = 7; break;
- case L'8': n = 8; break;
- case L'9': n = 9; break;
- case L'A': case L'a': n = 10; break;
- case L'B': case L'b': n = 11; break;
- case L'C': case L'c': n = 12; break;
- case L'D': case L'd': n = 13; break;
- case L'E': case L'e': n = 14; break;
- case L'F': case L'f': n = 15; break;
- case L'G': case L'g': n = 16; break;
- case L'H': case L'h': n = 17; break;
- case L'I': case L'i': n = 18; break;
- case L'J': case L'j': n = 19; break;
- case L'K': case L'k': n = 20; break;
- case L'L': case L'l': n = 21; break;
- case L'M': case L'm': n = 22; break;
- case L'N': case L'n': n = 23; break;
- case L'O': case L'o': n = 24; break;
- case L'P': case L'p': n = 25; break;
- case L'Q': case L'q': n = 26; break;
- case L'R': case L'r': n = 27; break;
- case L'S': case L's': n = 28; break;
- case L'T': case L't': n = 29; break;
- case L'U': case L'u': n = 30; break;
- case L'V': case L'v': n = 31; break;
- case L'W': case L'w': n = 32; break;
- case L'X': case L'x': n = 33; break;
- case L'Y': case L'y': n = 34; break;
- case L'Z': case L'z': n = 35; break;
- default: n = -1; break; /* error */
- }
-
- return n;
-}