[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[patches] cleaned-up version of OPTION_POSIX_C_LANG_WIDE_CHAR patch



Here's a revised version of the OPTION_POSIX_C_LANG_WIDE_CHAR patch. This has been tested on i686 Linux, with appropriate conditionalizations added for tests that can't be expected to work when this option group is disabled.

OK to commit now?

-Sandra

2007-12-13  Jim Blandy  <jimb@xxxxxxxxxxxxxxxx>
	    Sandra Loosemore  <sandra@xxxxxxxxxxxxxxxx>

	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.



Index: option-groups.def
===================================================================
*** option-groups.def	(revision 4501)
--- option-groups.def	(working copy)
*************** config OPTION_EGLIBC_LOCALES
*** 401,406 ****
--- 401,407 ----
  
  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,
*************** config OPTION_EGLIBC_WORDEXP
*** 645,650 ****
--- 646,680 ----
          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
*************** config OPTION_POSIX_REGEXP
*** 668,673 ****
--- 698,704 ----
  
  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.
*************** config OPTION_POSIX_WIDE_CHAR_DEVICE_IO
*** 692,697 ****
--- 723,747 ----
          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'.
Index: option-groups.mak
===================================================================
*** option-groups.mak	(revision 4501)
--- option-groups.mak	(working copy)
*************** include $(firstword $(..) ../)option-gro
*** 15,20 ****
--- 15,30 ----
  # 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 :=
Index: scripts/option-groups.awk
===================================================================
*** scripts/option-groups.awk	(revision 4501)
--- scripts/option-groups.awk	(working copy)
*************** NF == 2 {
*** 18,35 ****
  
  # Print final values.
  END {
!     print "/* This file is automatically generated."
      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 ""
!     print "   It is generated by scripts/option-groups.awk in the EGLIBC"
!     print "   source tree.  */"
      print ""
  
!     # Sort the variables by name.
      i=0
      for (var in vars)
          names[i++] = var
--- 18,37 ----
  
  # Print final values.
  END {
!     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 ""
!     print "#ifndef __GNU_OPTION_GROUPS_H"
!     print "#define __GNU_OPTION_GROUPS_H"
      print ""
  
!     # Produce a sorted list of variable names.
      i=0
      for (var in vars)
          names[i++] = var
*************** END {
*** 49,52 ****
--- 51,57 ----
              # option-groups.def.
          }
      }
+ 
+     print ""
+     print "#endif /* __GNU_OPTION_GROUPS_H */"
  }
Index: stdlib/Makefile
===================================================================
*** stdlib/Makefile	(revision 4501)
--- stdlib/Makefile	(working copy)
*************** routines-y	:=							      \
*** 38,44 ****
  	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						      \
--- 38,43 ----
*************** routines-y	:=							      \
*** 52,61 ****
  	system canonicalize						      \
  	a64l l64a							      \
  	getsubopt xpg_basename fmtmsg					      \
! 	strtoimax strtoumax wcstoimax wcstoumax				      \
  	getcontext setcontext makecontext swapcontext
  routines-$(OPTION_EGLIBC_LOCALE_CODE) +=				      \
  	strfmon strfmon_l
  ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP))
  routines-y += rpmatch
  endif
--- 51,63 ----
  	system canonicalize						      \
  	a64l l64a							      \
  	getsubopt xpg_basename fmtmsg					      \
! 	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
*************** static-only-routines = atexit
*** 69,75 ****
  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   \
  		   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	    \
--- 71,77 ----
  distribute	:= exit.h grouping.h abort-instr.h isomac.c tst-fmtmsg.sh   \
  		   allocalim.h
  test-srcs	:= tst-fmtmsg
! 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	    \
*************** tests		:= tst-strtol tst-strtod testmb t
*** 78,83 ****
--- 80,87 ----
  		   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)
Index: debug/Makefile
===================================================================
*** debug/Makefile	(revision 4501)
--- debug/Makefile	(working copy)
*************** routines  = noophooks \
*** 35,55 ****
  	    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 \
  	    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	\
  	    vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk
  
  static-only-routines := warning-nop stack_chk_fail_local
  
--- 35,57 ----
  	    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 \
  	    confstr_chk getgroups_chk ttyname_r_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				\
  	    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
  
Index: debug/tst-chk1.c
===================================================================
*** debug/tst-chk1.c	(revision 4501)
--- debug/tst-chk1.c	(working copy)
*************** do_test (void)
*** 319,324 ****
--- 319,325 ----
    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
