summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/ChangeLog.eglibc83
-rw-r--r--libc/debug/Makefile18
-rw-r--r--libc/debug/tst-chk1.c8
-rw-r--r--libc/libio/Makefile25
-rw-r--r--libc/libio/__fpurge.c2
-rw-r--r--libc/libio/fileops.c9
-rw-r--r--libc/libio/iofwide.c26
-rw-r--r--libc/libio/ioseekoff.c2
-rw-r--r--libc/libio/ioseekpos.c2
-rw-r--r--libc/libio/iosetbuffer.c2
-rw-r--r--libc/libio/libioP.h18
-rw-r--r--libc/libio/wdummyfileops.c161
-rw-r--r--libc/option-groups.def50
-rw-r--r--libc/option-groups.mak10
-rw-r--r--libc/posix/fnmatch_loop.c4
-rw-r--r--libc/scripts/option-groups.awk15
-rw-r--r--libc/stdio-common/Makefile16
-rw-r--r--libc/stdio-common/printf_fp.c11
-rw-r--r--libc/stdio-common/printf_fphex.c7
-rw-r--r--libc/stdio-common/printf_size.c8
-rw-r--r--libc/stdio-common/scanf14.c3
-rw-r--r--libc/stdio-common/tst-sprintf.c2
-rw-r--r--libc/stdio-common/tstdiomisc.c2
-rw-r--r--libc/stdio-common/vfprintf.c15
-rw-r--r--libc/stdio-common/vfscanf.c18
-rw-r--r--libc/stdlib/Makefile10
-rw-r--r--libc/time/Makefile4
-rw-r--r--libc/wcsmbs/Makefile14
-rw-r--r--libc/wctype/Makefile12
29 files changed, 508 insertions, 49 deletions
diff --git a/libc/ChangeLog.eglibc b/libc/ChangeLog.eglibc
index a3879ac2e..2095d426f 100644
--- a/libc/ChangeLog.eglibc
+++ b/libc/ChangeLog.eglibc
@@ -1,3 +1,86 @@
+2007-12-13 Jim Blandy <jimb@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ Implement the OPTION_POSIX_C_LANG_WIDE_CHAR option group.
+ * option-groups.def (OPTION_POSIX_C_LANG_WIDE_CHAR): New entry.
+ (OPTION_EGLIBC_LOCALE_CODE, OPTION_POSIX_WIDE_CHAR_DEVICE_IO):
+ Note dependence on OPTION_POSIX_C_LANG_WIDE_CHAR.
+ (OPTION_POSIX_WIDE_CHAR_DEVICE_IO): Doc fix; note effect on
+ support for 'ccs=CHARSET' strings in fopen and friends.
+ * option-groups.mak (option-disabled): New function.
+ * scripts/option-groups.awk: Generate preprocessor conditionals to
+ protect gnu/option-groups.h from multiple #inclusion.
+
+ * stdlib/Makefile (routines): Put in group: mblen mbstowcs mbtowc
+ wcstombs wctomb wcstoimax wcstoumax.
+ (tests): Put in group: testmb.
+ * debug/Makefile (routines): Put in group: wctomb_chk wcscpy_chk
+ wmemcpy_chk wmemmove_chk wmempcpy_chk wcpcpy_chk wcsncpy_chk
+ wcscat_chk wcsncat_chk wmemset_chk wcpncpy_chk swprintf_chk
+ vswprintf_chk wcrtomb_chk mbsnrtowcs_chk wcsnrtombs_chk
+ mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk wcstombs_chk.
+ * debug/tst-chk1.c (do_test): Make wide character parts conditional
+ on __OPTION_POSIX_WIDE_CHAR_DEVICE_IO.
+ * wcsmbs/Makefile (routines): Put in group: wcscat wcschr wcscmp
+ wcscpy wcscspn wcsdup wcslen wcsncat wcsncmp wcsncpy wcspbrk
+ wcsrchr wcsspn wcstok wcsstr wmemchr wmemcmp wmemmove wcpcpy
+ wcpncpy wmempcpy btowc wctob mbsinit mbrlen mbrtowc wcrtomb
+ mbsrtowcs wcsrtombs mbsnrtowcs wcsnrtombs wcsnlen wcschrnul wcstol
+ wcstoul wcstoll wcstoull wcstod wcstold wcstof wcstol_l wcstoul_l
+ wcstoll_l wcstoull_l wcstod_l wcstold_l wcstof_l wcscoll wcsxfrm
+ wcwidth wcswidth wcscoll_l wcsxfrm_l wcscasecmp wcsncase
+ wcscasecmp_l wcsncase_l wcsmbsload mbsrtowcs_l isoc99_swscanf
+ isoc99_vswscanf.
+ (tests): Put in group: tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-wcpncpy
+ tst-mbsrtowcs wcsatcliff.
+ * time/Makefile (routines): Put in group: wcsftime wcsftime_l
+ * libio/Makefile (routines): When group is disabled, add
+ wdummyfileops. Put in group: wfiledoalloc iowpadn swprintf
+ vswprintf iovswscanf swscanf wgenops wstrops wfileops wmemstream.
+ (tests): Put in group: tst_swprintf tst_swscanf tst-sscanf
+ tst-wmemstream1 tst-wmemstream2.
+ * libio/wdummyfileops.c: New file. Provide a dummy definition for
+ the _IO_FILE functions that prints an error message and dies.
+ * libio/libioP.h: #include <gnu/option-groups.h>.
+ (_IO_is_wide): New macro. Used as necessary to excise references
+ to wide character code.
+ * libio/iosetbuffer.c (_IO_setbuffer): Don't call _IO_WSETBUF if
+ wide characters are not supported.
+ * libio/ioseekoff.c (_IO_seekoff_unlocked): Use _IO_is_wide.
+ * libio/iofwide.c: #include <gnu/option-groups.h>.
+ (_IO_fwide): When the group is disabled, provide a simplified
+ definition that aborts if the caller attempts to make a stream
+ wide-oriented.
+ * libio/fileops.c (_IO_new_file_close_it): Use _IO_is_wide.
+ (_IO_new_file_fopen): Conditionalize for
+ __OPTION_POSIX_WIDE_CHAR_DEVICE_IO.
+ * libio/ioseekpos.c (_IO_seekpos_unlocked): Use _IO_is_wide.
+ * libio/__fpurge.c (__fpurge): Likewise.
+ * wctype/Makefile (routines): Put in group: wcfuncs wctype
+ iswctype wcfuncs_l wctype_l iswctype_l wctrans_l.
+ (tests): Put in group: test_wctype test_wcfuncs.
+ * posix/fnmatch_loop.c (FCT) (either internal_fnmatch or
+ internal_fnwmatch): Handle character categories accessed via
+ 'wctype' only if the group is enabled.
+ * stdio-common/Makefile (routines): Put in group: vfwprintf
+ vfwscanf printf-parsewc.
+ (tests): Put in group: bug18a tst-swscanf tst-wc-printf.
+ * stdio-common/printf_fp.c (__printf_fp): When the group is
+ disabled, fix 'wide' at zero.
+ * stdio-common/printf_fphex.c (__printf_fphex): Same.
+ * stdio-common/printf_size.c (__printf_size): Same.
+ * stdio-common/vfprintf.c (MULTIBYTE_SUPPORT): New macro.
+ (process_string_arg): If the format contains wide characters or
+ strings, assert that we have multibyte support.
+ * stdio-common/vfscanf.c (MULTIBYTE_SUPPORT): New macro.
+ (_IO_vfscanf_internal): If we see wide string or character format
+ directives, assert that we have multibyte support.
+ * stdio-common/scanf14.c (main): Make conditional on
+ __OPTION_EGLIBC_LOCALE_CODE.
+ * stdio-common/tst-sprintf.c (main): Make wide character test
+ conditional on __OPTION_POSIX_C_LANG_WIDE_CHAR.
+ * stdio-common/tstdiomisc.c (F): Likewise.
+
2007-12-11 Jim Blandy <jimb@codesourcery.com>
Clean up test results with OPTION_EGLIBC_LOCALE_CODE disabled.
diff --git a/libc/debug/Makefile b/libc/debug/Makefile
index a9e24b5c6..f410061f1 100644
--- a/libc/debug/Makefile
+++ b/libc/debug/Makefile
@@ -35,21 +35,23 @@ routines = noophooks \
read_chk pread_chk pread64_chk recv_chk recvfrom_chk \
readlink_chk readlinkat_chk getwd_chk getcwd_chk \
realpath_chk ptsname_r_chk fread_chk fread_u_chk \
- wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
- wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
- wcpncpy_chk \
- swprintf_chk vswprintf_chk \
confstr_chk getgroups_chk ttyname_r_chk \
- gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \
- wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \
- wcstombs_chk \
+ gethostname_chk getdomainname_chk \
stack_chk_fail fortify_fail \
$(static-only-routines)
routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin_r_chk
routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd
routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
- += wprintf_chk fwprintf_chk \
+ += wprintf_chk fwprintf_chk \
vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
+ wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
+ wcpncpy_chk \
+ swprintf_chk vswprintf_chk \
+ wcrtomb_chk mbsnrtowcs_chk \
+ wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \
+ wcstombs_chk
static-only-routines := warning-nop stack_chk_fail_local
diff --git a/libc/debug/tst-chk1.c b/libc/debug/tst-chk1.c
index 88e05da8b..9c6726d06 100644
--- a/libc/debug/tst-chk1.c
+++ b/libc/debug/tst-chk1.c
@@ -319,6 +319,7 @@ do_test (void)
snprintf (buf + 8, l0 + 3, "%d", num2);
CHK_FAIL_END
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
CHK_FAIL_START
swprintf (wbuf + 8, 3, L"%d", num1);
CHK_FAIL_END
@@ -326,6 +327,7 @@ do_test (void)
CHK_FAIL_START
swprintf (wbuf + 8, l0 + 3, L"%d", num1);
CHK_FAIL_END
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
# endif
memcpy (buf, str1 + 2, l0 + 9);
@@ -393,6 +395,7 @@ do_test (void)
CHK_FAIL_END
#endif
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
/* These ops can be done without runtime checking of object size. */
wmemcpy (wbuf, L"abcdefghij", 10);
@@ -617,6 +620,7 @@ do_test (void)
CHK_FAIL_END
#endif
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
/* Now checks for %n protection. */
@@ -1174,7 +1178,7 @@ do_test (void)
# endif
#endif
-#if __OPTION_EGLIBC_LOCALE_CODE
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
{
assert (MB_CUR_MAX <= 10);
@@ -1331,7 +1335,7 @@ do_test (void)
puts ("cannot set locale");
ret = 1;
}
-#endif
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
fd = posix_openpt (O_RDWR);
if (fd != -1)
diff --git a/libc/libio/Makefile b/libc/libio/Makefile
index 1a4ac0bc2..260e82951 100644
--- a/libc/libio/Makefile
+++ b/libc/libio/Makefile
@@ -28,15 +28,13 @@ headers := stdio.h libio.h _G_config.h bits/stdio.h bits/stdio-lock.h \
routines := \
filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \
- iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc \
+ iofopncook iofputs iofread iofsetpos ioftell \
iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs \
ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc \
iovsprintf iovsscanf \
iofgetpos64 iofopen64 iofsetpos64 \
- iowpadn \
- putchar putchar_u swprintf \
- vswprintf iovswscanf swscanf wgenops \
- wstrops wfileops iofwide wmemstream \
+ putchar putchar_u \
+ iofwide \
\
clearerr feof ferror fileno fputc freopen fseek getc getchar \
memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \
@@ -47,6 +45,14 @@ routines := \
__fpurge __fpending __fsetlocking \
\
libc_fatal fmemopen
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \
+ wfiledoalloc \
+ iowpadn \
+ swprintf \
+ vswprintf iovswscanf swscanf wgenops \
+ wstrops wfileops wmemstream
+routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += \
+ wdummyfileops
routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += \
fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
iofputws iofputws_u iogetwline ioungetwc putwc putwc_u \
@@ -54,16 +60,13 @@ routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += \
wprintf wscanf fwscanf vwscanf \
fwide
-tests = tst_swprintf tst_swscanf \
- test-fmemopen tst-ext tst-ext2 \
- tst-sscanf \
+tests = test-fmemopen tst-ext tst-ext2 \
tst-mmap-setvbuf tst-atime tst-eof \
tst-freopen bug-ungetc bug-fseek \
tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \
tst-mmap2-eofsync tst-mmap-offend bug-fopena+ \
bug-ungetc2 bug-ungetc3 bug-ungetc4 \
tst-memstream1 tst-memstream2 \
- tst-wmemstream1 tst-wmemstream2 \
bug-memstream1
tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+= tst-swscanf tst-fgetws tst-fopenloc tst-setvbuf1 \
@@ -74,6 +77,10 @@ tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
bug-wfflush bug-wmemstream1 tst-fopenloc2 \
tst_getwc \
tst_putwc tst_wprintf tst_wprintf2 tst_wscanf
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ += tst_swprintf tst_swscanf \
+ tst-sscanf \
+ tst-wmemstream1 tst-wmemstream2
test-srcs = test-freopen
all: # Make this the default target; it will be defined in Rules.
diff --git a/libc/libio/__fpurge.c b/libc/libio/__fpurge.c
index c02d8e921..f442a51d1 100644
--- a/libc/libio/__fpurge.c
+++ b/libc/libio/__fpurge.c
@@ -22,7 +22,7 @@
void
__fpurge (FILE *fp)
{
- if (fp->_mode > 0)
+ if (_IO_is_wide (fp))
{
/* Wide-char stream. */
if (_IO_in_backup (fp))
diff --git a/libc/libio/fileops.c b/libc/libio/fileops.c
index 95cd2d64c..16fa2c297 100644
--- a/libc/libio/fileops.c
+++ b/libc/libio/fileops.c
@@ -176,7 +176,7 @@ _IO_new_file_close_it (fp)
/* Free buffer. */
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
- if (fp->_mode > 0)
+ if (_IO_is_wide (fp))
{
if (_IO_have_wbackup (fp))
INTUSE(_IO_free_wbackup_area) (fp);
@@ -343,6 +343,7 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
cs = strstr (last_recognized + 1, ",ccs=");
if (cs != NULL)
{
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
/* Yep. Load the appropriate conversions and set the orientation
to wide. */
struct gconv_fcts fcts;
@@ -407,6 +408,12 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
/* Set the mode now. */
result->_mode = 1;
+#else
+ /* Treat this as if we couldn't find the given character set. */
+ (void) INTUSE(_IO_file_close_it) (fp);
+ __set_errno (EINVAL);
+ return NULL;
+#endif
}
}
#endif /* GNU libc */
diff --git a/libc/libio/iofwide.c b/libc/libio/iofwide.c
index a9936687d..c9326f80b 100644
--- a/libc/libio/iofwide.c
+++ b/libc/libio/iofwide.c
@@ -27,6 +27,7 @@
#include <libioP.h>
#ifdef _LIBC
+# include <gnu/option-groups.h>
# include <dlfcn.h>
# include <wchar.h>
#endif
@@ -44,6 +45,8 @@
#endif
+#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR
+
/* Prototypes of libio's codecvt functions. */
static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
__mbstate_t *statep,
@@ -521,3 +524,26 @@ do_max_length (struct _IO_codecvt *codecvt)
return MB_CUR_MAX;
#endif
}
+
+#else
+/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled. */
+
+#undef _IO_fwide
+int
+_IO_fwide (fp, mode)
+ _IO_FILE *fp;
+ int mode;
+{
+ /* Die helpfully if the user tries to create a wide stream; I
+ disbelieve that most users check the return value from
+ 'fwide (fp, 1)'. */
+ assert (mode <= 0);
+
+ /* We can only make streams byte-oriented, which is trivial. */
+ if (mode < 0)
+ fp->_mode = -1;
+
+ return fp->_mode;
+}
+
+#endif
diff --git a/libc/libio/ioseekoff.c b/libc/libio/ioseekoff.c
index dd8a37fa4..3e62506d3 100644
--- a/libc/libio/ioseekoff.c
+++ b/libc/libio/ioseekoff.c
@@ -62,7 +62,7 @@ _IO_seekoff_unlocked (fp, offset, dir, mode)
else
abort ();
}
- if (_IO_fwide (fp, 0) < 0)
+ if (! _IO_is_wide (fp))
INTUSE(_IO_free_backup_area) (fp);
else
INTUSE(_IO_free_wbackup_area) (fp);
diff --git a/libc/libio/ioseekpos.c b/libc/libio/ioseekpos.c
index cfa9ed808..144839384 100644
--- a/libc/libio/ioseekpos.c
+++ b/libc/libio/ioseekpos.c
@@ -36,7 +36,7 @@ _IO_seekpos_unlocked (fp, pos, mode)
/* If we have a backup buffer, get rid of it, since the __seekoff
callback may not know to do the right thing about it.
This may be over-kill, but it'll do for now. TODO */
- if (_IO_fwide (fp, 0) <= 0)
+ if (! _IO_is_wide (fp))
{
if (_IO_have_backup (fp))
INTUSE(_IO_free_backup_area) (fp);
diff --git a/libc/libio/iosetbuffer.c b/libc/libio/iosetbuffer.c
index d43d0ebca..917f90554 100644
--- a/libc/libio/iosetbuffer.c
+++ b/libc/libio/iosetbuffer.c
@@ -40,9 +40,11 @@ _IO_setbuffer (fp, buf, size)
if (!buf)
size = 0;
(void) _IO_SETBUF (fp, buf, size);
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp))
/* We also have to set the buffer using the wide char function. */
(void) _IO_WSETBUF (fp, buf, size);
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
_IO_release_lock (fp);
}
INTDEF(_IO_setbuffer)
diff --git a/libc/libio/libioP.h b/libc/libio/libioP.h
index 854f04929..ee6e52c2f 100644
--- a/libc/libio/libioP.h
+++ b/libc/libio/libioP.h
@@ -36,6 +36,10 @@
/*# include <comthread.h>*/
#endif
+#if defined _LIBC
+# include <gnu/option-groups.h>
+#endif
+
#include <math_ldbl_opt.h>
#include "iolibio.h"
@@ -493,8 +497,20 @@ extern void _IO_old_init (_IO_FILE *fp, int flags) __THROW;
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
+
+/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0',
+ except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it
+ expands to a constant, allowing the compiler to realize that it can
+ eliminate code that references wide stream handling functions.
+ This, in turn, allows us to omit them. */
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+# define _IO_is_wide(_f) ((_f)->_mode > 0)
+#else
+# define _IO_is_wide(_f) (0)
+#endif
+
# define _IO_do_flush(_f) \
- ((_f)->_mode <= 0 \
+ (! _IO_is_wide (_f) \
? INTUSE(_IO_do_write)(_f, (_f)->_IO_write_base, \
(_f)->_IO_write_ptr-(_f)->_IO_write_base) \
: INTUSE(_IO_wdo_write)(_f, (_f)->_wide_data->_IO_write_base, \
diff --git a/libc/libio/wdummyfileops.c b/libc/libio/wdummyfileops.c
new file mode 100644
index 000000000..c0150b8d7
--- /dev/null
+++ b/libc/libio/wdummyfileops.c
@@ -0,0 +1,161 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ As a special exception, if you link the code in this file with
+ files compiled with a GNU compiler to produce an executable,
+ that does not cause the resulting executable to be covered by
+ the GNU Lesser General Public License. This exception does not
+ however invalidate any other reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+ This exception applies to code released by its copyright holders
+ in files containing the exception. */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libioP.h>
+
+static void __THROW __attribute__ ((__noreturn__))
+_IO_wfile_wide_char_support_disabled (void)
+{
+ static const char errstr[]
+ = ("The application tried to use wide character I/O, but libc.so"
+ " was compiled\n"
+ "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n");
+ __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);
+ abort ();
+}
+
+static void
+_IO_wfile_disabled_void_int (_IO_FILE *fp, int x)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_int_int (_IO_FILE *fp, int x)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_int_none (_IO_FILE *fp)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_size_t
+_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_size_t
+_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_off64_t
+_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_off64_t
+_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_FILE *
+_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_ssize_t
+_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_ssize_t
+_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_off64_t
+_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_close (_IO_FILE *fp)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_showmanyc (_IO_FILE *fp)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static void
+_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale)
+{
+ _IO_wfile_wide_char_support_disabled ();
+}
+
+static const struct _IO_jump_t _IO_wfile_jumps_disabled =
+{
+ JUMP_INIT_DUMMY,
+ JUMP_INIT(finish, _IO_wfile_disabled_void_int),
+ JUMP_INIT(overflow, _IO_wfile_disabled_int_int),
+ JUMP_INIT(underflow, _IO_wfile_disabled_int_none),
+ JUMP_INIT(uflow, _IO_wfile_disabled_int_none),
+ JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int),
+ JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn),
+ JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn),
+ JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff),
+ JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos),
+ JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf),
+ JUMP_INIT(sync, _IO_wfile_disabled_int_none),
+ JUMP_INIT(doallocate, _IO_wfile_disabled_int_none),
+ JUMP_INIT(read, _IO_wfile_disabled_read),
+ JUMP_INIT(write, _IO_wfile_disabled_write),
+ JUMP_INIT(seek, _IO_wfile_disabled_seek),
+ JUMP_INIT(close, _IO_wfile_disabled_close),
+ JUMP_INIT(stat, _IO_wfile_disabled_stat),
+ JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc),
+ JUMP_INIT(imbue, _IO_wfile_disabled_imbue)
+};
+
+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps)
+libc_hidden_data_def (_IO_wfile_jumps)
+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap)
+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap)
diff --git a/libc/option-groups.def b/libc/option-groups.def
index 7800af90b..b58ea6e57 100644
--- a/libc/option-groups.def
+++ b/libc/option-groups.def
@@ -401,6 +401,7 @@ config OPTION_EGLIBC_LOCALES
config OPTION_EGLIBC_LOCALE_CODE
bool "Locale functions"
+ depends OPTION_POSIX_C_LANG_WIDE_CHAR
help
This option group includes locale support functions, programs,
and libraries. With OPTION_EGLIBC_LOCALE_FUNCTIONS disabled,
@@ -645,6 +646,35 @@ config OPTION_EGLIBC_WORDEXP
performing word expansion in the manner of the shell, and the
accompanying 'wordfree' function.
+config OPTION_POSIX_C_LANG_WIDE_CHAR
+ bool "ISO C library wide character functions, excluding I/O"
+ help
+ This option group includes the functions defined by the ISO C
+ standard for working with wide and multibyte characters in
+ memory. Functions for reading and writing wide and multibyte
+ characters from and to files call in the
+ OPTION_POSIX_WIDE_CHAR_DEVICE_IO option group.
+
+ This option group includes the following functions:
+
+ btowc mbsinit wcscspn wcstoll
+ iswalnum mbsrtowcs wcsftime wcstombs
+ iswalpha mbstowcs wcslen wcstoul
+ iswblank mbtowc wcsncat wcstoull
+ iswcntrl swprintf wcsncmp wcstoumax
+ iswctype swscanf wcsncpy wcsxfrm
+ iswdigit towctrans wcspbrk wctob
+ iswgraph towlower wcsrchr wctomb
+ iswlower towupper wcsrtombs wctrans
+ iswprint vswprintf wcsspn wctype
+ iswpunct vswscanf wcsstr wmemchr
+ iswspace wcrtomb wcstod wmemcmp
+ iswupper wcscat wcstof wmemcpy
+ iswxdigit wcschr wcstoimax wmemmove
+ mblen wcscmp wcstok wmemset
+ mbrlen wcscoll wcstol
+ mbrtowc wcscpy wcstold
+
config OPTION_POSIX_REGEXP
bool "Regular expressions"
help
@@ -668,6 +698,7 @@ config OPTION_POSIX_REGEXP
config OPTION_POSIX_WIDE_CHAR_DEVICE_IO
bool "Input and output functions for wide characters"
+ depends OPTION_POSIX_C_LANG_WIDE_CHAR
help
This option group includes functions for reading and writing
wide characters to and from <stdio.h> streams.
@@ -692,6 +723,25 @@ config OPTION_POSIX_WIDE_CHAR_DEVICE_IO
some of these functions; you will not be able to link or run
C++ programs if you disable this option group.
+ This option group also affects the behavior of the following
+ functions:
+
+ fdopen
+ fopen
+ fopen64
+ freopen
+ freopen64
+
+ These functions all take an OPENTYPE parameter which may
+ contain a string of the form ",ccs=CHARSET", indicating that
+ the underlying file uses the character set named CHARSET.
+ This produces a wide-oriented stream, which is only useful
+ when the functions included in this option group are present.
+ If the user attempts to open a file specifying a character set
+ in the OPENTYPE parameter, and EGLIBC was built with this
+ option group disabled, the function returns NULL, and sets
+ errno to EINVAL.
+
# This helps Emacs users browse this file using the page motion commands
# and commands like 'pages-directory'.
diff --git a/libc/option-groups.mak b/libc/option-groups.mak
index 2ade410a7..7d9f9a43e 100644
--- a/libc/option-groups.mak
+++ b/libc/option-groups.mak
@@ -15,6 +15,16 @@ include $(firstword $(..) ../)option-groups.defaults
# defaults from option-groups.defaults.
-include $(option_group_config_file)
+# $(call option-disabled, VAR) is 'y' if VAR is not 'y', or 'n' otherwise.
+# VAR should be a variable name, not a variable reference; this is
+# less general, but more terse for the intended use.
+# You can use it to add a file to a list if an option group is
+# disabled, like this:
+# routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += ...
+define option-disabled
+$(firstword $(subst y,n,$(filter y,$($(strip $(1))))) y)
+endef
+
# Establish 'routines-y', etc. as simply-expanded variables.
aux-y :=
extra-libs-others-y :=
diff --git a/libc/posix/fnmatch_loop.c b/libc/posix/fnmatch_loop.c
index 5d0e8b5a3..cecc36c9d 100644
--- a/libc/posix/fnmatch_loop.c
+++ b/libc/posix/fnmatch_loop.c
@@ -282,7 +282,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
/* Leave room for the null. */
CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
size_t c1 = 0;
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
wctype_t wt;
#endif
const CHAR *startp = p;
@@ -312,7 +312,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
}
str[c1] = L('\0');
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
wt = IS_CHAR_CLASS (str);
if (wt == 0)
/* Invalid character class name. */
diff --git a/libc/scripts/option-groups.awk b/libc/scripts/option-groups.awk
index 1ff51142d..91ebe4639 100644
--- a/libc/scripts/option-groups.awk
+++ b/libc/scripts/option-groups.awk
@@ -18,18 +18,20 @@ NF == 2 {
# Print final values.
END {
- print "/* This file is automatically generated."
+ print "/* This file is automatically generated by scripts/option-groups.awk"
+ print " in the EGLIBC source tree."
+ print ""
print " It defines macros that indicate which EGLIBC option groups were"
print " configured in 'option-groups.config' when this C library was"
print " built. For each option group named OPTION_foo, it #defines"
print " __OPTION_foo to be 1 if the group is enabled, or leaves that"
- print " symbol undefined if the group is disabled."
+ print " symbol undefined if the group is disabled. */"
print ""
- print " It is generated by scripts/option-groups.awk in the EGLIBC"
- print " source tree. */"
+ print "#ifndef __GNU_OPTION_GROUPS_H"
+ print "#define __GNU_OPTION_GROUPS_H"
print ""
- # Sort the variables by name.
+ # Produce a sorted list of variable names.
i=0
for (var in vars)
names[i++] = var
@@ -49,4 +51,7 @@ END {
# option-groups.def.
}
}
+
+ print ""
+ print "#endif /* __GNU_OPTION_GROUPS_H */"
}
diff --git a/libc/stdio-common/Makefile b/libc/stdio-common/Makefile
index acfabac16..356bea3e9 100644
--- a/libc/stdio-common/Makefile
+++ b/libc/stdio-common/Makefile
@@ -30,7 +30,7 @@ routines := \
_itoa _itowa itoa-digits itoa-udigits itowa-digits \
vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \
printf_size fprintf printf snprintf sprintf asprintf dprintf \
- vfwprintf vfscanf vfwscanf \
+ vfscanf \
fscanf scanf sscanf \
perror psignal \
tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
@@ -39,12 +39,18 @@ routines := \
flockfile ftrylockfile funlockfile \
isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
isoc99_vsscanf
+# Ideally, _itowa and itowa-digits would be in this option group as
+# well, but it is used unconditionally by printf_fp and printf_fphex,
+# and it didn't seem straightforward to disentangle it.
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \
+ vfwprintf vfwscanf
include ../Makeconfig
install-headers-nosubdir: $(inst_includedir)/bits/stdio_lim.h
-aux := errlist siglist printf-parsemb printf-parsewc fxprintf
+aux := errlist siglist printf-parsemb fxprintf
+aux-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += printf-parsewc
distribute := _itoa.h _itowa.h _i18n_number.h \
printf-parse.h stdio_lim.h.in tst-unbputc.sh tst-printf.sh
@@ -52,18 +58,20 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
temptest tst-fileno test-fwrite tst-ungetc tst-ferror \
xbug errnobug \
bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \
- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \
+ tfformat tiformat tllformat tstdiomisc tst-printfsz \
scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \
scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf \
tst-fseek tst-fmemopen tst-gets \
tst-sprintf tst-rndseek tst-fdopen tst-fphex \
tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
+ tst-fwrite bug16 bug17 tst-sprintf2 bug18 \
bug19 tst-popen2 scanf14 scanf15
tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+= tst-sscanf tst-swprintf bug15 test-vfprintf bug14 scanf13
tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
+= tst-perror bug19a bug20
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ += bug18a tst-swscanf tst-wc-printf
test-srcs = tst-unbputc tst-printf
diff --git a/libc/stdio-common/printf_fp.c b/libc/stdio-common/printf_fp.c
index 31868b01a..c7e5f6ccf 100644
--- a/libc/stdio-common/printf_fp.c
+++ b/libc/stdio-common/printf_fp.c
@@ -150,6 +150,10 @@ static wchar_t *group_number (wchar_t *buf, wchar_t *bufend,
wchar_t thousands_sep, int ngroups)
internal_function;
+/* Ideally, when OPTION_EGLIBC_LOCALE_CODE is disabled, this should do
+ all its work in ordinary characters, rather than doing it in wide
+ characters and then converting at the end. But that is a challenge
+ for another day. */
int
___printf_fp (FILE *fp,
@@ -211,7 +215,14 @@ ___printf_fp (FILE *fp,
mp_limb_t cy;
/* Nonzero if this is output on a wide character stream. */
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
int wide = info->wide;
+#else
+ /* This should never be called on a wide-oriented stream when
+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
+ be trusted to figure that out. */
+ const int wide = 0;
+#endif
/* Buffer in which we produce the output. */
wchar_t *wbuffer = NULL;
diff --git a/libc/stdio-common/printf_fphex.c b/libc/stdio-common/printf_fphex.c
index b8e241ffb..670292920 100644
--- a/libc/stdio-common/printf_fphex.c
+++ b/libc/stdio-common/printf_fphex.c
@@ -145,7 +145,14 @@ __printf_fphex (FILE *fp,
int done = 0;
/* Nonzero if this is output on a wide character stream. */
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
int wide = info->wide;
+#else
+ /* This should never be called on a wide-oriented stream when
+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
+ be trusted to figure that out. */
+ const int wide = 0;
+#endif
/* Figure out the decimal point character. */
diff --git a/libc/stdio-common/printf_size.c b/libc/stdio-common/printf_size.c
index 957de2f57..4407cf673 100644
--- a/libc/stdio-common/printf_size.c
+++ b/libc/stdio-common/printf_size.c
@@ -24,6 +24,7 @@
#include <math.h>
#include <printf.h>
#include <libioP.h>
+#include <gnu/option-groups.h>
/* This defines make it possible to use the same code for GNU C library and
@@ -117,7 +118,14 @@ __printf_size (FILE *fp, const struct printf_info *info,
struct printf_info fp_info;
int done = 0;
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
int wide = info->wide;
+#else
+ /* This should never be called on a wide-oriented stream when
+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
+ be trusted to figure that out. */
+ const int wide = 0;
+#endif
/* Fetch the argument value. */
diff --git a/libc/stdio-common/scanf14.c b/libc/stdio-common/scanf14.c
index 387ceba4b..b31505c0d 100644
--- a/libc/stdio-common/scanf14.c
+++ b/libc/stdio-common/scanf14.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#include <gnu/option-groups.h>
#define FAIL() \
do { \
@@ -36,6 +37,7 @@ main (void)
FAIL ();
else if (d != 2.25 || memcmp (c, " x", 2) != 0)
FAIL ();
+#if __OPTION_EGLIBC_LOCALE_CODE
if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
FAIL ();
else
@@ -45,6 +47,7 @@ main (void)
memset (lsp, 'x', sizeof L"3.25");
free (lsp);
}
+#endif
if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
FAIL ();
else
diff --git a/libc/stdio-common/tst-sprintf.c b/libc/stdio-common/tst-sprintf.c
index c04fef18f..e26b978d4 100644
--- a/libc/stdio-common/tst-sprintf.c
+++ b/libc/stdio-common/tst-sprintf.c
@@ -9,12 +9,14 @@ main (void)
char buf[100];
int result = 0;
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
if (sprintf (buf, "%.0ls", L"foo") != 0
|| strlen (buf) != 0)
{
puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output");
result = 1;
}
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
#define SIZE (1024*70000)
#define STR(x) #x
diff --git a/libc/stdio-common/tstdiomisc.c b/libc/stdio-common/tstdiomisc.c
index db038fa2b..32aed396a 100644
--- a/libc/stdio-common/tstdiomisc.c
+++ b/libc/stdio-common/tstdiomisc.c
@@ -66,6 +66,7 @@ F (void)
result |= strcmp (buf, "inf INF") != 0;
printf ("expected \"inf INF\", got \"%s\"\n", buf);
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%f %F", nanval, nanval);
result |= wcscmp (wbuf, L"nan NAN") != 0;
printf ("expected L\"nan NAN\", got L\"%S\"\n", wbuf);
@@ -74,6 +75,7 @@ F (void)
DBL_MAX * DBL_MAX, DBL_MAX * DBL_MAX);
result |= wcscmp (wbuf, L"inf INF") != 0;
printf ("expected L\"inf INF\", got L\"%S\"\n", wbuf);
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
return result;
}
diff --git a/libc/stdio-common/vfprintf.c b/libc/stdio-common/vfprintf.c
index 22f92ce77..2a42c7eac 100644
--- a/libc/stdio-common/vfprintf.c
+++ b/libc/stdio-common/vfprintf.c
@@ -107,6 +107,12 @@
# define EOF WEOF
#endif
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+# define MULTIBYTE_SUPPORT (1)
+#else
+# define MULTIBYTE_SUPPORT (0)
+#endif
+
#if __OPTION_EGLIBC_LOCALE_CODE
# define LOCALE_SUPPORT (1)
#else
@@ -1082,8 +1088,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
# define process_string_arg(fspec) \
LABEL (form_character): \
/* Character. */ \
- if (is_long) \
- goto LABEL (form_wcharacter); \
+ if (is_long) \
+ { \
+ assert (MULTIBYTE_SUPPORT); \
+ goto LABEL (form_wcharacter); \
+ } \
--width; /* Account for the character itself. */ \
if (!left) \
PAD (' '); \
@@ -1096,6 +1105,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
break; \
\
LABEL (form_wcharacter): \
+ assert (MULTIBYTE_SUPPORT); \
{ \
/* Wide character. */ \
char buf[MB_CUR_MAX]; \
@@ -1195,6 +1205,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
} \
else \
{ \
+ assert (MULTIBYTE_SUPPORT); \
const wchar_t *s2 = (const wchar_t *) string; \
mbstate_t mbstate; \
\
diff --git a/libc/stdio-common/vfscanf.c b/libc/stdio-common/vfscanf.c
index e89e23d62..d114df6df 100644
--- a/libc/stdio-common/vfscanf.c
+++ b/libc/stdio-common/vfscanf.c
@@ -134,6 +134,12 @@
# define WINT_T int
#endif
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+# define MULTIBYTE_SUPPORT (1)
+#else
+# define MULTIBYTE_SUPPORT (0)
+#endif
+
#define encode_error() do { \
errval = 4; \
__set_errno (EILSEQ); \
@@ -374,6 +380,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#ifndef COMPILE_WSCANF
if (!isascii ((unsigned char) *f))
{
+ assert (MULTIBYTE_SUPPORT);
+
/* Non-ASCII, may be a multibyte. */
int len = __mbrlen (f, strlen (f), &state);
if (len > 0)
@@ -810,6 +818,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
}
/* FALLTHROUGH */
case L_('C'):
+ assert (MULTIBYTE_SUPPORT);
+
if (width == -1)
width = 1;
@@ -1136,6 +1146,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* FALLTHROUGH */
case L_('S'):
+ assert (MULTIBYTE_SUPPORT);
+
{
#ifndef COMPILE_WSCANF
mbstate_t cstate;
@@ -2302,7 +2314,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
case L_('['): /* Character class. */
if (flags & LONG)
- STRING_ARG (wstr, wchar_t, 100);
+ {
+ assert (MULTIBYTE_SUPPORT);
+ STRING_ARG (wstr, wchar_t, 100);
+ }
else
STRING_ARG (str, char, 100);
@@ -2376,6 +2391,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (flags & LONG)
{
size_t now = read_in;
+ assert (MULTIBYTE_SUPPORT);
#ifdef COMPILE_WSCANF
if (__builtin_expect (inchar () == WEOF, 0))
input_error ();
diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile
index 47c5a9429..9a296cc85 100644
--- a/libc/stdlib/Makefile
+++ b/libc/stdlib/Makefile
@@ -38,7 +38,6 @@ routines-y := \
exit on_exit atexit cxa_atexit cxa_finalize old_atexit \
abs labs llabs \
div ldiv lldiv \
- mblen mbstowcs mbtowc wcstombs wctomb \
random random_r rand rand_r \
drand48 erand48 lrand48 nrand48 mrand48 jrand48 \
srand48 seed48 lcong48 \
@@ -52,10 +51,13 @@ routines-y := \
system canonicalize \
a64l l64a \
getsubopt xpg_basename fmtmsg \
- strtoimax strtoumax wcstoimax wcstoumax \
+ strtoimax strtoumax \
getcontext setcontext makecontext swapcontext
routines-$(OPTION_EGLIBC_LOCALE_CODE) += \
strfmon strfmon_l
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \
+ mblen mbstowcs mbtowc wcstombs wctomb \
+ wcstoimax wcstoumax
ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP))
routines-y += rpmatch
endif
@@ -69,7 +71,7 @@ static-only-routines = atexit
distribute := exit.h grouping.h abort-instr.h isomac.c tst-fmtmsg.sh \
allocalim.h
test-srcs := tst-fmtmsg
-tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
+tests := tst-strtol tst-strtod testrand testsort testdiv \
test-canon test-canon2 tst-strtoll tst-environ \
tst-xpg-basename tst-random tst-random2 tst-bsearch \
tst-limits tst-rand48 bug-strtod tst-setcontext \
@@ -78,6 +80,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tst-makecontext tst-qsort2
tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+= tst-strtod3 tst-strtod4 tst-strtod5 testmb2
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ += testmb
include ../Makeconfig
ifeq ($(build-shared),yes)
diff --git a/libc/time/Makefile b/libc/time/Makefile
index 407ab2d16..1b7de70e1 100644
--- a/libc/time/Makefile
+++ b/libc/time/Makefile
@@ -31,7 +31,9 @@ routines := offtime asctime clock ctime ctime_r difftime \
tzfile getitimer setitimer \
stime dysize timegm ftime \
getdate strptime strptime_l \
- strftime wcsftime strftime_l wcsftime_l
+ strftime strftime_l
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ := wcsftime wcsftime_l
aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup
distribute := datemsk
diff --git a/libc/wcsmbs/Makefile b/libc/wcsmbs/Makefile
index 1f27dff4e..3af34464b 100644
--- a/libc/wcsmbs/Makefile
+++ b/libc/wcsmbs/Makefile
@@ -27,9 +27,13 @@ subdir := wcsmbs
headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h
distribute := wcwidth.h wcsmbsload.h
-routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
+# These functions are used by printf_fp.c, even in the plain case; see
+# comments there for OPTION_EGLIBC_LOCALE_CODE.
+routines := wmemcpy wmemset
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
- wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \
+ wmemcmp wmemmove wcpcpy wcpncpy wmempcpy \
btowc wctob mbsinit \
mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
@@ -45,10 +49,12 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
+= isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf
-tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen \
- tst-wcpncpy tst-mbsrtowcs tst-wchar-h wcsatcliff
+tests := tst-wchar-h
tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+= tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ += tst-wcstof wcsmbs-tst1 tst-wcsnlen \
+ tst-wcpncpy tst-mbsrtowcs wcsatcliff
include ../Rules
diff --git a/libc/wctype/Makefile b/libc/wctype/Makefile
index b0e8f968e..ff66d87ef 100644
--- a/libc/wctype/Makefile
+++ b/libc/wctype/Makefile
@@ -19,13 +19,19 @@
#
# Sub-makefile for wctype portion of the library.
#
+include ../option-groups.mak
+
subdir := wctype
headers := wctype.h
distribute := wchar-lookup.h
-routines := wcfuncs wctype iswctype wctrans towctrans \
- wcfuncs_l wctype_l iswctype_l wctrans_l towctrans_l
+routines := wctrans towctrans towctrans_l
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ := wcfuncs wctype iswctype \
+ wcfuncs_l wctype_l iswctype_l wctrans_l
-tests := test_wctype test_wcfuncs
+tests :=
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+ += test_wctype test_wcfuncs
include ../Rules