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

[patches] Fix EGLIBC_LOCALE_CODE testing



I've committed the following patch, which gives us clean test runs
with OPTION_EGLIBC_LOCALE_CODE disabled.  This is important cleanup
that I should have done when I committed that option group originally.

It should bring us significantly closer to resolving the outstanding
test suite concerns for OPTION_POSIX_C_LANG_WIDE_CHAR, as well.

ChangeLog.eglibc:
2007-12-11  Jim Blandy  <jimb@xxxxxxxxxxxxxxxx>

	Clean up test results with OPTION_EGLIBC_LOCALE_CODE disabled.
	* debug/tst-chk1.c: Omit locale tests when group is disabled.
	* intl/Makefile (tests): Put tst-translit, tst-gettext2,
	tst-codeset, and tst-gettext3 in the group.
	* libio/Makefile (tests): Put tst-fgetws, tst-fopenloc,
	tst-setvbuf1, tst-ungetwc1, tst-ungetwc2, bug-ftell, bug-ungetwc2,
	tst-widetext, and tst-fopenloc in the group; some were formerly in
	OPTION_POSIX_WIDE_CHAR_DEVICE_IO.
	* nptl/Makefile (tests): Put tst-locale1 in the group.
	* posix/Makefile (tests): Put bug-regex17, bug-regex18,
	bug-regex20, bug-regex23, and bug-regex26 in the group.
	(tst-rxspencer): Pass --utf8 only when the group is enabled.
	* posix/bug-regex6.c: Omit non-C locale tests when group is disabled.
	* stdio-common/Makefile (tests): Put bug14 and scanf13 in the group.
	* stdlib/Makefile (tests): Put tst-strtod4, tst-strtod5, and
	testmb2 in the group.
	* stdlib/tst-strtod.c: Omit locale tests when group is disabled.
	* string/tst-strxfrm.c, string/tst-strxfrm2.c: Same.
	* time/Makefile (tests): Put tst-ftime_l in the group.

	Fix code broken by OPTION_EGLIBC_LOCALE_CODE.
	* posix/regex_internal.h: #include <gnu/option-groups.h>.
	(string_mb_cur_max, dfa_mb_cur_max): New macros for accessing the
	'mb_cur_max' fields of re_string_t and re_dfa_t, whose values can
	be constant when the group is disabled.  Use them throughout.
	* posix/regex_internal.c: Use string_mb_cur_max and dfa_mb_cur_max
	as appropriate.
	* posix/regcomp.c: Same.
	(re_compile_fastmap_iter): Process COMPLEX_BRACKET nodes only when
	the group is enabled.
	(init_dfa): When the group is disabled, clear map_notascii.
	(parse_bracket_exp): Process MB_CHAR elements only when the group
	is enabled.  Otherwise, fix 'nrules' at zero, for the compiler's
	benefit, and assume the collation sequence is the identity.
	(parse_bracket_element): Create MB_CHAR elements only when the
	group is enabled.
	(build_equiv_class): When the group is disabled, we know there
	will be no collation rules.
	(build_charclass): When the group is disabled, do not try to
	process references to wide character categories accessed via
	'wctype'.
	* posix/regexec.c: Use string_mb_cur_max and dfa_mb_cur_max
	as appropriate.
	(find_collation_sequence_value): Define function only when the
	group is enabled.
	(check_node_accept_bytes): Check character against 'wctype' style
	classes only if group is enabled.  When the group is disabled,
	Skip collation-rule-based matching.
	* posix/fnmatch.c: #include <gnu/option-groups.h>.
	Define HANDLE_MULTIBYTE only if when OPTION_EGLIBC_LOCALE_CODE is
	enabled.
	* posix/fnmatch_loop.c (FCT (internal_fnmatch or internal_fnwmatch)):
	If the group is disabled, assume that the collation sequence is
	the identity.
	* stdio-common/_i18n_number.h (_i18n_number_rewrite): Provide only
	a trivial definition when the group is disabled.
	* stdio-common/vfprintf.c: #include <gnu/option-groups.h>.
	(LOCALE_SUPPORT): Define.
	(vfprintf): Consult it as appropriate.
	* stdio-common/vfscanf.c: #include <gnu/option-groups.h>.
	(_IO_vfwscanf): If the group is disabled, don't try to consult the
	locale for decimal point and thousands separator characters, or
	for custom digits.
	* stdlib/strtod_l.c (__STRTOF_INTERNAL): Don't try to consult the
	locale's numeric settings.
	* string/strxfrm_l.c, string/strcoll_l.c: Don't try to consult the
	locale's collation settings.

Index: stdlib/Makefile
===================================================================
--- stdlib/Makefile	(revision 4499)
+++ stdlib/Makefile	(working copy)
@@ -73,11 +73,11 @@
 		   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	    \
-		   test-a64l tst-qsort tst-system testmb2 bug-strtod2	    \
+		   test-a64l tst-qsort tst-system bug-strtod2		    \
 		   tst-atof1 tst-atof2 tst-strtod2 tst-rand48-2             \
-		   tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2
+		   tst-makecontext tst-qsort2
 tests-$(OPTION_EGLIBC_LOCALE_CODE) \
-		+= tst-strtod3
+		+= tst-strtod3 tst-strtod4 tst-strtod5 testmb2
 include ../Makeconfig
 
 ifeq ($(build-shared),yes)
Index: stdlib/tst-strtod.c
===================================================================
--- stdlib/tst-strtod.c	(revision 4499)
+++ stdlib/tst-strtod.c	(working copy)
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include <string.h>
 #include <math.h>
+#include <gnu/option-groups.h>
 
 struct ltest
   {
@@ -174,7 +175,9 @@
 
   status |= long_dbl ();
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   status |= locale_test ();
+#endif
 
   return status ? EXIT_FAILURE : EXIT_SUCCESS;
 }
@@ -217,6 +220,7 @@
   return 0;
 }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 /* Perform a few tests in a locale with thousands separators.  */
 static int
 locale_test (void)