*************** do_test (void)
*** 326,331 ****
--- 327,333 ----
    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);
*************** do_test (void)
*** 393,398 ****
--- 395,401 ----
    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);
*************** do_test (void)
*** 617,622 ****
--- 620,626 ----
    CHK_FAIL_END
  #endif
  
+ #endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
  
    /* Now checks for %n protection.  */
  
*************** do_test (void)
*** 1174,1180 ****
  # endif
  #endif
  
! #if __OPTION_EGLIBC_LOCALE_CODE
    if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
      {
        assert (MB_CUR_MAX <= 10);
--- 1178,1184 ----
  # endif
  #endif
  
! #if __OPTION_POSIX_C_LANG_WIDE_CHAR
    if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
      {
        assert (MB_CUR_MAX <= 10);
*************** do_test (void)
*** 1331,1337 ****
        puts ("cannot set locale");
        ret = 1;
      }
! #endif
  
    fd = posix_openpt (O_RDWR);
    if (fd != -1)
--- 1335,1341 ----
        puts ("cannot set locale");
        ret = 1;
      }
! #endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
  
    fd = posix_openpt (O_RDWR);
Index: wcsmbs/Makefile
===================================================================
*** wcsmbs/Makefile	(revision 4501)
--- wcsmbs/Makefile	(working copy)
*************** subdir	:= wcsmbs
*** 27,35 ****
  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 \
  	    wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
! 	    wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \
  	    btowc wctob mbsinit \
  	    mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
  	    mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
--- 27,39 ----
  headers	:= wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h
  distribute := wcwidth.h wcsmbsload.h
  
! # 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 wmemmove wcpcpy wcpncpy wmempcpy \
  	    btowc wctob mbsinit \
  	    mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
  	    mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
*************** routines := wcscat wcschr wcscmp wcscpy 
*** 45,54 ****
  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-$(OPTION_EGLIBC_LOCALE_CODE) \
        += tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb
  
  include ../Rules
  
--- 49,60 ----
  routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)				\
  	 += isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf
  
! 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
  
Index: time/Makefile
===================================================================
*** time/Makefile	(revision 4501)
--- time/Makefile	(working copy)
*************** routines := offtime asctime clock ctime 
*** 31,37 ****
  	    tzfile getitimer setitimer			 \
  	    stime dysize timegm ftime			 \
  	    getdate strptime strptime_l			 \
! 	    strftime wcsftime strftime_l wcsftime_l
  aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup
  distribute := datemsk
  
--- 31,39 ----
  	    tzfile getitimer setitimer			 \
  	    stime dysize timegm ftime			 \
  	    getdate strptime strptime_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
  
Index: libio/Makefile
===================================================================
*** libio/Makefile	(revision 4501)
--- libio/Makefile	(working copy)
*************** headers	:= stdio.h libio.h _G_config.h b
*** 28,42 ****
  
  routines	:=							      \
  	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
! 	iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc	      \
  	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				      \
  									      \
  	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
  	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
--- 28,40 ----
  
  routines	:=							      \
  	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
! 	iofopncook iofputs iofread iofsetpos ioftell			      \
  	iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs	      \
  	ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc		      \
  	iovsprintf iovsscanf						      \
  	iofgetpos64 iofopen64 iofsetpos64				      \
! 	putchar putchar_u						      \
! 	iofwide								      \
  									      \
  	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
  	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
*************** routines	:=							      \
*** 47,52 ****
--- 45,58 ----
  	__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		      \
*************** routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE
*** 54,69 ****
  	wprintf wscanf fwscanf vwscanf					      \
  	fwide
  
! tests = tst_swprintf tst_swscanf				\
! 	test-fmemopen tst-ext tst-ext2				\
! 	tst-sscanf						\
  	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	\
--- 60,72 ----
  	wprintf wscanf fwscanf vwscanf					      \
  	fwide
  
! 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				\
  	bug-memstream1
  tests-$(OPTION_EGLIBC_LOCALE_CODE)				\
       += tst-swscanf tst-fgetws tst-fopenloc tst-setvbuf1	\
*************** tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO
*** 74,79 ****
--- 77,86 ----
  	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.
Index: libio/wdummyfileops.c
===================================================================
*** libio/wdummyfileops.c	(revision 0)
--- libio/wdummyfileops.c	(revision 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)
Index: libio/libioP.h
===================================================================
*** libio/libioP.h	(revision 4501)
--- libio/libioP.h	(working copy)
***************
*** 36,41 ****
--- 36,45 ----
  /*# include <comthread.h>*/
  #endif
  
