Switch to the OpenBSD implementations of the wide scanf functions.
This also gets us the C99 wcstoimax and wcstoumax, and a working fgetwc and
ungetwc, all of which are needed in the implementation.
This also brings several other files closer to upstream.
Change-Id: I23b025a8237a6dbb9aa50d2a96765ea729a85579
diff --git a/libc/Android.mk b/libc/Android.mk
index 0fee71a..1dff5ab 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -343,12 +343,14 @@
upstream-openbsd/lib/libc/locale/wcscoll.c \
upstream-openbsd/lib/libc/locale/wcstod.c \
upstream-openbsd/lib/libc/locale/wcstof.c \
+ upstream-openbsd/lib/libc/locale/wcstoimax.c \
upstream-openbsd/lib/libc/locale/wcstol.c \
upstream-openbsd/lib/libc/locale/wcstold.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/stdio/asprintf.c \
@@ -361,6 +363,7 @@
upstream-openbsd/lib/libc/stdio/fgetln.c \
upstream-openbsd/lib/libc/stdio/fgetpos.c \
upstream-openbsd/lib/libc/stdio/fgets.c \
+ upstream-openbsd/lib/libc/stdio/fgetwc.c \
upstream-openbsd/lib/libc/stdio/fileno.c \
upstream-openbsd/lib/libc/stdio/fprintf.c \
upstream-openbsd/lib/libc/stdio/fpurge.c \
@@ -375,6 +378,7 @@
upstream-openbsd/lib/libc/stdio/funopen.c \
upstream-openbsd/lib/libc/stdio/fvwrite.c \
upstream-openbsd/lib/libc/stdio/fwalk.c \
+ upstream-openbsd/lib/libc/stdio/fwscanf.c \
upstream-openbsd/lib/libc/stdio/getc.c \
upstream-openbsd/lib/libc/stdio/getchar.c \
upstream-openbsd/lib/libc/stdio/getdelim.c \
@@ -395,18 +399,24 @@
upstream-openbsd/lib/libc/stdio/setbuffer.c \
upstream-openbsd/lib/libc/stdio/sscanf.c \
upstream-openbsd/lib/libc/stdio/stdio.c \
+ upstream-openbsd/lib/libc/stdio/swscanf.c \
upstream-openbsd/lib/libc/stdio/tempnam.c \
upstream-openbsd/lib/libc/stdio/tmpnam.c \
upstream-openbsd/lib/libc/stdio/ungetc.c \
+ upstream-openbsd/lib/libc/stdio/ungetwc.c \
upstream-openbsd/lib/libc/stdio/vasprintf.c \
upstream-openbsd/lib/libc/stdio/vfprintf.c \
upstream-openbsd/lib/libc/stdio/vfscanf.c \
+ upstream-openbsd/lib/libc/stdio/vfwscanf.c \
upstream-openbsd/lib/libc/stdio/vprintf.c \
upstream-openbsd/lib/libc/stdio/vscanf.c \
upstream-openbsd/lib/libc/stdio/vsnprintf.c \
upstream-openbsd/lib/libc/stdio/vsprintf.c \
upstream-openbsd/lib/libc/stdio/vsscanf.c \
+ upstream-openbsd/lib/libc/stdio/vswscanf.c \
+ upstream-openbsd/lib/libc/stdio/vwscanf.c \
upstream-openbsd/lib/libc/stdio/wbuf.c \
+ upstream-openbsd/lib/libc/stdio/wscanf.c \
upstream-openbsd/lib/libc/stdlib/atoi.c \
upstream-openbsd/lib/libc/stdlib/atol.c \
upstream-openbsd/lib/libc/stdlib/atoll.c \
diff --git a/libc/bionic/flockfile.cpp b/libc/bionic/flockfile.cpp
index c60497d..3381e8e 100644
--- a/libc/bionic/flockfile.cpp
+++ b/libc/bionic/flockfile.cpp
@@ -29,7 +29,7 @@
#include <errno.h>
#include <stdio.h>
-#include "fileext.h"
+#include "local.h"
// We can't use the OpenBSD implementation which uses kernel-specific
// APIs not available on Linux. Instead we use a pthread_mutex_t within
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index e466c91..d23b4b7 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -74,24 +74,6 @@
return -1;
}
-int fwscanf(FILE* /*stream*/, const wchar_t* /*format*/, ... ) {
- errno = ENOTSUP;
- return -1;
-}
-
-int wscanf(const wchar_t* format, ... ) {
- va_list args;
- va_start (args, format);
- int result = fwscanf(stdout, format, args );
- va_end (args);
- return result;
-}
-
-int swscanf(const wchar_t* /*s*/, const wchar_t* /*format*/, ... ) {
- errno = ENOTSUP;
- return -1;
-}
-
int iswalnum(wint_t wc) { return isalnum(wc); }
int iswalpha(wint_t wc) { return isalpha(wc); }
int iswblank(wint_t wc) { return isblank(wc); }
@@ -123,10 +105,6 @@
}
}
-wint_t fgetwc(FILE* stream) {
- return static_cast<wint_t>(fgetc(stream));
-}
-
wchar_t* fgetws(wchar_t* ws, int n, FILE* stream) {
return reinterpret_cast<wchar_t*>(fgets(reinterpret_cast<char*>(ws), n, stream));
}
@@ -224,10 +202,6 @@
return toupper(wc);
}
-wint_t ungetwc(wint_t wc, FILE* stream) {
- return ungetc(static_cast<char>(wc), stream);
-}
-
int wctomb(char* s, wchar_t wc) {
if (s == NULL) {
return 0;
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 5199e4d..8853c08 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -254,13 +254,14 @@
} imaxdiv_t;
__BEGIN_DECLS
-
intmax_t imaxabs(intmax_t) __pure2;
imaxdiv_t imaxdiv(intmax_t, intmax_t) __pure2;
-
intmax_t strtoimax(const char *, char **, int);
uintmax_t strtoumax(const char *, char **, int);
-
+intmax_t wcstoimax(const wchar_t * __restrict,
+ wchar_t ** __restrict, int);
+uintmax_t wcstoumax(const wchar_t * __restrict,
+ wchar_t ** __restrict, int);
__END_DECLS
#endif /* _INTTYPES_H_ */
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 12715c2..669ce8d 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -97,9 +97,12 @@
extern wint_t towlower(wint_t);
extern wint_t towupper(wint_t);
extern wint_t ungetwc(wint_t, FILE *);
-extern int vfwprintf(FILE *, const wchar_t *, va_list);
-extern int vwprintf(const wchar_t *, va_list);
-extern int vswprintf(wchar_t *, size_t, const wchar_t *, va_list);
+extern int vfwprintf(FILE*, const wchar_t*, va_list);
+extern int vfwscanf(FILE*, const wchar_t*, va_list);
+extern int vswprintf(wchar_t*, size_t, const wchar_t*, va_list);
+extern int vswscanf(const wchar_t*, const wchar_t*, va_list);
+extern int vwprintf(const wchar_t*, va_list);
+extern int vwscanf(const wchar_t*, va_list);
extern size_t wcrtomb(char *, wchar_t, mbstate_t *);
extern int wcscasecmp(const wchar_t *, const wchar_t *);
extern wchar_t *wcscat(wchar_t *, const wchar_t *);
diff --git a/libc/stdio/fileext.h b/libc/stdio/fileext.h
index 8641924..fa6fed6 100644
--- a/libc/stdio/fileext.h
+++ b/libc/stdio/fileext.h
@@ -30,7 +30,6 @@
*/
#include <pthread.h>
-#include "wcio.h"
/*
* file extension
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 926e5a1..2dd32c9 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -61,11 +61,7 @@
static struct glue *lastglue = &uglue;
_THREAD_PRIVATE_MUTEX(__sfp_mutex);
-static struct __sfileext __sFext[3] = {
- _FILEEXT_INITIALIZER,
- _FILEEXT_INITIALIZER,
- _FILEEXT_INITIALIZER,
-};
+static struct __sfileext __sFext[3];
FILE __sF[3] = {
std(__SRD, STDIN_FILENO), /* stdin */
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index eecfeef..5fb2292 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -32,15 +32,15 @@
* SUCH DAMAGE.
*/
-#include "wcio.h"
-#include "fileext.h"
-
-
/*
* Information local to this implementation of stdio,
* in particular, macros and private variables.
*/
+#include <wchar.h>
+#include "wcio.h"
+#include "fileext.h"
+
int __sflush(FILE *);
int __sflush_locked(FILE *);
FILE *__sfp(void);
@@ -56,7 +56,12 @@
int _fwalk(int (*)(FILE *));
int __swsetup(FILE *);
int __sflags(const char *, int *);
+wint_t __fgetwc_unlock(FILE *);
+wint_t __ungetwc(wint_t, FILE *);
int __vfprintf(FILE *, const char *, __va_list);
+int __svfscanf(FILE * __restrict, const char * __restrict, __va_list);
+int __vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list);
+int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list);
/*
* Function to clean up streams, called from abort() and exit().
diff --git a/libc/stdio/wcio.h b/libc/stdio/wcio.h
index dd6db21..584a3f2 100644
--- a/libc/stdio/wcio.h
+++ b/libc/stdio/wcio.h
@@ -1,34 +1,34 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
+/* $OpenBSD: wcio.h,v 1.2 2013/04/17 17:40:35 tedu Exp $ */
+/* $NetBSD: wcio.h,v 1.3 2003/01/18 11:30:00 thorpej 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:
- * * Redistributions of source code must retain the above copyright
+ * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- * * 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.
+ * 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 COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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
+ * 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$
*/
-/* this file is only used to quiet the BSD stdio implementation
- * since we don't implement wchar support at all
- */
#ifndef _WCIO_H_
#define _WCIO_H_
@@ -36,22 +36,46 @@
#define WCIO_UNGETWC_BUFSIZE 1
struct wchar_io_data {
- int dummy;
+ mbstate_t wcio_mbstate_in;
+ mbstate_t wcio_mbstate_out;
+
+ wchar_t wcio_ungetwc_buf[WCIO_UNGETWC_BUFSIZE];
+ size_t wcio_ungetwc_inbuf;
+
+ int wcio_mode; /* orientation */
};
-/* BIONIC: disable wchar support */
#define WCIO_GET(fp) \
- ((struct wchar_io_data*) 0)
+ (_EXT(fp) ? &(_EXT(fp)->_wcio) : (struct wchar_io_data *)0)
-#define _SET_ORIENTATION(fp, mode) ((void)0)
+#define _SET_ORIENTATION(fp, mode) \
+do {\
+ struct wchar_io_data *_wcio = WCIO_GET(fp); \
+ if (_wcio && _wcio->wcio_mode == 0) \
+ _wcio->wcio_mode = (mode);\
+} while (0)
/*
* WCIO_FREE should be called by fclose
*/
-#define WCIO_FREE(fp) ((void)(0))
+#define WCIO_FREE(fp) \
+do {\
+ struct wchar_io_data *_wcio = WCIO_GET(fp); \
+ if (_wcio) { \
+ _wcio->wcio_mode = 0;\
+ _wcio->wcio_ungetwc_inbuf = 0;\
+ } \
+} while (0)
-#define WCIO_FREEUB(fp) ((void)0)
+#define WCIO_FREEUB(fp) \
+do {\
+ struct wchar_io_data *_wcio = WCIO_GET(fp); \
+ if (_wcio) { \
+ _wcio->wcio_ungetwc_inbuf = 0;\
+ } \
+} while (0)
-#define WCIO_INIT(fp) ((void)0)
+#define WCIO_INIT(fp) \
+ memset(&(_EXT(fp)->_wcio), 0, sizeof(struct wchar_io_data))
#endif /*_WCIO_H_*/
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
new file mode 100644
index 0000000..d46a7c7
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
@@ -0,0 +1,19 @@
+/* $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/wcstoumax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
new file mode 100644
index 0000000..ccd4713
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
@@ -0,0 +1,18 @@
+/* $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/stdio/fgetwc.c b/libc/upstream-openbsd/lib/libc/stdio/fgetwc.c
new file mode 100644
index 0000000..c16ffaf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetwc.c
@@ -0,0 +1,90 @@
+/* $OpenBSD: fgetwc.c,v 1.4 2009/11/09 00:18:27 kurt Exp $ */
+/* $NetBSD: fgetwc.c,v 1.3 2003/03/07 07:11:36 tshiozak 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$
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+wint_t
+__fgetwc_unlock(FILE *fp)
+{
+ struct wchar_io_data *wcio;
+ mbstate_t *st;
+ wchar_t wc;
+ size_t size;
+
+ _SET_ORIENTATION(fp, 1);
+ wcio = WCIO_GET(fp);
+ if (wcio == 0) {
+ errno = ENOMEM;
+ return WEOF;
+ }
+
+ /* if there're ungetwc'ed wchars, use them */
+ if (wcio->wcio_ungetwc_inbuf) {
+ wc = wcio->wcio_ungetwc_buf[--wcio->wcio_ungetwc_inbuf];
+
+ return wc;
+ }
+
+ st = &wcio->wcio_mbstate_in;
+
+ do {
+ char c;
+ int ch = __sgetc(fp);
+
+ if (ch == EOF) {
+ return WEOF;
+ }
+
+ c = ch;
+ size = mbrtowc(&wc, &c, 1, st);
+ if (size == (size_t)-1) {
+ errno = EILSEQ;
+ return WEOF;
+ }
+ } while (size == (size_t)-2);
+
+ return wc;
+}
+
+wint_t
+fgetwc(FILE *fp)
+{
+ wint_t r;
+
+ FLOCKFILE(fp);
+ r = __fgetwc_unlock(fp);
+ FUNLOCKFILE(fp);
+
+ return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/fwscanf.c
new file mode 100644
index 0000000..b716cbf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwscanf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: fwscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vfwscanf(fp, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/swscanf.c b/libc/upstream-openbsd/lib/libc/stdio/swscanf.c
new file mode 100644
index 0000000..a85e9ee
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/swscanf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: swscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vswscanf(str, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c b/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
new file mode 100644
index 0000000..c0321e9
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: ungetwc.c,v 1.5 2011/10/16 13:20:51 stsp Exp $ */
+/* $NetBSD: ungetwc.c,v 1.2 2003/01/18 11:29:59 thorpej 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$
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+wint_t
+__ungetwc(wint_t wc, FILE *fp)
+{
+ struct wchar_io_data *wcio;
+
+ if (wc == WEOF)
+ return WEOF;
+
+ _SET_ORIENTATION(fp, 1);
+ /*
+ * XXX since we have no way to transform a wchar string to
+ * a char string in reverse order, we can't use ungetc.
+ */
+ /* XXX should we flush ungetc buffer? */
+
+ wcio = WCIO_GET(fp);
+ if (wcio == 0) {
+ errno = ENOMEM; /* XXX */
+ return WEOF;
+ }
+
+ if (wcio->wcio_ungetwc_inbuf >= WCIO_UNGETWC_BUFSIZE) {
+ return WEOF;
+ }
+
+ wcio->wcio_ungetwc_buf[wcio->wcio_ungetwc_inbuf++] = wc;
+ __sclearerr(fp);
+
+ return wc;
+}
+
+wint_t
+ungetwc(wint_t wc, FILE *fp)
+{
+ wint_t r;
+
+ FLOCKFILE(fp);
+ r = __ungetwc(wc, fp);
+ FUNLOCKFILE(fp);
+ return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
new file mode 100644
index 0000000..e5cf5e1
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
@@ -0,0 +1,799 @@
+/* $OpenBSD: vfwscanf.c,v 1.2 2012/01/18 17:23:11 chl Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wctype.h>
+#include "local.h"
+
+#ifdef FLOATING_POINT
+#include "floatio.h"
+#endif
+
+#define BUF 513 /* Maximum length of numeric string. */
+
+/*
+ * Flags used during conversion.
+ */
+#define LONG 0x00001 /* l: long or double */
+#define LONGDBL 0x00002 /* L: long double */
+#define SHORT 0x00004 /* h: short */
+#define SHORTSHORT 0x00008 /* hh: 8 bit integer */
+#define LLONG 0x00010 /* ll: long long (+ deprecated q: quad) */
+#define POINTER 0x00020 /* p: void * (as hex) */
+#define SIZEINT 0x00040 /* z: (signed) size_t */
+#define MAXINT 0x00080 /* j: intmax_t */
+#define PTRINT 0x00100 /* t: ptrdiff_t */
+#define NOSKIP 0x00200 /* [ or c: do not skip blanks */
+#define SUPPRESS 0x00400 /* *: suppress assignment */
+#define UNSIGNED 0x00800 /* %[oupxX] conversions */
+
+/*
+ * The following are used in numeric conversions only:
+ * 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 HAVESIGN 0x02000 /* sign 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 PFXOK 0x08000 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x10000 /* no zero digits detected */
+
+/*
+ * Conversion types.
+ */
+#define CT_CHAR 0 /* %c conversion */
+#define CT_CCL 1 /* %[...] conversion */
+#define CT_STRING 2 /* %s conversion */
+#define CT_INT 3 /* integer, i.e., strtoimax or strtoumax */
+#define CT_FLOAT 4 /* floating, i.e., strtod */
+
+#define u_char unsigned char
+#define u_long unsigned long
+
+#define INCCL(_c) \
+ (cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
+ (wmemchr(ccls, (_c), ccle - ccls) != NULL))
+
+/*
+ * vfwscanf
+ */
+int
+__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, __va_list ap)
+{
+ wint_t c; /* character from format, or conversion */
+ size_t width; /* field width, or 0 */
+ wchar_t *p; /* points into all kinds of strings */
+ int n; /* handy integer */
+ int flags; /* flags as defined above */
+ wchar_t *p0; /* saves original value of p when necessary */
+ int nassigned; /* number of fields assigned */
+ int nconversions; /* number of conversions */
+ int nread; /* number of characters consumed from fp */
+ int base; /* base argument to strtoimax/strtouimax */
+ wchar_t buf[BUF]; /* buffer for numeric conversions */
+ const wchar_t *ccls; /* character class start */
+ const wchar_t *ccle; /* character class end */
+ int cclcompl; /* ccl is complemented? */
+ wint_t wi; /* handy wint_t */
+ char *mbp; /* multibyte string pointer for %c %s %[ */
+ size_t nconv; /* number of bytes in mb. conversion */
+ char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
+ mbstate_t mbs;
+#ifdef FLOATING_POINT
+ wchar_t decimal_point = 0;
+#endif
+
+ /* `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;
+ nconversions = 0;
+ nread = 0;
+ base = 0; /* XXX just to keep gcc happy */
+ ccls = ccle = NULL;
+ for (;;) {
+ c = *fmt++;
+ if (c == 0) {
+ return (nassigned);
+ }
+ if (iswspace(c)) {
+ while ((c = __fgetwc_unlock(fp)) != WEOF &&
+ iswspace(c))
+ ;
+ if (c != WEOF)
+ __ungetwc(c, fp);
+ continue;
+ }
+ if (c != '%')
+ goto literal;
+ width = 0;
+ flags = 0;
+ /*
+ * switch on the format. continue if done;
+ * break once format type is derived.
+ */
+again: c = *fmt++;
+ switch (c) {
+ case '%':
+literal:
+ if ((wi = __fgetwc_unlock(fp)) == WEOF)
+ goto input_failure;
+ if (wi != c) {
+ __ungetwc(wi, fp);
+ goto input_failure;
+ }
+ nread++;
+ continue;
+
+ case '*':
+ flags |= SUPPRESS;
+ goto again;
+ case 'j':
+ flags |= MAXINT;
+ goto again;
+ case 'L':
+ flags |= LONGDBL;
+ goto again;
+ case 'h':
+ if (*fmt == 'h') {
+ fmt++;
+ flags |= SHORTSHORT;
+ } else {
+ flags |= SHORT;
+ }
+ goto again;
+ case 'l':
+ if (*fmt == 'l') {
+ fmt++;
+ flags |= LLONG;
+ } else {
+ flags |= LONG;
+ }
+ goto again;
+ case 'q':
+ flags |= LLONG; /* deprecated */
+ goto again;
+ case 't':
+ flags |= PTRINT;
+ goto again;
+ case 'z':
+ flags |= SIZEINT;
+ goto again;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ width = width * 10 + c - '0';
+ goto again;
+
+ /*
+ * Conversions.
+ * Those marked `compat' are for 4.[123]BSD compatibility.
+ *
+ * (According to ANSI, E and X formats are supposed
+ * to the same as e and x. Sorry about that.)
+ */
+ case 'D': /* compat */
+ flags |= LONG;
+ /* FALLTHROUGH */
+ case 'd':
+ c = CT_INT;
+ base = 10;
+ break;
+
+ case 'i':
+ c = CT_INT;
+ base = 0;
+ break;
+
+ case 'O': /* compat */
+ flags |= LONG;
+ /* FALLTHROUGH */
+ case 'o':
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 8;
+ break;
+
+ case 'u':
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 10;
+ break;
+
+ case 'X':
+ case 'x':
+ flags |= PFXOK; /* enable 0x prefixing */
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 16;
+ break;
+
+#ifdef FLOATING_POINT
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'g': case 'G':
+ case 'a': case 'A':
+ c = CT_FLOAT;
+ break;
+#endif
+
+ case 's':
+ c = CT_STRING;
+ break;
+
+ case '[':
+ ccls = fmt;
+ if (*fmt == '^') {
+ cclcompl = 1;
+ fmt++;
+ } else
+ cclcompl = 0;
+ if (*fmt == ']')
+ fmt++;
+ while (*fmt != '\0' && *fmt != ']')
+ fmt++;
+ ccle = fmt;
+ fmt++;
+ flags |= NOSKIP;
+ c = CT_CCL;
+ break;
+
+ case 'c':
+ flags |= NOSKIP;
+ c = CT_CHAR;
+ break;
+
+ case 'p': /* pointer format is like hex */
+ flags |= POINTER | PFXOK;
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 16;
+ break;
+
+ case 'n':
+ nconversions++;
+ if (flags & SUPPRESS)
+ continue;
+ if (flags & SHORTSHORT)
+ *va_arg(ap, __signed char *) = nread;
+ else if (flags & SHORT)
+ *va_arg(ap, short *) = nread;
+ else if (flags & LONG)
+ *va_arg(ap, long *) = nread;
+ else if (flags & SIZEINT)
+ *va_arg(ap, ssize_t *) = nread;
+ else if (flags & PTRINT)
+ *va_arg(ap, ptrdiff_t *) = nread;
+ else if (flags & LLONG)
+ *va_arg(ap, long long *) = nread;
+ else if (flags & MAXINT)
+ *va_arg(ap, intmax_t *) = nread;
+ else
+ *va_arg(ap, int *) = nread;
+ continue;
+
+ /*
+ * Disgusting backwards compatibility hacks. XXX
+ */
+ case '\0': /* compat */
+ return (EOF);
+
+ default: /* compat */
+ if (isupper(c))
+ flags |= LONG;
+ c = CT_INT;
+ base = 10;
+ break;
+ }
+
+ /*
+ * Consume leading white space, except for formats
+ * that suppress this.
+ */
+ if ((flags & NOSKIP) == 0) {
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ iswspace(wi))
+ nread++;
+ if (wi == WEOF)
+ goto input_failure;
+ __ungetwc(wi, fp);
+ }
+
+ /*
+ * Do the conversion.
+ */
+ switch (c) {
+
+ case CT_CHAR:
+ /* scan arbitrary characters (sets NOSKIP) */
+ if (width == 0)
+ width = 1;
+ if (flags & LONG) {
+ if (!(flags & SUPPRESS))
+ p = va_arg(ap, wchar_t *);
+ n = 0;
+ while (width-- != 0 &&
+ (wi = __fgetwc_unlock(fp)) != WEOF) {
+ if (!(flags & SUPPRESS))
+ *p++ = (wchar_t)wi;
+ n++;
+ }
+ if (n == 0)
+ goto input_failure;
+ nread += n;
+ if (!(flags & SUPPRESS))
+ nassigned++;
+ } else {
+ if (!(flags & SUPPRESS))
+ mbp = va_arg(ap, char *);
+ n = 0;
+ bzero(&mbs, sizeof(mbs));
+ while (width != 0 &&
+ (wi = __fgetwc_unlock(fp)) != WEOF) {
+ if (width >= MB_CUR_MAX &&
+ !(flags & SUPPRESS)) {
+ nconv = wcrtomb(mbp, wi, &mbs);
+ if (nconv == (size_t)-1)
+ goto input_failure;
+ } else {
+ nconv = wcrtomb(mbbuf, wi,
+ &mbs);
+ if (nconv == (size_t)-1)
+ goto input_failure;
+ if (nconv > width) {
+ __ungetwc(wi, fp);
+ break;
+ }
+ if (!(flags & SUPPRESS))
+ memcpy(mbp, mbbuf,
+ nconv);
+ }
+ if (!(flags & SUPPRESS))
+ mbp += nconv;
+ width -= nconv;
+ n++;
+ }
+ if (n == 0)
+ goto input_failure;
+ nread += n;
+ if (!(flags & SUPPRESS))
+ nassigned++;
+ }
+ nconversions++;
+ break;
+
+ case CT_CCL:
+ /* scan a (nonempty) character class (sets NOSKIP) */
+ if (width == 0)
+ width = (size_t)~0; /* `infinity' */
+ /* take only those things in the class */
+ if ((flags & SUPPRESS) && (flags & LONG)) {
+ n = 0;
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ width-- != 0 && INCCL(wi))
+ n++;
+ if (wi != WEOF)
+ __ungetwc(wi, fp);
+ if (n == 0)
+ goto match_failure;
+ } else if (flags & LONG) {
+ p0 = p = va_arg(ap, wchar_t *);
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ width-- != 0 && INCCL(wi))
+ *p++ = (wchar_t)wi;
+ if (wi != WEOF)
+ __ungetwc(wi, fp);
+ n = p - p0;
+ if (n == 0)
+ goto match_failure;
+ *p = 0;
+ nassigned++;
+ } else {
+ if (!(flags & SUPPRESS))
+ mbp = va_arg(ap, char *);
+ n = 0;
+ bzero(&mbs, sizeof(mbs));
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ width != 0 && INCCL(wi)) {
+ if (width >= MB_CUR_MAX &&
+ !(flags & SUPPRESS)) {
+ nconv = wcrtomb(mbp, wi, &mbs);
+ if (nconv == (size_t)-1)
+ goto input_failure;
+ } else {
+ nconv = wcrtomb(mbbuf, wi,
+ &mbs);
+ if (nconv == (size_t)-1)
+ goto input_failure;
+ if (nconv > width)
+ break;
+ if (!(flags & SUPPRESS))
+ memcpy(mbp, mbbuf,
+ nconv);
+ }
+ if (!(flags & SUPPRESS))
+ mbp += nconv;
+ width -= nconv;
+ n++;
+ }
+ if (wi != WEOF)
+ __ungetwc(wi, fp);
+ if (!(flags & SUPPRESS)) {
+ *mbp = 0;
+ nassigned++;
+ }
+ }
+ nread += n;
+ nconversions++;
+ break;
+
+ case CT_STRING:
+ /* like CCL, but zero-length string OK, & no NOSKIP */
+ if (width == 0)
+ width = (size_t)~0;
+ if ((flags & SUPPRESS) && (flags & LONG)) {
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ width-- != 0 &&
+ !iswspace(wi))
+ nread++;
+ if (wi != WEOF)
+ __ungetwc(wi, fp);
+ } else if (flags & LONG) {
+ p0 = p = va_arg(ap, wchar_t *);
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ width-- != 0 &&
+ !iswspace(wi)) {
+ *p++ = (wchar_t)wi;
+ nread++;
+ }
+ if (wi != WEOF)
+ __ungetwc(wi, fp);
+ *p = 0;
+ nassigned++;
+ } else {
+ if (!(flags & SUPPRESS))
+ mbp = va_arg(ap, char *);
+ bzero(&mbs, sizeof(mbs));
+ while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+ width != 0 &&
+ !iswspace(wi)) {
+ if (width >= MB_CUR_MAX &&
+ !(flags & SUPPRESS)) {
+ nconv = wcrtomb(mbp, wi, &mbs);
+ if (nconv == (size_t)-1)
+ goto input_failure;
+ } else {
+ nconv = wcrtomb(mbbuf, wi,
+ &mbs);
+ if (nconv == (size_t)-1)
+ goto input_failure;
+ if (nconv > width)
+ break;
+ if (!(flags & SUPPRESS))
+ memcpy(mbp, mbbuf,
+ nconv);
+ }
+ if (!(flags & SUPPRESS))
+ mbp += nconv;
+ width -= nconv;
+ nread++;
+ }
+ if (wi != WEOF)
+ __ungetwc(wi, fp);
+ if (!(flags & SUPPRESS)) {
+ *mbp = 0;
+ nassigned++;
+ }
+ }
+ nconversions++;
+ continue;
+
+ case CT_INT:
+ /* scan an integer as if by strtoimax/strtoumax */
+ if (width == 0 || width > sizeof(buf) /
+ sizeof(*buf) - 1)
+ width = sizeof(buf) / sizeof(*buf) - 1;
+ flags |= SIGNOK | NDIGITS | NZDIGITS;
+ for (p = buf; width; width--) {
+ c = __fgetwc_unlock(fp);
+ /*
+ * Switch on the character; `goto ok'
+ * if we accept it as a part of number.
+ */
+ switch (c) {
+
+ /*
+ * The digit 0 is always legal, but is
+ * special. For %i conversions, if no
+ * 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.
+ * Also, if we have not scanned zero digits
+ * before this, do not turn off prefixing
+ * (someone else will turn it off if we
+ * have scanned any nonzero digits).
+ */
+ case '0':
+ if (base == 0) {
+ base = 8;
+ flags |= PFXOK;
+ }
+ if (flags & NZDIGITS)
+ flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
+ else
+ flags &= ~(SIGNOK|PFXOK|NDIGITS);
+ goto ok;
+
+ /* 1 through 7 always legal */
+ case '1': case '2': case '3':
+ case '4': 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);
+ goto ok;
+
+ /* sign ok only as first character */
+ case '+': case '-':
+ if (flags & SIGNOK) {
+ flags &= ~SIGNOK;
+ flags |= HAVESIGN;
+ goto ok;
+ }
+ break;
+
+ /*
+ * x ok iff flag still set and 2nd char (or
+ * 3rd char if we have a sign).
+ */
+ case 'x': case 'X':
+ if ((flags & PFXOK) && p ==
+ buf + 1 + !!(flags & HAVESIGN)) {
+ base = 16; /* if %i */
+ flags &= ~PFXOK;
+ goto ok;
+ }
+ break;
+ }
+
+ /*
+ * If we got here, c is not a legal character
+ * for a number. Stop accumulating digits.
+ */
+ if (c != WEOF)
+ __ungetwc(c, fp);
+ break;
+ ok:
+ /*
+ * c is legal: store it and look at the next.
+ */
+ *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 (flags & NDIGITS) {
+ if (p > buf)
+ __ungetwc(*--p, fp);
+ goto match_failure;
+ }
+ c = p[-1];
+ if (c == 'x' || c == 'X') {
+ --p;
+ __ungetwc(c, fp);
+ }
+ if ((flags & SUPPRESS) == 0) {
+ uintmax_t res;
+
+ *p = '\0';
+ if (flags & UNSIGNED)
+ res = wcstoimax(buf, NULL, base);
+ else
+ res = wcstoumax(buf, NULL, base);
+ if (flags & POINTER)
+ *va_arg(ap, void **) =
+ (void *)(uintptr_t)res;
+ else if (flags & MAXINT)
+ *va_arg(ap, intmax_t *) = res;
+ else if (flags & LLONG)
+ *va_arg(ap, long long *) = res;
+ else if (flags & SIZEINT)
+ *va_arg(ap, ssize_t *) = res;
+ else if (flags & PTRINT)
+ *va_arg(ap, ptrdiff_t *) = res;
+ else if (flags & LONG)
+ *va_arg(ap, long *) = res;
+ else if (flags & SHORT)
+ *va_arg(ap, short *) = res;
+ else if (flags & SHORTSHORT)
+ *va_arg(ap, __signed char *) = res;
+ else
+ *va_arg(ap, int *) = res;
+ nassigned++;
+ }
+ nread += p - buf;
+ nconversions++;
+ break;
+
+#ifdef FLOATING_POINT
+ case CT_FLOAT:
+ /* scan a floating point number as if by strtod */
+ if (width == 0 || width > sizeof(buf) /
+ sizeof(*buf) - 1)
+ width = sizeof(buf) / sizeof(*buf) - 1;
+ flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
+ for (p = buf; width; width--) {
+ c = __fgetwc_unlock(fp);
+ /*
+ * This code mimicks the integer conversion
+ * code, but is much simpler.
+ */
+ switch (c) {
+
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ flags &= ~(SIGNOK | NDIGITS);
+ goto fok;
+
+ case '+': case '-':
+ if (flags & SIGNOK) {
+ flags &= ~SIGNOK;
+ goto fok;
+ }
+ break;
+ case 'e': case 'E':
+ /* no exponent without some digits */
+ if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
+ flags =
+ (flags & ~(EXPOK|DPTOK)) |
+ SIGNOK | NDIGITS;
+ goto fok;
+ }
+ break;
+ default:
+ if (decimal_point == 0) {
+ bzero(&mbs, sizeof(mbs));
+ nconv = mbrtowc(&decimal_point,
+ localeconv()->decimal_point,
+ MB_CUR_MAX, &mbs);
+ if (nconv == 0 ||
+ nconv == (size_t)-1 ||
+ nconv == (size_t)-2)
+ decimal_point = '.';
+ }
+ if (c == decimal_point &&
+ (flags & DPTOK)) {
+ flags &= ~(SIGNOK | DPTOK);
+ goto fok;
+ }
+ break;
+ }
+ if (c != WEOF)
+ __ungetwc(c, fp);
+ break;
+ fok:
+ *p++ = c;
+ }
+ /*
+ * If no digits, might be missing exponent digits
+ * (just give back the exponent) or might be missing
+ * regular digits, but had sign and/or decimal point.
+ */
+ if (flags & NDIGITS) {
+ if (flags & EXPOK) {
+ /* no digits at all */
+ while (p > buf)
+ __ungetwc(*--p, fp);
+ goto match_failure;
+ }
+ /* just a bad exponent (e and maybe sign) */
+ c = *--p;
+ if (c != 'e' && c != 'E') {
+ __ungetwc(c, fp);/* sign */
+ c = *--p;
+ }
+ __ungetwc(c, fp);
+ }
+ if ((flags & SUPPRESS) == 0) {
+ *p = 0;
+ if (flags & LONGDBL) {
+ long double res = wcstold(buf, NULL);
+ *va_arg(ap, long double *) = res;
+ } else if (flags & LONG) {
+ double res = wcstod(buf, NULL);
+ *va_arg(ap, double *) = res;
+ } else {
+ float res = wcstof(buf, NULL);
+ *va_arg(ap, float *) = res;
+ }
+ nassigned++;
+ }
+ nread += p - buf;
+ nconversions++;
+ break;
+#endif /* FLOATING_POINT */
+ }
+ }
+input_failure:
+ return (nconversions != 0 ? nassigned : EOF);
+match_failure:
+ return (nassigned);
+}
+
+int
+vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, __va_list ap)
+{
+ int r;
+
+ FLOCKFILE(fp);
+ r = __vfwscanf(fp, fmt, ap);
+ FUNLOCKFILE(fp);
+ return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
new file mode 100644
index 0000000..cbaa250
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: vswscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * 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.
+ * 4. 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.
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "local.h"
+
+static int eofread(void *, char *, int);
+
+static int
+eofread(void *cookie, char *buf, int len)
+{
+ return (0);
+}
+
+int
+vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
+ __va_list ap)
+{
+ mbstate_t mbs;
+ FILE f;
+ struct __sfileext fext;
+ char *mbstr;
+ size_t len, mlen;
+ int r;
+ const wchar_t *strp;
+
+ /*
+ * XXX Convert the wide character string to multibyte, which
+ * __vfwscanf() will convert back to wide characters.
+ */
+ len = wcslen(str) * MB_CUR_MAX;
+ if ((mbstr = malloc(len + 1)) == NULL)
+ return (EOF);
+ bzero(&mbs, sizeof(mbs));
+ strp = str;
+ if ((mlen = wcsrtombs(mbstr, &strp, len, &mbs)) == (size_t)-1) {
+ free(mbstr);
+ return (EOF);
+ }
+ if (mlen == len)
+ mbstr[len] = '\0';
+ _FILEEXT_SETUP(&f, &fext);
+ f._flags = __SRD;
+ f._bf._base = f._p = (unsigned char *)mbstr;
+ f._bf._size = f._r = mlen;
+ f._read = eofread;
+ f._lb._base = NULL;
+ r = __vfwscanf(&f, fmt, ap);
+ free(mbstr);
+
+ return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vwscanf.c
new file mode 100644
index 0000000..7039f02
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vwscanf.c
@@ -0,0 +1,38 @@
+/* $OpenBSD: vwscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+vwscanf(const wchar_t * __restrict fmt, __va_list ap)
+{
+
+ return (vfwscanf(stdin, fmt, ap));
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/wscanf.c b/libc/upstream-openbsd/lib/libc/stdio/wscanf.c
new file mode 100644
index 0000000..06c0829
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/wscanf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: wscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+wscanf(const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vfwscanf(stdin, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}