@@ -274,3 +278,4 @@
 
   return result;
 }
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
Index: stdlib/strtod_l.c
===================================================================
--- stdlib/strtod_l.c	(revision 4499)
+++ stdlib/strtod_l.c	(working copy)
@@ -19,6 +19,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <gnu/option-groups.h>
 #include <xlocale.h>
 
 extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
@@ -480,6 +481,7 @@
   /* Used in several places.  */
   int cnt;
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   struct locale_data *current = loc->__locales[LC_NUMERIC];
 
   if (__builtin_expect (group, 0))
@@ -518,6 +520,17 @@
   decimal_len = strlen (decimal);
   assert (decimal_len > 0);
 #endif
+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */
+  /* Hard-code values from the 'C' locale.  */
+  grouping = NULL;
+#ifdef USE_WIDE_CHAR
+  decimal = L'.';
+# define decimal_len 1
+#else
+  decimal = ".";
+  decimal_len = 1;
+#endif
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
 
   /* Prepare number representation.  */
   exponent = 0;
Index: debug/tst-chk1.c
===================================================================
--- debug/tst-chk1.c	(revision 4499)
+++ debug/tst-chk1.c	(working copy)
@@ -30,6 +30,7 @@
 #include <wchar.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <gnu/option-groups.h>
 
 char *temp_filename;
 static void do_prepare (void);
@@ -1173,6 +1174,7 @@
 # endif
 #endif
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
     {
       assert (MB_CUR_MAX <= 10);
@@ -1329,6 +1331,7 @@
       puts ("cannot set locale");
       ret = 1;
     }
+#endif
 
   fd = posix_openpt (O_RDWR);
   if (fd != -1)
Index: time/Makefile
===================================================================
--- time/Makefile	(revision 4499)
+++ time/Makefile	(working copy)
@@ -36,11 +36,11 @@
 distribute := datemsk
 
 tests	:= test_time clocktest tst-posixtz \
-	   tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
+	   tst-getdate tst-mktime tst-mktime2 tst-strftime \
 	   tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \
 	   tst-strptime3
 tests-$(OPTION_EGLIBC_LOCALE_CODE) \
-	+= tst-strptime
+	+= tst-strptime tst-ftime_l
 tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
 	+= tst_wcsftime
 
Index: libio/Makefile
===================================================================
--- libio/Makefile	(revision 4499)
+++ libio/Makefile	(working copy)
@@ -65,12 +65,14 @@
 	tst-memstream1 tst-memstream2				\
 	tst-wmemstream1 tst-wmemstream2				\
 	bug-memstream1
-tests-$(OPTION_EGLIBC_LOCALE_CODE) \
-     += tst-swscanf
-tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)				  \
-     += bug-ftell bug-rewind bug-rewind2 bug-ungetwc1 bug-ungetwc2	  \
-	bug-wfflush bug-wmemstream1 tst-fgetws tst-fopenloc tst-fopenloc2 \
-	tst-setvbuf1 tst-ungetwc1 tst-ungetwc2 tst-widetext tst_getwc	  \
+tests-$(OPTION_EGLIBC_LOCALE_CODE)				\
+     += tst-swscanf tst-fgetws tst-fopenloc tst-setvbuf1	\
+	tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2	\
+	tst-widetext 
+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)		\
+     += bug-rewind bug-rewind2 bug-ungetwc1		\
+	bug-wfflush bug-wmemstream1 tst-fopenloc2	\
+	tst_getwc					\
 	tst_putwc tst_wprintf tst_wprintf2 tst_wscanf
 test-srcs = test-freopen
 
@@ -186,14 +188,14 @@
 include ../Rules
 
 ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
-# eglibc: ifeq (no,$(cross-compiling))
-tests: $(objpfx)test-freopen.out $(objpfx)tst-fopenloc.check
-# eglibc: endif
-
+tests: $(objpfx)test-freopen.out
 $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
 	$(SHELL) -e $< $(common-objpfx) '$(run-program-prefix)'	\
 	$(common-objpfx)libio/
+endif
 
+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+tests: $(objpfx)tst-fopenloc.check
 $(objpfx)tst-fopenloc.check: $(objpfx)tst-fopenloc.out
 	cmp ../iconvdata/testdata/ISO-8859-1..UTF8 $(objpfx)tst-fopenloc.out \
 	  > $@
Index: intl/Makefile
===================================================================
--- intl/Makefile	(revision 4499)
+++ intl/Makefile	(working copy)
@@ -63,7 +63,7 @@
 include ../Rules
 
 # eglibc: ifeq (no,$(cross-compiling))
-ifeq (yyes,$(OPTION_EGLIBC_LOCALES)$(build-shared))
+ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared))
 ifneq ($(strip $(MSGFMT)),:)
 tests: $(objpfx)tst-translit.out $(objpfx)tst-gettext2.out \
        $(objpfx)tst-codeset.out $(objpfx)tst-gettext3.out
Index: string/tst-strxfrm2.c
===================================================================
--- string/tst-strxfrm2.c	(revision 4499)
+++ string/tst-strxfrm2.c	(working copy)
@@ -1,6 +1,7 @@
 #include <locale.h>
 #include <stdio.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 static int
 do_test (void)
@@ -38,6 +39,7 @@
       res = 1;
     }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
     {
       puts ("setlocale failed");
@@ -75,6 +77,7 @@
 	  res = 1;
 	}
     }
+#endif
 
   return res;
 }
Index: string/tst-strxfrm.c
===================================================================
--- string/tst-strxfrm.c	(revision 4499)
+++ string/tst-strxfrm.c	(working copy)
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 
 char const string[] = "";
@@ -64,8 +65,10 @@
   int result = 0;
 
   result |= test ("C");
+#if __OPTION_EGLIBC_LOCALE_CODE
   result |= test ("en_US.ISO-8859-1");
   result |= test ("de_DE.UTF-8");
+#endif
 
   return result;
 }