+ #if defined _LIBC
+ # include <gnu/option-groups.h>
+ #endif
+ 
  #include <math_ldbl_opt.h>
  
  #include "iolibio.h"
*************** extern void _IO_old_init (_IO_FILE *fp, 
*** 493,500 ****
  
  
  #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
  # define _IO_do_flush(_f) \
!   ((_f)->_mode <= 0							      \
     ? 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,	      \
--- 497,516 ----
  
  
  #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) \
!   (! _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,	      \
Index: libio/iosetbuffer.c
===================================================================
*** libio/iosetbuffer.c	(revision 4501)
--- libio/iosetbuffer.c	(working copy)
*************** _IO_setbuffer (fp, buf, size)
*** 40,48 ****
--- 40,50 ----
    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)
Index: libio/ioseekoff.c
===================================================================
*** libio/ioseekoff.c	(revision 4501)
--- libio/ioseekoff.c	(working copy)
*************** _IO_seekoff_unlocked (fp, offset, dir, m
*** 62,68 ****
  	  else
  	    abort ();
  	}
!       if (_IO_fwide (fp, 0) < 0)
  	INTUSE(_IO_free_backup_area) (fp);
        else
  	INTUSE(_IO_free_wbackup_area) (fp);
--- 62,68 ----
  	  else
  	    abort ();
  	}
!       if (! _IO_is_wide (fp))
  	INTUSE(_IO_free_backup_area) (fp);
        else
  	INTUSE(_IO_free_wbackup_area) (fp);
Index: libio/iofwide.c
===================================================================
*** libio/iofwide.c	(revision 4501)
--- libio/iofwide.c	(working copy)
***************
*** 27,32 ****
--- 27,33 ----
  
  #include <libioP.h>
  #ifdef _LIBC
+ # include <gnu/option-groups.h>
  # include <dlfcn.h>
  # include <wchar.h>
  #endif
***************
*** 44,49 ****
--- 45,52 ----
  #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,
*************** do_max_length (struct _IO_codecvt *codec
*** 521,523 ****
--- 524,549 ----
    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
Index: libio/fileops.c
===================================================================
*** libio/fileops.c	(revision 4501)
--- libio/fileops.c	(working copy)
*************** _IO_new_file_close_it (fp)
*** 176,182 ****
  
    /* Free buffer. */
  #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
!   if (fp->_mode > 0)
      {
        if (_IO_have_wbackup (fp))
  	INTUSE(_IO_free_wbackup_area) (fp);
--- 176,182 ----
  
    /* Free buffer. */
  #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
!   if (_IO_is_wide (fp))
      {
        if (_IO_have_wbackup (fp))
  	INTUSE(_IO_free_wbackup_area) (fp);
*************** _IO_new_file_fopen (fp, filename, mode, 
*** 343,348 ****
--- 343,349 ----
        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;
*************** _IO_new_file_fopen (fp, filename, mode, 
*** 407,412 ****
--- 408,419 ----
  
  	  /* 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 */
Index: libio/ioseekpos.c
===================================================================
*** libio/ioseekpos.c	(revision 4501)
--- libio/ioseekpos.c	(working copy)
*************** _IO_seekpos_unlocked (fp, pos, mode)
*** 36,42 ****
    /* 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_have_backup (fp))
  	INTUSE(_IO_free_backup_area) (fp);
--- 36,42 ----
    /* 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_is_wide (fp))
      {
        if (_IO_have_backup (fp))
  	INTUSE(_IO_free_backup_area) (fp);
Index: libio/__fpurge.c
===================================================================
*** libio/__fpurge.c	(revision 4501)
--- libio/__fpurge.c	(working copy)
***************
*** 22,28 ****
  void
  __fpurge (FILE *fp)
  {
!   if (fp->_mode > 0)
      {
        /* Wide-char stream.  */
        if (_IO_in_backup (fp))
--- 22,28 ----
  void
  __fpurge (FILE *fp)
  {
!   if (_IO_is_wide (fp))
      {
        /* Wide-char stream.  */
        if (_IO_in_backup (fp))
Index: wctype/Makefile
===================================================================
*** wctype/Makefile	(revision 4501)
--- wctype/Makefile	(working copy)
***************
*** 19,31 ****
  #
  #	Sub-makefile for wctype portion of the library.
  #
  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
  
! tests	:= test_wctype test_wcfuncs
  
  include ../Rules
--- 19,37 ----
  #
  #	Sub-makefile for wctype portion of the library.
  #
+ include ../option-groups.mak
+ 
  subdir	:= wctype
  
  headers		:= wctype.h
  distribute	:= wchar-lookup.h
! routines 	:= wctrans towctrans towctrans_l
! routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
! 		:= wcfuncs wctype iswctype \
! 		   wcfuncs_l wctype_l iswctype_l wctrans_l
  
! tests	:= 
! tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
!      += test_wctype test_wcfuncs
  
  include ../Rules
Index: posix/fnmatch_loop.c
===================================================================
*** posix/fnmatch_loop.c	(revision 4501)
--- posix/fnmatch_loop.c	(working copy)
*************** FCT (pattern, string, string_end, no_lea
*** 282,288 ****
  		    /* 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)
  		    wctype_t wt;
  #endif
  		    const CHAR *startp = p;
--- 282,288 ----
  		    /* Leave room for the null.  */
  		    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
  		    size_t c1 = 0;
! #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;
*************** FCT (pattern, string, string_end, no_lea
*** 312,318 ****
  		      }
  		    str[c1] = L('\0');
  
! #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
  		    wt = IS_CHAR_CLASS (str);
  		    if (wt == 0)
  		      /* Invalid character class name.  */
--- 312,318 ----
  		      }
  		    str[c1] = L('\0');
  
! #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.  */
Index: stdio-common/Makefile
===================================================================
*** stdio-common/Makefile	(revision 4501)
--- stdio-common/Makefile	(working copy)
*************** routines	:=							      \
*** 30,36 ****
  	_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					      \
  	fscanf scanf sscanf						      \
  	perror psignal							      \
  	tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname		      \
--- 30,36 ----
  	_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	      \
! 	vfscanf								      \
  	fscanf scanf sscanf						      \
  	perror psignal							      \
  	tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname		      \
*************** routines	:=							      \
*** 39,50 ****
  	flockfile ftrylockfile funlockfile				      \
  	isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
  	isoc99_vsscanf
  
  include ../Makeconfig
  
  install-headers-nosubdir: $(inst_includedir)/bits/stdio_lim.h
  
! aux	:= errlist siglist printf-parsemb printf-parsewc fxprintf
  distribute := _itoa.h _itowa.h _i18n_number.h \
  	      printf-parse.h stdio_lim.h.in tst-unbputc.sh tst-printf.sh
  
--- 39,56 ----
  	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 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
  
*************** tests := tstscanf test_rdwr test-popen t
*** 52,69 ****
  	 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 \
  	 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 \
  	 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
  
  test-srcs = tst-unbputc tst-printf
  
--- 58,77 ----
  	 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 \
  	 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-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
  
Index: stdio-common/printf_fp.c
===================================================================
*** stdio-common/printf_fp.c	(revision 4501)
--- stdio-common/printf_fp.c	(working copy)
*************** static wchar_t *group_number (wchar_t *b
*** 150,155 ****
--- 150,159 ----
  			      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,
*************** ___printf_fp (FILE *fp,
*** 211,217 ****
--- 215,228 ----
    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;
Index: stdio-common/printf_fphex.c
===================================================================
*** stdio-common/printf_fphex.c	(revision 4501)
--- stdio-common/printf_fphex.c	(working copy)
*************** __printf_fphex (FILE *fp,
*** 145,151 ****
--- 145,158 ----
    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.  */
Index: stdio-common/printf_size.c
===================================================================
*** stdio-common/printf_size.c	(revision 4501)
--- stdio-common/printf_size.c	(working copy)
***************
*** 24,29 ****
--- 24,30 ----
  #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
*************** __printf_size (FILE *fp, const struct pr
*** 117,123 ****
--- 118,131 ----
  
    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.	*/
Index: stdio-common/vfprintf.c
===================================================================
*** stdio-common/vfprintf.c	(revision 4501)
--- stdio-common/vfprintf.c	(working copy)
***************
*** 107,112 ****
--- 107,118 ----
  # 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
*************** vfprintf (FILE *s, const CHAR_T *format,
*** 1082,1089 ****
  # define process_string_arg(fspec) \
      LABEL (form_character):						      \
        /* Character.  */							      \
!       if (is_long)							      \
! 	goto LABEL (form_wcharacter);					      \
        --width;	/* Account for the character itself.  */		      \
        if (!left)							      \
  	PAD (' ');							      \
--- 1088,1098 ----
  # define process_string_arg(fspec) \
      LABEL (form_character):						      \
        /* Character.  */							      \
!       if (is_long)                                                            \
!         {                                                                     \
!           assert (MULTIBYTE_SUPPORT);                                         \
!           goto LABEL (form_wcharacter);                                       \
!         }                                                                     \
        --width;	/* Account for the character itself.  */		      \
        if (!left)							      \
  	PAD (' ');							      \
*************** vfprintf (FILE *s, const CHAR_T *format,
*** 1096,1101 ****
--- 1105,1111 ----
        break;								      \
  									      \
      LABEL (form_wcharacter):						      \
+       assert (MULTIBYTE_SUPPORT);                                             \
        {									      \
  	/* Wide character.  */						      \
  	char buf[MB_CUR_MAX];						      \
*************** vfprintf (FILE *s, const CHAR_T *format,
*** 1195,1200 ****
--- 1205,1211 ----
  	  }								      \
  	else								      \
  	  {								      \
+             assert (MULTIBYTE_SUPPORT);                                       \
  	    const wchar_t *s2 = (const wchar_t *) string;		      \
  	    mbstate_t mbstate;						      \
  									      \
Index: stdio-common/vfscanf.c
===================================================================
*** stdio-common/vfscanf.c	(revision 4501)
--- stdio-common/vfscanf.c	(working copy)
***************
*** 134,139 ****
--- 134,145 ----
  # 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);				      \
*************** _IO_vfscanf_internal (_IO_FILE *s, const
*** 374,379 ****
--- 380,387 ----
  #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)
*************** _IO_vfscanf_internal (_IO_FILE *s, const
*** 810,815 ****
--- 818,825 ----
  	    }
  	  /* FALLTHROUGH */
  	case L_('C'):
+           assert (MULTIBYTE_SUPPORT);
+ 
  	  if (width == -1)
  	    width = 1;
  
*************** _IO_vfscanf_internal (_IO_FILE *s, const
*** 1136,1141 ****
--- 1146,1153 ----
  	  /* FALLTHROUGH */
  
  	case L_('S'):
+           assert (MULTIBYTE_SUPPORT);
+ 
  	  {
  #ifndef COMPILE_WSCANF
  	    mbstate_t cstate;
*************** _IO_vfscanf_internal (_IO_FILE *s, const
*** 2302,2308 ****
  
  	case L_('['):	/* Character class.  */
  	  if (flags & LONG)
! 	    STRING_ARG (wstr, wchar_t, 100);
  	  else
  	    STRING_ARG (str, char, 100);
  
--- 2314,2323 ----
  
  	case L_('['):	/* Character class.  */
  	  if (flags & LONG)
!             {
!               assert (MULTIBYTE_SUPPORT);
!               STRING_ARG (wstr, wchar_t, 100);
!             }
  	  else
  	    STRING_ARG (str, char, 100);
  
*************** _IO_vfscanf_internal (_IO_FILE *s, const
*** 2376,2381 ****
--- 2391,2397 ----
  	  if (flags & LONG)
  	    {
  	      size_t now = read_in;
+               assert (MULTIBYTE_SUPPORT);
  #ifdef COMPILE_WSCANF
  	      if (__builtin_expect (inchar () == WEOF, 0))
  		input_error ();
Index: stdio-common/scanf14.c
===================================================================
*** stdio-common/scanf14.c	(revision 4501)
--- stdio-common/scanf14.c	(working copy)
***************
*** 2,7 ****
--- 2,8 ----
  #include <stdlib.h>
  #include <string.h>
  #include <wchar.h>
+ #include <gnu/option-groups.h>
  
  #define FAIL() \
    do {							\
*************** main (void)
*** 36,41 ****
--- 37,43 ----
      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
*************** main (void)
*** 45,50 ****
--- 47,53 ----
        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
Index: stdio-common/tst-sprintf.c
===================================================================
*** stdio-common/tst-sprintf.c	(revision 4501)
--- stdio-common/tst-sprintf.c	(working copy)
*************** main (void)
*** 9,20 ****
--- 9,22 ----
    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
Index: stdio-common/tstdiomisc.c
===================================================================
*** stdio-common/tstdiomisc.c	(revision 4501)
--- stdio-common/tstdiomisc.c	(working copy)
*************** F (void)
*** 66,71 ****
--- 66,72 ----
    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);
*************** F (void)
*** 74,79 ****
--- 75,81 ----
  	    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;
  }