Index: string/strxfrm_l.c
===================================================================
--- string/strxfrm_l.c	(revision 4499)
+++ string/strxfrm_l.c	(working copy)
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/param.h>
+#include <gnu/option-groups.h>
 
 #ifndef STRING_TYPE
 # define STRING_TYPE char
@@ -87,7 +88,11 @@
 STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
 {
   struct locale_data *current = l->__locales[LC_COLLATE];
+#if __OPTION_EGLIBC_LOCALE_CODE
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
+#else
+  const uint_fast32_t nrules = 0;
+#endif
   /* We don't assign the following values right away since it might be
      unnecessary in case there are no rules.  */
   const unsigned char *rulesets;
Index: string/strcoll_l.c
===================================================================
--- string/strcoll_l.c	(revision 4499)
+++ string/strcoll_l.c	(working copy)
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 #ifndef STRING_TYPE
 # define STRING_TYPE char
@@ -49,7 +50,11 @@
      __locale_t l;
 {
   struct locale_data *current = l->__locales[LC_COLLATE];
+#if __OPTION_EGLIBC_LOCALE_CODE
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
+#else
+  const uint_fast32_t nrules = 0;
+#endif
   /* We don't assign the following values right away since it might be
      unnecessary in case there are no rules.  */
   const unsigned char *rulesets;
Index: nptl/Makefile
===================================================================
--- nptl/Makefile	(revision 4499)
+++ nptl/Makefile	(working copy)
@@ -251,7 +251,7 @@
 	tst-unload \
 	tst-dlsym1 \
 	tst-sysconf \
-	tst-locale1 tst-locale2 \
+	tst-locale2 \
 	tst-umask1 \
 	tst-popen1 \
 	tst-clock1 \
@@ -272,6 +272,8 @@
 # This test is written in C++.
 tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24
 
+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1 
+
 # Files which must not be linked with libpthread.
 tests-nolibpthread = tst-unload
 
Index: posix/regcomp.c
===================================================================
--- posix/regcomp.c	(revision 4499)
+++ posix/regcomp.c	(working copy)
@@ -304,7 +304,7 @@
 {
   re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
   int node_cnt;
-  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
+  int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE));
   for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
     {
       int node = init_state->nodes.elems[node_cnt];
@@ -314,9 +314,9 @@
 	{
 	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
 #ifdef RE_ENABLE_I18N
-	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+	  if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
 	    {
-	      unsigned char *buf = alloca (dfa->mb_cur_max), *p;
+	      unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p;
 	      wchar_t wc;
 	      mbstate_t state;
 
@@ -347,7 +347,11 @@
 		  re_set_fastmap (fastmap, icase, ch);
 	    }
 	}
-#ifdef RE_ENABLE_I18N
+
+      /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current
+         locale is always C, which has no rules and no multi-byte
+         characters.  */
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
       else if (type == COMPLEX_BRACKET)
 	{
 	  int i;
@@ -371,7 +375,7 @@
 		      re_set_fastmap (fastmap, icase, i);
 		}
 # else
-	      if (dfa->mb_cur_max > 1)
+	      if (dfa_mb_cur_max (dfa) > 1)
 		for (i = 0; i < SBC_MAX; ++i)
 		  if (__btowc (i) == WEOF)
 		    re_set_fastmap (fastmap, icase, i);
@@ -384,7 +388,7 @@
 	      memset (&state, '\0', sizeof (state));
 	      if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
 		re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
-	      if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+	      if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
 		{
 		  if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
 		      != (size_t) -1)
@@ -392,7 +396,7 @@
 		}
 	    }
 	}
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
       else if (type == OP_PERIOD
 #ifdef RE_ENABLE_I18N
 	       || type == OP_UTF8_PERIOD
@@ -835,11 +839,15 @@
 
   dfa->mb_cur_max = MB_CUR_MAX;
 #ifdef _LIBC
-  if (dfa->mb_cur_max == 6
+  if (dfa_mb_cur_max (dfa) == 6
       && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
     dfa->is_utf8 = 1;
+# if __OPTION_EGLIBC_LOCALE_CODE
   dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
 		       != 0);
+# else
+  dfa->map_notascii = 0;
+# endif
 #else
 # ifdef HAVE_LANGINFO_CODESET
   codeset_name = nl_langinfo (CODESET);
@@ -865,7 +873,7 @@
 #endif
 
 #ifdef RE_ENABLE_I18N
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     {
       if (dfa->is_utf8)
 	dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
@@ -1726,7 +1734,7 @@
   token->word_char = 0;
 #ifdef RE_ENABLE_I18N
   token->mb_partial = 0;
-  if (input->mb_cur_max > 1 &&
+  if (string_mb_cur_max (input) > 1 &&
       !re_string_first_byte (input, re_string_cur_idx (input)))
     {
       token->type = CHARACTER;
@@ -1747,7 +1755,7 @@
       token->opr.c = c2;
       token->type = CHARACTER;
 #ifdef RE_ENABLE_I18N
-      if (input->mb_cur_max > 1)
+      if (string_mb_cur_max (input) > 1)
 	{
 	  wint_t wc = re_string_wchar_at (input,
 					  re_string_cur_idx (input) + 1);
@@ -1861,7 +1869,7 @@
 
   token->type = CHARACTER;
 #ifdef RE_ENABLE_I18N
-  if (input->mb_cur_max > 1)
+  if (string_mb_cur_max (input) > 1)
     {
       wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
       token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
@@ -1961,7 +1969,7 @@
   token->opr.c = c;
 
 #ifdef RE_ENABLE_I18N
-  if (input->mb_cur_max > 1 &&
+  if (string_mb_cur_max (input) > 1 &&
       !re_string_first_byte (input, re_string_cur_idx (input)))
     {
       token->type = CHARACTER;
@@ -2175,7 +2183,7 @@
 	  return NULL;
 	}
 #ifdef RE_ENABLE_I18N
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	{
 	  while (!re_string_eoi (regexp)
 		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
@@ -2313,7 +2321,7 @@
 	  *err = REG_ESPACE;
 	  return NULL;
 	}
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	dfa->has_mb_node = 1;
       break;
     case OP_WORD:
@@ -2606,7 +2614,7 @@
        However, for !_LIBC we have no collation elements: if the
        character set is single byte, the single byte character set
        that we build below suffices.  parse_bracket_exp passes
-       no MBCSET if dfa->mb_cur_max == 1.  */
+       no MBCSET if dfa_mb_cur_max (dfa) == 1.  */
     if (mbcset)
       {
         /* Check the space of the arrays.  */
@@ -2702,7 +2710,13 @@
 		   reg_syntax_t syntax, reg_errcode_t *err)
 {
 #ifdef _LIBC
+#if __OPTION_EGLIBC_LOCALE_CODE
   const unsigned char *collseqmb;
+# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)])
+#else
+# define COLLSEQMB_LOOKUP(ix) (ix)
+#endif
+
   const char *collseqwc;
   uint32_t nrules;
   int32_t table_size;
@@ -2762,18 +2776,20 @@
 	  if (MB_CUR_MAX == 1)
 	  */
 	  if (nrules == 0)
-	    return collseqmb[br_elem->opr.ch];
+	    return COLLSEQMB_LOOKUP (br_elem->opr.ch);
 	  else
 	    {
 	      wint_t wc = __btowc (br_elem->opr.ch);
 	      return __collseq_table_lookup (collseqwc, wc);
 	    }
 	}
+#if __OPTION_EGLIBC_LOCALE_CODE
       else if (br_elem->type == MB_CHAR)
 	{
 	  if (nrules != 0)
 	    return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
 	}
+#endif
       else if (br_elem->type == COLL_SYM)
 	{
 	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);
@@ -2804,11 +2820,11 @@
 		{
 		  /* No valid character.  Match it as a single byte
 		     character.  */
-		  return collseqmb[br_elem->opr.name[0]];
+		  return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
 		}
 	    }
 	  else if (sym_name_len == 1)
-	    return collseqmb[br_elem->opr.name[0]];
+	    return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
 	}
       return UINT_MAX;
     }
@@ -2851,7 +2867,7 @@
 	 However, if we have no collation elements, and the character set
 	 is single byte, the single byte character set that we
 	 build below suffices. */
-      if (nrules > 0 || dfa->mb_cur_max > 1)
+      if (nrules > 0 || dfa_mb_cur_max (dfa) > 1)
 	{
           /* Check the space of the arrays.  */
           if (BE (*range_alloc == mbcset->nranges, 0))
@@ -2888,7 +2904,7 @@
 	  if (MB_CUR_MAX == 1)
 	  */
 	  if (nrules == 0)
-	    ch_collseq = collseqmb[ch];
+	    ch_collseq = COLLSEQMB_LOOKUP (ch);
 	  else
 	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
 	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
@@ -2969,7 +2985,10 @@
   re_bitset_ptr_t sbcset;
 #ifdef RE_ENABLE_I18N
   re_charset_t *mbcset;
-  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+  int coll_sym_alloc = 0, range_alloc = 0;
+#if __OPTION_EGLIBC_LOCALE_CODE
+  int mbchar_alloc = 0;
+#endif
   int equiv_class_alloc = 0, char_class_alloc = 0;
 #endif /* not RE_ENABLE_I18N */
   int non_match = 0;
@@ -2977,9 +2996,15 @@
   int token_len;
   int first_round = 1;
 #ifdef _LIBC
+#if __OPTION_EGLIBC_LOCALE_CODE
   collseqmb = (const unsigned char *)
     _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
   nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+#else
+  /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the
+     compiler can't figure that out.  */
+  nrules = 0;
+#endif
   if (nrules)
     {
       /*
@@ -3103,7 +3128,7 @@
 #else
 # ifdef RE_ENABLE_I18N
 	  *err = build_range_exp (sbcset,
-				  dfa->mb_cur_max > 1 ? mbcset : NULL,
+				  dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL,
 				  &range_alloc, &start_elem, &end_elem);
 # else
 	  *err = build_range_exp (sbcset, &start_elem, &end_elem);
@@ -3119,7 +3144,7 @@
 	    case SB_CHAR:
 	      bitset_set (sbcset, start_elem.opr.ch);
 	      break;
-#ifdef RE_ENABLE_I18N
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
 	    case MB_CHAR:
 	      /* Check whether the array has enough space.  */
 	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))
@@ -3137,7 +3162,7 @@
 		}
 	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
 	      break;
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
 	    case EQUIV_CLASS:
 	      *err = build_equiv_class (sbcset,
 #ifdef RE_ENABLE_I18N
@@ -3187,11 +3212,11 @@
 
 #ifdef RE_ENABLE_I18N
   /* Ensure only single byte characters are set.  */
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     bitset_mask (sbcset, dfa->sb_char);
 
   if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
-      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
+      || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes
 						     || mbcset->non_match)))
     {
       bin_tree_t *mbc_tree;
@@ -3260,7 +3285,7 @@
 		       re_token_t *token, int token_len, re_dfa_t *dfa,
 		       reg_syntax_t syntax, int accept_hyphen)
 {
-#ifdef RE_ENABLE_I18N
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
   int cur_char_size;
   cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
   if (cur_char_size > 1)
@@ -3270,7 +3295,7 @@
       re_string_skip_bytes (regexp, cur_char_size);
       return REG_NOERROR;
     }
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
   re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
   if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
       || token->type == OP_OPEN_EQUIV_CLASS)
@@ -3350,7 +3375,9 @@
 build_equiv_class (bitset_t sbcset, const unsigned char *name)
 #endif /* not RE_ENABLE_I18N */
 {
-#ifdef _LIBC
+  /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale
+     is supported; it has no collation rules.  */
+#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
   uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
   if (nrules != 0)
     {
@@ -3423,7 +3450,7 @@
       mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
     }
   else
-#endif /* _LIBC */
+#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
     {
       if (BE (strlen ((const char *) name) != 1, 0))
 	return REG_ECOLLATE;
@@ -3457,7 +3484,7 @@
       && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
     name = "alpha";
 
-#ifdef RE_ENABLE_I18N
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
   /* Check the space of the arrays.  */
   if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
     {
@@ -3473,7 +3500,7 @@
       *char_class_alloc = new_char_class_alloc;
     }
   mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
 
 #define BUILD_CHARCLASS_LOOP(ctype_func)	\
   do {						\
@@ -3584,7 +3611,7 @@
 
 #ifdef RE_ENABLE_I18N
   /* Ensure only single byte characters are set.  */
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     bitset_mask (sbcset, dfa->sb_char);
 #endif
 
@@ -3596,7 +3623,7 @@
     goto build_word_op_espace;
 
 #ifdef RE_ENABLE_I18N
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     {
       bin_tree_t *mbc_tree;
       /* Build a tree for complex bracket.  */
Index: posix/regex_internal.c
===================================================================
--- posix/regex_internal.c	(revision 4499)
+++ posix/regex_internal.c	(working copy)
@@ -44,8 +44,8 @@
   int init_buf_len;
 
   /* Ensure at least one character fits into the buffers.  */
-  if (init_len < dfa->mb_cur_max)
-    init_len = dfa->mb_cur_max;
+  if (init_len < dfa_mb_cur_max (dfa))
+    init_len = dfa_mb_cur_max (dfa);
   init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
   re_string_construct_common (str, len, pstr, trans, icase, dfa);
 
@@ -56,7 +56,7 @@
   pstr->word_char = dfa->word_char;
   pstr->word_ops_used = dfa->word_ops_used;
   pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
-  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
+  pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len;
   pstr->valid_raw_len = pstr->valid_len;
   return REG_NOERROR;
 }
@@ -83,7 +83,7 @@
   if (icase)
     {
 #ifdef RE_ENABLE_I18N
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	{
 	  while (1)
 	    {
@@ -92,7 +92,7 @@
 		return ret;
 	      if (pstr->valid_raw_len >= len)
 		break;
-	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
+	      if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa))
 		break;
 	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
 	      if (BE (ret != REG_NOERROR, 0))
@@ -106,7 +106,7 @@
   else
     {
 #ifdef RE_ENABLE_I18N
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	build_wcs_buffer (pstr);
       else
 #endif /* RE_ENABLE_I18N  */
@@ -131,7 +131,7 @@
 re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
 {
 #ifdef RE_ENABLE_I18N
-  if (pstr->mb_cur_max > 1)
+  if (string_mb_cur_max (pstr) > 1)
     {
       wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
       if (BE (new_wcs == NULL, 0))
@@ -171,7 +171,7 @@
   pstr->trans = trans;
   pstr->icase = icase ? 1 : 0;
   pstr->mbs_allocated = (trans != NULL || icase);
-  pstr->mb_cur_max = dfa->mb_cur_max;
+  pstr->mb_cur_max = dfa_mb_cur_max (dfa);
   pstr->is_utf8 = dfa->is_utf8;
   pstr->map_notascii = dfa->map_notascii;
   pstr->stop = pstr->len;
@@ -197,7 +197,7 @@
 {
 #ifdef _LIBC
   unsigned char buf[MB_LEN_MAX];
-  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+  assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
 #else
   unsigned char buf[64];
 #endif
@@ -220,7 +220,7 @@
 	{
 	  int i, ch;
 
-	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	  for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
 	    {
 	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
 	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
@@ -268,7 +268,7 @@
   size_t mbclen;
 #ifdef _LIBC
   char buf[MB_LEN_MAX];
-  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+  assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
 #else
   char buf[64];
 #endif
@@ -360,7 +360,7 @@
 	  {
 	    int i, ch;
 
-	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	    for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
 	      {
 		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
 		buf[i] = pstr->trans[ch];
@@ -555,8 +555,9 @@
 }
 
 /* This function re-construct the buffers.
-   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
-   convert to upper case in case of REG_ICASE, apply translation.  */
+   Concretely, convert to wide character in case of
+   string_mb_cur_max (pstr) > 1, convert to upper case in case of
+   REG_ICASE, apply translation.  */
 
 static reg_errcode_t
 internal_function
@@ -567,7 +568,7 @@
     {
       /* Reset buffer.  */
 #ifdef RE_ENABLE_I18N
-      if (pstr->mb_cur_max > 1)
+      if (string_mb_cur_max (pstr) > 1)
 	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
 #endif /* RE_ENABLE_I18N */
       pstr->len = pstr->raw_len;
@@ -658,7 +659,7 @@
 	      pstr->tip_context = re_string_context_at (pstr, offset - 1,
 							eflags);
 #ifdef RE_ENABLE_I18N
-	      if (pstr->mb_cur_max > 1)
+	      if (string_mb_cur_max (pstr) > 1)
 		memmove (pstr->wcs, pstr->wcs + offset,
 			 (pstr->valid_len - offset) * sizeof (wint_t));
 #endif /* RE_ENABLE_I18N */
@@ -687,7 +688,7 @@
 #endif
 	  pstr->valid_len = 0;
 #ifdef RE_ENABLE_I18N
-	  if (pstr->mb_cur_max > 1)
+	  if (string_mb_cur_max (pstr) > 1)
 	    {
 	      int wcs_idx;
 	      wint_t wc = WEOF;
@@ -699,7 +700,7 @@
 		  /* Special case UTF-8.  Multi-byte chars start with any
 		     byte other than 0x80 - 0xbf.  */
 		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;
-		  end = raw + (offset - pstr->mb_cur_max);
+		  end = raw + (offset - string_mb_cur_max (pstr));
 		  if (end < pstr->raw_mbs)
 		    end = pstr->raw_mbs;
 		  p = raw + offset - 1;
@@ -791,7 +792,7 @@
 
   /* Then build the buffers.  */
 #ifdef RE_ENABLE_I18N
-  if (pstr->mb_cur_max > 1)
+  if (string_mb_cur_max (pstr) > 1)
     {
       if (pstr->icase)
 	{
@@ -829,7 +830,7 @@
     return re_string_peek_byte (pstr, idx);
 
 #ifdef RE_ENABLE_I18N
-  if (pstr->mb_cur_max > 1
+  if (string_mb_cur_max (pstr) > 1
       && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
     return re_string_peek_byte (pstr, idx);
 #endif
@@ -918,7 +919,7 @@
     return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
 	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
 #ifdef RE_ENABLE_I18N
-  if (input->mb_cur_max > 1)
+  if (string_mb_cur_max (input) > 1)
     {
       wint_t wc;
       int wc_idx = idx;
@@ -1429,7 +1430,7 @@
   dfa->nodes[dfa->nodes_len].constraint = 0;
 #ifdef RE_ENABLE_I18N
   dfa->nodes[dfa->nodes_len].accept_mb =
-    (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
+    (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET;
 #endif
   dfa->nexts[dfa->nodes_len] = -1;
   re_node_set_init_empty (dfa->edests + dfa->nodes_len);
Index: posix/regex_internal.h
===================================================================
--- posix/regex_internal.h	(revision 4499)
+++ posix/regex_internal.h	(working copy)
@@ -27,6 +27,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if defined _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
 # include <langinfo.h>
 #endif
@@ -373,6 +377,13 @@
 };
 typedef struct re_string_t re_string_t;
 
+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
+   help the compiler make use of that fact.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
+# define string_mb_cur_max(str) ((str)->mb_cur_max + 0)
+#else
+# define string_mb_cur_max(str) (1)
+#endif
 
 struct re_dfa_t;
 typedef struct re_dfa_t re_dfa_t;
@@ -657,6 +668,14 @@
   __libc_lock_define (, lock)
 };
 
+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
+   help the compiler make use of that fact.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
+# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0)
+#else
+# define dfa_mb_cur_max(dfa) (1)
+#endif
+
 #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
 #define re_node_set_remove(set,id) \
   (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
@@ -717,7 +736,7 @@
 re_string_char_size_at (const re_string_t *pstr, int idx)
 {
   int byte_idx;
-  if (pstr->mb_cur_max == 1)
+  if (string_mb_cur_max (pstr) == 1)
     return 1;
   for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
     if (pstr->wcs[idx + byte_idx] != WEOF)
@@ -729,7 +748,7 @@
 internal_function __attribute ((pure))
 re_string_wchar_at (const re_string_t *pstr, int idx)
 {
-  if (pstr->mb_cur_max == 1)
+  if (string_mb_cur_max (pstr) == 1)
     return (wint_t) pstr->mbs[idx];
   return (wint_t) pstr->wcs[idx];
 }
Index: posix/fnmatch_loop.c
===================================================================
--- posix/fnmatch_loop.c	(revision 4499)
+++ posix/fnmatch_loop.c	(working copy)
@@ -52,10 +52,15 @@
   const char *collseq = (const char *)
     _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
 # else
+#  if __OPTION_EGLIBC_LOCALE_CODE
   const UCHAR *collseq = (const UCHAR *)
     _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
-# endif
-#endif
+#   define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)])
+#  else
+#   define COLLSEQ_BYTE_LOOKUP(ix) (ix)
+#  endif /* __OPTION_EGLIBC_LOCALE_CODE */
+# endif /* WIDE_CHAR_VERSION */
+#endif /* _LIBC */
 
   while ((c = *p++) != L('\0'))
     {
@@ -676,8 +681,10 @@
 			else
 			  lcollseq = __collseq_table_lookup (collseq, cold);
 # else
-			fcollseq = collseq[fn];
-			lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+			fcollseq = COLLSEQ_BYTE_LOOKUP (fn);
+			lcollseq = (is_seqval
+                                    ? cold
+                                    : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold));
 # endif
 
 			is_seqval = 0;
@@ -853,7 +860,7 @@
 				    goto matched;
 				  }
 # else
-				hcollseq = collseq[cend];
+				hcollseq = COLLSEQ_BYTE_LOOKUP (cend);
 # endif
 			      }
 
Index: posix/regexec.c
===================================================================
--- posix/regexec.c	(revision 4499)
+++ posix/regexec.c	(working copy)
@@ -185,11 +185,11 @@
 static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
 				    const re_string_t *input, int idx)
      internal_function;
-# ifdef _LIBC
+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
 static unsigned int find_collation_sequence_value (const unsigned char *mbs,
 						   size_t name_len)
      internal_function;
-# endif /* _LIBC */
+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
 #endif /* RE_ENABLE_I18N */
 static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
 				       const re_dfastate_t *state,
@@ -711,7 +711,7 @@
   incr = (range < 0) ? -1 : 1;
   left_lim = (range < 0) ? start + range : start;
   right_lim = (range < 0) ? start : start + range;
-  sb = dfa->mb_cur_max == 1;
+  sb = dfa_mb_cur_max (dfa) == 1;
   match_kind =
     (fastmap
      ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
@@ -3405,7 +3405,7 @@
 	  if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
 	    goto out_free;
 
-	  if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
+	  if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1)
 	    need_word_trtable = 1;
 
 	  dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
@@ -3547,7 +3547,7 @@
       else if (type == OP_PERIOD)
 	{
 #ifdef RE_ENABLE_I18N
-	  if (dfa->mb_cur_max > 1)
+	  if (dfa_mb_cur_max (dfa) > 1)
 	    bitset_merge (accepts, dfa->sb_char);
 	  else
 #endif
@@ -3598,7 +3598,7 @@
 		  continue;
 		}
 #ifdef RE_ENABLE_I18N
-	      if (dfa->mb_cur_max > 1)
+	      if (dfa_mb_cur_max (dfa) > 1)
 		for (j = 0; j < BITSET_WORDS; ++j)
 		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
 	      else
@@ -3617,7 +3617,7 @@
 		  continue;
 		}
 #ifdef RE_ENABLE_I18N
-	      if (dfa->mb_cur_max > 1)
+	      if (dfa_mb_cur_max (dfa) > 1)
 		for (j = 0; j < BITSET_WORDS; ++j)
 		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
 	      else
@@ -3789,12 +3789,6 @@
   if (node->type == COMPLEX_BRACKET)
     {
       const re_charset_t *cset = node->opr.mbcset;
-# ifdef _LIBC
-      const unsigned char *pin
-	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
-      int j;
-      uint32_t nrules;
-# endif /* _LIBC */
       int match_len = 0;
       wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
 		    ? re_string_wchar_at (input, str_idx) : 0);
@@ -3806,6 +3800,7 @@
 	    match_len = char_len;
 	    goto check_node_accept_bytes_match;
 	  }
+#if __OPTION_EGLIBC_LOCALE_CODE
       /* match with character_class?  */
       for (i = 0; i < cset->nchar_classes; ++i)
 	{
@@ -3816,8 +3811,16 @@
 	      goto check_node_accept_bytes_match;
 	    }
 	}
+#endif
 
-# ifdef _LIBC
+      /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C
+         locale is supported; it has no collation rules.  */
+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
+      const unsigned char *pin
+	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+      int j;
+      uint32_t nrules;
+
       nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
       if (nrules != 0)
 	{
@@ -3910,8 +3913,12 @@
 	    }
 	}
       else
-# endif /* _LIBC */
+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
 	{
+          /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is
+             disabled, there can be no multibyte range endpoints, and
+             cset->nranges is always zero.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
 	  /* match with range expression?  */
 #if __GNUC__ >= 2
 	  wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
@@ -3930,6 +3937,7 @@
 		  goto check_node_accept_bytes_match;
 		}
 	    }
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
 	}
     check_node_accept_bytes_match:
       if (!cset->non_match)
@@ -3945,7 +3953,7 @@
   return 0;
 }
 
-# ifdef _LIBC
+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
 static unsigned int
 internal_function
 find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
@@ -4003,7 +4011,7 @@
       return UINT_MAX;
     }
 }
-# endif /* _LIBC */
+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
 #endif /* RE_ENABLE_I18N */
 
 /* Check whether the node accepts the byte which is IDX-th
@@ -4088,7 +4096,7 @@
   if (pstr->icase)
     {
 #ifdef RE_ENABLE_I18N
-      if (pstr->mb_cur_max > 1)
+      if (string_mb_cur_max (pstr) > 1)
 	{
 	  ret = build_wcs_upper_buffer (pstr);
 	  if (BE (ret != REG_NOERROR, 0))
@@ -4101,7 +4109,7 @@
   else
     {
 #ifdef RE_ENABLE_I18N
-      if (pstr->mb_cur_max > 1)
+      if (string_mb_cur_max (pstr) > 1)
 	build_wcs_buffer (pstr);
       else
 #endif /* RE_ENABLE_I18N  */
Index: posix/Makefile
===================================================================
--- posix/Makefile	(revision 4499)
+++ posix/Makefile	(working copy)
@@ -86,9 +86,8 @@
 		   tst-gnuglob bug-regex6 bug-regex7 \
 		   bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
 		   bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
-		   bug-regex17 bug-regex18 bug-regex20 \
-		   bug-regex21 bug-regex23 bug-regex24 \
-		   bug-regex26 bug-regex27 bug-regex28 \
+		   bug-regex21 bug-regex24 \
+		   bug-regex27 bug-regex28 \
 		   tst-nice tst-nanosleep tst-regex2 \
 		   transbug tst-rxspencer tst-pcre tst-boost \
 		   tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
@@ -98,9 +97,10 @@
 		   tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
 		   tst-execvp3 tst-execvp4 \
 		   tst-fnmatch2 tst-cpucount tst-cpuset
-tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+tests-$(OPTION_EGLIBC_LOCALE_CODE)					    \
 		+= tst-fnmatch tst-regex tst-regexloc bug-regex1 bug-regex5 \
-		   bug-regex19 bug-regex22 bug-regex25
+		   bug-regex17 bug-regex18 bug-regex19 bug-regex20	    \
+		   bug-regex22 bug-regex23 bug-regex25 bug-regex26
 tests-$(OPTION_EGLIBC_INET) \
 	        += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \
 		   tst-rfc3484 tst-rfc3484-2 tst-getaddrinfo3
@@ -214,7 +214,10 @@
 bug-regex23-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex25-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex26-ENV = LOCPATH=$(common-objpfx)localedata
-tst-rxspencer-ARGS = --utf8 rxspencer/tests
+tst-rxspencer-ARGS = rxspencer/tests
+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+tst-rxspencer-ARGS += --utf8 
+endif
 tst-rxspencer-ENV = LOCPATH=$(common-objpfx)localedata
 tst-pcre-ARGS = PCRE.tests
 tst-boost-ARGS = BOOST.tests
Index: posix/bug-regex6.c
===================================================================
--- posix/bug-regex6.c	(revision 4499)
+++ posix/bug-regex6.c	(working copy)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <regex.h>
+#include <gnu/option-groups.h>
 
 
 int
@@ -31,7 +32,12 @@
   regex_t re;
   regmatch_t mat[10];
   int i, j, ret = 0;
-  const char *locales[] = { "C", "de_DE.UTF-8" };
+  const char *locales[] = {
+    "C",
+#if __OPTION_EGLIBC_LOCALE_CODE
+    "de_DE.UTF-8"
+#endif
+  };
   const char *string = "http://www.regex.com/pattern/matching.html#intro";;
   regmatch_t expect[10] = {
     { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 },
Index: posix/fnmatch.c
===================================================================
--- posix/fnmatch.c	(revision 4499)
+++ posix/fnmatch.c	(working copy)
@@ -31,6 +31,10 @@
 #include <fnmatch.h>
 #include <ctype.h>
 
+#if defined _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 #if HAVE_STRING_H || defined _LIBC
 # include <string.h>
 #else
@@ -132,7 +136,7 @@
 #   define ISWCTYPE(WC, WT)	iswctype (WC, WT)
 #  endif
 
-#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
+#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || (_LIBC && __OPTION_EGLIBC_LOCALE_CODE)
 /* In this case we are implementing the multibyte character handling.  */
 #   define HANDLE_MULTIBYTE	1
 #  endif
Index: stdio-common/_i18n_number.h
===================================================================
--- stdio-common/_i18n_number.h	(revision 4499)
+++ stdio-common/_i18n_number.h	(working copy)
@@ -19,10 +19,13 @@
 
 #include <wchar.h>
 #include <wctype.h>
+#include <gnu/option-groups.h>
 
 #include "../locale/outdigits.h"
 #include "../locale/outdigitswc.h"
 
+#if __OPTION_EGLIBC_LOCALE_CODE
+
 static CHAR_T *
 _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr)
 {
@@ -93,3 +96,13 @@
 
   return w;
 }
+
+#else
+
+static CHAR_T *
+_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr)
+{
+  return w;
+}
+
+#endif
Index: stdio-common/Makefile
===================================================================
--- stdio-common/Makefile	(revision 4499)
+++ stdio-common/Makefile	(working copy)
@@ -56,12 +56,12 @@
 	 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 bug14 \
+	 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 scanf13 scanf14 scanf15
+	 bug19 tst-popen2 scanf14 scanf15
 tests-$(OPTION_EGLIBC_LOCALE_CODE) \
-      += tst-sscanf tst-swprintf bug15 test-vfprintf
+      += tst-sscanf tst-swprintf bug15 test-vfprintf bug14 scanf13
 tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
       += tst-perror bug19a bug20
 
Index: stdio-common/vfprintf.c
===================================================================
--- stdio-common/vfprintf.c	(revision 4499)
+++ stdio-common/vfprintf.c	(working copy)
@@ -31,6 +31,7 @@
 #include "_itoa.h"
 #include <locale/localeinfo.h>
 #include <stdio.h>
+#include <gnu/option-groups.h>
 
 /* This code is shared between the standard stdio implementation found
    in GNU C library and the libio implementation originally found in
@@ -106,6 +107,12 @@
 # define EOF WEOF
 #endif
 
+#if __OPTION_EGLIBC_LOCALE_CODE
+# define LOCALE_SUPPORT (1)
+#else
+# define LOCALE_SUPPORT (0)
+#endif
+
 #include "_i18n_number.h"
 
 /* Include the shared code for parsing the format string.  */
@@ -1151,7 +1158,8 @@
 		/* Search for the end of the string, but don't search past    \
 		   the length (in bytes) specified by the precision.  Also    \
 		   don't use incomplete characters.  */			      \
-		if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1)   \
+		if (! LOCALE_SUPPORT                                          \
+                    ||_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1) \
 		  len = __strnlen (string, prec);			      \
 		else							      \
 		  {							      \
@@ -1381,7 +1389,9 @@
     LABEL (flag_quote):
       group = 1;
 
-      if (grouping == (const char *) -1)
+      if (! LOCALE_SUPPORT)
+        grouping = NULL;
+      else if (grouping == (const char *) -1)
 	{
 #ifdef COMPILE_WPRINTF
 	  thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
@@ -1622,7 +1632,9 @@
     free (workstart);
     workstart = NULL;
 
-    if (grouping == (const char *) -1)
+    if (! LOCALE_SUPPORT)
+      grouping = NULL;
+    else if (grouping == (const char *) -1)
       {
 #ifdef COMPILE_WPRINTF
 	thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
Index: stdio-common/vfscanf.c
===================================================================
--- stdio-common/vfscanf.c	(revision 4499)
+++ stdio-common/vfscanf.c	(working copy)
@@ -29,6 +29,7 @@
 #include <wctype.h>
 #include <bits/libc-lock.h>
 #include <locale/localeinfo.h>
+#include <gnu/option-groups.h>
 
 #ifdef	__GNUC__
 # define HAVE_LONGLONG
@@ -293,24 +294,35 @@
   ARGCHECK (s, format);
 
  {
-#ifndef COMPILE_WSCANF
+#if __OPTION_EGLIBC_LOCALE_CODE && !defined (COMPILE_WSCANF)
    struct locale_data *const curnumeric = loc->__locales[LC_NUMERIC];
 #endif
 
+#if __OPTION_EGLIBC_LOCALE_CODE
    /* Figure out the decimal point character.  */
-#ifdef COMPILE_WSCANF
+# ifdef COMPILE_WSCANF
    decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
-#else
+# else
    decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string;
-#endif
+# endif
    /* Figure out the thousands separator character.  */
-#ifdef COMPILE_WSCANF
+# ifdef COMPILE_WSCANF
    thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
-#else
+# else
    thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string;
    if (*thousands == '\0')
      thousands = NULL;
-#endif
+# endif
+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */
+   /* Hard-code values from the C locale.  */
+# ifdef COMPILE_WSCANF
+   decimal = L'.';
+   thousands = L'\0';
+# else
+   decimal = ".";
+   thousands = NULL;
+# endif
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
  }
 
   /* Lock the stream.  */
@@ -1365,10 +1377,17 @@
 	      const char *mbdigits[10];
 	      const char *mbdigits_extended[10];
 #endif
+#if __OPTION_EGLIBC_LOCALE_CODE
 	      /*  "to_inpunct" is a map from ASCII digits to their
 		  equivalent in locale. This is defined for locales
 		  which use an extra digits set.  */
 	      wctrans_t map = __wctrans ("to_inpunct");
+#else
+              /* This will always be the case when
+                 OPTION_EGLIBC_LOCALE_CODE is disabled, but the
+                 compiler can't figure that out.  */
+              wctrans_t map = NULL;
+#endif
 	      int n;
 
 	      from_level = 0;
@@ -2026,6 +2045,7 @@
 		--width;
 	    }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 	  wctrans_t map;
 	  if (__builtin_expect ((flags & I18N) != 0, 0)
 	      /* Hexadecimal floats make no sense, fixing localized
@@ -2242,6 +2262,7 @@
 	      ;
 #endif
 	    }
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
 
 	  /* Have we read any character?  If we try to read a number
 	     in hexadecimal notation and we have read only the `0x'