summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch')
-rw-r--r--meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch16842
1 files changed, 16842 insertions, 0 deletions
diff --git a/meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch b/meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch
new file mode 100644
index 0000000000..0514e282e6
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch
@@ -0,0 +1,16842 @@
1From 2a5d7bcf0ff791c95ee1388772408a1bf4454694 Mon Sep 17 00:00:00 2001
2From: Khem Raj <raj.khem@gmail.com>
3Date: Wed, 18 Mar 2015 01:33:49 +0000
4Subject: [PATCH 24/27] eglibc: Forward port eglibc options groups support
5
6Upstream-Status: Pending
7
8Signed-off-by: Khem Raj <raj.khem@gmail.com>
9---
10 Makeconfig | 20 +-
11 Makerules | 19 +
12 argp/Makefile | 2 +
13 argp/argp-fmtstream.c | 25 +-
14 argp/argp-help.c | 13 +-
15 argp/argp-namefrob.h | 2 +
16 catgets/Makefile | 17 +-
17 crypt/Makefile | 20 +-
18 crypt/crypt-entry.c | 13 +
19 crypt/crypt_common.c | 42 +
20 crypt/crypt_util.c | 18 -
21 csu/Makefile | 2 +
22 debug/Makefile | 41 +-
23 debug/segfault.c | 11 +-
24 debug/tst-chk1.c | 7 +
25 dlfcn/Makefile | 7 +-
26 elf/dl-support.c | 3 +
27 elf/rtld.c | 17 +-
28 extra-lib.mk | 6 +-
29 grp/Makefile | 5 +
30 hesiod/Makefile | 6 +-
31 iconv/Makefile | 7 +
32 iconv/gconv_db.c | 3 +
33 iconv/gconv_trans.c | 7 +
34 iconv/iconv_prog.c | 8 +
35 iconvdata/Makefile | 27 +-
36 include/netdb.h | 4 +
37 inet/Makefile | 22 +-
38 intl/Makefile | 3 +-
39 intl/dcigettext.c | 39 +-
40 io/Makefile | 18 +-
41 libidn/Makefile | 5 +-
42 libidn/toutf8.c | 11 +-
43 libio/Makefile | 66 +-
44 libio/__fpurge.c | 2 +-
45 libio/fileops.c | 10 +-
46 libio/iofwide.c | 26 +
47 libio/ioseekoff.c | 2 +-
48 libio/ioseekpos.c | 2 +-
49 libio/iosetbuffer.c | 4 +
50 libio/libioP.h | 18 +-
51 libio/wdummyfileops.c | 161 +
52 locale/C-ctype.c | 20 +
53 locale/Makefile | 41 +-
54 locale/catnames.c | 48 +
55 locale/dummy-setlocale.c | 33 +
56 locale/localeinfo.h | 2 +-
57 locale/programs/charmap-dir.c | 6 +
58 locale/programs/ld-collate.c | 17 +-
59 locale/programs/ld-ctype.c | 27 +-
60 locale/programs/ld-messages.c | 5 +
61 locale/programs/ld-time.c | 31 +-
62 locale/programs/linereader.c | 2 +-
63 locale/programs/localedef.c | 8 +
64 locale/programs/locfile.c | 5 +-
65 locale/programs/locfile.h | 59 +-
66 locale/setlocale.c | 30 -
67 locale/xlocale.c | 37 +
68 localedata/Makefile | 35 +-
69 login/Makefile | 17 +-
70 malloc/Makefile | 10 +-
71 malloc/memusage.c | 7 +-
72 malloc/memusage.sh | 2 +-
73 math/Makefile | 6 +-
74 misc/Makefile | 25 +-
75 misc/err.c | 11 +
76 misc/error.c | 5 +
77 misc/tst-efgcvt.c | 2 +-
78 nis/Makefile | 31 +-
79 nptl/Makefile | 28 +-
80 nptl/pthread_create.c | 5 +
81 nscd/Makefile | 33 +-
82 nscd/nis_hash.c | 3 +
83 nss/Makefile | 67 +-
84 nss/fixed-nsswitch.conf | 22 +
85 nss/fixed-nsswitch.functions | 121 +
86 nss/gen-fixed-nsswitch.c | 803 +++
87 nss/getent.c | 46 +-
88 nss/getnssent_r.c | 9 +-
89 nss/nsswitch.c | 109 +-
90 nss/nsswitch.h | 18 +-
91 posix/Makefile | 94 +-
92 posix/bug-regex1.c | 3 +
93 posix/bug-regex6.c | 8 +-
94 posix/fnmatch.c | 6 +-
95 posix/fnmatch_loop.c | 23 +-
96 posix/glob.c | 15 +-
97 posix/regcomp.c | 98 +-
98 posix/regex.h | 11 +
99 posix/regex_internal.c | 45 +-
100 posix/regex_internal.h | 23 +-
101 posix/regexec-compat.c | 39 +
102 posix/regexec.c | 71 +-
103 posix/xregex.c | 8215 +++++++++++++++++++++++++++++++
104 pwd/Makefile | 2 +
105 resolv/Makefile | 21 +-
106 stdio-common/Makefile | 35 +-
107 stdio-common/_i18n_number.h | 13 +
108 stdio-common/fxprintf.c | 5 +
109 stdio-common/printf_fp.c | 22 +
110 stdio-common/printf_fphex.c | 13 +
111 stdio-common/printf_size.c | 8 +
112 stdio-common/scanf14.c | 3 +
113 stdio-common/tst-popen.c | 3 +
114 stdio-common/tst-sprintf.c | 4 +-
115 stdio-common/tstdiomisc.c | 5 +
116 stdio-common/vfprintf.c | 31 +-
117 stdio-common/vfscanf.c | 53 +-
118 stdlib/Makefile | 34 +-
119 stdlib/strtod_l.c | 13 +
120 stdlib/tst-strtod.c | 5 +
121 streams/Makefile | 5 +-
122 string/Makefile | 14 +-
123 string/strcoll_l.c | 5 +
124 string/strerror_l.c | 5 +
125 string/strxfrm_l.c | 5 +
126 string/test-strcmp.c | 28 -
127 string/tst-strxfrm.c | 3 +
128 string/tst-strxfrm2.c | 3 +
129 sunrpc/Makefile | 44 +-
130 sysdeps/arm/Makefile | 5 +-
131 sysdeps/generic/ldsodefs.h | 8 +
132 sysdeps/gnu/Makefile | 3 +-
133 sysdeps/ieee754/ldbl-opt/Makefile | 27 +-
134 sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 40 +-
135 sysdeps/ieee754/ldbl-opt/nldbl-compat.h | 24 +-
136 sysdeps/nptl/Makefile | 3 +
137 sysdeps/nptl/bits/libc-lock.h | 45 +
138 sysdeps/nptl/bits/libc-lockP.h | 50 +-
139 sysdeps/nptl/small-macros-fns.c | 72 +
140 sysdeps/unix/sysv/linux/gethostid.c | 6 +
141 sysdeps/unix/sysv/linux/libc_fatal.c | 3 +
142 time/Makefile | 18 +-
143 time/strftime_l.c | 12 +-
144 time/strptime_l.c | 14 +-
145 timezone/Makefile | 2 +-
146 wcsmbs/Makefile | 27 +-
147 wcsmbs/wcsmbsload.c | 13 +
148 wctype/Makefile | 14 +-
149 139 files changed, 11363 insertions(+), 583 deletions(-)
150 create mode 100644 crypt/crypt_common.c
151 create mode 100644 libio/wdummyfileops.c
152 create mode 100644 locale/catnames.c
153 create mode 100644 locale/dummy-setlocale.c
154 create mode 100644 nscd/nis_hash.c
155 create mode 100644 nss/fixed-nsswitch.conf
156 create mode 100644 nss/fixed-nsswitch.functions
157 create mode 100644 nss/gen-fixed-nsswitch.c
158 create mode 100644 posix/regexec-compat.c
159 create mode 100644 posix/xregex.c
160 create mode 100644 sysdeps/nptl/small-macros-fns.c
161
162diff --git a/Makeconfig b/Makeconfig
163index f136b88..52dae8f 100644
164--- a/Makeconfig
165+++ b/Makeconfig
166@@ -609,7 +609,7 @@ elf-objpfx = $(common-objpfx)elf/
167 # and run on the build system, causes that program with those
168 # arguments to be run on the host for which the library is built.
169 ifndef test-wrapper
170-test-wrapper =
171+test-wrapper = $(cross-test-wrapper)
172 endif
173 # Likewise, but the name of the program is preceded by
174 # <variable>=<value> assignments for environment variables.
175@@ -1089,6 +1089,24 @@ libm = $(common-objpfx)math/libm.a
176 libmvec = $(common-objpfx)mathvec/libmvec.a
177 endif
178
179+# Generate a header file that #defines preprocessor symbols indicating
180+# which option groups are enabled. Note that the option-groups.config file
181+# may not exist at all.
182+before-compile += $(common-objpfx)gnu/option-groups.h
183+common-generated += gnu/option-groups.h gnu/option-groups.stmp
184+headers += gnu/option-groups.h
185+$(common-objpfx)gnu/option-groups.h: $(common-objpfx)gnu/option-groups.stmp; @:
186+$(common-objpfx)gnu/option-groups.stmp: \
187+ $(..)scripts/option-groups.awk \
188+ $(..)option-groups.defaults \
189+ $(wildcard $(common-objpfx)option-groups.config)
190+ $(make-target-directory)
191+ @rm -f ${@:stmp=T} $@
192+ LC_ALL=C $(AWK) -f $^ > ${@:stmp=T}
193+ $(move-if-change) ${@:stmp=T} ${@:stmp=h}
194+ touch $@
195+
196+
197 # These are the subdirectories containing the library source. The order
198 # is more or less arbitrary. The sorting step will take care of the
199 # dependencies.
200diff --git a/Makerules b/Makerules
201index f9ca3f5..1dd41aa 100644
202--- a/Makerules
203+++ b/Makerules
204@@ -456,6 +456,25 @@ define sed-remove-objpfx
205 endef
206 endif
207
208+# Include targets in the selected option groups.
209+aux += $(aux-y)
210+extra-libs += $(extra-libs-y)
211+extra-libs-others += $(extra-libs-others-y)
212+extra-objs += $(extra-objs-y)
213+install-bin += $(install-bin-y)
214+install-others += $(install-others-y)
215+install-sbin += $(install-sbin-y)
216+modules += $(modules-y)
217+others += $(others-y)
218+others-pie += $(others-pie-y)
219+routines += $(routines-y)
220+static-only-routines += $(static-only-routines-y)
221+sysdep_routines += $(sysdep_routines-y)
222+test-srcs += $(test-srcs-y)
223+tests += $(tests-y)
224+xtests += $(xtests-y)
225+
226+
227 # Modify the list of routines we build for different targets
228
229 ifeq (yes,$(build-shared))
230diff --git a/argp/Makefile b/argp/Makefile
231index 1a87629..f7c1e40 100644
232--- a/argp/Makefile
233+++ b/argp/Makefile
234@@ -18,6 +18,8 @@
235 #
236 # Makefile for argp.
237 #
238+include ../option-groups.mak
239+
240 subdir := argp
241
242 include ../Makeconfig
243diff --git a/argp/argp-fmtstream.c b/argp/argp-fmtstream.c
244index 2b845e0..c344e7b 100644
245--- a/argp/argp-fmtstream.c
246+++ b/argp/argp-fmtstream.c
247@@ -42,6 +42,7 @@
248 #ifdef _LIBC
249 # include <wchar.h>
250 # include <libio/libioP.h>
251+# include <gnu/option-groups.h>
252 # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
253 #endif
254
255@@ -100,7 +101,11 @@ __argp_fmtstream_free (argp_fmtstream_t fs)
256 __argp_fmtstream_update (fs);
257 if (fs->p > fs->buf)
258 {
259+#ifdef _LIBC
260 __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
261+#else
262+ fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
263+#endif
264 }
265 free (fs->buf);
266 free (fs);
267@@ -145,9 +150,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
268 size_t i;
269 for (i = 0; i < pad; i++)
270 {
271+#ifdef _LIBC
272 if (_IO_fwide (fs->stream, 0) > 0)
273- putwc_unlocked (L' ', fs->stream);
274+ {
275+#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
276+ putwc_unlocked (L' ', fs->stream);
277+#else
278+ abort ();
279+#endif
280+ }
281 else
282+#endif
283 putc_unlocked (' ', fs->stream);
284 }
285 }
286@@ -308,9 +321,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
287 *nl++ = ' ';
288 else
289 for (i = 0; i < fs->wmargin; ++i)
290+#ifdef _LIBC
291 if (_IO_fwide (fs->stream, 0) > 0)
292- putwc_unlocked (L' ', fs->stream);
293+ {
294+#ifdef OPTION_POSIX_WIDE_CHAR_DEVICE_IO
295+ putwc_unlocked (L' ', fs->stream);
296+#else
297+ abort ();
298+#endif
299+ }
300 else
301+#endif
302 putc_unlocked (' ', fs->stream);
303
304 /* Copy the tail of the original buffer into the current buffer
305diff --git a/argp/argp-help.c b/argp/argp-help.c
306index b055e45..6b3c4c1 100644
307--- a/argp/argp-help.c
308+++ b/argp/argp-help.c
309@@ -51,6 +51,7 @@ char *alloca ();
310 #ifdef _LIBC
311 # include <../libio/libioP.h>
312 # include <wchar.h>
313+# include <gnu/option-groups.h>
314 #endif
315
316 #ifndef _
317@@ -1702,7 +1703,7 @@ char *__argp_basename (char *name)
318 }
319
320 char *
321-__argp_short_program_name (void)
322+(__argp_short_program_name) (void)
323 {
324 # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
325 return program_invocation_short_name;
326@@ -1873,9 +1874,17 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
327 #endif
328 }
329
330+#ifdef _LIBC
331 if (_IO_fwide (stream, 0) > 0)
332- putwc_unlocked (L'\n', stream);
333+ {
334+#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
335+ putwc_unlocked (L'\n', stream);
336+#else
337+ abort ();
338+#endif
339+ }
340 else
341+#endif
342 putc_unlocked ('\n', stream);
343
344 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
345diff --git a/argp/argp-namefrob.h b/argp/argp-namefrob.h
346index f67c58f..e2002dc 100644
347--- a/argp/argp-namefrob.h
348+++ b/argp/argp-namefrob.h
349@@ -76,10 +76,12 @@
350 #undef __argp_fmtstream_wmargin
351 #define __argp_fmtstream_wmargin argp_fmtstream_wmargin
352
353+#if 0
354 #include "mempcpy.h"
355 #include "strcase.h"
356 #include "strchrnul.h"
357 #include "strndup.h"
358+#endif
359
360 /* normal libc functions we call */
361 #undef __flockfile
362diff --git a/catgets/Makefile b/catgets/Makefile
363index 4624a88..05714fd 100644
364--- a/catgets/Makefile
365+++ b/catgets/Makefile
366@@ -22,20 +22,23 @@ subdir := catgets
367
368 include ../Makeconfig
369
370+include ../option-groups.mak
371+
372 headers = nl_types.h
373-routines = catgets open_catalog
374-others = gencat
375-install-bin = gencat
376-extra-objs = $(gencat-modules:=.o)
377+routines-$(OPTION_EGLIBC_CATGETS) := catgets open_catalog
378+others-$(OPTION_EGLIBC_CATGETS) := gencat
379+install-bin-$(OPTION_EGLIBC_CATGETS) := gencat
380+extra-objs-$(OPTION_EGLIBC_CATGETS) := $(gencat-modules:=.o)
381
382-tests = tst-catgets
383-test-srcs = test-gencat
384+tests-$(OPTION_EGLIBC_CATGETS) := tst-catgets
385+test-srcs-$(OPTION_EGLIBC_CATGETS) := test-gencat
386
387+ifeq (y,$(OPTION_EGLIBC_CATGETS))
388 ifeq ($(run-built-tests),yes)
389 tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
390 $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out
391 endif
392-
393+endif
394 gencat-modules = xmalloc
395
396 # To find xmalloc.c
397diff --git a/crypt/Makefile b/crypt/Makefile
398index 34c4dd7..7c18c88 100644
399--- a/crypt/Makefile
400+++ b/crypt/Makefile
401@@ -18,21 +18,25 @@
402 #
403 # Sub-makefile for crypt() portion of the library.
404 #
405+include ../option-groups.mak
406+
407 subdir := crypt
408
409 include ../Makeconfig
410
411 headers := crypt.h
412
413-extra-libs := libcrypt
414-extra-libs-others := $(extra-libs)
415+extra-libs-$(OPTION_EGLIBC_CRYPT) := libcrypt
416+extra-libs-others-y := $(extra-libs-y)
417
418-libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
419- crypt_util
420+libcrypt-routines :=crypt-entry md5-crypt sha256-crypt sha512-crypt crypt_common
421+libcrypt-routines-$(OPTION_EGLIBC_CRYPT_UFC) := crypt crypt_util
422+libcrypt-routines += $(libcrypt-routines-y)
423
424-tests := cert md5c-test sha256c-test sha512c-test badsalttest
425+tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test badsalttest
426+tests-$(OPTION_EGLIBC_CRYPT_UFC) += cert
427
428-ifeq ($(crypt-in-libc),yes)
429+ifeq ($(crypt-in-libc)$(OPTION_EGLIBC_CRYPT),yesy)
430 routines += $(libcrypt-routines)
431 endif
432
433@@ -44,7 +48,7 @@ LDLIBS-crypt.so = -lfreebl3
434 else
435 libcrypt-routines += md5 sha256 sha512
436
437-tests += md5test sha256test sha512test
438+tests-$(OPTION_EGLIBC_CRYPT) += md5test sha256test sha512test
439
440 # The test md5test-giant uses up to 400 MB of RSS and runs on a fast
441 # machine over a minute.
442@@ -64,8 +68,10 @@ $(objpfx)sha256test: $(patsubst %, $(objpfx)%.o,$(sha256-routines))
443 $(objpfx)sha512test: $(patsubst %, $(objpfx)%.o,$(sha512-routines))
444 endif
445
446+ifeq ($(OPTION_EGLIBC_CRYPT),y)
447 ifeq (yes,$(build-shared))
448 $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.so
449 else
450 $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.a
451 endif
452+endif # eglibc: OPTION_EGLIBC_CRYPT
453diff --git a/crypt/crypt-entry.c b/crypt/crypt-entry.c
454index 7e655ba..6ae5c2b 100644
455--- a/crypt/crypt-entry.c
456+++ b/crypt/crypt-entry.c
457@@ -27,6 +27,7 @@
458 #include <stdio.h>
459 #endif
460 #include <string.h>
461+#include <gnu/option-groups.h>
462 #include <errno.h>
463 #include <fips-private.h>
464
465@@ -76,9 +77,11 @@ __crypt_r (key, salt, data)
466 const char *salt;
467 struct crypt_data * __restrict data;
468 {
469+#if __OPTION_EGLIBC_CRYPT_UFC
470 ufc_long res[4];
471 char ktab[9];
472 ufc_long xx = 25; /* to cope with GCC long long compiler bugs */
473+#endif /*__OPTION_EGLIBC_CRYPT_UFC*/
474
475 #ifdef _LIBC
476 /* Try to find out whether we have to use MD5 encryption replacement. */
477@@ -105,6 +108,7 @@ __crypt_r (key, salt, data)
478 sizeof (struct crypt_data));
479 #endif
480
481+#if __OPTION_EGLIBC_CRYPT_UFC
482 /*
483 * Hack DES tables according to salt
484 */
485@@ -144,6 +148,10 @@ __crypt_r (key, salt, data)
486 */
487 _ufc_output_conversion_r (res[0], res[1], salt, data);
488 return data->crypt_3_buf;
489+#else /* __OPTION_EGLIBC_CRYPT_UFC */
490+ __set_errno (ENOSYS);
491+ return NULL;
492+#endif /* __OPTION_EGLIBC_CRYPT_UFC */
493 }
494 weak_alias (__crypt_r, crypt_r)
495
496@@ -168,7 +176,12 @@ crypt (key, salt)
497 return __sha512_crypt (key, salt);
498 #endif
499
500+#if __OPTION_EGLIBC_CRYPT_UFC
501 return __crypt_r (key, salt, &_ufc_foobar);
502+#else /* __OPTION_EGLIBC_CRYPT_UFC */
503+ __set_errno (ENOSYS);
504+ return NULL;
505+#endif /* __OPTION_EGLIBC_CRYPT_UFC */
506 }
507
508
509diff --git a/crypt/crypt_common.c b/crypt/crypt_common.c
510new file mode 100644
511index 0000000..cce6a31
512--- /dev/null
513+++ b/crypt/crypt_common.c
514@@ -0,0 +1,42 @@
515+/*
516+ * crypt: crypt(3) implementation
517+ *
518+ * Copyright (C) 1991-2014 Free Software Foundation, Inc.
519+ *
520+ * This library is free software; you can redistribute it and/or
521+ * modify it under the terms of the GNU Lesser General Public
522+ * License as published by the Free Software Foundation; either
523+ * version 2.1 of the License, or (at your option) any later version.
524+ *
525+ * This library is distributed in the hope that it will be useful,
526+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
527+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
528+ * Lesser General Public License for more details.
529+ *
530+ * You should have received a copy of the GNU Lesser General Public
531+ * License along with this library; see the file COPYING.LIB. If not,
532+ * see <http://www.gnu.org/licenses/>.
533+ *
534+ * General Support routines
535+ *
536+ */
537+
538+#include "crypt-private.h"
539+
540+/* Table with characters for base64 transformation. */
541+static const char b64t[64] =
542+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
543+
544+void
545+__b64_from_24bit (char **cp, int *buflen,
546+ unsigned int b2, unsigned int b1, unsigned int b0,
547+ int n)
548+{
549+ unsigned int w = (b2 << 16) | (b1 << 8) | b0;
550+ while (n-- > 0 && (*buflen) > 0)
551+ {
552+ *(*cp)++ = b64t[w & 0x3f];
553+ --(*buflen);
554+ w >>= 6;
555+ }
556+}
557diff --git a/crypt/crypt_util.c b/crypt/crypt_util.c
558index 1597885..9297974 100644
559--- a/crypt/crypt_util.c
560+++ b/crypt/crypt_util.c
561@@ -242,10 +242,6 @@ static ufc_long eperm32tab[4][256][2];
562 */
563 static ufc_long efp[16][64][2];
564
565-/* Table with characters for base64 transformation. */
566-static const char b64t[64] =
567-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
568-
569 /*
570 * For use by the old, non-reentrant routines
571 * (crypt/encrypt/setkey)
572@@ -949,17 +945,3 @@ setkey(__key)
573 {
574 __setkey_r(__key, &_ufc_foobar);
575 }
576-
577-void
578-__b64_from_24bit (char **cp, int *buflen,
579- unsigned int b2, unsigned int b1, unsigned int b0,
580- int n)
581-{
582- unsigned int w = (b2 << 16) | (b1 << 8) | b0;
583- while (n-- > 0 && (*buflen) > 0)
584- {
585- *(*cp)++ = b64t[w & 0x3f];
586- --(*buflen);
587- w >>= 6;
588- }
589-}
590diff --git a/csu/Makefile b/csu/Makefile
591index 9f0855a..b1c3363 100644
592--- a/csu/Makefile
593+++ b/csu/Makefile
594@@ -22,6 +22,8 @@
595 # crtn.o, special "initializer" and "finalizer" files used in the link
596 # to make the .init and .fini sections work right.
597
598+include ../option-groups.mak
599+
600 subdir := csu
601
602 include ../Makeconfig
603diff --git a/debug/Makefile b/debug/Makefile
604index 9ff357b..d23d97d 100644
605--- a/debug/Makefile
606+++ b/debug/Makefile
607@@ -18,6 +18,8 @@
608 #
609 # Sub-makefile for debug portion of the library.
610 #
611+include ../option-groups.mak
612+
613 subdir := debug
614
615 include ../Makeconfig
616@@ -27,7 +29,7 @@ headers := execinfo.h
617 # Note that ptsname_r_chk and getlogin_r are not here, but in
618 # login/Makefile instead. If that subdir is omitted from the
619 # build, its _FORTIFY_SOURCE support will be too.
620-routines = backtrace backtracesyms backtracesymsfd noophooks \
621+routines = noophooks \
622 memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \
623 strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \
624 sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \
625@@ -36,20 +38,27 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \
626 read_chk pread_chk pread64_chk recv_chk recvfrom_chk \
627 readlink_chk readlinkat_chk getwd_chk getcwd_chk \
628 realpath_chk fread_chk fread_u_chk \
629- wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
630- wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
631- wcpncpy_chk \
632- swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \
633- vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \
634 confstr_chk getgroups_chk ttyname_r_chk \
635- gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \
636- wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \
637- wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \
638+ gethostname_chk getdomainname_chk \
639+ asprintf_chk vasprintf_chk dprintf_chk \
640 vdprintf_chk obprintf_chk \
641 longjmp_chk ____longjmp_chk \
642 fdelt_chk poll_chk ppoll_chk \
643 stack_chk_fail fortify_fail \
644 $(static-only-routines)
645+routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd
646+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
647+ += wprintf_chk fwprintf_chk \
648+ vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk
649+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
650+ += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
651+ wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
652+ wcpncpy_chk \
653+ swprintf_chk vswprintf_chk \
654+ wcrtomb_chk mbsnrtowcs_chk \
655+ wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \
656+ wcstombs_chk
657+
658 static-only-routines := warning-nop stack_chk_fail_local
659
660 CFLAGS-backtrace.c = -fno-omit-frame-pointer
661@@ -131,11 +140,15 @@ LDFLAGS-tst-backtrace4 = -rdynamic
662 LDFLAGS-tst-backtrace5 = -rdynamic
663 LDFLAGS-tst-backtrace6 = -rdynamic
664
665-tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
666- tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
667- tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
668- tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \
669- tst-backtrace5 tst-backtrace6
670+tests = tst-longjmp_chk test-strcpy_chk test-stpcpy_chk tst-longjmp_chk2
671+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
672+ += tst-chk1 tst-chk2 tst-chk3 tst-lfschk1 tst-lfschk2 tst-lfschk3
673+tests-$(OPTION_EGLIBC_BACKTRACE) \
674+ += backtrace-tst tst-backtrace2 tst-backtrace3 tst-backtrace4 \
675+ tst-backtrace5 tst-backtrace6
676+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_EGLIBC_CXX_TESTS))
677+tests += tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6
678+endif
679
680 ifeq (,$(CXX))
681 tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \
682diff --git a/debug/segfault.c b/debug/segfault.c
683index 3459a2a..ee9a146 100644
684--- a/debug/segfault.c
685+++ b/debug/segfault.c
686@@ -30,6 +30,7 @@
687 #include <unistd.h>
688 #include <_itoa.h>
689 #include <ldsodefs.h>
690+#include <gnu/option-groups.h>
691
692 /* This file defines macros to access the content of the sigcontext element
693 passed up by the signal handler. */
694@@ -68,11 +69,13 @@ write_strsignal (int fd, int signal)
695 static void
696 catch_segfault (int signal, SIGCONTEXT ctx)
697 {
698- int fd, cnt, i;
699- void **arr;
700+ int fd;
701 struct sigaction sa;
702+#if __OPTION_EGLIBC_BACKTRACE
703+ int cnt, i;
704+ void **arr;
705 uintptr_t pc;
706-
707+#endif
708 /* This is the name of the file we are writing to. If none is given
709 or we cannot write to this file write to stderr. */
710 fd = 2;
711@@ -91,6 +94,7 @@ catch_segfault (int signal, SIGCONTEXT ctx)
712 REGISTER_DUMP;
713 #endif
714
715+#if __OPTION_EGLIBC_BACKTRACE
716 WRITE_STRING ("\nBacktrace:\n");
717
718 /* Get the backtrace. */
719@@ -113,6 +117,7 @@ catch_segfault (int signal, SIGCONTEXT ctx)
720
721 /* Now generate nicely formatted output. */
722 __backtrace_symbols_fd (arr + i, cnt - i, fd);
723+#endif
724
725 #ifdef HAVE_PROC_SELF
726 /* Now the link map. */
727diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c
728index 53559e6..362d92a 100644
729--- a/debug/tst-chk1.c
730+++ b/debug/tst-chk1.c
731@@ -31,6 +31,7 @@
732 #include <sys/select.h>
733 #include <sys/socket.h>
734 #include <sys/un.h>
735+#include <gnu/option-groups.h>
736
737
738 #define obstack_chunk_alloc malloc
739@@ -307,6 +308,7 @@ do_test (void)
740 snprintf (buf + 8, l0 + 3, "%d", num2);
741 CHK_FAIL_END
742
743+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
744 CHK_FAIL_START
745 swprintf (wbuf + 8, 3, L"%d", num1);
746 CHK_FAIL_END
747@@ -314,6 +316,7 @@ do_test (void)
748 CHK_FAIL_START
749 swprintf (wbuf + 8, l0 + 3, L"%d", num1);
750 CHK_FAIL_END
751+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
752 # endif
753
754 memcpy (buf, str1 + 2, l0 + 9);
755@@ -381,6 +384,7 @@ do_test (void)
756 CHK_FAIL_END
757 #endif
758
759+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
760
761 /* These ops can be done without runtime checking of object size. */
762 wmemcpy (wbuf, L"abcdefghij", 10);
763@@ -605,6 +609,7 @@ do_test (void)
764 CHK_FAIL_END
765 #endif
766
767+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
768
769 /* Now checks for %n protection. */
770
771@@ -1192,6 +1197,7 @@ do_test (void)
772 # endif
773 #endif
774
775+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
776 if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
777 {
778 assert (MB_CUR_MAX <= 10);
779@@ -1348,6 +1354,7 @@ do_test (void)
780 puts ("cannot set locale");
781 ret = 1;
782 }
783+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
784
785 int fd = posix_openpt (O_RDWR);
786 if (fd != -1)
787diff --git a/dlfcn/Makefile b/dlfcn/Makefile
788index 759780d..3827607 100644
789--- a/dlfcn/Makefile
790+++ b/dlfcn/Makefile
791@@ -15,6 +15,8 @@
792 # License along with the GNU C Library; if not, see
793 # <http://www.gnu.org/licenses/>.
794
795+include ../option-groups.mak
796+
797 subdir := dlfcn
798
799 include ../Makeconfig
800@@ -36,8 +38,11 @@ endif
801 ifeq (yes,$(build-shared))
802 tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
803 bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
804- bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen
805+ tstatexit bug-dl-leaf tst-rec-dlopen
806 endif
807+
808+tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3
809+
810 modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
811 defaultmod2 errmsg1mod modatexit modcxaatexit \
812 bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \
813diff --git a/elf/dl-support.c b/elf/dl-support.c
814index 4d036f1..c15f405 100644
815--- a/elf/dl-support.c
816+++ b/elf/dl-support.c
817@@ -19,6 +19,7 @@
818 /* This file defines some things that for the dynamic linker are defined in
819 rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */
820
821+#include <gnu/option-groups.h>
822 #include <errno.h>
823 #include <libintl.h>
824 #include <stdlib.h>
825@@ -42,7 +43,9 @@ char **_dl_argv = &__progname; /* This is checked for some error messages. */
826 const char *_dl_platform;
827 size_t _dl_platformlen;
828
829+#if __OPTION_EGLIBC_RTLD_DEBUG
830 int _dl_debug_mask;
831+#endif
832 int _dl_lazy;
833 ElfW(Addr) _dl_use_load_bias = -2;
834 int _dl_dynamic_weak;
835diff --git a/elf/rtld.c b/elf/rtld.c
836index 6d3add7..fc3a2db 100644
837--- a/elf/rtld.c
838+++ b/elf/rtld.c
839@@ -16,6 +16,7 @@
840 License along with the GNU C Library; if not, see
841 <http://www.gnu.org/licenses/>. */
842
843+#include <gnu/option-groups.h>
844 #include <errno.h>
845 #include <dlfcn.h>
846 #include <fcntl.h>
847@@ -2201,6 +2202,7 @@ print_missing_version (int errcode __attribute__ ((unused)),
848 objname, errstring);
849 }
850
851+#if __OPTION_EGLIBC_RTLD_DEBUG
852 /* Nonzero if any of the debugging options is enabled. */
853 static int any_debug attribute_relro;
854
855@@ -2310,6 +2312,7 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
856 _exit (0);
857 }
858 }
859+#endif /* __OPTION_EGLIBC_RTLD_DEBUG */
860
861 static void
862 process_dl_audit (char *str)
863@@ -2349,8 +2352,9 @@ process_envvars (enum mode *modep)
864 char **runp = _environ;
865 char *envline;
866 enum mode mode = normal;
867+#if __OPTION_EGLIBC_RTLD_DEBUG
868 char *debug_output = NULL;
869-
870+#endif
871 /* This is the default place for profiling data file. */
872 GLRO(dl_profile_output)
873 = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0];
874@@ -2377,12 +2381,14 @@ process_envvars (enum mode *modep)
875 break;
876
877 case 5:
878+#if __OPTION_EGLIBC_RTLD_DEBUG
879 /* Debugging of the dynamic linker? */
880 if (memcmp (envline, "DEBUG", 5) == 0)
881 {
882 process_dl_debug (&envline[6]);
883 break;
884 }
885+#endif
886 if (memcmp (envline, "AUDIT", 5) == 0)
887 process_dl_audit (&envline[6]);
888 break;
889@@ -2448,13 +2454,14 @@ process_envvars (enum mode *modep)
890 break;
891 }
892
893+#if __OPTION_EGLIBC_RTLD_DEBUG
894 /* Where to place the profiling data file. */
895 if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0)
896 {
897 debug_output = &envline[13];
898 break;
899 }
900-
901+#endif
902 if (!__libc_enable_secure
903 && memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
904 GLRO(dl_dynamic_weak) = 1;
905@@ -2491,7 +2498,9 @@ process_envvars (enum mode *modep)
906 {
907 mode = trace;
908 GLRO(dl_verbose) = 1;
909+#if __OPTION_EGLIBC_RTLD_DEBUG
910 GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
911+#endif
912 GLRO(dl_trace_prelink) = &envline[17];
913 }
914 break;
915@@ -2538,12 +2547,15 @@ process_envvars (enum mode *modep)
916 if (__access ("/etc/suid-debug", F_OK) != 0)
917 {
918 unsetenv ("MALLOC_CHECK_");
919+#if __OPTION_EGLIBC_RTLD_DEBUG
920 GLRO(dl_debug_mask) = 0;
921+#endif
922 }
923
924 if (mode != normal)
925 _exit (5);
926 }
927+#if __OPTION_EGLIBC_RTLD_DEBUG
928 /* If we have to run the dynamic linker in debugging mode and the
929 LD_DEBUG_OUTPUT environment variable is given, we write the debug
930 messages to this file. */
931@@ -2568,6 +2580,7 @@ process_envvars (enum mode *modep)
932 /* We use standard output if opening the file failed. */
933 GLRO(dl_debug_fd) = STDOUT_FILENO;
934 }
935+#endif /* __OPTION_EGLIBC_RTLD_DEBUG */
936 }
937
938
939diff --git a/extra-lib.mk b/extra-lib.mk
940index b10748d..d71a06f 100644
941--- a/extra-lib.mk
942+++ b/extra-lib.mk
943@@ -25,7 +25,9 @@ install-lib := $(install-lib)
944 extra-objs := $(extra-objs)
945
946 # The modules that go in $(lib).
947-all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines)
948+all-$(lib)-routines := $($(lib)-routines) \
949+ $($(lib)-routines-y) \
950+ $($(lib)-sysdep_routines)
951
952 # Add each flavor of library to the lists of things to build and install.
953 install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
954@@ -101,7 +103,7 @@ endif
955 endif
956
957 # This will define `libof-ROUTINE := LIB' for each of the routines.
958-cpp-srcs-left := $($(lib)-routines) $($(lib)-sysdep_routines)
959+cpp-srcs-left := $(all-$(lib)-routines)
960 ifneq (,$(cpp-srcs-left))
961 include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
962 endif
963diff --git a/grp/Makefile b/grp/Makefile
964index c63b552..7486f32 100644
965--- a/grp/Makefile
966+++ b/grp/Makefile
967@@ -18,6 +18,8 @@
968 #
969 # Sub-makefile for grp portion of the library.
970 #
971+include ../option-groups.mak
972+
973 subdir := grp
974
975 include ../Makeconfig
976@@ -29,6 +31,9 @@ routines := fgetgrent initgroups setgroups \
977 getgrent_r getgrgid_r getgrnam_r fgetgrent_r
978
979 tests := testgrp
980+ifneq (y,$(OPTION_EGLIBC_NSSWITCH))
981+LDLIBS-testgrp += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs)
982+endif
983
984 ifeq (yes,$(build-shared))
985 test-srcs := tst_fgetgrent
986diff --git a/hesiod/Makefile b/hesiod/Makefile
987index ac0bc01..38263b4 100644
988--- a/hesiod/Makefile
989+++ b/hesiod/Makefile
990@@ -18,12 +18,14 @@
991 #
992 # Sub-makefile for hesiod portion of the library.
993 #
994+include ../option-groups.mak
995+
996 subdir := hesiod
997
998 include ../Makeconfig
999
1000-extra-libs := libnss_hesiod
1001-extra-libs-others = $(extra-libs)
1002+extra-libs-$(OPTION_EGLIBC_INET) += libnss_hesiod
1003+extra-libs-others-y += $(extra-libs-y)
1004
1005 subdir-dirs = nss_hesiod
1006 vpath %.c nss_hesiod
1007diff --git a/iconv/Makefile b/iconv/Makefile
1008index 0d55eda..a1847c6 100644
1009--- a/iconv/Makefile
1010+++ b/iconv/Makefile
1011@@ -18,6 +18,8 @@
1012 #
1013 # Makefile for iconv.
1014 #
1015+include ../option-groups.mak
1016+
1017 subdir := iconv
1018
1019 include ../Makeconfig
1020@@ -39,6 +41,11 @@ CFLAGS-iconv_charmap.c = -I../locale/programs
1021 CFLAGS-dummy-repertoire.c = -I../locale/programs
1022 CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \
1023 -DDEFAULT_CHARMAP=null_pointer -DNEED_NULL_POINTER
1024+
1025+ifneq (y,$(OPTION_EGLIBC_SPAWN))
1026+CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS
1027+endif
1028+
1029 CFLAGS-linereader.c = -DNO_TRANSLITERATION
1030 CFLAGS-simple-hash.c = -I../locale
1031
1032diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
1033index ce46216..ea18964 100644
1034--- a/iconv/gconv_db.c
1035+++ b/iconv/gconv_db.c
1036@@ -25,6 +25,7 @@
1037 #include <sys/param.h>
1038 #include <bits/libc-lock.h>
1039 #include <locale/localeinfo.h>
1040+#include <gnu/option-groups.h>
1041
1042 #include <dlfcn.h>
1043 #include <gconv_int.h>
1044@@ -828,9 +829,11 @@ free_modules_db (struct gconv_module *node)
1045 /* Free all resources if necessary. */
1046 libc_freeres_fn (free_mem)
1047 {
1048+#if __OPTION_EGLIBC_LOCALE_CODE
1049 /* First free locale memory. This needs to be done before freeing derivations,
1050 as ctype cleanup functions dereference steps arrays which we free below. */
1051 _nl_locale_subfreeres ();
1052+#endif
1053
1054 /* finddomain.c has similar problem. */
1055 extern void _nl_finddomain_subfreeres (void) attribute_hidden;
1056diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c
1057index 5d5d4d7..a7d3072 100644
1058--- a/iconv/gconv_trans.c
1059+++ b/iconv/gconv_trans.c
1060@@ -23,6 +23,7 @@
1061 #include <stdint.h>
1062 #include <string.h>
1063 #include <stdlib.h>
1064+#include <gnu/option-groups.h>
1065
1066 #include <bits/libc-lock.h>
1067 #include "gconv_int.h"
1068@@ -38,15 +39,19 @@ __gconv_transliterate (struct __gconv_step *step,
1069 unsigned char **outbufstart, size_t *irreversible)
1070 {
1071 /* Find out about the locale's transliteration. */
1072+#if __OPTION_EGLIBC_LOCALE_CODE
1073 uint_fast32_t size;
1074 const uint32_t *from_idx;
1075 const uint32_t *from_tbl;
1076 const uint32_t *to_idx;
1077 const uint32_t *to_tbl;
1078+#endif
1079 const uint32_t *winbuf;
1080 const uint32_t *winbufend;
1081+#if __OPTION_EGLIBC_LOCALE_CODE
1082 uint_fast32_t low;
1083 uint_fast32_t high;
1084+#endif
1085
1086 /* The input buffer. There are actually 4-byte values. */
1087 winbuf = (const uint32_t *) *inbufp;
1088@@ -58,6 +63,7 @@ __gconv_transliterate (struct __gconv_step *step,
1089 PTR_DEMANGLE (fct);
1090 #endif
1091
1092+#if __OPTION_EGLIBC_LOCALE_CODE
1093 /* If there is no transliteration information in the locale don't do
1094 anything and return the error. */
1095 size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_TAB_SIZE);
1096@@ -193,6 +199,7 @@ __gconv_transliterate (struct __gconv_step *step,
1097 sorted. */
1098 break;
1099 }
1100+#endif
1101
1102 /* One last chance: use the default replacement. */
1103 if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN) != 0)
1104diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
1105index e249bce..403ece5 100644
1106--- a/iconv/iconv_prog.c
1107+++ b/iconv/iconv_prog.c
1108@@ -35,6 +35,7 @@
1109 #ifdef _POSIX_MAPPED_FILES
1110 # include <sys/mman.h>
1111 #endif
1112+#include <gnu/option-groups.h>
1113 #include <charmap.h>
1114 #include <gconv_int.h>
1115 #include "iconv_prog.h"
1116@@ -221,10 +222,17 @@ main (int argc, char *argv[])
1117 bool to_wrong =
1118 (iconv_open (to_code, "UTF-8") == (iconv_t) -1
1119 && errno == EINVAL);
1120+#if __OPTION_EGLIBC_LOCALE_CODE
1121 const char *from_pretty =
1122 (from_code[0] ? from_code : nl_langinfo (CODESET));
1123 const char *to_pretty =
1124 (orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET));
1125+#else
1126+ const char *from_pretty =
1127+ (from_code[0] ? from_code : "ANSI_X3.4-1968");
1128+ const char *to_pretty =
1129+ (orig_to_code[0] ? orig_to_code : "ANSI_X3.4-1968");
1130+#endif
1131
1132 if (from_wrong)
1133 {
1134diff --git a/iconvdata/Makefile b/iconvdata/Makefile
1135index a3d1d09..0832708 100644
1136--- a/iconvdata/Makefile
1137+++ b/iconvdata/Makefile
1138@@ -18,12 +18,15 @@
1139 #
1140 # Makefile for iconv data and code.
1141 #
1142+include ../option-groups.mak
1143+
1144 subdir := iconvdata
1145
1146 include ../Makeconfig
1147
1148 # Names of all the shared objects which implement the transformations.
1149-modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \
1150+modules-$(OPTION_EGLIBC_CHARSETS) \
1151+ := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \
1152 ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10 \
1153 ISO8859-11 ISO8859-13 ISO8859-14 ISO8859-15 ISO8859-16 \
1154 T.61 ISO_6937 SJIS KOI-8 HP-ROMAN8 HP-ROMAN9 EBCDIC-AT-DE \
1155@@ -63,11 +66,13 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \
1156 MAC-CENTRALEUROPE KOI8-RU ISO8859-9E \
1157 CP770 CP771 CP772 CP773 CP774
1158
1159-modules.so := $(addsuffix .so, $(modules))
1160+modules.so := $(addsuffix .so, $(modules-y))
1161
1162 ifeq (yes,$(build-shared))
1163 tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
1164- tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9
1165+ tst-iconv6 bug-iconv5 bug-iconv8 bug-iconv9
1166+tests-$(OPTION_EGLIBC_LOCALE_CODE) += bug-iconv6 tst-iconv7
1167+
1168 ifeq ($(have-thread-library),yes)
1169 tests += bug-iconv3
1170 endif
1171@@ -127,13 +132,13 @@ ifeq (yes,$(build-shared))
1172 # Rule to generate the shared objects.
1173 charmaps = ../localedata/charmaps
1174 -include $(objpfx)iconv-rules
1175-extra-modules-left := $(modules)
1176+extra-modules-left := $(modules-y)
1177 include extra-module.mk
1178
1179
1180 extra-objs += $(modules.so)
1181-install-others = $(addprefix $(inst_gconvdir)/, $(modules.so)) \
1182- $(inst_gconvdir)/gconv-modules
1183+install-others-y += $(addprefix $(inst_gconvdir)/, $(modules.so))
1184+install-others-$(OPTION_EGLIBC_CHARSETS) += $(inst_gconvdir)/gconv-modules
1185
1186 # We can build the conversion tables for numerous charsets automatically.
1187
1188@@ -201,7 +206,7 @@ before-compile += $(addprefix $(objpfx),$(generated-modules:=.h))
1189 ifndef avoid-generated
1190 $(objpfx)iconv-rules: Makefile
1191 $(make-target-directory)
1192- { echo $(filter-out lib%, $(modules)); \
1193+ { echo $(filter-out lib%, $(modules-y)); \
1194 echo 8bit $(gen-8bit-modules); \
1195 echo 8bit-gap $(gen-8bit-gap-modules); } | \
1196 LC_ALL=C \
1197@@ -245,7 +250,7 @@ $(addprefix $(inst_gconvdir)/, $(modules.so)): \
1198 $(do-install-program)
1199 $(inst_gconvdir)/gconv-modules: gconv-modules $(+force)
1200 $(do-install)
1201-ifeq (no,$(cross-compiling))
1202+# eglibc: ifeq (no,$(cross-compiling))
1203 # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary
1204 # if this libc has more gconv modules than the previously installed one.
1205 if test -f "$(inst_gconvdir)/gconv-modules.cache"; then \
1206@@ -254,9 +259,9 @@ ifeq (no,$(cross-compiling))
1207 $(common-objpfx)iconv/iconvconfig \
1208 $(addprefix --prefix=,$(install_root)); \
1209 fi
1210-else
1211- @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache'
1212-endif
1213+# eglibc: else
1214+# eglibc: @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache'
1215+# eglibc: endif
1216
1217 endif # build-shared = yes
1218
1219diff --git a/include/netdb.h b/include/netdb.h
1220index e1f051d..f6d15aa 100644
1221--- a/include/netdb.h
1222+++ b/include/netdb.h
1223@@ -232,6 +232,10 @@ extern enum nss_status _nss_ ## service ## _gethostbyname2_r \
1224 (const char *name, int af, struct hostent *host, \
1225 char *buffer, size_t buflen, int *errnop, \
1226 int *h_errnop); \
1227+extern enum nss_status _nss_ ## service ## _gethostbyname3_r \
1228+ (const char *name, int af, struct hostent *result, \
1229+ char *buffer, size_t buflen, int *errnop, \
1230+ int *h_errnop, int32_t *ttlp, char **canonp); \
1231 extern enum nss_status _nss_ ## service ## _gethostbyname_r \
1232 (const char *name, struct hostent *host, char *buffer, \
1233 size_t buflen, int *errnop, int *h_errnop); \
1234diff --git a/inet/Makefile b/inet/Makefile
1235index f1d871f..7cb1709 100644
1236--- a/inet/Makefile
1237+++ b/inet/Makefile
1238@@ -18,6 +18,8 @@
1239 #
1240 # Sub-makefile for inet portion of the library.
1241 #
1242+include ../option-groups.mak
1243+
1244 subdir := inet
1245
1246 include ../Makeconfig
1247@@ -27,7 +29,8 @@ headers := netinet/ether.h netinet/in.h netinet/in_systm.h \
1248 netinet/tcp.h netinet/ip.h $(wildcard arpa/*.h protocols/*.h) \
1249 aliases.h ifaddrs.h netinet/ip6.h netinet/icmp6.h bits/in.h
1250
1251-routines := htonl htons \
1252+routines-$(OPTION_EGLIBC_INET) \
1253+ += htonl htons \
1254 inet_lnaof inet_mkadr \
1255 inet_netof inet_ntoa inet_net herrno herrno-loc \
1256 gethstbyad gethstbyad_r gethstbynm gethstbynm2 gethstbynm2_r \
1257@@ -39,18 +42,23 @@ routines := htonl htons \
1258 getservent_r \
1259 ether_aton ether_aton_r ether_hton ether_line \
1260 ether_ntoa ether_ntoa_r ether_ntoh \
1261- rcmd rexec ruserpass \
1262 getnetgrent_r getnetgrent \
1263- getaliasent_r getaliasent getaliasname getaliasname_r \
1264- in6_addr getnameinfo if_index ifaddrs inet6_option \
1265+ in6_addr getnameinfo if_index ifaddrs \
1266 getipv4sourcefilter setipv4sourcefilter \
1267- getsourcefilter setsourcefilter inet6_opt inet6_rth
1268+ getsourcefilter setsourcefilter
1269+routines-$(OPTION_EGLIBC_RCMD) \
1270+ += rcmd rexec ruserpass
1271+routines-$(OPTION_EGLIBC_DB_ALIASES) \
1272+ += getaliasent_r getaliasent getaliasname getaliasname_r
1273+routines-$(OPTION_EGLIBC_ADVANCED_INET6) \
1274+ += inet6_option inet6_opt inet6_rth
1275
1276-aux := check_pf check_native ifreq
1277+aux-$(OPTION_EGLIBC_INET) += check_pf check_native ifreq
1278
1279 tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
1280- tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
1281+ tst-gethnm test-ifaddrs bug-if1 tst-ether_line \
1282 tst-getni1 tst-getni2 tst-inet6_rth tst-checks
1283+tests-$(OPTION_EGLIBC_ADVANCED_INET6) += test-inet6_opt
1284
1285 include ../Rules
1286
1287diff --git a/intl/Makefile b/intl/Makefile
1288index 9ecf8fe..587bc0d 100644
1289--- a/intl/Makefile
1290+++ b/intl/Makefile
1291@@ -16,6 +16,7 @@
1292 # <http://www.gnu.org/licenses/>.
1293
1294 # Makefile for intl subdirectory: message handling code from GNU gettext.
1295+include ../option-groups.mak
1296
1297 subdir = intl
1298
1299@@ -48,7 +49,7 @@ endif
1300 $(objpfx)plural.o: plural.c
1301
1302 ifeq ($(run-built-tests),yes)
1303-ifeq (yes,$(build-shared))
1304+ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared))
1305 ifneq ($(strip $(MSGFMT)),:)
1306 tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \
1307 $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \
1308diff --git a/intl/dcigettext.c b/intl/dcigettext.c
1309index 8a3f091..e271648 100644
1310--- a/intl/dcigettext.c
1311+++ b/intl/dcigettext.c
1312@@ -100,11 +100,15 @@ extern int errno;
1313 # include "libgnuintl.h"
1314 #endif
1315 #include "hash-string.h"
1316+#ifdef _LIBC
1317+# include <gnu/option-groups.h>
1318+#endif
1319
1320 /* Handle multi-threaded applications. */
1321 #ifdef _LIBC
1322 # include <bits/libc-lock.h>
1323 # define gl_rwlock_define_initialized __libc_rwlock_define_initialized
1324+# define gl_rwlock_define __libc_rwlock_define
1325 # define gl_rwlock_rdlock __libc_rwlock_rdlock
1326 # define gl_rwlock_wrlock __libc_rwlock_wrlock
1327 # define gl_rwlock_unlock __libc_rwlock_unlock
1328@@ -523,8 +527,10 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
1329 saved_errno = errno;
1330
1331 #ifdef _LIBC
1332- __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
1333- __libc_rwlock_rdlock (__libc_setlocale_lock);
1334+# if __OPTION_EGLIBC_LOCALE_CODE
1335+ gl_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
1336+ gl_rwlock_rdlock (__libc_setlocale_lock);
1337+# endif
1338 #endif
1339
1340 gl_rwlock_rdlock (_nl_state_lock);
1341@@ -550,7 +556,11 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
1342 #ifdef HAVE_PER_THREAD_LOCALE
1343 # ifndef IN_LIBGLOCALE
1344 # ifdef _LIBC
1345- localename = strdupa (__current_locale_name (category));
1346+# if __OPTION_EGLIBC_LOCALE_CODE
1347+ localename = strdupa (__current_locale_name (category));
1348+# else
1349+ localename = "C";
1350+# endif
1351 # else
1352 categoryname = category_to_name (category);
1353 # define CATEGORYNAME_INITIALIZED
1354@@ -581,10 +591,12 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
1355 else
1356 retval = (char *) (*foundp)->translation;
1357
1358- gl_rwlock_unlock (_nl_state_lock);
1359 # ifdef _LIBC
1360- __libc_rwlock_unlock (__libc_setlocale_lock);
1361+# if __OPTION_EGLIBC_LOCALE_CODE
1362+ gl_rwlock_unlock (__libc_setlocale_lock);
1363+# endif
1364 # endif
1365+ gl_rwlock_unlock (_nl_state_lock);
1366 __set_errno (saved_errno);
1367 return retval;
1368 }
1369@@ -838,10 +850,13 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
1370 if (plural)
1371 retval = plural_lookup (domain, n, retval, retlen);
1372
1373- gl_rwlock_unlock (_nl_state_lock);
1374 #ifdef _LIBC
1375- __libc_rwlock_unlock (__libc_setlocale_lock);
1376+# if __OPTION_EGLIBC_LOCALE_CODE
1377+
1378+ gl_rwlock_unlock (__libc_setlocale_lock);
1379+# endif
1380 #endif
1381+ gl_rwlock_unlock (_nl_state_lock);
1382 return retval;
1383 }
1384 }
1385@@ -850,10 +865,12 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
1386 return_untranslated:
1387 /* Return the untranslated MSGID. */
1388 FREE_BLOCKS (block_list);
1389- gl_rwlock_unlock (_nl_state_lock);
1390 #ifdef _LIBC
1391- __libc_rwlock_unlock (__libc_setlocale_lock);
1392+# if __OPTION_EGLIBC_LOCALE_CODE
1393+ gl_rwlock_unlock (__libc_setlocale_lock);
1394+# endif
1395 #endif
1396+ gl_rwlock_unlock (_nl_state_lock);
1397 #ifndef _LIBC
1398 if (!ENABLE_SECURE)
1399 {
1400@@ -1550,7 +1567,11 @@ guess_category_value (int category, const char *categoryname)
1401 `LC_xxx', and `LANG'. On some systems this can be done by the
1402 `setlocale' function itself. */
1403 # ifdef _LIBC
1404+# if __OPTION_EGLIBC_LOCALE_CODE
1405 locale = __current_locale_name (category);
1406+# else
1407+ locale = "C";
1408+# endif
1409 # else
1410 locale_defaulted = 0;
1411 # if HAVE_USELOCALE
1412diff --git a/io/Makefile b/io/Makefile
1413index 613dce0..697439e 100644
1414--- a/io/Makefile
1415+++ b/io/Makefile
1416@@ -18,6 +18,8 @@
1417 #
1418 # Sub-makefile for I/O portion of the library.
1419 #
1420+include ../option-groups.mak
1421+
1422 subdir := io
1423
1424 include ../Makeconfig
1425@@ -36,7 +38,7 @@ routines := \
1426 fxstatat fxstatat64 \
1427 statfs fstatfs statfs64 fstatfs64 \
1428 statvfs fstatvfs statvfs64 fstatvfs64 \
1429- umask chmod fchmod lchmod fchmodat \
1430+ umask chmod fchmod fchmodat \
1431 mkdir mkdirat \
1432 open open_2 open64 open64_2 openat openat_2 openat64 openat64_2 \
1433 read write lseek lseek64 access euidaccess faccessat \
1434@@ -49,11 +51,13 @@ routines := \
1435 ttyname ttyname_r isatty \
1436 link linkat symlink symlinkat readlink readlinkat \
1437 unlink unlinkat rmdir \
1438- ftw ftw64 fts poll ppoll \
1439+ poll ppoll \
1440 posix_fadvise posix_fadvise64 \
1441 posix_fallocate posix_fallocate64 \
1442 sendfile sendfile64 \
1443 utimensat futimens
1444+routines-$(OPTION_EGLIBC_BSD) += lchmod
1445+routines-$(OPTION_EGLIBC_FTRAVERSE) += ftw ftw64 fts
1446
1447 aux := have_o_cloexec
1448
1449@@ -64,18 +68,22 @@ static-only-routines = stat fstat lstat stat64 fstat64 lstat64 \
1450 fstatat fstatat64 mknod mknodat
1451
1452 others := pwd
1453-test-srcs := ftwtest
1454+test-srcs-$(OPTION_EGLIBC_FTRAVERSE) := ftwtest
1455 tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
1456- tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \
1457+ tst-fcntl tst-statvfs \
1458 tst-openat tst-unlinkat tst-fstatat tst-futimesat \
1459 tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
1460 tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
1461- tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
1462+ tst-mknodat tst-mkfifoat tst-ttyname_r \
1463 tst-posix_fallocate
1464+tests-$(OPTION_EGLIBC_FTRAVERSE) += bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 \
1465+ bug-ftw5
1466
1467 ifeq ($(run-built-tests),yes)
1468+ifeq (y,$(OPTION_EGLIBC_FTRAVERSE))
1469 tests-special += $(objpfx)ftwtest.out
1470 endif
1471+endif
1472
1473 include ../Rules
1474
1475diff --git a/libidn/Makefile b/libidn/Makefile
1476index 940fa52..43aad0c 100644
1477--- a/libidn/Makefile
1478+++ b/libidn/Makefile
1479@@ -16,6 +16,7 @@
1480 # <http://www.gnu.org/licenses/>.
1481
1482 # Makefile for libidn subdirectory of GNU C Library.
1483+include ../option-groups.mak
1484
1485 subdir := libidn
1486
1487@@ -23,8 +24,8 @@ include ../Makeconfig
1488
1489 routines = idn-stub
1490
1491-extra-libs = libcidn
1492-extra-libs-others = $(extra-libs)
1493+extra-libs-$(OPTION_EGLIBC_IDN) = libcidn
1494+extra-libs-others-y = $(extra-libs-y)
1495
1496 libcidn-routines := punycode toutf8 nfkc stringprep rfc3454 profiles idna \
1497 iconvme
1498diff --git a/libidn/toutf8.c b/libidn/toutf8.c
1499index c7e67ca..62df478 100644
1500--- a/libidn/toutf8.c
1501+++ b/libidn/toutf8.c
1502@@ -33,6 +33,11 @@
1503 /* Get strlen. */
1504 #include <string.h>
1505
1506+/* Get __OPTION_EGLIBC_LOCALE_CODE. */
1507+#ifdef _LIBC
1508+# include <gnu/option-groups.h>
1509+#endif
1510+
1511 /* Get iconv_string. */
1512 #include "iconvme.h"
1513
1514@@ -47,7 +52,11 @@
1515 #endif
1516
1517 #ifdef _LIBC
1518-# define stringprep_locale_charset() nl_langinfo (CODESET)
1519+# if __OPTION_EGLIBC_LOCALE_CODE
1520+# define stringprep_locale_charset() nl_langinfo (CODESET)
1521+# else
1522+# define stringprep_locale_charset() "ANSI_X3.4-1968"
1523+# endif
1524 #else
1525 /**
1526 * stringprep_locale_charset - return charset used in current locale
1527diff --git a/libio/Makefile b/libio/Makefile
1528index 7b3bcf9..27c9186 100644
1529--- a/libio/Makefile
1530+++ b/libio/Makefile
1531@@ -18,6 +18,8 @@
1532 #
1533 # Specific makefile for libio.
1534 #
1535+include ../option-groups.mak
1536+
1537 subdir := libio
1538
1539 include ../Makeconfig
1540@@ -27,16 +29,13 @@ headers := stdio.h libio.h _G_config.h bits/stdio.h bits/stdio-lock.h \
1541
1542 routines := \
1543 filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \
1544- iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc \
1545+ iofopncook iofputs iofread iofsetpos ioftell \
1546 iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs \
1547 ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc \
1548 iovsprintf iovsscanf \
1549 iofgetpos64 iofopen64 iofsetpos64 \
1550- fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
1551- iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u \
1552- putwchar putwchar_u putchar putchar_u fwprintf swprintf vwprintf \
1553- wprintf wscanf fwscanf vwscanf vswprintf iovswscanf swscanf wgenops \
1554- wstrops wfileops iofwide fwide wmemstream \
1555+ putchar putchar_u \
1556+ iofwide \
1557 \
1558 clearerr feof ferror fileno fputc freopen fseek getc getchar \
1559 memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \
1560@@ -48,24 +47,49 @@ routines := \
1561 \
1562 libc_fatal fmemopen oldfmemopen
1563
1564-tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
1565- tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
1566- tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf \
1567- tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof \
1568- tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \
1569+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \
1570+ wfiledoalloc \
1571+ iowpadn \
1572+ swprintf \
1573+ vswprintf iovswscanf swscanf wgenops \
1574+ wstrops wfileops wmemstream
1575+routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += \
1576+ wdummyfileops
1577+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += \
1578+ fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
1579+ iofputws iofputws_u iogetwline ioungetwc putwc putwc_u \
1580+ putwchar putwchar_u fwprintf vwprintf \
1581+ wprintf wscanf fwscanf vwscanf \
1582+ fwide
1583+
1584+tests = test-fmemopen tst-ext tst-ext2 \
1585+ tst-mmap-setvbuf tst-atime tst-eof \
1586+ tst-freopen bug-ungetc bug-fseek \
1587 tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \
1588- tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \
1589- bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \
1590+ tst-mmap2-eofsync tst-mmap-offend bug-fopena+ \
1591+ bug-ungetc2 bug-ungetc3 bug-ungetc4 \
1592 tst-memstream1 tst-memstream2 \
1593- tst-wmemstream1 tst-wmemstream2 \
1594- bug-memstream1 bug-wmemstream1 \
1595- tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
1596- tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
1597- tst-ftell-append tst-fputws
1598+ bug-memstream1 tst-popen1 tst-fwrite-error \
1599+ tst-ftell-active-handler tst-ftell-append
1600+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
1601+ += tst-swscanf tst-fgetws tst-setvbuf1 \
1602+ tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2 \
1603+ tst-widetext tst-fputws
1604+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
1605+ += bug-rewind bug-rewind2 bug-ungetwc1 \
1606+ bug-wfflush bug-wmemstream1 tst-fopenloc2 \
1607+ tst_getwc \
1608+ tst_putwc tst_wprintf tst_wprintf2 tst_wscanf \
1609+ tst-fgetwc bug-wsetpos tst-fseek tst-ftell-partial-wide
1610+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
1611+ += tst_swprintf tst_swscanf \
1612+ tst-sscanf \
1613+ tst-wmemstream1 tst-wmemstream2
1614+
1615 ifeq (yes,$(build-shared))
1616 # Add test-fopenloc only if shared library is enabled since it depends on
1617 # shared localedata objects.
1618-tests += tst-fopenloc
1619+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-fopenloc
1620 endif
1621 test-srcs = test-freopen
1622
1623@@ -164,13 +188,17 @@ shared-only-routines = oldiofopen oldiofdopen oldiofclose oldfileops \
1624 oldiofsetpos64
1625
1626 ifeq ($(run-built-tests),yes)
1627+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
1628 tests-special += $(objpfx)test-freopen.out
1629+endif
1630+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
1631 ifeq (yes,$(build-shared))
1632 # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
1633 # library is enabled since they depend on tst-fopenloc.out.
1634 tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
1635 endif
1636 endif
1637+endif
1638
1639 include ../Rules
1640
1641diff --git a/libio/__fpurge.c b/libio/__fpurge.c
1642index 065cf61..e32a3e9 100644
1643--- a/libio/__fpurge.c
1644+++ b/libio/__fpurge.c
1645@@ -21,7 +21,7 @@
1646 void
1647 __fpurge (FILE *fp)
1648 {
1649- if (fp->_mode > 0)
1650+ if (_IO_is_wide (fp))
1651 {
1652 /* Wide-char stream. */
1653 if (_IO_in_backup (fp))
1654diff --git a/libio/fileops.c b/libio/fileops.c
1655index cbcd6f5..19e43c2 100644
1656--- a/libio/fileops.c
1657+++ b/libio/fileops.c
1658@@ -39,6 +39,7 @@
1659 #include <string.h>
1660 #include <errno.h>
1661 #include <unistd.h>
1662+#include <gnu/option-groups.h>
1663 #include <stdlib.h>
1664 #if _LIBC
1665 # include "../wcsmbs/wcsmbsload.h"
1666@@ -173,7 +174,7 @@ _IO_new_file_close_it (_IO_FILE *fp)
1667
1668 /* Free buffer. */
1669 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
1670- if (fp->_mode > 0)
1671+ if (_IO_is_wide (fp))
1672 {
1673 if (_IO_have_wbackup (fp))
1674 _IO_free_wbackup_area (fp);
1675@@ -348,6 +349,7 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode,
1676 cs = strstr (last_recognized + 1, ",ccs=");
1677 if (cs != NULL)
1678 {
1679+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
1680 /* Yep. Load the appropriate conversions and set the orientation
1681 to wide. */
1682 struct gconv_fcts fcts;
1683@@ -418,6 +420,12 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode,
1684
1685 /* Set the mode now. */
1686 result->_mode = 1;
1687+#else
1688+ /* Treat this as if we couldn't find the given character set. */
1689+ (void) _IO_file_close_it (fp);
1690+ __set_errno (EINVAL);
1691+ return NULL;
1692+#endif
1693 }
1694 }
1695
1696diff --git a/libio/iofwide.c b/libio/iofwide.c
1697index 0c175d1..3e9f52b 100644
1698--- a/libio/iofwide.c
1699+++ b/libio/iofwide.c
1700@@ -26,6 +26,7 @@
1701
1702 #include <libioP.h>
1703 #ifdef _LIBC
1704+# include <gnu/option-groups.h>
1705 # include <dlfcn.h>
1706 # include <wchar.h>
1707 #endif
1708@@ -43,6 +44,8 @@
1709 #endif
1710
1711
1712+#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR
1713+
1714 /* Prototypes of libio's codecvt functions. */
1715 static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
1716 __mbstate_t *statep,
1717@@ -499,3 +502,26 @@ do_max_length (struct _IO_codecvt *codecvt)
1718 return MB_CUR_MAX;
1719 #endif
1720 }
1721+
1722+#else
1723+/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled. */
1724+
1725+#undef _IO_fwide
1726+int
1727+_IO_fwide (fp, mode)
1728+ _IO_FILE *fp;
1729+ int mode;
1730+{
1731+ /* Die helpfully if the user tries to create a wide stream; I
1732+ disbelieve that most users check the return value from
1733+ 'fwide (fp, 1)'. */
1734+ assert (mode <= 0);
1735+
1736+ /* We can only make streams byte-oriented, which is trivial. */
1737+ if (mode < 0)
1738+ fp->_mode = -1;
1739+
1740+ return fp->_mode;
1741+}
1742+
1743+#endif
1744diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c
1745index 11765cf..15d6230 100644
1746--- a/libio/ioseekoff.c
1747+++ b/libio/ioseekoff.c
1748@@ -60,7 +60,7 @@ _IO_seekoff_unlocked (fp, offset, dir, mode)
1749 else
1750 abort ();
1751 }
1752- if (_IO_fwide (fp, 0) < 0)
1753+ if (! _IO_is_wide (fp))
1754 _IO_free_backup_area (fp);
1755 else
1756 _IO_free_wbackup_area (fp);
1757diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c
1758index a7652a1..6938b68 100644
1759--- a/libio/ioseekpos.c
1760+++ b/libio/ioseekpos.c
1761@@ -35,7 +35,7 @@ _IO_seekpos_unlocked (fp, pos, mode)
1762 /* If we have a backup buffer, get rid of it, since the __seekoff
1763 callback may not know to do the right thing about it.
1764 This may be over-kill, but it'll do for now. TODO */
1765- if (_IO_fwide (fp, 0) <= 0)
1766+ if (! _IO_is_wide (fp))
1767 {
1768 if (_IO_have_backup (fp))
1769 _IO_free_backup_area (fp);
1770diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c
1771index 0a41c10..3d99fa0 100644
1772--- a/libio/iosetbuffer.c
1773+++ b/libio/iosetbuffer.c
1774@@ -24,6 +24,8 @@
1775 This exception applies to code released by its copyright holders
1776 in files containing the exception. */
1777
1778+#include <gnu/option-groups.h>
1779+
1780 #include "libioP.h"
1781
1782 void
1783@@ -38,9 +40,11 @@ _IO_setbuffer (fp, buf, size)
1784 if (!buf)
1785 size = 0;
1786 (void) _IO_SETBUF (fp, buf, size);
1787+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
1788 if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp))
1789 /* We also have to set the buffer using the wide char function. */
1790 (void) _IO_WSETBUF (fp, buf, size);
1791+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
1792 _IO_release_lock (fp);
1793 }
1794 libc_hidden_def (_IO_setbuffer)
1795diff --git a/libio/libioP.h b/libio/libioP.h
1796index 0f16e2d..d2626d6 100644
1797--- a/libio/libioP.h
1798+++ b/libio/libioP.h
1799@@ -44,6 +44,10 @@
1800 /*# include <comthread.h>*/
1801 #endif
1802
1803+#if defined _LIBC
1804+# include <gnu/option-groups.h>
1805+#endif
1806+
1807 #include <math_ldbl_opt.h>
1808
1809 #include "iolibio.h"
1810@@ -523,8 +527,20 @@ extern void _IO_old_init (_IO_FILE *fp, int flags) __THROW;
1811
1812
1813 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
1814+
1815+/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0',
1816+ except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it
1817+ expands to a constant, allowing the compiler to realize that it can
1818+ eliminate code that references wide stream handling functions.
1819+ This, in turn, allows us to omit them. */
1820+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
1821+# define _IO_is_wide(_f) ((_f)->_mode > 0)
1822+#else
1823+# define _IO_is_wide(_f) (0)
1824+#endif
1825+
1826 # define _IO_do_flush(_f) \
1827- ((_f)->_mode <= 0 \
1828+ (! _IO_is_wide (_f) \
1829 ? _IO_do_write(_f, (_f)->_IO_write_base, \
1830 (_f)->_IO_write_ptr-(_f)->_IO_write_base) \
1831 : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base, \
1832diff --git a/libio/wdummyfileops.c b/libio/wdummyfileops.c
1833new file mode 100644
1834index 0000000..c0150b8
1835--- /dev/null
1836+++ b/libio/wdummyfileops.c
1837@@ -0,0 +1,161 @@
1838+/* Copyright (C) 2007 Free Software Foundation, Inc.
1839+ This file is part of the GNU C Library.
1840+
1841+ The GNU C Library is free software; you can redistribute it and/or
1842+ modify it under the terms of the GNU Lesser General Public
1843+ License as published by the Free Software Foundation; either
1844+ version 2.1 of the License, or (at your option) any later version.
1845+
1846+ The GNU C Library is distributed in the hope that it will be useful,
1847+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1848+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1849+ Lesser General Public License for more details.
1850+
1851+ You should have received a copy of the GNU Lesser General Public
1852+ License along with the GNU C Library; if not, write to the Free
1853+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1854+ 02111-1307 USA.
1855+
1856+ As a special exception, if you link the code in this file with
1857+ files compiled with a GNU compiler to produce an executable,
1858+ that does not cause the resulting executable to be covered by
1859+ the GNU Lesser General Public License. This exception does not
1860+ however invalidate any other reasons why the executable file
1861+ might be covered by the GNU Lesser General Public License.
1862+ This exception applies to code released by its copyright holders
1863+ in files containing the exception. */
1864+
1865+#include <assert.h>
1866+#include <stdio.h>
1867+#include <stdlib.h>
1868+#include <libioP.h>
1869+
1870+static void __THROW __attribute__ ((__noreturn__))
1871+_IO_wfile_wide_char_support_disabled (void)
1872+{
1873+ static const char errstr[]
1874+ = ("The application tried to use wide character I/O, but libc.so"
1875+ " was compiled\n"
1876+ "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n");
1877+ __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);
1878+ abort ();
1879+}
1880+
1881+static void
1882+_IO_wfile_disabled_void_int (_IO_FILE *fp, int x)
1883+{
1884+ _IO_wfile_wide_char_support_disabled ();
1885+}
1886+
1887+static int
1888+_IO_wfile_disabled_int_int (_IO_FILE *fp, int x)
1889+{
1890+ _IO_wfile_wide_char_support_disabled ();
1891+}
1892+
1893+static int
1894+_IO_wfile_disabled_int_none (_IO_FILE *fp)
1895+{
1896+ _IO_wfile_wide_char_support_disabled ();
1897+}
1898+
1899+static _IO_size_t
1900+_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
1901+{
1902+ _IO_wfile_wide_char_support_disabled ();
1903+}
1904+
1905+static _IO_size_t
1906+_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n)
1907+{
1908+ _IO_wfile_wide_char_support_disabled ();
1909+}
1910+
1911+static _IO_off64_t
1912+_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode)
1913+{
1914+ _IO_wfile_wide_char_support_disabled ();
1915+}
1916+
1917+static _IO_off64_t
1918+_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags)
1919+{
1920+ _IO_wfile_wide_char_support_disabled ();
1921+}
1922+
1923+static _IO_FILE *
1924+_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length)
1925+{
1926+ _IO_wfile_wide_char_support_disabled ();
1927+}
1928+
1929+static _IO_ssize_t
1930+_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length)
1931+{
1932+ _IO_wfile_wide_char_support_disabled ();
1933+}
1934+
1935+static _IO_ssize_t
1936+_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length)
1937+{
1938+ _IO_wfile_wide_char_support_disabled ();
1939+}
1940+
1941+static _IO_off64_t
1942+_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode)
1943+{
1944+ _IO_wfile_wide_char_support_disabled ();
1945+}
1946+
1947+static int
1948+_IO_wfile_disabled_close (_IO_FILE *fp)
1949+{
1950+ _IO_wfile_wide_char_support_disabled ();
1951+}
1952+
1953+static int
1954+_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf)
1955+{
1956+ _IO_wfile_wide_char_support_disabled ();
1957+}
1958+
1959+static int
1960+_IO_wfile_disabled_showmanyc (_IO_FILE *fp)
1961+{
1962+ _IO_wfile_wide_char_support_disabled ();
1963+}
1964+
1965+static void
1966+_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale)
1967+{
1968+ _IO_wfile_wide_char_support_disabled ();
1969+}
1970+
1971+static const struct _IO_jump_t _IO_wfile_jumps_disabled =
1972+{
1973+ JUMP_INIT_DUMMY,
1974+ JUMP_INIT(finish, _IO_wfile_disabled_void_int),
1975+ JUMP_INIT(overflow, _IO_wfile_disabled_int_int),
1976+ JUMP_INIT(underflow, _IO_wfile_disabled_int_none),
1977+ JUMP_INIT(uflow, _IO_wfile_disabled_int_none),
1978+ JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int),
1979+ JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn),
1980+ JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn),
1981+ JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff),
1982+ JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos),
1983+ JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf),
1984+ JUMP_INIT(sync, _IO_wfile_disabled_int_none),
1985+ JUMP_INIT(doallocate, _IO_wfile_disabled_int_none),
1986+ JUMP_INIT(read, _IO_wfile_disabled_read),
1987+ JUMP_INIT(write, _IO_wfile_disabled_write),
1988+ JUMP_INIT(seek, _IO_wfile_disabled_seek),
1989+ JUMP_INIT(close, _IO_wfile_disabled_close),
1990+ JUMP_INIT(stat, _IO_wfile_disabled_stat),
1991+ JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc),
1992+ JUMP_INIT(imbue, _IO_wfile_disabled_imbue)
1993+};
1994+
1995+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps)
1996+libc_hidden_data_def (_IO_wfile_jumps)
1997+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap)
1998+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap)
1999diff --git a/locale/C-ctype.c b/locale/C-ctype.c
2000index aa5f19f..06be081 100644
2001--- a/locale/C-ctype.c
2002+++ b/locale/C-ctype.c
2003@@ -19,8 +19,11 @@
2004 #include "localeinfo.h"
2005 #include <endian.h>
2006 #include <stdint.h>
2007+#include <gnu/option-groups.h>
2008
2009+#if __OPTION_EGLIBC_LOCALE_CODE
2010 #include "C-translit.h"
2011+#endif
2012
2013 /* This table's entries are taken from POSIX.2 Table 2-6
2014 ``LC_CTYPE Category Definition in the POSIX Locale''.
2015@@ -634,6 +637,7 @@ const struct __locale_data _nl_C_LC_CTYPE attribute_hidden =
2016 { .word = L'7' },
2017 { .word = L'8' },
2018 { .word = L'9' },
2019+#if __OPTION_EGLIBC_LOCALE_CODE
2020 /* _NL_CTYPE_TRANSLIT_TAB_SIZE */
2021 { .word = NTRANSLIT },
2022 /* _NL_CTYPE_TRANSLIT_FROM_IDX */
2023@@ -644,6 +648,22 @@ const struct __locale_data _nl_C_LC_CTYPE attribute_hidden =
2024 { .wstr = translit_to_idx },
2025 /* _NL_CTYPE_TRANSLIT_TO_TBL */
2026 { .wstr = (uint32_t *) translit_to_tbl },
2027+#else
2028+ /* If the locale code isn't enabled, we don't have the
2029+ transliteration code in iconv/gconv_trans.c anyway, so there's
2030+ no need for the transliteration tables here. We'll fall back
2031+ on the default missing replacement, '?'. */
2032+ /* _NL_CTYPE_TRANSLIT_TAB_SIZE */
2033+ { .word = 0 },
2034+ /* _NL_CTYPE_TRANSLIT_FROM_IDX */
2035+ { .wstr = NULL },
2036+ /* _NL_CTYPE_TRANSLIT_FROM_TBL */
2037+ { .wstr = NULL },
2038+ /* _NL_CTYPE_TRANSLIT_TO_IDX */
2039+ { .wstr = NULL },
2040+ /* _NL_CTYPE_TRANSLIT_TO_TBL */
2041+ { .wstr = NULL },
2042+#endif
2043 /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN */
2044 { .word = 1 },
2045 /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING */
2046diff --git a/locale/Makefile b/locale/Makefile
2047index f1b4343..599a1a9 100644
2048--- a/locale/Makefile
2049+++ b/locale/Makefile
2050@@ -18,27 +18,43 @@
2051 #
2052 # Makefile for locales.
2053 #
2054+include ../option-groups.mak
2055+
2056 subdir := locale
2057
2058 include ../Makeconfig
2059
2060 headers = locale.h bits/locale.h langinfo.h xlocale.h
2061-routines = setlocale findlocale loadlocale loadarchive \
2062- localeconv nl_langinfo nl_langinfo_l mb_cur_max \
2063- newlocale duplocale freelocale uselocale
2064-tests = tst-C-locale tst-locname tst-duplocale
2065+# catnames is needed by OPTION_EGLIBC_LOCALE_CODE and by the 'intl' code.
2066+# If we put the latter in an option group, too, we can omit catnames
2067+# when both option groups are disabled. libstdc++-v3 needs mb_cur_max.
2068+routines-y := catnames mb_cur_max
2069+routines-$(OPTION_EGLIBC_LOCALE_CODE) \
2070+ += setlocale findlocale loadlocale loadarchive \
2071+ localeconv nl_langinfo nl_langinfo_l \
2072+ newlocale duplocale freelocale uselocale
2073+ifneq (y,$(OPTION_EGLIBC_LOCALE_CODE))
2074+routines-y += dummy-setlocale
2075+endif
2076+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-C-locale tst-locname tst-duplocale
2077 categories = ctype messages monetary numeric time paper name \
2078 address telephone measurement identification collate
2079-aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \
2080- xlocale localename global-locale coll-lookup
2081-others = localedef locale
2082+# C-messages belongs in an intl option group.
2083+aux-y := C-ctype C-time \
2084+ SYS_libc C_name xlocale global-locale coll-lookup
2085+aux-$(OPTION_EGLIBC_LOCALE_CODE) \
2086+ += $(filter-out $(aux-y), \
2087+ $(categories:%=lc-%) $(categories:%=C-%)) \
2088+ localename
2089+others-$(OPTION_EGLIBC_LOCALE_CODE) = localedef locale
2090 #others-static = localedef locale
2091-install-bin = localedef locale
2092-extra-objs = $(localedef-modules:=.o) $(localedef-aux:=.o) \
2093+install-bin = $(others-y)
2094+extra-objs-$(OPTION_EGLIBC_LOCALE_CODE) \
2095+ = $(localedef-modules:=.o) $(localedef-aux:=.o) \
2096 $(locale-modules:=.o) $(lib-modules:=.o)
2097
2098-extra-libs = libBrokenLocale
2099-extra-libs-others = $(extra-libs)
2100+extra-libs-$(OPTION_EGLIBC_LOCALE_CODE) = libBrokenLocale
2101+extra-libs-others = $(extra-libs-y)
2102
2103 libBrokenLocale-routines = broken_cur_max
2104
2105@@ -93,6 +109,9 @@ CPPFLAGS-locale-programs = -DLOCALE_PATH='$(localepath)' \
2106 CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts
2107 CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts
2108 CFLAGS-charmap-dir.c = -Wno-write-strings
2109+ifneq (y,$(OPTION_EGLIBC_SPAWN))
2110+CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS
2111+endif
2112
2113 # Set libof-* for each routine.
2114 cpp-srcs-left := $(localedef-modules) $(localedef-aux) $(locale-modules) \
2115diff --git a/locale/catnames.c b/locale/catnames.c
2116new file mode 100644
2117index 0000000..9fad357
2118--- /dev/null
2119+++ b/locale/catnames.c
2120@@ -0,0 +1,48 @@
2121+/* Copyright (C) 2006 Free Software Foundation, Inc.
2122+ This file is part of the GNU C Library.
2123+
2124+ The GNU C Library is free software; you can redistribute it and/or
2125+ modify it under the terms of the GNU Lesser General Public
2126+ License as published by the Free Software Foundation; either
2127+ version 2.1 of the License, or (at your option) any later version.
2128+
2129+ The GNU C Library is distributed in the hope that it will be useful,
2130+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2131+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2132+ Lesser General Public License for more details.
2133+
2134+ You should have received a copy of the GNU Lesser General Public
2135+ License along with the GNU C Library; if not, write to the Free
2136+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2137+ 02111-1307 USA. */
2138+
2139+#include "localeinfo.h"
2140+
2141+/* Define an array of category names (also the environment variable names). */
2142+const union catnamestr_t _nl_category_names attribute_hidden =
2143+ {
2144+ {
2145+#define DEFINE_CATEGORY(category, category_name, items, a) \
2146+ category_name,
2147+#include "categories.def"
2148+#undef DEFINE_CATEGORY
2149+ }
2150+ };
2151+
2152+const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
2153+ {
2154+#define DEFINE_CATEGORY(category, category_name, items, a) \
2155+ [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)),
2156+#include "categories.def"
2157+#undef DEFINE_CATEGORY
2158+ };
2159+
2160+/* An array of their lengths, for convenience. */
2161+const uint8_t _nl_category_name_sizes[] attribute_hidden =
2162+ {
2163+#define DEFINE_CATEGORY(category, category_name, items, a) \
2164+ [category] = sizeof (category_name) - 1,
2165+#include "categories.def"
2166+#undef DEFINE_CATEGORY
2167+ [LC_ALL] = sizeof ("LC_ALL") - 1
2168+ };
2169diff --git a/locale/dummy-setlocale.c b/locale/dummy-setlocale.c
2170new file mode 100644
2171index 0000000..219964a
2172--- /dev/null
2173+++ b/locale/dummy-setlocale.c
2174@@ -0,0 +1,33 @@
2175+/* Copyright (C) 2006 Free Software Foundation, Inc.
2176+ This file is part of the GNU C Library.
2177+
2178+ The GNU C Library is free software; you can redistribute it and/or
2179+ modify it under the terms of the GNU Lesser General Public
2180+ License as published by the Free Software Foundation; either
2181+ version 2.1 of the License, or (at your option) any later version.
2182+
2183+ The GNU C Library is distributed in the hope that it will be useful,
2184+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2185+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2186+ Lesser General Public License for more details.
2187+
2188+ You should have received a copy of the GNU Lesser General Public
2189+ License along with the GNU C Library; if not, write to the Free
2190+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2191+ 02111-1307 USA. */
2192+
2193+#include <string.h>
2194+#include <locale.h>
2195+
2196+char *
2197+setlocale (int category, const char *locale)
2198+{
2199+ if (! locale
2200+ || locale[0] == '\0'
2201+ || strcmp (locale, "C") == 0
2202+ || strcmp (locale, "POSIX") == 0)
2203+ return (char *) "C";
2204+ else
2205+ return NULL;
2206+}
2207+libc_hidden_def (setlocale)
2208diff --git a/locale/localeinfo.h b/locale/localeinfo.h
2209index bdab9fe..a7516c0 100644
2210--- a/locale/localeinfo.h
2211+++ b/locale/localeinfo.h
2212@@ -232,7 +232,7 @@ __libc_tsd_define (extern, __locale_t, LOCALE)
2213 unused. We can manage this playing some tricks with weak references.
2214 But with thread-local locale settings, it becomes quite ungainly unless
2215 we can use __thread variables. So only in that case do we attempt this. */
2216-#ifndef SHARED
2217+#if !defined SHARED && !defined IN_GLIBC_LOCALEDEF
2218 # include <tls.h>
2219 # define NL_CURRENT_INDIRECT 1
2220 #endif
2221diff --git a/locale/programs/charmap-dir.c b/locale/programs/charmap-dir.c
2222index cf7adea..ef3b811 100644
2223--- a/locale/programs/charmap-dir.c
2224+++ b/locale/programs/charmap-dir.c
2225@@ -19,7 +19,9 @@
2226 #include <error.h>
2227 #include <fcntl.h>
2228 #include <libintl.h>
2229+#ifndef NO_UNCOMPRESS
2230 #include <spawn.h>
2231+#endif
2232 #include <stdio.h>
2233 #include <stdlib.h>
2234 #include <string.h>
2235@@ -156,6 +158,7 @@ charmap_closedir (CHARMAP_DIR *cdir)
2236 return closedir (dir);
2237 }
2238
2239+#ifndef NO_UNCOMPRESS
2240 /* Creates a subprocess decompressing the given pathname, and returns
2241 a stream reading its output (the decompressed data). */
2242 static
2243@@ -204,6 +207,7 @@ fopen_uncompressed (const char *pathname, const char *compressor)
2244 }
2245 return NULL;
2246 }
2247+#endif
2248
2249 /* Opens a charmap for reading, given its name (not an alias name). */
2250 FILE *
2251@@ -226,6 +230,7 @@ charmap_open (const char *directory, const char *name)
2252 if (stream != NULL)
2253 return stream;
2254
2255+#ifndef NO_UNCOMPRESS
2256 memcpy (p, ".gz", 4);
2257 stream = fopen_uncompressed (pathname, "gzip");
2258 if (stream != NULL)
2259@@ -235,6 +240,7 @@ charmap_open (const char *directory, const char *name)
2260 stream = fopen_uncompressed (pathname, "bzip2");
2261 if (stream != NULL)
2262 return stream;
2263+#endif
2264
2265 return NULL;
2266 }
2267diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
2268index a39a94f..16e9039 100644
2269--- a/locale/programs/ld-collate.c
2270+++ b/locale/programs/ld-collate.c
2271@@ -351,7 +351,7 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen,
2272 }
2273 if (wcs != NULL)
2274 {
2275- size_t nwcs = wcslen ((wchar_t *) wcs);
2276+ size_t nwcs = wcslen_uint32 (wcs);
2277 uint32_t zero = 0;
2278 /* Handle <U0000> as a single character. */
2279 if (nwcs == 0)
2280@@ -1777,8 +1777,7 @@ symbol `%s' has the same encoding as"), (*eptr)->name);
2281
2282 if ((*eptr)->nwcs == runp->nwcs)
2283 {
2284- int c = wmemcmp ((wchar_t *) (*eptr)->wcs,
2285- (wchar_t *) runp->wcs, runp->nwcs);
2286+ int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs);
2287
2288 if (c == 0)
2289 {
2290@@ -2011,9 +2010,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
2291 one consecutive entry. */
2292 if (runp->wcnext != NULL
2293 && runp->nwcs == runp->wcnext->nwcs
2294- && wmemcmp ((wchar_t *) runp->wcs,
2295- (wchar_t *)runp->wcnext->wcs,
2296- runp->nwcs - 1) == 0
2297+ && wmemcmp_uint32 (runp->wcs,
2298+ runp->wcnext->wcs,
2299+ runp->nwcs - 1) == 0
2300 && (runp->wcs[runp->nwcs - 1]
2301 == runp->wcnext->wcs[runp->nwcs - 1] + 1))
2302 {
2303@@ -2037,9 +2036,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
2304 runp = runp->wcnext;
2305 while (runp->wcnext != NULL
2306 && runp->nwcs == runp->wcnext->nwcs
2307- && wmemcmp ((wchar_t *) runp->wcs,
2308- (wchar_t *)runp->wcnext->wcs,
2309- runp->nwcs - 1) == 0
2310+ && wmemcmp_uint32 (runp->wcs,
2311+ runp->wcnext->wcs,
2312+ runp->nwcs - 1) == 0
2313 && (runp->wcs[runp->nwcs - 1]
2314 == runp->wcnext->wcs[runp->nwcs - 1] + 1));
2315
2316diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
2317index 3f464ef..b7b6b51 100644
2318--- a/locale/programs/ld-ctype.c
2319+++ b/locale/programs/ld-ctype.c
2320@@ -926,7 +926,7 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
2321 allocate_arrays (ctype, charmap, ctype->repertoire);
2322
2323 default_missing_len = (ctype->default_missing
2324- ? wcslen ((wchar_t *) ctype->default_missing)
2325+ ? wcslen_uint32 (ctype->default_missing)
2326 : 0);
2327
2328 init_locale_data (&file, nelems);
2329@@ -1937,7 +1937,7 @@ read_translit_entry (struct linereader *ldfile, struct locale_ctype_t *ctype,
2330 ignore = 1;
2331 else
2332 /* This value is usable. */
2333- obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4);
2334+ obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4);
2335
2336 first = 0;
2337 }
2338@@ -2471,8 +2471,8 @@ with character code range values one must use the absolute ellipsis `...'"));
2339 }
2340
2341 handle_tok_digit:
2342- class_bit = _ISwdigit;
2343- class256_bit = _ISdigit;
2344+ class_bit = BITw (tok_digit);
2345+ class256_bit = BIT (tok_digit);
2346 handle_digits = 1;
2347 goto read_charclass;
2348
2349@@ -3929,8 +3929,7 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
2350
2351 while (idx < number)
2352 {
2353- int res = wcscmp ((const wchar_t *) sorted[idx]->from,
2354- (const wchar_t *) runp->from);
2355+ int res = wcscmp_uint32 (sorted[idx]->from, runp->from);
2356 if (res == 0)
2357 {
2358 replace = 1;
2359@@ -3967,11 +3966,11 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
2360 for (size_t cnt = 0; cnt < number; ++cnt)
2361 {
2362 struct translit_to_t *srunp;
2363- from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
2364+ from_len += wcslen_uint32 (sorted[cnt]->from) + 1;
2365 srunp = sorted[cnt]->to;
2366 while (srunp != NULL)
2367 {
2368- to_len += wcslen ((const wchar_t *) srunp->str) + 1;
2369+ to_len += wcslen_uint32 (srunp->str) + 1;
2370 srunp = srunp->next;
2371 }
2372 /* Plus one for the extra NUL character marking the end of
2373@@ -3995,18 +3994,18 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
2374 ctype->translit_from_idx[cnt] = from_len;
2375 ctype->translit_to_idx[cnt] = to_len;
2376
2377- len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
2378- wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len],
2379- (const wchar_t *) sorted[cnt]->from, len);
2380+ len = wcslen_uint32 (sorted[cnt]->from) + 1;
2381+ wmemcpy_uint32 (&ctype->translit_from_tbl[from_len],
2382+ sorted[cnt]->from, len);
2383 from_len += len;
2384
2385 ctype->translit_to_idx[cnt] = to_len;
2386 srunp = sorted[cnt]->to;
2387 while (srunp != NULL)
2388 {
2389- len = wcslen ((const wchar_t *) srunp->str) + 1;
2390- wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len],
2391- (const wchar_t *) srunp->str, len);
2392+ len = wcslen_uint32 (srunp->str) + 1;
2393+ wmemcpy_uint32 (&ctype->translit_to_tbl[to_len],
2394+ srunp->str, len);
2395 to_len += len;
2396 srunp = srunp->next;
2397 }
2398diff --git a/locale/programs/ld-messages.c b/locale/programs/ld-messages.c
2399index ec1a80b..736eed8 100644
2400--- a/locale/programs/ld-messages.c
2401+++ b/locale/programs/ld-messages.c
2402@@ -25,6 +25,7 @@
2403 #include <string.h>
2404 #include <stdint.h>
2405 #include <sys/uio.h>
2406+#include <gnu/option-groups.h>
2407
2408 #include <assert.h>
2409
2410@@ -124,6 +125,7 @@ No definition for %s category found"), "LC_MESSAGES"));
2411 }
2412 else
2413 {
2414+#if __OPTION_POSIX_REGEXP
2415 int result;
2416 regex_t re;
2417
2418@@ -140,6 +142,7 @@ No definition for %s category found"), "LC_MESSAGES"));
2419 }
2420 else if (result != 0)
2421 regfree (&re);
2422+#endif
2423 }
2424
2425 if (messages->noexpr == NULL)
2426@@ -158,6 +161,7 @@ No definition for %s category found"), "LC_MESSAGES"));
2427 }
2428 else
2429 {
2430+#if __OPTION_POSIX_REGEXP
2431 int result;
2432 regex_t re;
2433
2434@@ -174,6 +178,7 @@ No definition for %s category found"), "LC_MESSAGES"));
2435 }
2436 else if (result != 0)
2437 regfree (&re);
2438+#endif
2439 }
2440 }
2441
2442diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c
2443index db490c6..75dc505 100644
2444--- a/locale/programs/ld-time.c
2445+++ b/locale/programs/ld-time.c
2446@@ -215,8 +215,10 @@ No definition for %s category found"), "LC_TIME"));
2447 }
2448 else
2449 {
2450+ static const uint32_t wt_fmt_ampm[]
2451+ = { '%','I',':','%','M',':','%','S',' ','%','p',0 };
2452 time->t_fmt_ampm = "%I:%M:%S %p";
2453- time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p";
2454+ time->wt_fmt_ampm = wt_fmt_ampm;
2455 }
2456 }
2457
2458@@ -226,7 +228,7 @@ No definition for %s category found"), "LC_TIME"));
2459 const int days_per_month[12] = { 31, 29, 31, 30, 31, 30,
2460 31, 31, 30, 31 ,30, 31 };
2461 size_t idx;
2462- wchar_t *wstr;
2463+ uint32_t *wstr;
2464
2465 time->era_entries =
2466 (struct era_data *) xmalloc (time->num_era
2467@@ -464,18 +466,18 @@ No definition for %s category found"), "LC_TIME"));
2468 }
2469
2470 /* Now generate the wide character name and format. */
2471- wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */
2472- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end offset */
2473- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end start */
2474- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end end */
2475+ wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */
2476+ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */
2477+ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */
2478+ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */
2479 if (wstr != NULL)
2480 {
2481- time->era_entries[idx].wname = (uint32_t *) wstr + 1;
2482- wstr = wcschr (wstr + 1, L':'); /* end name */
2483+ time->era_entries[idx].wname = wstr + 1;
2484+ wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */
2485 if (wstr != NULL)
2486 {
2487 *wstr = L'\0';
2488- time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
2489+ time->era_entries[idx].wformat = wstr + 1;
2490 }
2491 else
2492 time->era_entries[idx].wname =
2493@@ -530,7 +532,16 @@ No definition for %s category found"), "LC_TIME"));
2494 if (time->date_fmt == NULL)
2495 time->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
2496 if (time->wdate_fmt == NULL)
2497- time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y";
2498+ {
2499+ static const uint32_t wdate_fmt[] =
2500+ { '%','a',' ',
2501+ '%','b',' ',
2502+ '%','e',' ',
2503+ '%','H',':','%','M',':','%','S',' ',
2504+ '%','Z',' ',
2505+ '%','Y',0 };
2506+ time->wdate_fmt = wdate_fmt;
2507+ }
2508 }
2509
2510
2511diff --git a/locale/programs/linereader.c b/locale/programs/linereader.c
2512index 2e05130..653b68c 100644
2513--- a/locale/programs/linereader.c
2514+++ b/locale/programs/linereader.c
2515@@ -595,7 +595,7 @@ get_string (struct linereader *lr, const struct charmap_t *charmap,
2516 {
2517 int return_widestr = lr->return_widestr;
2518 char *buf;
2519- wchar_t *buf2 = NULL;
2520+ uint32_t *buf2 = NULL;
2521 size_t bufact;
2522 size_t bufmax = 56;
2523
2524diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
2525index 2a0f2aa..583d233 100644
2526--- a/locale/programs/localedef.c
2527+++ b/locale/programs/localedef.c
2528@@ -114,6 +114,7 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
2529 #define OPT_LIST_ARCHIVE 309
2530 #define OPT_LITTLE_ENDIAN 400
2531 #define OPT_BIG_ENDIAN 401
2532+#define OPT_UINT32_ALIGN 402
2533
2534 /* Definitions of arguments for argp functions. */
2535 static const struct argp_option options[] =
2536@@ -150,6 +151,8 @@ static const struct argp_option options[] =
2537 N_("Generate little-endian output") },
2538 { "big-endian", OPT_BIG_ENDIAN, NULL, 0,
2539 N_("Generate big-endian output") },
2540+ { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0,
2541+ N_("Set the target's uint32_t alignment in bytes (default 4)") },
2542 { NULL, 0, NULL, 0, NULL }
2543 };
2544
2545@@ -239,12 +242,14 @@ main (int argc, char *argv[])
2546 ctype locale. (P1003.2 4.35.5.2) */
2547 setlocale (LC_CTYPE, "POSIX");
2548
2549+#ifndef NO_SYSCONF
2550 /* Look whether the system really allows locale definitions. POSIX
2551 defines error code 3 for this situation so I think it must be
2552 a fatal error (see P1003.2 4.35.8). */
2553 if (sysconf (_SC_2_LOCALEDEF) < 0)
2554 WITH_CUR_LOCALE (error (3, 0, _("\
2555 FATAL: system does not define `_POSIX2_LOCALEDEF'")));
2556+#endif
2557
2558 /* Process charmap file. */
2559 charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1);
2560@@ -338,6 +343,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
2561 case OPT_BIG_ENDIAN:
2562 set_big_endian (true);
2563 break;
2564+ case OPT_UINT32_ALIGN:
2565+ uint32_align_mask = strtol (arg, NULL, 0) - 1;
2566+ break;
2567 case 'c':
2568 force_output = 1;
2569 break;
2570diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c
2571index 33da52e..f790c4c 100644
2572--- a/locale/programs/locfile.c
2573+++ b/locale/programs/locfile.c
2574@@ -544,6 +544,9 @@ compare_files (const char *filename1, const char *filename2, size_t size,
2575 machine running localedef. */
2576 bool swap_endianness_p;
2577
2578+/* The target's value of __align__(uint32_t) - 1. */
2579+unsigned int uint32_align_mask = 3;
2580+
2581 /* When called outside a start_locale_structure/end_locale_structure
2582 or start_locale_prelude/end_locale_prelude block, record that the
2583 next byte in FILE's obstack will be the first byte of a new element.
2584@@ -621,7 +624,7 @@ add_locale_string (struct locale_file *file, const char *string)
2585 void
2586 add_locale_wstring (struct locale_file *file, const uint32_t *string)
2587 {
2588- add_locale_uint32_array (file, string, wcslen ((const wchar_t *) string) + 1);
2589+ add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1);
2590 }
2591
2592 /* Record that FILE's next element is the 32-bit integer VALUE. */
2593diff --git a/locale/programs/locfile.h b/locale/programs/locfile.h
2594index 6fc441b..118b171 100644
2595--- a/locale/programs/locfile.h
2596+++ b/locale/programs/locfile.h
2597@@ -71,6 +71,8 @@ extern void write_all_categories (struct localedef_t *definitions,
2598
2599 extern bool swap_endianness_p;
2600
2601+extern unsigned int uint32_align_mask;
2602+
2603 /* Change the output to be big-endian if BIG_ENDIAN is true and
2604 little-endian otherwise. */
2605 static inline void
2606@@ -89,7 +91,8 @@ maybe_swap_uint32 (uint32_t value)
2607 }
2608
2609 /* Likewise, but munge an array of N uint32_ts starting at ARRAY. */
2610-static inline void
2611+static void
2612+__attribute__ ((unused))
2613 maybe_swap_uint32_array (uint32_t *array, size_t n)
2614 {
2615 if (swap_endianness_p)
2616@@ -99,7 +102,8 @@ maybe_swap_uint32_array (uint32_t *array, size_t n)
2617
2618 /* Like maybe_swap_uint32_array, but the array of N elements is at
2619 the end of OBSTACK's current object. */
2620-static inline void
2621+static void
2622+__attribute__ ((unused))
2623 maybe_swap_uint32_obstack (struct obstack *obstack, size_t n)
2624 {
2625 maybe_swap_uint32_array ((uint32_t *) obstack_next_free (obstack) - n, n);
2626@@ -276,4 +280,55 @@ extern void identification_output (struct localedef_t *locale,
2627 const struct charmap_t *charmap,
2628 const char *output_path);
2629
2630+static size_t wcslen_uint32 (const uint32_t *str) __attribute__ ((unused));
2631+static uint32_t * wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused));
2632+static uint32_t * wcschr_uint32 (const uint32_t *s, uint32_t ch) __attribute__ ((unused));
2633+static int wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) __attribute__ ((unused));
2634+static int wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused));
2635+
2636+static size_t
2637+wcslen_uint32 (const uint32_t *str)
2638+{
2639+ size_t len = 0;
2640+ while (str[len] != 0)
2641+ len++;
2642+ return len;
2643+}
2644+
2645+static int
2646+wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n)
2647+{
2648+ while (n-- != 0)
2649+ {
2650+ int diff = *s1++ - *s2++;
2651+ if (diff != 0)
2652+ return diff;
2653+ }
2654+ return 0;
2655+}
2656+
2657+static int
2658+wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2)
2659+{
2660+ while (*s1 != 0 && *s1 == *s2)
2661+ s1++, s2++;
2662+ return *s1 - *s2;
2663+}
2664+
2665+static uint32_t *
2666+wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n)
2667+{
2668+ return memcpy (s1, s2, n * sizeof (uint32_t));
2669+}
2670+
2671+static uint32_t *
2672+wcschr_uint32 (const uint32_t *s, uint32_t ch)
2673+{
2674+ do
2675+ if (*s == ch)
2676+ return (uint32_t *) s;
2677+ while (*s++ != 0);
2678+ return 0;
2679+}
2680+
2681 #endif /* locfile.h */
2682diff --git a/locale/setlocale.c b/locale/setlocale.c
2683index fa9cb3a..8eee284 100644
2684--- a/locale/setlocale.c
2685+++ b/locale/setlocale.c
2686@@ -64,36 +64,6 @@ static char *const _nl_current_used[] =
2687 #endif
2688
2689
2690-/* Define an array of category names (also the environment variable names). */
2691-const union catnamestr_t _nl_category_names attribute_hidden =
2692- {
2693- {
2694-#define DEFINE_CATEGORY(category, category_name, items, a) \
2695- category_name,
2696-#include "categories.def"
2697-#undef DEFINE_CATEGORY
2698- }
2699- };
2700-
2701-const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
2702- {
2703-#define DEFINE_CATEGORY(category, category_name, items, a) \
2704- [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)),
2705-#include "categories.def"
2706-#undef DEFINE_CATEGORY
2707- };
2708-
2709-/* An array of their lengths, for convenience. */
2710-const uint8_t _nl_category_name_sizes[] attribute_hidden =
2711- {
2712-#define DEFINE_CATEGORY(category, category_name, items, a) \
2713- [category] = sizeof (category_name) - 1,
2714-#include "categories.def"
2715-#undef DEFINE_CATEGORY
2716- [LC_ALL] = sizeof ("LC_ALL") - 1
2717- };
2718-
2719-
2720 #ifdef NL_CURRENT_INDIRECT
2721 # define WEAK_POSTLOAD(postload) weak_extern (postload)
2722 #else
2723diff --git a/locale/xlocale.c b/locale/xlocale.c
2724index fec4564..f00269c 100644
2725--- a/locale/xlocale.c
2726+++ b/locale/xlocale.c
2727@@ -18,6 +18,7 @@
2728 <http://www.gnu.org/licenses/>. */
2729
2730 #include <locale.h>
2731+#include <gnu/option-groups.h>
2732 #include "localeinfo.h"
2733
2734 #define DEFINE_CATEGORY(category, category_name, items, a) \
2735@@ -25,6 +26,19 @@ extern struct __locale_data _nl_C_##category;
2736 #include "categories.def"
2737 #undef DEFINE_CATEGORY
2738
2739+/* If the locale support code isn't enabled, don't generate strong
2740+ reference to the C locale_data structures here; let the Makefile
2741+ decide which ones to include. (In the static linking case, the
2742+ strong reference to the 'class', 'toupper', and 'tolower' tables
2743+ will cause C-ctype.o to be brought in, as it should be, even when
2744+ the reference to _nl_C_LC_CTYPE will be weak.) */
2745+#if ! __OPTION_EGLIBC_LOCALE_CODE
2746+# define DEFINE_CATEGORY(category, category_name, items, a) \
2747+ weak_extern (_nl_C_##category)
2748+# include "categories.def"
2749+# undef DEFINE_CATEGORY
2750+#endif
2751+
2752 /* Defined in locale/C-ctype.c. */
2753 extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
2754 extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
2755@@ -52,3 +66,26 @@ const struct __locale_struct _nl_C_locobj attribute_hidden =
2756 .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128,
2757 .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128
2758 };
2759+
2760+
2761+#if ! __OPTION_EGLIBC_LOCALE_CODE
2762+/* When locale code is enabled, these are each defined in the
2763+ appropriate lc-CATEGORY.c file, so that static links (when __thread
2764+ is supported) bring in only those lc-CATEGORY.o files for
2765+ categories the program actually uses; look for NL_CURRENT_INDIRECT
2766+ in localeinfo.h.
2767+
2768+ When locale code is disabled, the _nl_C_CATEGORY objects are the
2769+ only possible referents. At the moment, there isn't a way to get
2770+ __OPTION_EGLIBC_LOCALE_CODE defined in every compilation unit that
2771+ #includes localeinfo.h, so we can't just turn off
2772+ NL_CURRENT_INDIRECT. So we'll define the _nl_current_CATEGORY
2773+ pointers here. */
2774+#if defined (NL_CURRENT_INDIRECT)
2775+#define DEFINE_CATEGORY(category, category_name, items, a) \
2776+ __thread struct __locale_data * const *_nl_current_##category \
2777+ attribute_hidden = &_nl_C_locobj.__locales[category];
2778+#include "categories.def"
2779+#undef DEFINE_CATEGORY
2780+#endif
2781+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
2782diff --git a/localedata/Makefile b/localedata/Makefile
2783index ebf6ac9..1870753 100644
2784--- a/localedata/Makefile
2785+++ b/localedata/Makefile
2786@@ -21,12 +21,22 @@ subdir := localedata
2787
2788 include ../Makeconfig
2789
2790-# List with all available character set descriptions.
2791-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*)
2792+include ../option-groups.mak
2793
2794 # List with all available character set descriptions.
2795-locales := $(wildcard locales/*)
2796-
2797+all-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*)
2798+
2799+all-locales := $(wildcard locales/*)
2800+
2801+# If the EGLIBC_LOCALES option group is not enabled, trim the
2802+# list of charmap and locale source files.
2803+ifeq ($(OPTION_EGLIBC_LOCALES),y)
2804+charmaps := $(all-charmaps)
2805+locales := $(all-locales)
2806+else
2807+charmaps :=
2808+locales := locales/POSIX
2809+endif
2810
2811 subdir-dirs = tests-mbwc
2812 vpath %.c tests-mbwc
2813@@ -71,14 +81,20 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \
2814 tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \
2815 tst_wctype tst_wcwidth
2816
2817-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
2818+# Since these tests build their own locale files, they're not
2819+# dependent on the OPTION_EGLIBC_LOCALES option group. But they do
2820+# need the locale functions to be present.
2821+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
2822+ += $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
2823 tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
2824 tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
2825 tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \
2826 tst-wctype
2827+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
2828 tests-static = bug-setlocale1-static
2829 tests += $(tests-static)
2830-ifeq (yes,$(build-shared))
2831+endif
2832+ifeq (yesy,$(build-shared)$(OPTION_EGLIBC_LOCALE_CODE))
2833 ifneq (no,$(PERL))
2834 tests-special += $(objpfx)mtrace-tst-leaks.out
2835 endif
2836@@ -95,6 +111,7 @@ tests: $(objdir)/iconvdata/gconv-modules
2837 tests-static += tst-langinfo-static
2838
2839 ifeq ($(run-built-tests),yes)
2840+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
2841 tests-special += $(objpfx)sort-test.out $(objpfx)tst-fmon.out \
2842 $(objpfx)tst-locale.out $(objpfx)tst-rpmatch.out \
2843 $(objpfx)tst-trans.out $(objpfx)tst-ctype.out \
2844@@ -109,6 +126,7 @@ LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 \
2845 tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8
2846 include ../gen-locales.mk
2847 endif
2848+endif
2849
2850 include ../Rules
2851
2852@@ -191,6 +209,11 @@ endif
2853
2854 include SUPPORTED
2855
2856+# Only install locale data if OPTION_EGLIBC_LOCALES is selected.
2857+ifneq ($(OPTION_EGLIBC_LOCALES),y)
2858+SUPPORTED-LOCALES :=
2859+endif
2860+
2861 INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES))
2862
2863 # Sometimes the whole collection of locale files should be installed.
2864diff --git a/login/Makefile b/login/Makefile
2865index 0f4bb22..4036ddb 100644
2866--- a/login/Makefile
2867+++ b/login/Makefile
2868@@ -18,6 +18,7 @@
2869 #
2870 # Sub-makefile for login portion of the library.
2871 #
2872+include ../option-groups.mak
2873
2874 subdir := login
2875
2876@@ -25,14 +26,16 @@ include ../Makeconfig
2877
2878 headers := utmp.h bits/utmp.h lastlog.h pty.h
2879
2880-routines := getlogin getlogin_r setlogin getlogin_r_chk \
2881- getutent getutent_r getutid getutline getutid_r getutline_r \
2882- utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \
2883- ptsname_r_chk
2884+routines := getpt grantpt unlockpt ptsname ptsname_r_chk
2885+routines-$(OPTION_EGLIBC_UTMP) \
2886+ += getutent getutent_r getutid getutline getutid_r getutline_r \
2887+ utmp_file utmpname updwtmp
2888+routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin getlogin_r getlogin_r_chk
2889+routines-$(OPTION_EGLIBC_BSD) += setlogin
2890
2891 CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"'
2892
2893-others = utmpdump
2894+others-$(OPTION_EGLIBC_UTMP) += utmpdump
2895
2896 ifeq (yes,$(build-pt-chown))
2897 others += pt_chown
2898@@ -46,8 +49,8 @@ vpath %.c programs
2899 tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin
2900
2901 # Build the -lutil library with these extra functions.
2902-extra-libs := libutil
2903-extra-libs-others := $(extra-libs)
2904+extra-libs-$(OPTION_EGLIBC_UTMP) := libutil
2905+extra-libs-others := $(extra-libs-y)
2906
2907 libutil-routines:= login login_tty logout logwtmp openpty forkpty
2908
2909diff --git a/malloc/Makefile b/malloc/Makefile
2910index 67ed293..272ca4d 100644
2911--- a/malloc/Makefile
2912+++ b/malloc/Makefile
2913@@ -18,6 +18,8 @@
2914 #
2915 # Makefile for malloc routines
2916 #
2917+include ../option-groups.mak
2918+
2919 subdir := malloc
2920
2921 include ../Makeconfig
2922@@ -39,9 +41,15 @@ install-lib := libmcheck.a
2923 non-lib.a := libmcheck.a
2924
2925 # Additional library.
2926+ifeq ($(OPTION_EGLIBC_MEMUSAGE),y)
2927 extra-libs = libmemusage
2928 extra-libs-others = $(extra-libs)
2929
2930+ifdef OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
2931+CPPFLAGS-memusage += -D__OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE=$(OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE)
2932+endif
2933+endif
2934+
2935 libmemusage-routines = memusage
2936 libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
2937
2938@@ -71,7 +79,7 @@ endif
2939 # Unless we get a test for the availability of libgd which also works
2940 # for cross-compiling we disable the memusagestat generation in this
2941 # situation.
2942-ifneq ($(cross-compiling),yes)
2943+ifeq ($(cross-compiling)$(OPTION_EGLIBC_MEMUSAGE),noy)
2944 # If the gd library is available we build the `memusagestat' program.
2945 ifneq ($(LIBGD),no)
2946 others: $(objpfx)memusage
2947diff --git a/malloc/memusage.c b/malloc/memusage.c
2948index a57ba8e..732ba9d 100644
2949--- a/malloc/memusage.c
2950+++ b/malloc/memusage.c
2951@@ -33,6 +33,7 @@
2952 #include <stdint.h>
2953 #include <sys/mman.h>
2954 #include <sys/time.h>
2955+#include <gnu/option-groups.h>
2956
2957 #include <memusage.h>
2958
2959@@ -93,7 +94,11 @@ static __thread uintptr_t start_sp;
2960 #define peak_stack peak_use[1]
2961 #define peak_total peak_use[2]
2962
2963-#define DEFAULT_BUFFER_SIZE 32768
2964+#ifndef __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
2965+# define DEFAULT_BUFFER_SIZE 32768
2966+#else
2967+# define DEFAULT_BUFFER_SIZE __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE
2968+#endif
2969 static size_t buffer_size;
2970
2971 static int fd = -1;
2972diff --git a/malloc/memusage.sh b/malloc/memusage.sh
2973index 8ab8cc2..d18f446 100755
2974--- a/malloc/memusage.sh
2975+++ b/malloc/memusage.sh
2976@@ -35,7 +35,7 @@ do_missing_arg() {
2977
2978 # Print help message
2979 do_help() {
2980- echo $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]...
2981+ printf $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]...
2982 Profile memory usage of PROGRAM.
2983
2984 -n,--progname=NAME Name of the program file to profile
2985diff --git a/math/Makefile b/math/Makefile
2986index 6388bae..ed1c511 100644
2987--- a/math/Makefile
2988+++ b/math/Makefile
2989@@ -21,6 +21,8 @@ subdir := math
2990
2991 include ../Makeconfig
2992
2993+include ../option-groups.mak
2994+
2995 # Installed header files.
2996 headers := math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \
2997 bits/huge_valf.h bits/huge_vall.h bits/inf.h bits/nan.h \
2998@@ -34,8 +36,8 @@ aux := setfpucw fpu_control
2999
3000 # Build the -lm library.
3001
3002-extra-libs := libm
3003-extra-libs-others = $(extra-libs)
3004+extra-libs-$(OPTION_EGLIBC_LIBM) := libm
3005+extra-libs-others-$(OPTION_EGLIBC_LIBM) = $(extra-libs-$(OPTION_EGLIBC_LIBM))
3006
3007 libm-support = s_lib_version s_matherr s_signgam \
3008 fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg \
3009diff --git a/misc/Makefile b/misc/Makefile
3010index aecb0da..e6b7c23 100644
3011--- a/misc/Makefile
3012+++ b/misc/Makefile
3013@@ -19,6 +19,10 @@
3014 # Sub-makefile for misc portion of the library.
3015 #
3016
3017+# Some system-dependent implementations of these functions use option
3018+# groups (see sysdeps/unix/sysv/linux/Makefile, for example).
3019+include ../option-groups.mak
3020+
3021 subdir := misc
3022
3023 include ../Makeconfig
3024@@ -46,40 +50,47 @@ routines := brk sbrk sstk ioctl \
3025 select pselect \
3026 acct chroot fsync sync fdatasync syncfs reboot \
3027 gethostid sethostid \
3028- revoke vhangup \
3029+ vhangup \
3030 swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \
3031 mkostemp mkostemp64 mkstemps mkstemps64 mkostemps mkostemps64 \
3032 ualarm usleep \
3033 gtty stty \
3034 ptrace \
3035- fstab mntent mntent_r \
3036+ mntent mntent_r \
3037 utimes lutimes futimes futimesat \
3038 truncate ftruncate truncate64 ftruncate64 \
3039- chflags fchflags \
3040 insremque getttyent getusershell getpass ttyslot \
3041 syslog syscall daemon \
3042 mmap mmap64 munmap mprotect msync madvise mincore remap_file_pages\
3043 mlock munlock mlockall munlockall \
3044- efgcvt efgcvt_r qefgcvt qefgcvt_r \
3045 hsearch hsearch_r tsearch lsearch \
3046 err error ustat \
3047- getsysstats dirname regexp \
3048+ getsysstats dirname \
3049 getloadavg getclktck \
3050 fgetxattr flistxattr fremovexattr fsetxattr getxattr \
3051 listxattr lgetxattr llistxattr lremovexattr lsetxattr \
3052 removexattr setxattr getauxval ifunc-impl-list
3053
3054+routines-$(OPTION_POSIX_REGEXP) += regexp
3055+routines-$(OPTION_EGLIBC_FSTAB) += fstab
3056+routines-$(OPTION_EGLIBC_BSD) += chflags fchflags revoke
3057+routines-$(OPTION_EGLIBC_FCVT) += efgcvt efgcvt_r qefgcvt qefgcvt_r
3058+
3059 generated += tst-error1.mtrace tst-error1-mem.out
3060
3061 aux := init-misc
3062 install-lib := libg.a
3063 gpl2lgpl := error.c error.h
3064
3065-tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
3066- tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
3067+tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
3068+ tst-pselect tst-insremque tst-mntent2 bug-hsearch1
3069+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += tst-error1
3070+tests-$(OPTION_EGLIBC_FCVT) += tst-efgcvt
3071 ifeq ($(run-built-tests),yes)
3072+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
3073 tests-special += $(objpfx)tst-error1-mem.out
3074 endif
3075+endif
3076
3077 CFLAGS-select.c = -fexceptions -fasynchronous-unwind-tables
3078 CFLAGS-tsearch.c = $(uses-callbacks)
3079diff --git a/misc/err.c b/misc/err.c
3080index 7b98157..efce8d5 100644
3081--- a/misc/err.c
3082+++ b/misc/err.c
3083@@ -22,6 +22,7 @@
3084 #include <errno.h>
3085 #include <string.h>
3086 #include <stdio.h>
3087+#include <gnu/option-groups.h>
3088
3089 #include <wchar.h>
3090 #define flockfile(s) _IO_flockfile (s)
3091@@ -37,6 +38,7 @@ extern char *__progname;
3092 va_end (ap); \
3093 }
3094
3095+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
3096 static void
3097 convert_and_print (const char *format, __gnuc_va_list ap)
3098 {
3099@@ -81,6 +83,7 @@ convert_and_print (const char *format, __gnuc_va_list ap)
3100
3101 __vfwprintf (stderr, wformat, ap);
3102 }
3103+#endif
3104
3105 void
3106 vwarnx (const char *format, __gnuc_va_list ap)
3107@@ -88,9 +91,13 @@ vwarnx (const char *format, __gnuc_va_list ap)
3108 flockfile (stderr);
3109 if (_IO_fwide (stderr, 0) > 0)
3110 {
3111+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
3112 __fwprintf (stderr, L"%s: ", __progname);
3113 convert_and_print (format, ap);
3114 putwc_unlocked (L'\n', stderr);
3115+#else
3116+ abort ();
3117+#endif
3118 }
3119 else
3120 {
3121@@ -111,6 +118,7 @@ vwarn (const char *format, __gnuc_va_list ap)
3122 flockfile (stderr);
3123 if (_IO_fwide (stderr, 0) > 0)
3124 {
3125+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
3126 __fwprintf (stderr, L"%s: ", __progname);
3127 if (format)
3128 {
3129@@ -119,6 +127,9 @@ vwarn (const char *format, __gnuc_va_list ap)
3130 }
3131 __set_errno (error);
3132 __fwprintf (stderr, L"%m\n");
3133+#else
3134+ abort ();
3135+#endif
3136 }
3137 else
3138 {
3139diff --git a/misc/error.c b/misc/error.c
3140index aaa120d..d6cbc82 100644
3141--- a/misc/error.c
3142+++ b/misc/error.c
3143@@ -35,6 +35,7 @@
3144 #endif
3145
3146 #ifdef _LIBC
3147+# include <gnu/option-groups.h>
3148 # include <libintl.h>
3149 # include <stdbool.h>
3150 # include <stdint.h>
3151@@ -205,6 +206,7 @@ error_tail (int status, int errnum, const char *message, va_list args)
3152 #if _LIBC
3153 if (_IO_fwide (stderr, 0) > 0)
3154 {
3155+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
3156 size_t len = strlen (message) + 1;
3157 wchar_t *wmessage = NULL;
3158 mbstate_t st;
3159@@ -265,6 +267,9 @@ error_tail (int status, int errnum, const char *message, va_list args)
3160
3161 if (use_malloc)
3162 free (wmessage);
3163+#else
3164+ abort ();
3165+#endif
3166 }
3167 else
3168 #endif
3169diff --git a/misc/tst-efgcvt.c b/misc/tst-efgcvt.c
3170index 5083fec..79ed36c 100644
3171--- a/misc/tst-efgcvt.c
3172+++ b/misc/tst-efgcvt.c
3173@@ -59,7 +59,7 @@ static testcase ecvt_tests[] =
3174 { 123.01, -4, 3, "" },
3175 { 126.71, -4, 3, "" },
3176 { 0.0, 4, 1, "0000" },
3177-#if DBL_MANT_DIG == 53
3178+#if DBL_MANT_DIG == 53 && !(defined __powerpc__ && defined __NO_FPRS__ && !defined _SOFT_FLOAT && !defined _SOFT_DOUBLE)
3179 { 0x1p-1074, 3, -323, "494" },
3180 { -0x1p-1074, 3, -323, "494" },
3181 #endif
3182diff --git a/nis/Makefile b/nis/Makefile
3183index 037e674..c967850 100644
3184--- a/nis/Makefile
3185+++ b/nis/Makefile
3186@@ -18,6 +18,8 @@
3187 #
3188 # Makefile for NIS/NIS+ part.
3189 #
3190+include ../option-groups.mak
3191+
3192 subdir := nis
3193
3194 include ../Makeconfig
3195@@ -30,19 +32,26 @@ endif
3196
3197 # These are the databases available for the nis (and perhaps later nisplus)
3198 # service. This must be a superset of the services in nss.
3199-databases = proto service hosts network grp pwd rpc ethers \
3200- spwd netgrp alias publickey
3201+databases-y := proto service hosts network grp pwd rpc ethers \
3202+ spwd netgrp publickey
3203+databases-$(OPTION_EGLIBC_DB_ALIASES) += alias
3204
3205 # Specify rules for the nss_* modules.
3206-services := nis nisplus compat
3207+# The 'compat' module includes nis support, and the 'nss' directory
3208+# includes a bare-bones "files" library, so we'll include 'compat' in
3209+# OPTION_EGLIBC_NIS.
3210+services-y :=
3211+services-$(OPTION_EGLIBC_NIS) += nis nisplus compat
3212+
3213+extra-libs-$(OPTION_EGLIBC_NIS) += libnsl
3214+extra-libs-y += $(services-y:%=libnss_%)
3215
3216-extra-libs = libnsl $(services:%=libnss_%)
3217 # These libraries will be built in the `others' pass rather than
3218 # the `lib' pass, because they depend on libc.so being built already.
3219-extra-libs-others = $(extra-libs)
3220+extra-libs-others-y += $(extra-libs-y)
3221
3222 # The sources are found in the appropriate subdir.
3223-subdir-dirs = $(services:%=nss_%)
3224+subdir-dirs = $(services-y:%=nss_%)
3225 vpath %.c $(subdir-dirs)
3226
3227 libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
3228@@ -60,11 +69,11 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
3229 libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups)
3230 libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes))
3231
3232-libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \
3233+libnss_nis-routines := $(addprefix nis-,$(databases-y)) nis-initgroups \
3234 nss-nis
3235 libnss_nis-inhibit-o = $(filter-out .os,$(object-suffixes))
3236
3237-libnss_nisplus-routines := $(addprefix nisplus-,$(databases)) nisplus-parser \
3238+libnss_nisplus-routines := $(addprefix nisplus-,$(databases-y)) nisplus-parser \
3239 nss-nisplus nisplus-initgroups
3240 libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes))
3241
3242@@ -80,12 +89,12 @@ libnsl-libc = $(common-objpfx)linkobj/libc.so
3243 # Target-specific variable setting to link objects using deprecated
3244 # RPC interfaces with the version of libc.so that makes them available
3245 # for new links:
3246-$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \
3247+$(services-y:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \
3248 libc-for-link = $(libnsl-libc)
3249
3250
3251 ifeq ($(build-shared),yes)
3252-$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
3253+$(others-y:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
3254 else
3255-$(others:%=$(objpfx)%): $(objpfx)libnsl.a
3256+$(others-y:%=$(objpfx)%): $(objpfx)libnsl.a
3257 endif
3258diff --git a/nptl/Makefile b/nptl/Makefile
3259index aaca0a4..596ca3c 100644
3260--- a/nptl/Makefile
3261+++ b/nptl/Makefile
3262@@ -18,6 +18,8 @@
3263 #
3264 # Sub-makefile for NPTL portion of the library.
3265 #
3266+include ../option-groups.mak
3267+
3268 subdir := nptl
3269
3270 include ../Makeconfig
3271@@ -118,7 +120,7 @@ libpthread-routines = nptl-init vars events version pt-interp \
3272 pt-raise pt-system \
3273 flockfile ftrylockfile funlockfile \
3274 sigaction \
3275- herrno res pt-allocrtsig \
3276+ pt-allocrtsig \
3277 pthread_kill_other_threads \
3278 pthread_getaffinity pthread_setaffinity \
3279 pthread_attr_getaffinity pthread_attr_setaffinity \
3280@@ -138,8 +140,10 @@ libpthread-routines = nptl-init vars events version pt-interp \
3281 # pthread_setgid pthread_setegid pthread_setregid \
3282 # pthread_setresgid
3283
3284+libpthread-routines-$(OPTION_EGLIBC_INET) := herrno res
3285 libpthread-shared-only-routines = version pt-interp pt-allocrtsig \
3286 unwind-forcedunwind
3287+
3288 libpthread-static-only-routines = pthread_atfork
3289
3290 # Since cancellation handling is in large parts handled using exceptions
3291@@ -220,7 +224,7 @@ tests = tst-typesizes \
3292 tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
3293 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
3294 tst-mutexpi9 \
3295- tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
3296+ tst-spin1 tst-spin2 tst-spin3 \
3297 tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
3298 tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
3299 tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
3300@@ -256,14 +260,14 @@ tests = tst-typesizes \
3301 tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
3302 tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
3303 tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
3304- tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
3305+ tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \
3306 tst-cancel-self tst-cancel-self-cancelstate \
3307 tst-cancel-self-canceltype tst-cancel-self-testcancel \
3308 tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
3309 tst-flock1 tst-flock2 \
3310 tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
3311 tst-signal6 tst-signal7 \
3312- tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
3313+ tst-exec2 tst-exec3 tst-exec4 \
3314 tst-exit1 tst-exit2 tst-exit3 \
3315 tst-stdio1 tst-stdio2 \
3316 tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \
3317@@ -271,13 +275,12 @@ tests = tst-typesizes \
3318 tst-unload \
3319 tst-dlsym1 \
3320 tst-sysconf \
3321- tst-locale1 tst-locale2 \
3322+ tst-locale2 \
3323 tst-umask1 \
3324 tst-popen1 \
3325 tst-clock1 \
3326 tst-context1 \
3327 tst-sched1 \
3328- tst-backtrace1 \
3329 tst-abstime \
3330 tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
3331 tst-getpid3 \
3332@@ -288,9 +291,16 @@ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
3333 tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
3334 test-srcs = tst-oddstacklimit
3335
3336-# Test expected to fail on most targets (except x86_64) due to bug
3337-# 18435 - pthread_once hangs when init routine throws an exception.
3338-test-xfail-tst-once5 = yes
3339+# This test uses the posix_spawn functions.
3340+tests-$(OPTION_EGLIBC_SPAWN) += tst-exec1
3341+
3342+# This test uses the 'backtrace' functions.
3343+tests-$(OPTION_EGLIBC_BACKTRACE) += tst-backtrace1
3344+
3345+# This test is written in C++.
3346+tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24
3347+
3348+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1
3349
3350 # Files which must not be linked with libpthread.
3351 tests-nolibpthread = tst-unload
3352diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
3353index d10f4ea..14257ce 100644
3354--- a/nptl/pthread_create.c
3355+++ b/nptl/pthread_create.c
3356@@ -33,6 +33,7 @@
3357 #include <default-sched.h>
3358 #include <futex-internal.h>
3359
3360+#include <gnu/option-groups.h>
3361 #include <shlib-compat.h>
3362
3363 #include <stap-probe.h>
3364@@ -262,8 +263,10 @@ START_THREAD_DEFN
3365 THREAD_SETMEM (pd, cpuclock_offset, now);
3366 #endif
3367
3368+#if __OPTION_EGLIBC_INET
3369 /* Initialize resolver state pointer. */
3370 __resp = &pd->res;
3371+#endif
3372
3373 /* Initialize pointers to locale data. */
3374 __ctype_init ();
3375@@ -346,8 +349,10 @@ START_THREAD_DEFN
3376 /* Run the destructor for the thread-local data. */
3377 __nptl_deallocate_tsd ();
3378
3379+#if __OPTION_EGLIBC_INET
3380 /* Clean up any state libc stored in thread-local variables. */
3381 __libc_thread_freeres ();
3382+#endif
3383
3384 /* If this is the last thread we terminate the process now. We
3385 do not notify the debugger, it might just irritate it if there
3386diff --git a/nscd/Makefile b/nscd/Makefile
3387index ede941d..f4f3f8d 100644
3388--- a/nscd/Makefile
3389+++ b/nscd/Makefile
3390@@ -18,14 +18,17 @@
3391 #
3392 # Sub-makefile for nscd portion of the library.
3393 #
3394+include ../option-groups.mak
3395+
3396 subdir := nscd
3397
3398 include ../Makeconfig
3399
3400 ifneq ($(use-nscd),no)
3401-routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
3402+routines-$(OPTION_EGLIBC_INET) += \
3403+ nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
3404 nscd_initgroups nscd_getserv_r nscd_netgroup
3405-aux := nscd_helper
3406+aux-$(OPTION_EGLIBC_INET) += nscd_helper
3407 endif
3408
3409 # To find xmalloc.c
3410@@ -37,14 +40,18 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
3411 dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
3412 xmalloc xstrdup aicache initgrcache gai res_hconf \
3413 netgroupcache
3414-
3415+ifneq (y,$(OPTION_EGLIBC_NIS))
3416+# If we haven't build libnsl.so, then we'll need to include our
3417+# own copy of nis_hash.
3418+nscd-modules += nis_hash
3419+endif
3420 ifeq ($(build-nscd)$(have-thread-library),yesyes)
3421
3422-others += nscd
3423-others-pie += nscd
3424-install-sbin := nscd
3425+others-$(OPTION_EGLIBC_INET) += nscd
3426+others-pie-$(OPTION_EGLIBC_INET) += nscd
3427+install-sbin-$(OPTION_EGLIBC_INET) += nscd
3428
3429-extra-objs = $(nscd-modules:=.o)
3430+extra-objs-$(OPTION_EGLIBC_INET) += $(nscd-modules:=.o)
3431
3432 endif
3433
3434@@ -100,7 +107,15 @@ include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
3435 $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o)
3436
3437 ifeq ($(build-shared),yes)
3438-$(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so
3439+$(objpfx)nscd: $(shared-thread-library)
3440+else
3441+$(objpfx)nscd: $(static-thread-library)
3442+endif
3443+
3444+ifeq (y,$(OPTION_EGLIBC_NIS))
3445+ifeq ($(build-shared),yes)
3446+$(objpfx)nscd: $(common-objpfx)nis/libnsl.so
3447 else
3448-$(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a
3449+$(objpfx)nscd: $(common-objpfx)nis/libnsl.a
3450+endif
3451 endif
3452diff --git a/nscd/nis_hash.c b/nscd/nis_hash.c
3453new file mode 100644
3454index 0000000..d244c41
3455--- /dev/null
3456+++ b/nscd/nis_hash.c
3457@@ -0,0 +1,3 @@
3458+/* If OPTION_EGLIBC_NIS is disabled, nscd can't get this from libnsl.so;
3459+ we need our own copy. */
3460+#include "../nis/nis_hash.c"
3461diff --git a/nss/Makefile b/nss/Makefile
3462index 65ab7b5..19f0aef 100644
3463--- a/nss/Makefile
3464+++ b/nss/Makefile
3465@@ -18,28 +18,35 @@
3466 #
3467 # Makefile for name service switch.
3468 #
3469+include ../option-groups.mak
3470+
3471 subdir := nss
3472
3473 include ../Makeconfig
3474
3475 headers := nss.h
3476
3477-# This is the trivial part which goes into libc itself.
3478-routines = nsswitch getnssent getnssent_r digits_dots \
3479- $(addsuffix -lookup,$(databases))
3480-
3481 # These are the databases that go through nss dispatch.
3482 # Caution: if you add a database here, you must add its real name
3483 # in databases.def, too.
3484-databases = proto service hosts network grp pwd ethers \
3485- spwd netgrp alias sgrp
3486+databases-y = grp pwd spwd sgrp
3487+databases-$(OPTION_EGLIBC_INET) \
3488+ += proto service hosts network ethers \
3489+ netgrp
3490+databases-$(OPTION_EGLIBC_DB_ALIASES) += alias
3491+
3492+routines-$(OPTION_EGLIBC_INET) += digits_dots
3493
3494 ifneq (,$(filter sunrpc,$(subdirs)))
3495-databases += key rpc
3496+databases-$(OPTION_EGLIBC_INET) += key rpc
3497 have-sunrpc := 1
3498 else
3499 have-sunrpc := 0
3500 endif
3501+# This is the trivial part which goes into libc itself.
3502+routines-y += nsswitch getnssent getnssent_r \
3503+ $(addsuffix -lookup,$(databases-y))
3504+
3505 CPPFLAGS-getent.c = -DHAVE_SUNRPC=$(have-sunrpc)
3506
3507 others := getent makedb
3508@@ -47,8 +54,9 @@ install-bin := getent makedb
3509 makedb-modules = xmalloc hash-string
3510 extra-objs += $(makedb-modules:=.o)
3511
3512-tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent
3513-xtests = bug-erange
3514+tests = tst-nss-test1 tst-nss-getpwent
3515+tests-$(OPTION_EGLIBC_INET) += test-netdb test-digits-dots
3516+xtests-$(OPTION_EGLIBC_INET) += bug-erange
3517
3518 # Specify rules for the nss_* modules. We have some services.
3519 services := files db
3520@@ -63,7 +71,7 @@ subdir-dirs = $(services:%=nss_%)
3521 vpath %.c $(subdir-dirs) ../locale/programs ../intl
3522
3523
3524-libnss_files-routines := $(addprefix files-,$(databases)) \
3525+libnss_files-routines := $(addprefix files-,$(databases-y)) \
3526 files-initgroups files-have_o_cloexec files-init
3527
3528 libnss_db-dbs := $(addprefix db-,\
3529@@ -86,6 +94,45 @@ tests-static = tst-nss-static
3530 tests += $(tests-static)
3531 endif
3532
3533+ifneq ($(OPTION_EGLIBC_NSSWITCH),y)
3534+
3535+ifndef OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG
3536+$(error OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG variable left unset)
3537+endif
3538+
3539+ifndef OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS
3540+$(error OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS variable left unset)
3541+endif
3542+
3543+ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)))
3544+$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed config file)
3545+$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG))
3546+endif
3547+
3548+ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)))
3549+$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed functions file)
3550+$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS))
3551+endif
3552+
3553+before-compile := $(objpfx)fixed-nsswitch.h
3554+generated := fixed-nsswitch.h
3555+$(objpfx)fixed-nsswitch.h $(objfpx)fixed-nsswitch-libs: \
3556+ $(objpfx)gen-fixed-nsswitch \
3557+ $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)
3558+ $< $(objpfx)fixed-nsswitch.h \
3559+ $(objpfx)fixed-nsswitch-libs \
3560+ $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)
3561+
3562+$(objpfx)gen-fixed-nsswitch: gen-fixed-nsswitch.c \
3563+ $(common-objpfx)option-groups.config \
3564+ $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)
3565+ $(native-compile)
3566+gen-fixed-nsswitch-CFLAGS = \
3567+ -g3 -O -Wall \
3568+ -I $(objpfx) \
3569+ -DFIXED_FUNCTIONS='"$(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)"'
3570+endif
3571+
3572 include ../Rules
3573
3574 ifeq (yes,$(have-selinux))
3575diff --git a/nss/fixed-nsswitch.conf b/nss/fixed-nsswitch.conf
3576new file mode 100644
3577index 0000000..91bb675
3578--- /dev/null
3579+++ b/nss/fixed-nsswitch.conf
3580@@ -0,0 +1,22 @@
3581+# /etc/nsswitch.conf
3582+#
3583+# Example configuration for fixed name service.
3584+# See the description of OPTION_EGLIBC_NSSWITCH in option-groups.def
3585+# for details.
3586+#
3587+
3588+aliases: files
3589+
3590+passwd: files
3591+group: files
3592+shadow: files
3593+
3594+hosts: files dns
3595+networks: files dns
3596+
3597+protocols: files
3598+services: files
3599+ethers: files
3600+rpc: files
3601+
3602+netgroup: files
3603diff --git a/nss/fixed-nsswitch.functions b/nss/fixed-nsswitch.functions
3604new file mode 100644
3605index 0000000..2f3fa83
3606--- /dev/null
3607+++ b/nss/fixed-nsswitch.functions
3608@@ -0,0 +1,121 @@
3609+/* List of functions defined for fixed NSS in GNU C Library.
3610+ Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc.
3611+ This file is part of the GNU C Library.
3612+
3613+ The GNU C Library is free software; you can redistribute it and/or
3614+ modify it under the terms of the GNU Lesser General Public
3615+ License as published by the Free Software Foundation; either
3616+ version 2.1 of the License, or (at your option) any later version.
3617+
3618+ The GNU C Library is distributed in the hope that it will be useful,
3619+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3620+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3621+ Lesser General Public License for more details.
3622+
3623+ You should have received a copy of the GNU Lesser General Public
3624+ License along with the GNU C Library; if not, write to the Free
3625+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
3626+ 02111-1307 USA. */
3627+
3628+/* When OPTION_EGLIBC_NSSWITCH is disabled (see option-groups.def),
3629+ EGLIBC does not use the 'dlopen' and 'dlsym' functions to look for
3630+ database query functions in the individual name service libraries.
3631+ Instead, it uses a set of functions chosen at compile time, as
3632+ directed by the OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS file. This
3633+ file is a sample of what you might use there.
3634+
3635+ This file is C source code; it should only contain invocations of
3636+ the following macros:
3637+
3638+ - DEFINE_ENT (DATABASE, SERVICE, X)
3639+
3640+ Declare the 'setXent', 'getXent_r', and 'endXent' functions that
3641+ query DATABASE using the service library 'libnss_SERVICE.so.2'.
3642+ DATABASE should be the full name of the database as it appears in
3643+ 'nsswitch.conf', like 'passwd' or 'aliases'.
3644+
3645+ (The non-reentrant 'getXent' functions are implemented in terms
3646+ of the reentrant 'getXent_r' functions, so there is no need to
3647+ refer to them explicitly here.)
3648+
3649+ - DEFINE_GETBY (DATABASE, SERVICE, X, KEY)
3650+
3651+ Declare the 'getXbyKEY_r' functions that query DATABASE using
3652+ SERVICE. DATABASE and SERVICE are as described above.
3653+
3654+ (The non-reentrant 'getXbyKEY' functions are implemented in terms
3655+ of the reentrant 'getXbyKEY_r' functions, so there is no need to
3656+ refer to them explicitly here.)
3657+
3658+ Use the special key 'name3' for the service library function that
3659+ implements the 'getaddrinfo' function.
3660+
3661+ - DEFINE_GET (DATABASE, SERVICE, QUERY)
3662+
3663+ Declare the 'getQUERY_r' functions that query DATABASE using
3664+ SERVICE. This is used for functions like 'getpwnam'.
3665+
3666+ (The non-reentrant 'getQUERY' functions are implemented in terms
3667+ of the reentrant 'getQUERY_r' functions, so there is no need to
3668+ refer to them explicitly here.)
3669+
3670+ This sample file only includes functions that consult the files in
3671+ '/etc', and the Domain Name System (DNS). */
3672+
3673+/* aliases */
3674+DEFINE_ENT (aliases, files, alias)
3675+DEFINE_GETBY (aliases, files, alias, name)
3676+
3677+/* ethers */
3678+DEFINE_ENT (ethers, files, ether)
3679+
3680+/* group */
3681+DEFINE_ENT (group, files, gr)
3682+DEFINE_GET (group, files, grgid)
3683+DEFINE_GET (group, files, grnam)
3684+
3685+/* hosts */
3686+DEFINE_ENT (hosts, files, host)
3687+DEFINE_GETBY (hosts, files, host, addr)
3688+DEFINE_GETBY (hosts, files, host, name)
3689+DEFINE_GETBY (hosts, files, host, name2)
3690+DEFINE_GET (hosts, files, hostton)
3691+DEFINE_GET (hosts, files, ntohost)
3692+DEFINE_GETBY (hosts, dns, host, addr)
3693+DEFINE_GETBY (hosts, dns, host, name)
3694+DEFINE_GETBY (hosts, dns, host, name2)
3695+DEFINE_GETBY (hosts, dns, host, name3)
3696+
3697+/* netgroup */
3698+DEFINE_ENT (netgroup, files, netgr)
3699+
3700+/* networks */
3701+DEFINE_ENT (networks, files, net)
3702+DEFINE_GETBY (networks, files, net, name)
3703+DEFINE_GETBY (networks, files, net, addr)
3704+DEFINE_GETBY (networks, dns, net, name)
3705+DEFINE_GETBY (networks, dns, net, addr)
3706+
3707+/* protocols */
3708+DEFINE_ENT (protocols, files, proto)
3709+DEFINE_GETBY (protocols, files, proto, name)
3710+DEFINE_GETBY (protocols, files, proto, number)
3711+
3712+/* passwd */
3713+DEFINE_ENT (passwd, files, pw)
3714+DEFINE_GET (passwd, files, pwnam)
3715+DEFINE_GET (passwd, files, pwuid)
3716+
3717+/* rpc */
3718+DEFINE_ENT (rpc, files, rpc)
3719+DEFINE_GETBY (rpc, files, rpc, name)
3720+DEFINE_GETBY (rpc, files, rpc, number)
3721+
3722+/* services */
3723+DEFINE_ENT (services, files, serv)
3724+DEFINE_GETBY (services, files, serv, name)
3725+DEFINE_GETBY (services, files, serv, port)
3726+
3727+/* shadow */
3728+DEFINE_ENT (shadow, files, sp)
3729+DEFINE_GET (shadow, files, spnam)
3730diff --git a/nss/gen-fixed-nsswitch.c b/nss/gen-fixed-nsswitch.c
3731new file mode 100644
3732index 0000000..6e1c98c
3733--- /dev/null
3734+++ b/nss/gen-fixed-nsswitch.c
3735@@ -0,0 +1,803 @@
3736+/* gen-fixed-nsswitch.c --- generate fixed name service data structures
3737+ Copyright (C) 1996-1999, 2001-2006, 2007 Free Software Foundation, Inc.
3738+ This file is part of the GNU C Library.
3739+
3740+ The GNU C Library is free software; you can redistribute it and/or
3741+ modify it under the terms of the GNU Lesser General Public
3742+ License as published by the Free Software Foundation; either
3743+ version 2.1 of the License, or (at your option) any later version.
3744+
3745+ The GNU C Library is distributed in the hope that it will be useful,
3746+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3747+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3748+ Lesser General Public License for more details.
3749+
3750+ You should have received a copy of the GNU Lesser General Public
3751+ License along with the GNU C Library; if not, write to the Free
3752+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
3753+ 02111-1307 USA. */
3754+
3755+#define _GNU_SOURCE
3756+
3757+#include <stdlib.h>
3758+#include <stdio.h>
3759+#include <errno.h>
3760+#include <string.h>
3761+#include <stdarg.h>
3762+#include <assert.h>
3763+#include <ctype.h>
3764+
3765+#include "gnu/lib-names.h"
3766+#include "nss.h"
3767+
3768+/* Provide a fallback definition to allow this file to be compiled outside
3769+ libc. */
3770+#ifndef internal_function
3771+# define internal_function
3772+#endif
3773+
3774+
3775+/* Simple utilities. */
3776+
3777+void __attribute__ ((noreturn))
3778+error (const char *message)
3779+{
3780+ fprintf (stderr, "%s\n", message);
3781+ exit (1);
3782+}
3783+
3784+
3785+void *
3786+check_alloc (void *p)
3787+{
3788+ if (p)
3789+ return p;
3790+ else
3791+ error ("out of memory");
3792+}
3793+
3794+void *
3795+xmalloc (size_t size)
3796+{
3797+ return check_alloc (malloc (size));
3798+}
3799+
3800+
3801+/* Format ARGS according to FORMAT, and return the result as a
3802+ malloc'ed string. */
3803+char *
3804+saprintf (const char *format, ...)
3805+{
3806+ va_list args;
3807+ size_t len;
3808+ char *buf;
3809+
3810+ va_start (args, format);
3811+ len = vsnprintf (NULL, 0, format, args);
3812+ va_end (args);
3813+
3814+ buf = xmalloc (len + 1);
3815+ va_start (args, format);
3816+ assert (len == vsnprintf (buf, len + 1, format, args));
3817+ va_end (args);
3818+
3819+ return buf;
3820+}
3821+
3822+
3823+
3824+/* Data structures representing the configuration file in memory. */
3825+
3826+/* These are copied from nsswitch.h.
3827+
3828+ We could simply #include that file, but this program runs on the
3829+ build machine and links against the build machine's libraries,
3830+ whereas that header is meant for use by target code; it uses
3831+ 'libc_hidden_proto', 'internal_function', and related hair. Since
3832+ we've copied the parsing code, we might as well copy the data
3833+ structure definitions as well. */
3834+
3835+/* Actions performed after lookup finished. */
3836+typedef enum
3837+{
3838+ NSS_ACTION_CONTINUE,
3839+ NSS_ACTION_RETURN
3840+} lookup_actions;
3841+
3842+
3843+typedef struct service_library
3844+{
3845+ /* Name of service (`files', `dns', `nis', ...). */
3846+ const char *name;
3847+ /* Pointer to the loaded shared library. */
3848+ void *lib_handle;
3849+ /* And the link to the next entry. */
3850+ struct service_library *next;
3851+} service_library;
3852+
3853+
3854+/* For mapping a function name to a function pointer. It is known in
3855+ nsswitch.c:nss_lookup_function that a string pointer for the lookup key
3856+ is the first member. */
3857+typedef struct
3858+{
3859+ const char *fct_name;
3860+ void *fct_ptr;
3861+} known_function;
3862+
3863+
3864+typedef struct service_user
3865+{
3866+ /* And the link to the next entry. */
3867+ struct service_user *next;
3868+ /* Action according to result. */
3869+ lookup_actions actions[5];
3870+ /* Link to the underlying library object. */
3871+ service_library *library;
3872+ /* Collection of known functions.
3873+
3874+ With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a
3875+ 'tsearch'-style tree.
3876+
3877+ With OPTION_EGLIBC_NSSWITCH disabled, this is an array of
3878+ pointers to known_function structures, NULL-terminated. */
3879+ union
3880+ {
3881+ void *tree;
3882+ const known_function **array;
3883+ } known;
3884+ /* Name of the service (`files', `dns', `nis', ...). */
3885+ const char *name;
3886+} service_user;
3887+
3888+/* To access the action based on the status value use this macro. */
3889+#define nss_next_action(ni, status) ((ni)->actions[2 + status])
3890+
3891+
3892+typedef struct name_database_entry
3893+{
3894+ /* And the link to the next entry. */
3895+ struct name_database_entry *next;
3896+ /* List of service to be used. */
3897+ service_user *service;
3898+ /* Name of the database. */
3899+ const char *name;
3900+} name_database_entry;
3901+
3902+
3903+typedef struct name_database
3904+{
3905+ /* List of all known databases. */
3906+ name_database_entry *entry;
3907+ /* List of libraries with service implementation. */
3908+ service_library *library;
3909+} name_database;
3910+
3911+
3912+
3913+/* Gathering the contents of the FIXED_FUNCTIONS file. */
3914+
3915+/* It should be possible to generate this list automatically by
3916+ looking at the services and databases used in the nsswitch.conf
3917+ file, and having a hard-coded set of queries supported on each
3918+ database. */
3919+
3920+/* We #include the FIXED_FUNCTIONS file several times to build an
3921+ array of function structures holding its data. */
3922+enum function_kind {
3923+ fk_end = 0, /* Last entry. */
3924+ fk_setent, /* Like setpwent. */
3925+ fk_getent, /* Like getpwent. */
3926+ fk_endent, /* Like endpwent. */
3927+ fk_getby, /* Like gethostbyname. */
3928+ fk_get /* Like getpwnam. */
3929+};
3930+
3931+
3932+struct function {
3933+ /* What kind of function this is. */
3934+ enum function_kind kind;
3935+
3936+ /* The database and service of the function being hardwired in. */
3937+ char *database, *service;
3938+
3939+ /* The kind of entry being queried, for 'fk_setent', 'fk_getent',
3940+ 'fk_endent', and 'fk_getby' functions. */
3941+ char *entry;
3942+
3943+ /* The key, for 'fk_getby' entries. */
3944+ char *key;
3945+
3946+ /* The value and key, for 'fk_get' entries. */
3947+ char *value_and_key;
3948+};
3949+
3950+
3951+const struct function functions[] =
3952+ {
3953+
3954+#define DEFINE_ENT(database, service, entry) \
3955+ { fk_setent, #database, #service, #entry }, \
3956+ { fk_getent, #database, #service, #entry }, \
3957+ { fk_endent, #database, #service, #entry },
3958+#define DEFINE_GETBY(database, service, entry, key) \
3959+ { fk_getby, #database, #service, #entry, #key },
3960+#define DEFINE_GET(database, service, value_and_key) \
3961+ { fk_get, #database, #service, NULL, NULL, #value_and_key },
3962+
3963+#include FIXED_FUNCTIONS
3964+
3965+#undef DEFINE_ENT
3966+#undef DEFINE_GETBY
3967+#undef DEFINE_GET
3968+
3969+ { fk_end }
3970+ };
3971+
3972+
3973+/* Parsing the config file. Functions copied from nsswitch.c. */
3974+
3975+#define __strchrnul strchrnul
3976+#define __getline getline
3977+#define __strncasecmp strncasecmp
3978+
3979+/* Prototypes for the local functions. */
3980+static name_database *nss_parse_file (const char *fname) internal_function;
3981+static name_database_entry *nss_getline (char *line) internal_function;
3982+static service_user *nss_parse_service_list (const char *line)
3983+ internal_function;
3984+
3985+static name_database *
3986+internal_function
3987+nss_parse_file (const char *fname)
3988+{
3989+ FILE *fp;
3990+ name_database *result;
3991+ name_database_entry *last;
3992+ char *line;
3993+ size_t len;
3994+
3995+ /* Open the configuration file. */
3996+ fp = fopen (fname, "rc");
3997+ if (fp == NULL)
3998+ return NULL;
3999+
4000+ // /* No threads use this stream. */
4001+ // __fsetlocking (fp, FSETLOCKING_BYCALLER);
4002+
4003+ result = (name_database *) xmalloc (sizeof (name_database));
4004+
4005+ result->entry = NULL;
4006+ result->library = NULL;
4007+ last = NULL;
4008+ line = NULL;
4009+ len = 0;
4010+ do
4011+ {
4012+ name_database_entry *this;
4013+ ssize_t n;
4014+
4015+ n = __getline (&line, &len, fp);
4016+ if (n < 0)
4017+ break;
4018+ if (line[n - 1] == '\n')
4019+ line[n - 1] = '\0';
4020+
4021+ /* Because the file format does not know any form of quoting we
4022+ can search forward for the next '#' character and if found
4023+ make it terminating the line. */
4024+ *__strchrnul (line, '#') = '\0';
4025+
4026+ /* If the line is blank it is ignored. */
4027+ if (line[0] == '\0')
4028+ continue;
4029+
4030+ /* Each line completely specifies the actions for a database. */
4031+ this = nss_getline (line);
4032+ if (this != NULL)
4033+ {
4034+ if (last != NULL)
4035+ last->next = this;
4036+ else
4037+ result->entry = this;
4038+
4039+ last = this;
4040+ }
4041+ }
4042+ while (!feof_unlocked (fp));
4043+
4044+ /* Free the buffer. */
4045+ free (line);
4046+ /* Close configuration file. */
4047+ fclose (fp);
4048+
4049+ return result;
4050+}
4051+
4052+
4053+/* Read the source names:
4054+ `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*'
4055+ */
4056+static service_user *
4057+internal_function
4058+nss_parse_service_list (const char *line)
4059+{
4060+ service_user *result = NULL, **nextp = &result;
4061+
4062+ while (1)
4063+ {
4064+ service_user *new_service;
4065+ const char *name;
4066+
4067+ while (isspace (line[0]))
4068+ ++line;
4069+ if (line[0] == '\0')
4070+ /* No source specified. */
4071+ return result;
4072+
4073+ /* Read <source> identifier. */
4074+ name = line;
4075+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[')
4076+ ++line;
4077+ if (name == line)
4078+ return result;
4079+
4080+
4081+ new_service = (service_user *) xmalloc (sizeof (*new_service));
4082+ new_service->name = (char *) xmalloc (line - name + 1);
4083+
4084+ *((char *) __mempcpy ((char *) new_service->name, name, line - name))
4085+ = '\0';
4086+
4087+ /* Set default actions. */
4088+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
4089+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE;
4090+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE;
4091+ new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
4092+ new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
4093+ new_service->library = NULL;
4094+ new_service->known.tree = NULL;
4095+ new_service->next = NULL;
4096+
4097+ while (isspace (line[0]))
4098+ ++line;
4099+
4100+ if (line[0] == '[')
4101+ {
4102+ /* Read criterions. */
4103+ do
4104+ ++line;
4105+ while (line[0] != '\0' && isspace (line[0]));
4106+
4107+ do
4108+ {
4109+ int not;
4110+ enum nss_status status;
4111+ lookup_actions action;
4112+
4113+ /* Grok ! before name to mean all statii but that one. */
4114+ not = line[0] == '!';
4115+ if (not)
4116+ ++line;
4117+
4118+ /* Read status name. */
4119+ name = line;
4120+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
4121+ && line[0] != ']')
4122+ ++line;
4123+
4124+ /* Compare with known statii. */
4125+ if (line - name == 7)
4126+ {
4127+ if (__strncasecmp (name, "SUCCESS", 7) == 0)
4128+ status = NSS_STATUS_SUCCESS;
4129+ else if (__strncasecmp (name, "UNAVAIL", 7) == 0)
4130+ status = NSS_STATUS_UNAVAIL;
4131+ else
4132+ return result;
4133+ }
4134+ else if (line - name == 8)
4135+ {
4136+ if (__strncasecmp (name, "NOTFOUND", 8) == 0)
4137+ status = NSS_STATUS_NOTFOUND;
4138+ else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
4139+ status = NSS_STATUS_TRYAGAIN;
4140+ else
4141+ return result;
4142+ }
4143+ else
4144+ return result;
4145+
4146+ while (isspace (line[0]))
4147+ ++line;
4148+ if (line[0] != '=')
4149+ return result;
4150+ do
4151+ ++line;
4152+ while (isspace (line[0]));
4153+
4154+ name = line;
4155+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
4156+ && line[0] != ']')
4157+ ++line;
4158+
4159+ if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
4160+ action = NSS_ACTION_RETURN;
4161+ else if (line - name == 8
4162+ && __strncasecmp (name, "CONTINUE", 8) == 0)
4163+ action = NSS_ACTION_CONTINUE;
4164+ else
4165+ return result;
4166+
4167+ if (not)
4168+ {
4169+ /* Save the current action setting for this status,
4170+ set them all to the given action, and reset this one. */
4171+ const lookup_actions save = new_service->actions[2 + status];
4172+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action;
4173+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = action;
4174+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = action;
4175+ new_service->actions[2 + NSS_STATUS_SUCCESS] = action;
4176+ new_service->actions[2 + status] = save;
4177+ }
4178+ else
4179+ new_service->actions[2 + status] = action;
4180+
4181+ /* Skip white spaces. */
4182+ while (isspace (line[0]))
4183+ ++line;
4184+ }
4185+ while (line[0] != ']');
4186+
4187+ /* Skip the ']'. */
4188+ ++line;
4189+ }
4190+
4191+ *nextp = new_service;
4192+ nextp = &new_service->next;
4193+ }
4194+}
4195+
4196+static name_database_entry *
4197+internal_function
4198+nss_getline (char *line)
4199+{
4200+ const char *name;
4201+ name_database_entry *result;
4202+ size_t len;
4203+
4204+ /* Ignore leading white spaces. ATTENTION: this is different from
4205+ what is implemented in Solaris. The Solaris man page says a line
4206+ beginning with a white space character is ignored. We regard
4207+ this as just another misfeature in Solaris. */
4208+ while (isspace (line[0]))
4209+ ++line;
4210+
4211+ /* Recognize `<database> ":"'. */
4212+ name = line;
4213+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':')
4214+ ++line;
4215+ if (line[0] == '\0' || name == line)
4216+ /* Syntax error. */
4217+ return NULL;
4218+ *line++ = '\0';
4219+
4220+ len = strlen (name) + 1;
4221+
4222+ result = (name_database_entry *) xmalloc (sizeof (*result));
4223+ result->name = (char *) xmalloc (len);
4224+
4225+ /* Save the database name. */
4226+ memcpy ((char *) result->name, name, len);
4227+
4228+ /* Parse the list of services. */
4229+ result->service = nss_parse_service_list (line);
4230+
4231+ result->next = NULL;
4232+ return result;
4233+}
4234+
4235+
4236+
4237+/* Generating code for statically initialized nsswitch structures. */
4238+
4239+
4240+/* Return the service-neutral suffix of the name of the service
4241+ library function referred to by the function F. The result is
4242+ allocated with malloc. */
4243+char *
4244+known_function_suffix (const struct function *f)
4245+{
4246+ switch (f->kind)
4247+ {
4248+ case fk_setent:
4249+ return saprintf ("set%sent", f->entry);
4250+
4251+ case fk_getent:
4252+ return saprintf ("get%sent_r", f->entry);
4253+
4254+ case fk_endent:
4255+ return saprintf ("end%sent", f->entry);
4256+
4257+ case fk_getby:
4258+ return saprintf ("get%sby%s_r", f->entry, f->key);
4259+
4260+ case fk_get:
4261+ return saprintf ("get%s_r", f->value_and_key);
4262+
4263+ default:
4264+ abort ();
4265+ }
4266+}
4267+
4268+
4269+/* Return the name of the service library function referred to by the
4270+ function F. The result is allocated with malloc. */
4271+char *
4272+known_function_name (const struct function *f)
4273+{
4274+ return saprintf ("_nss_%s_%s", f->service, known_function_suffix (f));
4275+}
4276+
4277+
4278+/* Write initialized known_function structures to OUT for
4279+ all the functions we'll use. */
4280+void
4281+generate_known_functions (FILE *out)
4282+{
4283+ int i;
4284+
4285+ /* First, generate weak references to the functions. The service
4286+ libraries depend on libc, and if these references weren't weak,
4287+ we'd be making libc depend circularly on the service
4288+ libraries. */
4289+ for (i = 0; functions[i].kind; i++)
4290+ {
4291+ char *name = known_function_name (&functions[i]);
4292+ fprintf (out, "typeof (%s) %s __attribute__ ((weak));\n",
4293+ name, name);
4294+ }
4295+ fputs ("\n", out);
4296+
4297+ /* Then, a table mapping names to functions. */
4298+ fputs ("static const known_function fixed_known_functions[] = {\n",
4299+ out);
4300+ for (i = 0; functions[i].kind; i++)
4301+ {
4302+ const struct function *f = &functions[i];
4303+ char *suffix = known_function_suffix (f);
4304+
4305+ fprintf (out, " /* %2d */ { \"%s\", _nss_%s_%s },\n",
4306+ i, suffix, f->service, suffix);
4307+ }
4308+ fputs ("};\n", out);
4309+ fputs ("\n", out);
4310+}
4311+
4312+
4313+/* Print code to OUT for an initialized array of pointers to the
4314+ 'known_function' structures needed for USER, which is for
4315+ DATABASE. Return its name, allocated with malloc. */
4316+char *
4317+generate_known_function_list (FILE *out,
4318+ const name_database_entry *database,
4319+ const service_user *user)
4320+{
4321+ char *list_name = saprintf ("fixed_%s_%s_known_funcs",
4322+ database->name, user->name);
4323+ fprintf (out, "static const known_function *%s[] = {\n",
4324+ list_name);
4325+ int i;
4326+ for (i = 0; functions[i].kind; i++)
4327+ if (strcmp (functions[i].database, database->name) == 0
4328+ && strcmp (functions[i].service, user->name) == 0)
4329+ fprintf (out, " &fixed_known_functions[%d], /* %s */\n",
4330+ i, known_function_name (&functions[i]));
4331+ fputs (" NULL\n", out);
4332+ fputs ("};\n", out);
4333+ fputs ("\n", out);
4334+
4335+ return list_name;
4336+}
4337+
4338+
4339+/* Return the name of the status value STATUS, as a statically
4340+ allocated string. */
4341+const char *
4342+lookup_status_name (enum nss_status status)
4343+{
4344+ switch (status)
4345+ {
4346+ case NSS_STATUS_TRYAGAIN: return "NSS_STATUS_TRYAGAIN";
4347+ case NSS_STATUS_UNAVAIL: return "NSS_STATUS_UNAVAIL";
4348+ case NSS_STATUS_NOTFOUND: return "NSS_STATUS_NOTFOUND";
4349+ case NSS_STATUS_SUCCESS: return "NSS_STATUS_SUCCESS";
4350+ case NSS_STATUS_RETURN: return "NSS_STATUS_RETURN";
4351+ default: abort ();
4352+ };
4353+}
4354+
4355+
4356+/* Return the name of ACTION as a statically allocated string. */
4357+const char *
4358+lookup_action_name (lookup_actions action)
4359+{
4360+ switch (action)
4361+ {
4362+ case NSS_ACTION_CONTINUE: return "NSS_ACTION_CONTINUE";
4363+ case NSS_ACTION_RETURN: return "NSS_ACTION_RETURN";
4364+ default: abort ();
4365+ }
4366+}
4367+
4368+
4369+/* Print code to OUT for the list of service_user structures starting
4370+ with USER, which are all for DATABASE. Return the name of the
4371+ first structure in that list, or zero if USER is NULL. */
4372+char *
4373+generate_service_user_list (FILE *out,
4374+ name_database_entry *database,
4375+ service_user *user)
4376+{
4377+ if (user)
4378+ {
4379+ /* Generate the tail of the list. */
4380+ char *next_name = generate_service_user_list (out, database, user->next);
4381+ /* Generate our known function list. */
4382+ char *known_function_list_name =
4383+ generate_known_function_list (out, database, user);
4384+
4385+ char *name = saprintf ("fixed_%s_%s_user", database->name, user->name);
4386+
4387+ fprintf (out, "static const service_user %s = {\n", name);
4388+ if (next_name)
4389+ fprintf (out, " (service_user *) &%s,\n", next_name);
4390+ else
4391+ fprintf (out, " NULL, /* no next entry */\n");
4392+ fputs (" {\n", out);
4393+ int i;
4394+ for (i = 0; i < sizeof (user->actions) / sizeof (user->actions[0]); i++)
4395+ fprintf (out, " %s, /* %s */\n",
4396+ lookup_action_name (user->actions[i]),
4397+ lookup_status_name (i - 2));
4398+ fputs (" },\n", out);
4399+ fprintf (out, " NULL, /* we never need the service library */\n");
4400+ fprintf (out, " { .array = %s },\n", known_function_list_name);
4401+ fprintf (out, " \"%s\"\n", user->name);
4402+ fputs ("};\n", out);
4403+ fputs ("\n", out);
4404+
4405+ return name;
4406+ }
4407+ else
4408+ return NULL;
4409+}
4410+
4411+
4412+/* Print code to OUT for the list of name_database_entry structures
4413+ starting with DATABASE. Return the name of the first structure
4414+ in that list, or zero if DATABASE is NULL. */
4415+char *
4416+generate_name_database_entries (FILE *out, name_database_entry *database)
4417+{
4418+ if (database)
4419+ {
4420+ char *next_name = generate_name_database_entries (out, database->next);
4421+ char *service_user_name
4422+ = generate_service_user_list (out, database, database->service);
4423+ char *name = saprintf ("fixed_%s_name_database", database->name);
4424+
4425+ fprintf (out, "static const name_database_entry %s = {\n", name);
4426+
4427+ if (next_name)
4428+ fprintf (out, " (name_database_entry *) &%s,\n", next_name);
4429+ else
4430+ fprintf (out, " NULL,\n");
4431+
4432+ if (service_user_name)
4433+ fprintf (out, " (service_user *) &%s,\n", service_user_name);
4434+ else
4435+ fprintf (out, " NULL,\n");
4436+
4437+ fprintf (out, " \"%s\"\n", database->name);
4438+ fprintf (out, "};\n");
4439+ fputs ("\n", out);
4440+
4441+ return name;
4442+ }
4443+ else
4444+ return NULL;
4445+}
4446+
4447+
4448+void
4449+generate_name_database (FILE *out, name_database *service_table)
4450+{
4451+ /* Produce a linked list of the known name_database_entry
4452+ structures. */
4453+ char *entries = generate_name_database_entries (out, service_table->entry);
4454+
4455+ /* Now produce the main structure that points to them all. */
4456+ fprintf (out, "static const name_database fixed_name_database = {\n");
4457+ if (entries)
4458+ fprintf (out, " (name_database_entry *) &%s,\n", entries);
4459+ else
4460+ fprintf (out, " NULL,\n");
4461+ fputs (" NULL /* we don't need the libraries */\n"
4462+ "};\n",
4463+ out);
4464+}
4465+
4466+
4467+
4468+/* Generating the list of service libraries we generate references to. */
4469+
4470+/* String with revision number of the shared object files. */
4471+static const char *const nss_shlib_revision = LIBNSS_FILES_SO + 15;
4472+
4473+void
4474+generate_service_lib_list (FILE *out, name_database *service_table)
4475+{
4476+ int i, j;
4477+ int printed_any = 0;
4478+
4479+ for (i = 0; functions[i].kind; i++)
4480+ {
4481+ /* Mention each service library only once. */
4482+ for (j = 0; j < i; j++)
4483+ if (strcmp (functions[i].service, functions[j].service) == 0)
4484+ break;
4485+
4486+ if (j >= i)
4487+ {
4488+ if (printed_any)
4489+ putc (' ', out);
4490+ fprintf (out, "-lnss_%s",
4491+ functions[i].service,
4492+ nss_shlib_revision);
4493+ printed_any = 1;
4494+ }
4495+ }
4496+}
4497+
4498+
4499+/* Main. */
4500+
4501+int
4502+main (int argc, char **argv)
4503+{
4504+ if (argc != 4)
4505+ {
4506+ fprintf (stderr, "usage: gen-fixed-nsswitch HEADER SERVLIBS CONFIG\n");
4507+ exit (1);
4508+ }
4509+
4510+ name_database *service_table = nss_parse_file (argv[3]);
4511+
4512+ FILE *header = fopen (argv[1], "w");
4513+ if (! header)
4514+ {
4515+ fprintf (stderr,
4516+ "gen-fixed-nsswitch: couldn't open output file %s: %s\n",
4517+ argv[1], strerror (errno));
4518+ exit (1);
4519+ }
4520+ fputs ("/* Generated by nss/gen-fixed-nsswitch.c. */\n", header);
4521+ fputs ("\n", header);
4522+ generate_known_functions (header);
4523+ generate_name_database (header, service_table);
4524+ fclose (header);
4525+
4526+ FILE *service_lib_list = fopen (argv[2], "w");
4527+ if (! service_lib_list)
4528+ {
4529+ fprintf (stderr,
4530+ "gen-fixed-nsswitch: couldn't open output file %s: %s\n",
4531+ argv[2], strerror (errno));
4532+ exit (1);
4533+ }
4534+ generate_service_lib_list (service_lib_list, service_table);
4535+ fclose (service_lib_list);
4536+
4537+ return 0;
4538+}
4539diff --git a/nss/getent.c b/nss/getent.c
4540index 34df848..674c8ee 100644
4541--- a/nss/getent.c
4542+++ b/nss/getent.c
4543@@ -39,6 +39,7 @@
4544 #include <netinet/ether.h>
4545 #include <netinet/in.h>
4546 #include <sys/socket.h>
4547+#include <gnu/option-groups.h>
4548
4549 /* Get libc version number. */
4550 #include <version.h>
4551@@ -91,6 +92,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
4552 fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
4553 }
4554
4555+#if __OPTION_EGLIBC_DB_ALIASES
4556 /* This is for aliases */
4557 static void
4558 print_aliases (struct aliasent *alias)
4559@@ -135,7 +137,9 @@ aliases_keys (int number, char *key[])
4560
4561 return result;
4562 }
4563+#endif /* __OPTION_EGLIBC_DB_ALIASES */
4564
4565+#if __OPTION_EGLIBC_INET
4566 /* This is for ethers */
4567 static int
4568 ethers_keys (int number, char *key[])
4569@@ -179,6 +183,7 @@ ethers_keys (int number, char *key[])
4570
4571 return result;
4572 }
4573+#endif /* __OPTION_EGLIBC_INET */
4574
4575 /* This is for group */
4576 static void
4577@@ -301,6 +306,7 @@ gshadow_keys (int number, char *key[])
4578 return result;
4579 }
4580
4581+#if __OPTION_EGLIBC_INET
4582 /* This is for hosts */
4583 static void
4584 print_hosts (struct hostent *host)
4585@@ -598,6 +604,7 @@ networks_keys (int number, char *key[])
4586
4587 return result;
4588 }
4589+#endif /* __OPTION_EGLIBC_INET */
4590
4591 /* Now is all for passwd */
4592 static void
4593@@ -650,6 +657,7 @@ passwd_keys (int number, char *key[])
4594 return result;
4595 }
4596
4597+#if __OPTION_EGLIBC_INET
4598 /* This is for protocols */
4599 static void
4600 print_protocols (struct protoent *proto)
4601@@ -807,6 +815,7 @@ services_keys (int number, char *key[])
4602
4603 return result;
4604 }
4605+#endif /* __OPTION_EGLIBC_INET */
4606
4607 /* This is for shadow */
4608 static void
4609@@ -873,23 +882,36 @@ struct
4610 } databases[] =
4611 {
4612 #define D(name) { #name, name ## _keys },
4613-D(ahosts)
4614-D(ahostsv4)
4615-D(ahostsv6)
4616-D(aliases)
4617-D(ethers)
4618+
4619+#if __OPTION_EGLIBC_INET
4620+# define DN(name) D(name)
4621+#else
4622+# define DN(name)
4623+#endif
4624+
4625+#if __OPTION_EGLIBC_DB_ALIASES
4626+# define DA(name) D(name)
4627+#else
4628+# define DA(name)
4629+#endif
4630+
4631+DN(ahosts)
4632+DN(ahostsv4)
4633+DN(ahostsv6)
4634+DA(aliases)
4635+DN(ethers)
4636 D(group)
4637 D(gshadow)
4638-D(hosts)
4639-D(initgroups)
4640-D(netgroup)
4641-D(networks)
4642+DN(hosts)
4643+DN(initgroups)
4644+DN(netgroup)
4645+DN(networks)
4646 D(passwd)
4647-D(protocols)
4648+DN(protocols)
4649 #if HAVE_SUNRPC
4650-D(rpc)
4651+DN(rpc)
4652 #endif
4653-D(services)
4654+DN(services)
4655 D(shadow)
4656 #undef D
4657 { NULL, NULL }
4658diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c
4659index f5b9036..f09f7fe 100644
4660--- a/nss/getnssent_r.c
4661+++ b/nss/getnssent_r.c
4662@@ -16,6 +16,7 @@
4663 <http://www.gnu.org/licenses/>. */
4664
4665 #include <errno.h>
4666+#include <gnu/option-groups.h>
4667 #include <netdb.h>
4668 #include "nsswitch.h"
4669
4670@@ -59,11 +60,13 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct,
4671 } fct;
4672 int no_more;
4673
4674+#if __OPTION_EGLIBC_INET
4675 if (res && __res_maybe_init (&_res, 0) == -1)
4676 {
4677 __set_h_errno (NETDB_INTERNAL);
4678 return;
4679 }
4680+#endif /* __OPTION_EGLIBC_INET */
4681
4682 /* Cycle through the services and run their `setXXent' functions until
4683 we find an available service. */
4684@@ -101,11 +104,13 @@ __nss_endent (const char *func_name, db_lookup_function lookup_fct,
4685 } fct;
4686 int no_more;
4687
4688+#if __OPTION_EGLIBC_INET
4689 if (res && __res_maybe_init (&_res, 0) == -1)
4690 {
4691 __set_h_errno (NETDB_INTERNAL);
4692 return;
4693 }
4694+#endif /* __OPTION_EGLIBC_INET */
4695
4696 /* Cycle through all the services and run their endXXent functions. */
4697 no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1);
4698@@ -141,12 +146,14 @@ __nss_getent_r (const char *getent_func_name,
4699 int no_more;
4700 enum nss_status status;
4701
4702+#if __OPTION_EGLIBC_INET
4703 if (res && __res_maybe_init (&_res, 0) == -1)
4704 {
4705 *h_errnop = NETDB_INTERNAL;
4706 *result = NULL;
4707 return errno;
4708 }
4709+#endif /* __OPTION_EGLIBC_INET */
4710
4711 /* Initialize status to return if no more functions are found. */
4712 status = NSS_STATUS_NOTFOUND;
4713@@ -161,7 +168,7 @@ __nss_getent_r (const char *getent_func_name,
4714 int is_last_nip = *nip == *last_nip;
4715
4716 status = DL_CALL_FCT (fct.f,
4717- (resbuf, buffer, buflen, &errno, &h_errno));
4718+ (resbuf, buffer, buflen, &errno, h_errnop));
4719
4720 /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
4721 provided buffer is too small. In this case we should give
4722diff --git a/nss/nsswitch.c b/nss/nsswitch.c
4723index 9712623..c81e207 100644
4724--- a/nss/nsswitch.c
4725+++ b/nss/nsswitch.c
4726@@ -26,6 +26,7 @@
4727 #include <stdio_ext.h>
4728 #include <stdlib.h>
4729 #include <string.h>
4730+#include <gnu/option-groups.h>
4731
4732 #include <aliases.h>
4733 #include <grp.h>
4734@@ -41,6 +42,15 @@
4735 #include "../nscd/nscd_proto.h"
4736 #include <sysdep.h>
4737
4738+/* When OPTION_EGLIBC_NSSWITCH is disabled, we use fixed tables of
4739+ databases and services, generated at library build time. Thus:
4740+ - We can't reconfigure individual databases, so we don't need a
4741+ name-to-database map.
4742+ - We never add databases or service libraries, or look up functions
4743+ at runtime, so there's no need for a lock to protect our tables.
4744+ See ../option-groups.def for the details. */
4745+#if __OPTION_EGLIBC_NSSWITCH
4746+
4747 /* Prototypes for the local functions. */
4748 static name_database *nss_parse_file (const char *fname) internal_function;
4749 static name_database_entry *nss_getline (char *line) internal_function;
4750@@ -79,6 +89,9 @@ bool __nss_database_custom[NSS_DBSIDX_max];
4751
4752 __libc_lock_define_initialized (static, lock)
4753
4754+#define lock_nsswitch __libc_lock_lock (lock)
4755+#define unlock_nsswitch __libc_lock_unlock (lock)
4756+
4757 #if !defined DO_STATIC_NSS || defined SHARED
4758 /* String with revision number of the shared object files. */
4759 static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
4760@@ -93,6 +106,20 @@ static name_database *service_table;
4761 __libc_freeres. */
4762 static name_database_entry *defconfig_entries;
4763
4764+#else /* __OPTION_EGLIBC_NSSWITCH */
4765+
4766+/* Bring in the statically initialized service table we generated at
4767+ build time. */
4768+#include "fixed-nsswitch.h"
4769+
4770+const static name_database *service_table = &fixed_name_database;
4771+
4772+/* Nothing ever changes, so there's no need to lock anything. */
4773+#define lock_nsswitch (0)
4774+#define unlock_nsswitch (0)
4775+
4776+#endif /* __OPTION_EGLIBC_NSSWITCH */
4777+
4778
4779 #ifdef USE_NSCD
4780 /* Nonzero if this is the nscd process. */
4781@@ -109,20 +136,22 @@ __nss_database_lookup (const char *database, const char *alternate_name,
4782 const char *defconfig, service_user **ni)
4783 {
4784 /* Prevent multiple threads to change the service table. */
4785- __libc_lock_lock (lock);
4786+ lock_nsswitch;
4787
4788 /* Reconsider database variable in case some other thread called
4789 `__nss_configure_lookup' while we waited for the lock. */
4790 if (*ni != NULL)
4791 {
4792- __libc_lock_unlock (lock);
4793+ unlock_nsswitch;
4794 return 0;
4795 }
4796
4797+#if __OPTION_EGLIBC_NSSWITCH
4798 /* Are we initialized yet? */
4799 if (service_table == NULL)
4800 /* Read config file. */
4801 service_table = nss_parse_file (_PATH_NSSWITCH_CONF);
4802+#endif
4803
4804 /* Test whether configuration data is available. */
4805 if (service_table != NULL)
4806@@ -144,6 +173,7 @@ __nss_database_lookup (const char *database, const char *alternate_name,
4807 *ni = entry->service;
4808 }
4809
4810+#if __OPTION_EGLIBC_NSSWITCH
4811 /* No configuration data is available, either because nsswitch.conf
4812 doesn't exist or because it doesn't have a line for this database.
4813
4814@@ -166,13 +196,23 @@ __nss_database_lookup (const char *database, const char *alternate_name,
4815 {
4816 entry->next = defconfig_entries;
4817 entry->service = *ni;
4818- entry->name[0] = '\0';
4819+ entry->name = "";
4820 defconfig_entries = entry;
4821 }
4822 }
4823 }
4824+#else
4825+ /* Without the dynamic behavior, we can't process defconfig. The
4826+ databases the user specified at library build time are all you
4827+ get. */
4828+ if (*ni == NULL)
4829+ {
4830+ unlock_nsswitch;
4831+ return -1;
4832+ }
4833+#endif
4834
4835- __libc_lock_unlock (lock);
4836+ unlock_nsswitch;
4837
4838 return *ni != NULL ? 0 : -1;
4839 }
4840@@ -252,6 +292,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name,
4841 libc_hidden_def (__nss_next2)
4842
4843
4844+#if __OPTION_EGLIBC_NSSWITCH
4845 int
4846 attribute_compat_text_section
4847 __nss_next (service_user **ni, const char *fct_name, void **fctp, int status,
4848@@ -300,13 +341,13 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
4849 }
4850
4851 /* Prevent multiple threads to change the service table. */
4852- __libc_lock_lock (lock);
4853+ lock_nsswitch;
4854
4855 /* Install new rules. */
4856 *databases[cnt].dbp = new_db;
4857 __nss_database_custom[cnt] = true;
4858
4859- __libc_lock_unlock (lock);
4860+ unlock_nsswitch;
4861
4862 return 0;
4863 }
4864@@ -402,7 +443,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
4865 void **found, *result;
4866
4867 /* We now modify global data. Protect it. */
4868- __libc_lock_lock (lock);
4869+ lock_nsswitch;
4870
4871 /* Search the tree of functions previously requested. Data in the
4872 tree are `known_function' structures, whose first member is a
4873@@ -413,7 +454,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
4874 enough to a pointer to our structure to use as a lookup key that
4875 will be passed to `known_compare' (above). */
4876
4877- found = __tsearch (&fct_name, &ni->known, &known_compare);
4878+ found = __tsearch (&fct_name, &ni->known.tree, &known_compare);
4879 if (found == NULL)
4880 /* This means out-of-memory. */
4881 result = NULL;
4882@@ -440,7 +481,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
4883 #endif
4884 /* Oops. We can't instantiate this node properly.
4885 Remove it from the tree. */
4886- __tdelete (&fct_name, &ni->known, &known_compare);
4887+ __tdelete (&fct_name, &ni->known.tree, &known_compare);
4888 free (known);
4889 result = NULL;
4890 }
4891@@ -520,13 +561,43 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
4892 }
4893
4894 /* Remove the lock. */
4895- __libc_lock_unlock (lock);
4896+ unlock_nsswitch;
4897
4898 return result;
4899 }
4900 libc_hidden_def (__nss_lookup_function)
4901
4902
4903+#else /* below if ! __OPTION_EGLIBC_NSSWITCH */
4904+
4905+
4906+int
4907+__nss_configure_lookup (const char *dbname, const char *service_line)
4908+{
4909+ /* We can't dynamically configure lookup without
4910+ OPTION_EGLIBC_NSSWITCH. */
4911+ __set_errno (EINVAL);
4912+ return -1;
4913+}
4914+
4915+
4916+void *
4917+__nss_lookup_function (service_user *ni, const char *fct_name)
4918+{
4919+ int i;
4920+ const known_function **known = ni->known.array;
4921+
4922+ for (i = 0; known[i]; i++)
4923+ if (strcmp (fct_name, known[i]->fct_name) == 0)
4924+ return known[i]->fct_ptr;
4925+
4926+ return NULL;
4927+}
4928+libc_hidden_def (__nss_lookup_function)
4929+#endif
4930+
4931+
4932+#if __OPTION_EGLIBC_NSSWITCH
4933 static name_database *
4934 internal_function
4935 nss_parse_file (const char *fname)
4936@@ -632,8 +703,10 @@ nss_parse_service_list (const char *line)
4937 + (line - name + 1));
4938 if (new_service == NULL)
4939 return result;
4940+ new_service->name = (char *) (new_service + 1);
4941
4942- *((char *) __mempcpy (new_service->name, name, line - name)) = '\0';
4943+ *((char *) __mempcpy ((char *) new_service->name, name, line - name))
4944+ = '\0';
4945
4946 /* Set default actions. */
4947 new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
4948@@ -642,7 +715,7 @@ nss_parse_service_list (const char *line)
4949 new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
4950 new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
4951 new_service->library = NULL;
4952- new_service->known = NULL;
4953+ new_service->known.tree = NULL;
4954 new_service->next = NULL;
4955
4956 while (isspace (line[0]))
4957@@ -778,9 +851,10 @@ nss_getline (char *line)
4958 result = (name_database_entry *) malloc (sizeof (name_database_entry) + len);
4959 if (result == NULL)
4960 return NULL;
4961+ result->name = (char *) (result + 1);
4962
4963 /* Save the database name. */
4964- memcpy (result->name, name, len);
4965+ memcpy ((char *) result->name, name, len);
4966
4967 /* Parse the list of services. */
4968 result->service = nss_parse_service_list (line);
4969@@ -816,6 +890,7 @@ nss_new_service (name_database *database, const char *name)
4970 return *currentp;
4971 }
4972 #endif
4973+#endif /* __OPTION_EGLIBC_NSSWITCH */
4974
4975
4976 #if defined SHARED && defined USE_NSCD
4977@@ -834,6 +909,7 @@ nss_load_all_libraries (const char *service, const char *def)
4978 }
4979
4980
4981+#if __OPTION_EGLIBC_INET
4982 /* Called by nscd and nscd alone. */
4983 void
4984 __nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
4985@@ -857,8 +933,10 @@ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
4986 __nss_not_use_nscd_services = -1;
4987 __nss_not_use_nscd_netgroup = -1;
4988 }
4989+#endif /* __OPTION_EGLIBC_INET */
4990 #endif
4991
4992+#if __OPTION_EGLIBC_NSSWITCH
4993 static void
4994 free_database_entries (name_database_entry *entry)
4995 {
4996@@ -871,8 +949,8 @@ free_database_entries (name_database_entry *entry)
4997 {
4998 service_user *olds = service;
4999
5000- if (service->known != NULL)
5001- __tdestroy (service->known, free);
5002+ if (service->known.tree != NULL)
5003+ __tdestroy (service->known.tree, free);
5004
5005 service = service->next;
5006 free (olds);
5007@@ -926,3 +1004,4 @@ libc_freeres_fn (free_mem)
5008
5009 free (top);
5010 }
5011+#endif /* __OPTION_EGLIBC_NSSWITCH */
5012diff --git a/nss/nsswitch.h b/nss/nsswitch.h
5013index a5318fa..1730977 100644
5014--- a/nss/nsswitch.h
5015+++ b/nss/nsswitch.h
5016@@ -65,10 +65,20 @@ typedef struct service_user
5017 lookup_actions actions[5];
5018 /* Link to the underlying library object. */
5019 service_library *library;
5020- /* Collection of known functions. */
5021- void *known;
5022+ /* Collection of known functions.
5023+
5024+ With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a
5025+ 'tsearch'-style tree.
5026+
5027+ With OPTION_EGLIBC_NSSWITCH disabled, this is an array of
5028+ pointers to known_function structures, NULL-terminated. */
5029+ union
5030+ {
5031+ void *tree;
5032+ const known_function **array;
5033+ } known;
5034 /* Name of the service (`files', `dns', `nis', ...). */
5035- char name[0];
5036+ const char *name;
5037 } service_user;
5038
5039 /* To access the action based on the status value use this macro. */
5040@@ -82,7 +92,7 @@ typedef struct name_database_entry
5041 /* List of service to be used. */
5042 service_user *service;
5043 /* Name of the database. */
5044- char name[0];
5045+ const char *name;
5046 } name_database_entry;
5047
5048
5049diff --git a/posix/Makefile b/posix/Makefile
5050index 15e8818..609ed03 100644
5051--- a/posix/Makefile
5052+++ b/posix/Makefile
5053@@ -18,6 +18,8 @@
5054 #
5055 # Sub-makefile for POSIX portion of the library.
5056 #
5057+include ../option-groups.mak
5058+
5059 subdir := posix
5060
5061 include ../Makeconfig
5062@@ -43,13 +45,24 @@ routines := \
5063 getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \
5064 getresuid getresgid setresuid setresgid \
5065 pathconf sysconf fpathconf \
5066- glob glob64 fnmatch regex \
5067+ glob glob64 fnmatch \
5068 confstr \
5069 getopt getopt1 getopt_init \
5070 sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \
5071 sched_primin sched_rr_gi sched_getaffinity sched_setaffinity \
5072- getaddrinfo gai_strerror wordexp \
5073 pread pwrite pread64 pwrite64 \
5074+ posix_madvise \
5075+ get_child_max sched_cpucount sched_cpualloc sched_cpufree
5076+
5077+routines-$(OPTION_EGLIBC_INET) += getaddrinfo gai_strerror
5078+
5079+ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC))
5080+routines-$(OPTION_POSIX_REGEXP) += regex
5081+else
5082+routines-$(OPTION_POSIX_REGEXP) += xregex
5083+endif
5084+
5085+routines-$(OPTION_EGLIBC_SPAWN) += \
5086 spawn_faction_init spawn_faction_destroy spawn_faction_addclose \
5087 spawn_faction_addopen spawn_faction_adddup2 \
5088 spawnattr_init spawnattr_destroy \
5089@@ -61,37 +74,54 @@ routines := \
5090 posix_madvise \
5091 get_child_max sched_cpucount sched_cpualloc sched_cpufree
5092
5093+routines-$(OPTION_EGLIBC_WORDEXP) += wordexp
5094+
5095 aux := init-posix environ
5096-tests := tstgetopt testfnm runtests runptests \
5097+tests := tstgetopt testfnm runtests \
5098 tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \
5099- tst-mmap tst-getaddrinfo tst-truncate \
5100- tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \
5101- tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \
5102- tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \
5103- bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
5104- bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
5105- bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
5106- bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
5107- bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
5108+ tst-mmap tst-truncate \
5109+ tst-truncate64 tst-fork tst-dir \
5110+ tst-chmod bug-regex2 bug-regex3 bug-regex4 \
5111+ tst-gnuglob bug-regex6 bug-regex7 \
5112+ bug-regex8 bug-regex9 bug-regex10 bug-regex12 \
5113+ bug-regex14 bug-regex15 \
5114+ bug-regex21 bug-regex24 \
5115+ bug-regex27 bug-regex28 \
5116 bug-regex29 bug-regex30 bug-regex31 bug-regex32 \
5117- bug-regex33 tst-nice tst-nanosleep tst-regex2 \
5118- transbug tst-rxspencer tst-pcre tst-boost \
5119- bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
5120- tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \
5121+ tst-nice tst-nanosleep \
5122+ transbug \
5123+ tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
5124+ bug-glob1 bug-glob2 bug-glob3 tst-sysconf \
5125 tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
5126 tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
5127 tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
5128- tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
5129- tst-rfc3484-3 \
5130- tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \
5131+ tst-execvp3 tst-execvp4 \
5132+ tst-fnmatch2 tst-cpucount tst-cpuset \
5133 bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
5134 bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
5135 tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
5136 tst-fnmatch3 bug-regex36 tst-getaddrinfo5
5137-xtests := bug-ga2
5138+
5139+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
5140+ += tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \
5141+ bug-regex23 bug-regex25 bug-regex32 bug-regex33
5142+tests-$(OPTION_EGLIBC_INET) \
5143+ += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \
5144+ tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 tst-getaddrinfo3
5145+tests-$(OPTION_POSIX_REGEXP_GLIBC) \
5146+ += runptests bug-regex11 bug-regex13 bug-regex16 \
5147+ tst-regex2 tst-rxspencer tst-pcre tst-boost
5148+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP_GLIBC))
5149+tests += tst-regex bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
5150+ bug-regex22 bug-regex26
5151+endif
5152+xtests-$(OPTION_EGLIBC_INET) += bug-ga2
5153+
5154 ifeq (yes,$(build-shared))
5155 test-srcs := globtest
5156-tests += wordexp-test tst-exec tst-spawn
5157+tests += tst-exec
5158+tests-$(OPTION_EGLIBC_SPAWN) += tst-spawn
5159+tests-$(OPTION_EGLIBC_WORDEXP) += wordexp-test
5160 endif
5161 tests-static = tst-exec-static tst-spawn-static
5162 tests += $(tests-static)
5163@@ -117,7 +147,10 @@ generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
5164
5165 ifeq ($(run-built-tests),yes)
5166 ifeq (yes,$(build-shared))
5167-tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out
5168+tests-special += $(objpfx)globtest.out
5169+ifeq (y,$(OPTION_EGLIBC_WORDEXP))
5170+tests-special += $(objpfx)wordexp-tst.out
5171+endif
5172 endif
5173 endif
5174
5175@@ -125,12 +158,16 @@ endif
5176 # XXX Please note that for now we ignore the result of this test.
5177 tests-special += $(objpfx)annexc.out
5178 ifeq ($(run-built-tests),yes)
5179-tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
5180+tests-special += $(objpfx)bug-regex2-mem.out \
5181 $(objpfx)bug-regex21-mem.out $(objpfx)bug-regex31-mem.out \
5182- $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
5183- $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
5184+ $(objpfx)tst-getconf.out \
5185 $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
5186 $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
5187+ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC))
5188+tests-special += $(objpfx)bug-regex14-mem.out $(objpfx)tst-rxspencer-no-utf8-mem.out \
5189+ $(objpfx)tst-pcre-mem.out $(objpfx)tst-boost-mem.out
5190+endif
5191+
5192 xtests-special += $(objpfx)bug-ga2-mem.out
5193 endif
5194
5195@@ -143,6 +180,8 @@ $(objpfx)globtest.out: globtest.sh $(objpfx)globtest
5196 $(SHELL) $< $(common-objpfx) '$(test-via-rtld-prefix)' \
5197 '$(test-program-prefix)' '$(test-wrapper-env)'; \
5198 $(evaluate-test)
5199+LDLIBS-globtest += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs)
5200+
5201 $(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test
5202 $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
5203 '$(run-program-env)' '$(test-program-prefix-after-env)'; \
5204@@ -205,7 +244,10 @@ tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir);
5205 tst-chmod-ARGS = $(objdir)
5206 tst-vfork3-ARGS = --test-dir=$(objpfx)
5207
5208-tst-rxspencer-ARGS = --utf8 rxspencer/tests
5209+tst-rxspencer-ARGS = rxspencer/tests
5210+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
5211+tst-rxspencer-ARGS += --utf8
5212+endif
5213 tst-rxspencer-no-utf8-ARGS = rxspencer/tests
5214 tst-pcre-ARGS = PCRE.tests
5215 tst-boost-ARGS = BOOST.tests
5216diff --git a/posix/bug-regex1.c b/posix/bug-regex1.c
5217index 38eb543..17cd1a0 100644
5218--- a/posix/bug-regex1.c
5219+++ b/posix/bug-regex1.c
5220@@ -4,6 +4,7 @@
5221 #include <string.h>
5222 #include <regex.h>
5223 #include <wchar.h>
5224+#include <gnu/option-groups.h>
5225
5226 int
5227 main (void)
5228@@ -17,7 +18,9 @@ main (void)
5229 memset (&regex, '\0', sizeof (regex));
5230
5231 setlocale (LC_ALL, "de_DE.ISO-8859-1");
5232+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
5233 fwide (stdout, -1);
5234+#endif
5235
5236 re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_DEBUG);
5237
5238diff --git a/posix/bug-regex6.c b/posix/bug-regex6.c
5239index efcc890..3b270c7 100644
5240--- a/posix/bug-regex6.c
5241+++ b/posix/bug-regex6.c
5242@@ -22,6 +22,7 @@
5243 #include <string.h>
5244 #include <sys/types.h>
5245 #include <regex.h>
5246+#include <gnu/option-groups.h>
5247
5248
5249 int
5250@@ -30,7 +31,12 @@ main (int argc, char *argv[])
5251 regex_t re;
5252 regmatch_t mat[10];
5253 int i, j, ret = 0;
5254- const char *locales[] = { "C", "de_DE.UTF-8" };
5255+ const char *locales[] = {
5256+ "C",
5257+#if __OPTION_EGLIBC_LOCALE_CODE
5258+ "de_DE.UTF-8"
5259+#endif
5260+ };
5261 const char *string = "http://www.regex.com/pattern/matching.html#intro";
5262 regmatch_t expect[10] = {
5263 { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 },
5264diff --git a/posix/fnmatch.c b/posix/fnmatch.c
5265index fd85efa..01cc9fe 100644
5266--- a/posix/fnmatch.c
5267+++ b/posix/fnmatch.c
5268@@ -30,6 +30,10 @@
5269 #include <ctype.h>
5270 #include <string.h>
5271
5272+#if defined _LIBC
5273+# include <gnu/option-groups.h>
5274+#endif
5275+
5276 #if defined STDC_HEADERS || defined _LIBC
5277 # include <stdlib.h>
5278 #endif
5279@@ -131,7 +135,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
5280 # define ISWCTYPE(WC, WT) iswctype (WC, WT)
5281 # endif
5282
5283-# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
5284+# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS && _LIBC && __OPTION_EGLIBC_LOCALE_CODE)
5285 /* In this case we are implementing the multibyte character handling. */
5286 # define HANDLE_MULTIBYTE 1
5287 # endif
5288diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
5289index f46c9df..74e1754 100644
5290--- a/posix/fnmatch_loop.c
5291+++ b/posix/fnmatch_loop.c
5292@@ -15,6 +15,8 @@
5293 License along with the GNU C Library; if not, see
5294 <http://www.gnu.org/licenses/>. */
5295
5296+#include <gnu/option-groups.h>
5297+
5298 #include <stdint.h>
5299
5300 struct STRUCT
5301@@ -54,10 +56,15 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
5302 const char *collseq = (const char *)
5303 _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
5304 # else
5305+# if __OPTION_EGLIBC_LOCALE_CODE
5306 const UCHAR *collseq = (const UCHAR *)
5307 _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
5308-# endif
5309-#endif
5310+# define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)])
5311+# else
5312+# define COLLSEQ_BYTE_LOOKUP(ix) (ix)
5313+# endif /* __OPTION_EGLIBC_LOCALE_CODE */
5314+# endif /* WIDE_CHAR_VERSION */
5315+#endif /* _LIBC */
5316
5317 while ((c = *p++) != L('\0'))
5318 {
5319@@ -277,7 +284,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
5320 /* Leave room for the null. */
5321 CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
5322 size_t c1 = 0;
5323-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
5324+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
5325 wctype_t wt;
5326 #endif
5327 const CHAR *startp = p;
5328@@ -307,7 +314,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
5329 }
5330 str[c1] = L('\0');
5331
5332-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
5333+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
5334 wt = IS_CHAR_CLASS (str);
5335 if (wt == 0)
5336 /* Invalid character class name. */
5337@@ -680,8 +687,10 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
5338 else
5339 lcollseq = __collseq_table_lookup (collseq, cold);
5340 # else
5341- fcollseq = collseq[fn];
5342- lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
5343+ fcollseq = COLLSEQ_BYTE_LOOKUP (fn);
5344+ lcollseq = (is_seqval
5345+ ? cold
5346+ : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold));
5347 # endif
5348
5349 is_seqval = 0;
5350@@ -857,7 +866,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
5351 goto matched;
5352 }
5353 # else
5354- hcollseq = collseq[cend];
5355+ hcollseq = COLLSEQ_BYTE_LOOKUP (cend);
5356 # endif
5357 }
5358
5359diff --git a/posix/glob.c b/posix/glob.c
5360index d65e55d..1ac00a1 100644
5361--- a/posix/glob.c
5362+++ b/posix/glob.c
5363@@ -25,6 +25,9 @@
5364 #include <sys/types.h>
5365 #include <sys/stat.h>
5366 #include <stddef.h>
5367+#ifdef _LIBC
5368+# include <gnu/option-groups.h>
5369+#endif
5370
5371 /* Outcomment the following line for production quality code. */
5372 /* #define NDEBUG 1 */
5373@@ -607,6 +610,7 @@ glob (pattern, flags, errfunc, pglob)
5374 if (home_dir == NULL || home_dir[0] == '\0')
5375 home_dir = "c:/users/default"; /* poor default */
5376 # else
5377+# if ! _LIBC || __OPTION_EGLIBC_GETLOGIN
5378 if (home_dir == NULL || home_dir[0] == '\0')
5379 {
5380 int success;
5381@@ -623,19 +627,19 @@ glob (pattern, flags, errfunc, pglob)
5382 if (success)
5383 {
5384 struct passwd *p;
5385-# if defined HAVE_GETPWNAM_R || defined _LIBC
5386+# if defined HAVE_GETPWNAM_R || defined _LIBC
5387 long int pwbuflen = GETPW_R_SIZE_MAX ();
5388 char *pwtmpbuf;
5389 struct passwd pwbuf;
5390 int malloc_pwtmpbuf = 0;
5391 int save = errno;
5392
5393-# ifndef _LIBC
5394+# ifndef _LIBC
5395 if (pwbuflen == -1)
5396 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
5397 Try a moderate value. */
5398 pwbuflen = 1024;
5399-# endif
5400+# endif
5401 if (__libc_use_alloca (alloca_used + pwbuflen))
5402 pwtmpbuf = alloca_account (pwbuflen, alloca_used);
5403 else
5404@@ -682,9 +686,9 @@ glob (pattern, flags, errfunc, pglob)
5405 }
5406 __set_errno (save);
5407 }
5408-# else
5409+# else
5410 p = getpwnam (name);
5411-# endif
5412+# endif
5413 if (p != NULL)
5414 {
5415 if (!malloc_pwtmpbuf)
5416@@ -713,6 +717,7 @@ glob (pattern, flags, errfunc, pglob)
5417 }
5418 }
5419 }
5420+# endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */
5421 if (home_dir == NULL || home_dir[0] == '\0')
5422 {
5423 if (flags & GLOB_TILDE_CHECK)
5424diff --git a/posix/regcomp.c b/posix/regcomp.c
5425index bf8aa16..6a41251 100644
5426--- a/posix/regcomp.c
5427+++ b/posix/regcomp.c
5428@@ -18,6 +18,7 @@
5429 <http://www.gnu.org/licenses/>. */
5430
5431 #include <stdint.h>
5432+#include <gnu/option-groups.h>
5433
5434 #ifdef _LIBC
5435 # include <locale/weight.h>
5436@@ -309,7 +310,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
5437 {
5438 re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
5439 int node_cnt;
5440- int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
5441+ int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE));
5442 for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
5443 {
5444 int node = init_state->nodes.elems[node_cnt];
5445@@ -319,9 +320,9 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
5446 {
5447 re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
5448 #ifdef RE_ENABLE_I18N
5449- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
5450+ if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
5451 {
5452- unsigned char *buf = alloca (dfa->mb_cur_max), *p;
5453+ unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p;
5454 wchar_t wc;
5455 mbstate_t state;
5456
5457@@ -352,7 +353,11 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
5458 re_set_fastmap (fastmap, icase, ch);
5459 }
5460 }
5461-#ifdef RE_ENABLE_I18N
5462+
5463+ /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current
5464+ locale is always C, which has no rules and no multi-byte
5465+ characters. */
5466+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
5467 else if (type == COMPLEX_BRACKET)
5468 {
5469 re_charset_t *cset = dfa->nodes[node].opr.mbcset;
5470@@ -380,7 +385,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
5471 i.e. where we would not find an invalid sequence. This only
5472 applies to multibyte character sets; for single byte character
5473 sets, the SIMPLE_BRACKET again suffices. */
5474- if (dfa->mb_cur_max > 1
5475+ if (dfa_mb_cur_max (dfa) > 1
5476 && (cset->nchar_classes || cset->non_match || cset->nranges
5477 # ifdef _LIBC
5478 || cset->nequiv_classes
5479@@ -408,7 +413,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
5480 memset (&state, '\0', sizeof (state));
5481 if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
5482 re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
5483- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
5484+ if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
5485 {
5486 if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state)
5487 != (size_t) -1)
5488@@ -417,7 +422,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
5489 }
5490 }
5491 }
5492-#endif /* RE_ENABLE_I18N */
5493+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
5494 else if (type == OP_PERIOD
5495 #ifdef RE_ENABLE_I18N
5496 || type == OP_UTF8_PERIOD
5497@@ -860,11 +865,15 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
5498
5499 dfa->mb_cur_max = MB_CUR_MAX;
5500 #ifdef _LIBC
5501- if (dfa->mb_cur_max == 6
5502+ if (dfa_mb_cur_max (dfa) == 6
5503 && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
5504 dfa->is_utf8 = 1;
5505+# if __OPTION_EGLIBC_LOCALE_CODE
5506 dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
5507 != 0);
5508+# else
5509+ dfa->map_notascii = 0;
5510+# endif
5511 #else
5512 # ifdef HAVE_LANGINFO_CODESET
5513 codeset_name = nl_langinfo (CODESET);
5514@@ -890,7 +899,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
5515 #endif
5516
5517 #ifdef RE_ENABLE_I18N
5518- if (dfa->mb_cur_max > 1)
5519+ if (dfa_mb_cur_max (dfa) > 1)
5520 {
5521 if (dfa->is_utf8)
5522 dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
5523@@ -1788,7 +1797,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
5524 token->word_char = 0;
5525 #ifdef RE_ENABLE_I18N
5526 token->mb_partial = 0;
5527- if (input->mb_cur_max > 1 &&
5528+ if (string_mb_cur_max (input) > 1 &&
5529 !re_string_first_byte (input, re_string_cur_idx (input)))
5530 {
5531 token->type = CHARACTER;
5532@@ -1809,7 +1818,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
5533 token->opr.c = c2;
5534 token->type = CHARACTER;
5535 #ifdef RE_ENABLE_I18N
5536- if (input->mb_cur_max > 1)
5537+ if (string_mb_cur_max (input) > 1)
5538 {
5539 wint_t wc = re_string_wchar_at (input,
5540 re_string_cur_idx (input) + 1);
5541@@ -1923,7 +1932,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
5542
5543 token->type = CHARACTER;
5544 #ifdef RE_ENABLE_I18N
5545- if (input->mb_cur_max > 1)
5546+ if (string_mb_cur_max (input) > 1)
5547 {
5548 wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
5549 token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
5550@@ -2023,7 +2032,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
5551 token->opr.c = c;
5552
5553 #ifdef RE_ENABLE_I18N
5554- if (input->mb_cur_max > 1 &&
5555+ if (string_mb_cur_max (input) > 1 &&
5556 !re_string_first_byte (input, re_string_cur_idx (input)))
5557 {
5558 token->type = CHARACTER;
5559@@ -2246,7 +2255,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
5560 return NULL;
5561 }
5562 #ifdef RE_ENABLE_I18N
5563- if (dfa->mb_cur_max > 1)
5564+ if (dfa_mb_cur_max (dfa) > 1)
5565 {
5566 while (!re_string_eoi (regexp)
5567 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
5568@@ -2384,7 +2393,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
5569 *err = REG_ESPACE;
5570 return NULL;
5571 }
5572- if (dfa->mb_cur_max > 1)
5573+ if (dfa_mb_cur_max (dfa) > 1)
5574 dfa->has_mb_node = 1;
5575 break;
5576 case OP_WORD:
5577@@ -2690,7 +2699,7 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
5578 However, for !_LIBC we have no collation elements: if the
5579 character set is single byte, the single byte character set
5580 that we build below suffices. parse_bracket_exp passes
5581- no MBCSET if dfa->mb_cur_max == 1. */
5582+ no MBCSET if dfa_mb_cur_max (dfa) == 1. */
5583 if (mbcset)
5584 {
5585 /* Check the space of the arrays. */
5586@@ -2786,7 +2795,13 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5587 reg_syntax_t syntax, reg_errcode_t *err)
5588 {
5589 #ifdef _LIBC
5590+#if __OPTION_EGLIBC_LOCALE_CODE
5591 const unsigned char *collseqmb;
5592+# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)])
5593+#else
5594+# define COLLSEQMB_LOOKUP(ix) (ix)
5595+#endif
5596+
5597 const char *collseqwc;
5598 uint32_t nrules;
5599 int32_t table_size;
5600@@ -2834,18 +2849,20 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5601 if (MB_CUR_MAX == 1)
5602 */
5603 if (nrules == 0)
5604- return collseqmb[br_elem->opr.ch];
5605+ return COLLSEQMB_LOOKUP (br_elem->opr.ch);
5606 else
5607 {
5608 wint_t wc = __btowc (br_elem->opr.ch);
5609 return __collseq_table_lookup (collseqwc, wc);
5610 }
5611 }
5612+#if __OPTION_EGLIBC_LOCALE_CODE
5613 else if (br_elem->type == MB_CHAR)
5614 {
5615 if (nrules != 0)
5616 return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
5617 }
5618+#endif
5619 else if (br_elem->type == COLL_SYM)
5620 {
5621 size_t sym_name_len = strlen ((char *) br_elem->opr.name);
5622@@ -2876,11 +2893,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5623 {
5624 /* No valid character. Match it as a single byte
5625 character. */
5626- return collseqmb[br_elem->opr.name[0]];
5627+ return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
5628 }
5629 }
5630 else if (sym_name_len == 1)
5631- return collseqmb[br_elem->opr.name[0]];
5632+ return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
5633 }
5634 return UINT_MAX;
5635 }
5636@@ -2920,7 +2937,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5637 However, if we have no collation elements, and the character set
5638 is single byte, the single byte character set that we
5639 build below suffices. */
5640- if (nrules > 0 || dfa->mb_cur_max > 1)
5641+ if (nrules > 0 || dfa_mb_cur_max (dfa) > 1)
5642 {
5643 /* Check the space of the arrays. */
5644 if (BE (*range_alloc == mbcset->nranges, 0))
5645@@ -2957,7 +2974,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5646 if (MB_CUR_MAX == 1)
5647 */
5648 if (nrules == 0)
5649- ch_collseq = collseqmb[ch];
5650+ ch_collseq = COLLSEQMB_LOOKUP (ch);
5651 else
5652 ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
5653 if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
5654@@ -3035,7 +3052,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5655 re_bitset_ptr_t sbcset;
5656 #ifdef RE_ENABLE_I18N
5657 re_charset_t *mbcset;
5658- int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
5659+ int coll_sym_alloc = 0, range_alloc = 0;
5660+#if __OPTION_EGLIBC_LOCALE_CODE
5661+ int mbchar_alloc = 0;
5662+#endif
5663 int equiv_class_alloc = 0, char_class_alloc = 0;
5664 #endif /* not RE_ENABLE_I18N */
5665 int non_match = 0;
5666@@ -3043,9 +3063,15 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5667 int token_len;
5668 int first_round = 1;
5669 #ifdef _LIBC
5670+#if __OPTION_EGLIBC_LOCALE_CODE
5671 collseqmb = (const unsigned char *)
5672 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
5673 nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
5674+#else
5675+ /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the
5676+ compiler can't figure that out. */
5677+ nrules = 0;
5678+#endif
5679 if (nrules)
5680 {
5681 /*
5682@@ -3175,7 +3201,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5683 #else
5684 # ifdef RE_ENABLE_I18N
5685 *err = build_range_exp (sbcset,
5686- dfa->mb_cur_max > 1 ? mbcset : NULL,
5687+ dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL,
5688 &range_alloc, &start_elem, &end_elem);
5689 # else
5690 *err = build_range_exp (sbcset, &start_elem, &end_elem);
5691@@ -3191,7 +3217,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5692 case SB_CHAR:
5693 bitset_set (sbcset, start_elem.opr.ch);
5694 break;
5695-#ifdef RE_ENABLE_I18N
5696+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
5697 case MB_CHAR:
5698 /* Check whether the array has enough space. */
5699 if (BE (mbchar_alloc == mbcset->nmbchars, 0))
5700@@ -3209,7 +3235,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5701 }
5702 mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
5703 break;
5704-#endif /* RE_ENABLE_I18N */
5705+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
5706 case EQUIV_CLASS:
5707 *err = build_equiv_class (sbcset,
5708 #ifdef RE_ENABLE_I18N
5709@@ -3259,11 +3285,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
5710
5711 #ifdef RE_ENABLE_I18N
5712 /* Ensure only single byte characters are set. */
5713- if (dfa->mb_cur_max > 1)
5714+ if (dfa_mb_cur_max (dfa) > 1)
5715 bitset_mask (sbcset, dfa->sb_char);
5716
5717 if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
5718- || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
5719+ || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes
5720 || mbcset->non_match)))
5721 {
5722 bin_tree_t *mbc_tree;
5723@@ -3332,7 +3358,7 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
5724 re_token_t *token, int token_len, re_dfa_t *dfa,
5725 reg_syntax_t syntax, int accept_hyphen)
5726 {
5727-#ifdef RE_ENABLE_I18N
5728+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
5729 int cur_char_size;
5730 cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
5731 if (cur_char_size > 1)
5732@@ -3342,7 +3368,7 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
5733 re_string_skip_bytes (regexp, cur_char_size);
5734 return REG_NOERROR;
5735 }
5736-#endif /* RE_ENABLE_I18N */
5737+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
5738 re_string_skip_bytes (regexp, token_len); /* Skip a token. */
5739 if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
5740 || token->type == OP_OPEN_EQUIV_CLASS)
5741@@ -3422,7 +3448,9 @@ build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
5742 build_equiv_class (bitset_t sbcset, const unsigned char *name)
5743 #endif /* not RE_ENABLE_I18N */
5744 {
5745-#ifdef _LIBC
5746+ /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale
5747+ is supported; it has no collation rules. */
5748+#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
5749 uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
5750 if (nrules != 0)
5751 {
5752@@ -3492,7 +3520,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
5753 mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
5754 }
5755 else
5756-#endif /* _LIBC */
5757+#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
5758 {
5759 if (BE (strlen ((const char *) name) != 1, 0))
5760 return REG_ECOLLATE;
5761@@ -3526,7 +3554,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
5762 && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
5763 name = "alpha";
5764
5765-#ifdef RE_ENABLE_I18N
5766+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
5767 /* Check the space of the arrays. */
5768 if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
5769 {
5770@@ -3542,7 +3570,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
5771 *char_class_alloc = new_char_class_alloc;
5772 }
5773 mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
5774-#endif /* RE_ENABLE_I18N */
5775+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
5776
5777 #define BUILD_CHARCLASS_LOOP(ctype_func) \
5778 do { \
5779@@ -3653,7 +3681,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
5780
5781 #ifdef RE_ENABLE_I18N
5782 /* Ensure only single byte characters are set. */
5783- if (dfa->mb_cur_max > 1)
5784+ if (dfa_mb_cur_max (dfa) > 1)
5785 bitset_mask (sbcset, dfa->sb_char);
5786 #endif
5787
5788@@ -3665,7 +3693,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
5789 goto build_word_op_espace;
5790
5791 #ifdef RE_ENABLE_I18N
5792- if (dfa->mb_cur_max > 1)
5793+ if (dfa_mb_cur_max (dfa) > 1)
5794 {
5795 bin_tree_t *mbc_tree;
5796 /* Build a tree for complex bracket. */
5797diff --git a/posix/regex.h b/posix/regex.h
5798index 5b1981e..2941f94 100644
5799--- a/posix/regex.h
5800+++ b/posix/regex.h
5801@@ -21,6 +21,7 @@
5802 #define _REGEX_H 1
5803
5804 #include <sys/types.h>
5805+#include <gnu/option-groups.h>
5806
5807 /* Allow the use in C++ code. */
5808 #ifdef __cplusplus
5809@@ -156,6 +157,8 @@ typedef unsigned long int reg_syntax_t;
5810 treated as 'a\{1'. */
5811 # define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
5812
5813+/* EGLIBC: Old regex implementation does not support these. */
5814+# if __OPTION_POSIX_REGEXP_GLIBC
5815 /* If this bit is set, then ignore case when matching.
5816 If not set, then case is significant. */
5817 # define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
5818@@ -172,6 +175,7 @@ typedef unsigned long int reg_syntax_t;
5819 /* If this bit is set, then no_sub will be set to 1 during
5820 re_compile_pattern. */
5821 # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
5822+# endif /* __OPTION_POSIX_REGEXP_GLIBC */
5823 #endif
5824
5825 /* This global variable defines the particular regexp syntax to use (for
5826@@ -231,8 +235,13 @@ extern reg_syntax_t re_syntax_options;
5827 (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
5828 | RE_INTERVALS | RE_NO_EMPTY_RANGES)
5829
5830+#if __OPTION_POSIX_REGEXP_GLIBC
5831 #define RE_SYNTAX_POSIX_BASIC \
5832 (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
5833+#else
5834+#define RE_SYNTAX_POSIX_BASIC \
5835+ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
5836+#endif
5837
5838 /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
5839 RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
5840@@ -298,9 +307,11 @@ extern reg_syntax_t re_syntax_options;
5841 /* Like REG_NOTBOL, except for the end-of-line. */
5842 #define REG_NOTEOL (1 << 1)
5843
5844+#if __OPTION_POSIX_REGEXP_GLIBC
5845 /* Use PMATCH[0] to delimit the start and end of the search in the
5846 buffer. */
5847 #define REG_STARTEND (1 << 2)
5848+#endif
5849
5850
5851 /* If any error codes are removed, changed, or added, update the
5852diff --git a/posix/regex_internal.c b/posix/regex_internal.c
5853index 8597d7e..d53b2a8 100644
5854--- a/posix/regex_internal.c
5855+++ b/posix/regex_internal.c
5856@@ -43,8 +43,8 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
5857 int init_buf_len;
5858
5859 /* Ensure at least one character fits into the buffers. */
5860- if (init_len < dfa->mb_cur_max)
5861- init_len = dfa->mb_cur_max;
5862+ if (init_len < dfa_mb_cur_max (dfa))
5863+ init_len = dfa_mb_cur_max (dfa);
5864 init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
5865 re_string_construct_common (str, len, pstr, trans, icase, dfa);
5866
5867@@ -55,7 +55,7 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
5868 pstr->word_char = dfa->word_char;
5869 pstr->word_ops_used = dfa->word_ops_used;
5870 pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
5871- pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
5872+ pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len;
5873 pstr->valid_raw_len = pstr->valid_len;
5874 return REG_NOERROR;
5875 }
5876@@ -82,7 +82,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len,
5877 if (icase)
5878 {
5879 #ifdef RE_ENABLE_I18N
5880- if (dfa->mb_cur_max > 1)
5881+ if (dfa_mb_cur_max (dfa) > 1)
5882 {
5883 while (1)
5884 {
5885@@ -91,7 +91,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len,
5886 return ret;
5887 if (pstr->valid_raw_len >= len)
5888 break;
5889- if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
5890+ if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa))
5891 break;
5892 ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
5893 if (BE (ret != REG_NOERROR, 0))
5894@@ -105,7 +105,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len,
5895 else
5896 {
5897 #ifdef RE_ENABLE_I18N
5898- if (dfa->mb_cur_max > 1)
5899+ if (dfa_mb_cur_max (dfa) > 1)
5900 build_wcs_buffer (pstr);
5901 else
5902 #endif /* RE_ENABLE_I18N */
5903@@ -130,7 +130,7 @@ internal_function __attribute_warn_unused_result__
5904 re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
5905 {
5906 #ifdef RE_ENABLE_I18N
5907- if (pstr->mb_cur_max > 1)
5908+ if (string_mb_cur_max (pstr) > 1)
5909 {
5910 wint_t *new_wcs;
5911
5912@@ -177,7 +177,7 @@ re_string_construct_common (const char *str, int len, re_string_t *pstr,
5913 pstr->trans = trans;
5914 pstr->icase = icase ? 1 : 0;
5915 pstr->mbs_allocated = (trans != NULL || icase);
5916- pstr->mb_cur_max = dfa->mb_cur_max;
5917+ pstr->mb_cur_max = dfa_mb_cur_max (dfa);
5918 pstr->is_utf8 = dfa->is_utf8;
5919 pstr->map_notascii = dfa->map_notascii;
5920 pstr->stop = pstr->len;
5921@@ -203,7 +203,7 @@ build_wcs_buffer (re_string_t *pstr)
5922 {
5923 #ifdef _LIBC
5924 unsigned char buf[MB_LEN_MAX];
5925- assert (MB_LEN_MAX >= pstr->mb_cur_max);
5926+ assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
5927 #else
5928 unsigned char buf[64];
5929 #endif
5930@@ -226,7 +226,7 @@ build_wcs_buffer (re_string_t *pstr)
5931 {
5932 int i, ch;
5933
5934- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
5935+ for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
5936 {
5937 ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
5938 buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
5939@@ -275,7 +275,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
5940 size_t mbclen;
5941 #ifdef _LIBC
5942 char buf[MB_LEN_MAX];
5943- assert (MB_LEN_MAX >= pstr->mb_cur_max);
5944+ assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
5945 #else
5946 char buf[64];
5947 #endif
5948@@ -369,7 +369,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
5949 {
5950 int i, ch;
5951
5952- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
5953+ for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
5954 {
5955 ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
5956 buf[i] = pstr->trans[ch];
5957@@ -567,8 +567,9 @@ re_string_translate_buffer (re_string_t *pstr)
5958 }
5959
5960 /* This function re-construct the buffers.
5961- Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
5962- convert to upper case in case of REG_ICASE, apply translation. */
5963+ Concretely, convert to wide character in case of
5964+ string_mb_cur_max (pstr) > 1, convert to upper case in case of
5965+ REG_ICASE, apply translation. */
5966
5967 static reg_errcode_t
5968 internal_function __attribute_warn_unused_result__
5969@@ -579,7 +580,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
5970 {
5971 /* Reset buffer. */
5972 #ifdef RE_ENABLE_I18N
5973- if (pstr->mb_cur_max > 1)
5974+ if (string_mb_cur_max (pstr) > 1)
5975 memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
5976 #endif /* RE_ENABLE_I18N */
5977 pstr->len = pstr->raw_len;
5978@@ -670,7 +671,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
5979 pstr->tip_context = re_string_context_at (pstr, offset - 1,
5980 eflags);
5981 #ifdef RE_ENABLE_I18N
5982- if (pstr->mb_cur_max > 1)
5983+ if (string_mb_cur_max (pstr) > 1)
5984 memmove (pstr->wcs, pstr->wcs + offset,
5985 (pstr->valid_len - offset) * sizeof (wint_t));
5986 #endif /* RE_ENABLE_I18N */
5987@@ -699,7 +700,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
5988 #endif
5989 pstr->valid_len = 0;
5990 #ifdef RE_ENABLE_I18N
5991- if (pstr->mb_cur_max > 1)
5992+ if (string_mb_cur_max (pstr) > 1)
5993 {
5994 int wcs_idx;
5995 wint_t wc = WEOF;
5996@@ -711,7 +712,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
5997 /* Special case UTF-8. Multi-byte chars start with any
5998 byte other than 0x80 - 0xbf. */
5999 raw = pstr->raw_mbs + pstr->raw_mbs_idx;
6000- end = raw + (offset - pstr->mb_cur_max);
6001+ end = raw + (offset - string_mb_cur_max (pstr));
6002 if (end < pstr->raw_mbs)
6003 end = pstr->raw_mbs;
6004 p = raw + offset - 1;
6005@@ -803,7 +804,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
6006
6007 /* Then build the buffers. */
6008 #ifdef RE_ENABLE_I18N
6009- if (pstr->mb_cur_max > 1)
6010+ if (string_mb_cur_max (pstr) > 1)
6011 {
6012 if (pstr->icase)
6013 {
6014@@ -841,7 +842,7 @@ re_string_peek_byte_case (const re_string_t *pstr, int idx)
6015 return re_string_peek_byte (pstr, idx);
6016
6017 #ifdef RE_ENABLE_I18N
6018- if (pstr->mb_cur_max > 1
6019+ if (string_mb_cur_max (pstr) > 1
6020 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
6021 return re_string_peek_byte (pstr, idx);
6022 #endif
6023@@ -930,7 +931,7 @@ re_string_context_at (const re_string_t *input, int idx, int eflags)
6024 return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
6025 : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
6026 #ifdef RE_ENABLE_I18N
6027- if (input->mb_cur_max > 1)
6028+ if (string_mb_cur_max (input) > 1)
6029 {
6030 wint_t wc;
6031 int wc_idx = idx;
6032@@ -1444,7 +1445,7 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
6033 dfa->nodes[dfa->nodes_len].constraint = 0;
6034 #ifdef RE_ENABLE_I18N
6035 dfa->nodes[dfa->nodes_len].accept_mb =
6036- (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
6037+ (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET;
6038 #endif
6039 dfa->nexts[dfa->nodes_len] = -1;
6040 re_node_set_init_empty (dfa->edests + dfa->nodes_len);
6041diff --git a/posix/regex_internal.h b/posix/regex_internal.h
6042index 154e969..c43909a 100644
6043--- a/posix/regex_internal.h
6044+++ b/posix/regex_internal.h
6045@@ -26,6 +26,10 @@
6046 #include <stdlib.h>
6047 #include <string.h>
6048
6049+#if defined _LIBC
6050+# include <gnu/option-groups.h>
6051+#endif
6052+
6053 #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
6054 # include <langinfo.h>
6055 #endif
6056@@ -369,6 +373,13 @@ struct re_string_t
6057 };
6058 typedef struct re_string_t re_string_t;
6059
6060+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
6061+ help the compiler make use of that fact. */
6062+#if __OPTION_EGLIBC_LOCALE_CODE
6063+# define string_mb_cur_max(str) ((str)->mb_cur_max + 0)
6064+#else
6065+# define string_mb_cur_max(str) (1)
6066+#endif
6067
6068 struct re_dfa_t;
6069 typedef struct re_dfa_t re_dfa_t;
6070@@ -654,6 +665,14 @@ struct re_dfa_t
6071 __libc_lock_define (, lock)
6072 };
6073
6074+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
6075+ help the compiler make use of that fact. */
6076+#if __OPTION_EGLIBC_LOCALE_CODE
6077+# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0)
6078+#else
6079+# define dfa_mb_cur_max(dfa) (1)
6080+#endif
6081+
6082 #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
6083 #define re_node_set_remove(set,id) \
6084 (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
6085@@ -714,7 +733,7 @@ internal_function __attribute__ ((pure, unused))
6086 re_string_char_size_at (const re_string_t *pstr, int idx)
6087 {
6088 int byte_idx;
6089- if (pstr->mb_cur_max == 1)
6090+ if (string_mb_cur_max (pstr) == 1)
6091 return 1;
6092 for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
6093 if (pstr->wcs[idx + byte_idx] != WEOF)
6094@@ -726,7 +745,7 @@ static wint_t
6095 internal_function __attribute__ ((pure, unused))
6096 re_string_wchar_at (const re_string_t *pstr, int idx)
6097 {
6098- if (pstr->mb_cur_max == 1)
6099+ if (string_mb_cur_max (pstr) == 1)
6100 return (wint_t) pstr->mbs[idx];
6101 return (wint_t) pstr->wcs[idx];
6102 }
6103diff --git a/posix/regexec-compat.c b/posix/regexec-compat.c
6104new file mode 100644
6105index 0000000..0f9b7c7
6106--- /dev/null
6107+++ b/posix/regexec-compat.c
6108@@ -0,0 +1,39 @@
6109+/* Extended regular expression matching and search library.
6110+ Copyright (C) 2008 Free Software Foundation, Inc.
6111+ This file is part of the GNU C Library.
6112+ Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
6113+
6114+ The GNU C Library is free software; you can redistribute it and/or
6115+ modify it under the terms of the GNU Lesser General Public
6116+ License as published by the Free Software Foundation; either
6117+ version 2.1 of the License, or (at your option) any later version.
6118+
6119+ The GNU C Library is distributed in the hope that it will be useful,
6120+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6121+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6122+ Lesser General Public License for more details.
6123+
6124+ You should have received a copy of the GNU Lesser General Public
6125+ License along with the GNU C Library; if not, write to the Free
6126+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
6127+ 02111-1307 USA. */
6128+
6129+#ifdef _LIBC
6130+# include <shlib-compat.h>
6131+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
6132+
6133+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
6134+__typeof__ (__regexec) __compat_regexec;
6135+
6136+int
6137+attribute_compat_text_section
6138+__compat_regexec (const regex_t *__restrict preg,
6139+ const char *__restrict string, size_t nmatch,
6140+ regmatch_t pmatch[], int eflags)
6141+{
6142+ return regexec (preg, string, nmatch, pmatch,
6143+ eflags & (REG_NOTBOL | REG_NOTEOL));
6144+}
6145+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
6146+# endif
6147+#endif
6148diff --git a/posix/regexec.c b/posix/regexec.c
6149index 70cd606..e3b49e4 100644
6150--- a/posix/regexec.c
6151+++ b/posix/regexec.c
6152@@ -18,6 +18,7 @@
6153 <http://www.gnu.org/licenses/>. */
6154
6155 #include <stdint.h>
6156+#include <gnu/option-groups.h>
6157
6158 static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
6159 int n) internal_function;
6160@@ -186,11 +187,11 @@ static int build_trtable (const re_dfa_t *dfa,
6161 static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6162 const re_string_t *input, int idx)
6163 internal_function;
6164-# ifdef _LIBC
6165+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
6166 static unsigned int find_collation_sequence_value (const unsigned char *mbs,
6167 size_t name_len)
6168 internal_function;
6169-# endif /* _LIBC */
6170+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
6171 #endif /* RE_ENABLE_I18N */
6172 static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
6173 const re_dfastate_t *state,
6174@@ -255,25 +256,9 @@ regexec (preg, string, nmatch, pmatch, eflags)
6175 return err != REG_NOERROR;
6176 }
6177
6178-#ifdef _LIBC
6179-# include <shlib-compat.h>
6180-versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
6181-
6182-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
6183-__typeof__ (__regexec) __compat_regexec;
6184-
6185-int
6186-attribute_compat_text_section
6187-__compat_regexec (const regex_t *__restrict preg,
6188- const char *__restrict string, size_t nmatch,
6189- regmatch_t pmatch[], int eflags)
6190-{
6191- return regexec (preg, string, nmatch, pmatch,
6192- eflags & (REG_NOTBOL | REG_NOTEOL));
6193-}
6194-compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
6195-# endif
6196-#endif
6197+/* EGLIBC: The code that used to be here was move to a separate file
6198+ so that it can be shared with xregex.c. */
6199+#include "regexec-compat.c"
6200
6201 /* Entry points for GNU code. */
6202
6203@@ -728,7 +713,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
6204 incr = (range < 0) ? -1 : 1;
6205 left_lim = (range < 0) ? start + range : start;
6206 right_lim = (range < 0) ? start : start + range;
6207- sb = dfa->mb_cur_max == 1;
6208+ sb = dfa_mb_cur_max (dfa) == 1;
6209 match_kind =
6210 (fastmap
6211 ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
6212@@ -3448,7 +3433,7 @@ out_free:
6213 if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
6214 goto out_free;
6215
6216- if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
6217+ if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1)
6218 need_word_trtable = 1;
6219
6220 dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
6221@@ -3590,7 +3575,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
6222 else if (type == OP_PERIOD)
6223 {
6224 #ifdef RE_ENABLE_I18N
6225- if (dfa->mb_cur_max > 1)
6226+ if (dfa_mb_cur_max (dfa) > 1)
6227 bitset_merge (accepts, dfa->sb_char);
6228 else
6229 #endif
6230@@ -3641,7 +3626,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
6231 continue;
6232 }
6233 #ifdef RE_ENABLE_I18N
6234- if (dfa->mb_cur_max > 1)
6235+ if (dfa_mb_cur_max (dfa) > 1)
6236 for (j = 0; j < BITSET_WORDS; ++j)
6237 any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
6238 else
6239@@ -3660,7 +3645,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
6240 continue;
6241 }
6242 #ifdef RE_ENABLE_I18N
6243- if (dfa->mb_cur_max > 1)
6244+ if (dfa_mb_cur_max (dfa) > 1)
6245 for (j = 0; j < BITSET_WORDS; ++j)
6246 any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
6247 else
6248@@ -3836,12 +3821,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6249 if (node->type == COMPLEX_BRACKET)
6250 {
6251 const re_charset_t *cset = node->opr.mbcset;
6252-# ifdef _LIBC
6253- const unsigned char *pin
6254- = ((const unsigned char *) re_string_get_buffer (input) + str_idx);
6255- int j;
6256- uint32_t nrules;
6257-# endif /* _LIBC */
6258 int match_len = 0;
6259 wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
6260 ? re_string_wchar_at (input, str_idx) : 0);
6261@@ -3853,6 +3832,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6262 match_len = char_len;
6263 goto check_node_accept_bytes_match;
6264 }
6265+#if __OPTION_EGLIBC_LOCALE_CODE
6266 /* match with character_class? */
6267 for (i = 0; i < cset->nchar_classes; ++i)
6268 {
6269@@ -3863,14 +3843,22 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6270 goto check_node_accept_bytes_match;
6271 }
6272 }
6273+#endif
6274+
6275+ /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C
6276+ locale is supported; it has no collation rules. */
6277+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
6278+ const unsigned char *pin
6279+ = ((const unsigned char *) re_string_get_buffer (input) + str_idx);
6280+ int j;
6281+ uint32_t nrules;
6282
6283-# ifdef _LIBC
6284 nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
6285 if (nrules != 0)
6286 {
6287 unsigned int in_collseq = 0;
6288 const int32_t *table, *indirect;
6289- const unsigned char *weights, *extra;
6290+ const unsigned char *weights, *extra = NULL;
6291 const char *collseqwc;
6292
6293 /* match with collating_symbol? */
6294@@ -3955,8 +3943,12 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6295 }
6296 }
6297 else
6298-# endif /* _LIBC */
6299+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
6300 {
6301+ /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is
6302+ disabled, there can be no multibyte range endpoints, and
6303+ cset->nranges is always zero. */
6304+#if __OPTION_EGLIBC_LOCALE_CODE
6305 /* match with range expression? */
6306 #if __GNUC__ >= 2
6307 wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
6308@@ -3975,6 +3967,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6309 goto check_node_accept_bytes_match;
6310 }
6311 }
6312+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
6313 }
6314 check_node_accept_bytes_match:
6315 if (!cset->non_match)
6316@@ -3990,7 +3983,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
6317 return 0;
6318 }
6319
6320-# ifdef _LIBC
6321+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
6322 static unsigned int
6323 internal_function
6324 find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
6325@@ -4048,7 +4041,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
6326 return UINT_MAX;
6327 }
6328 }
6329-# endif /* _LIBC */
6330+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
6331 #endif /* RE_ENABLE_I18N */
6332
6333 /* Check whether the node accepts the byte which is IDX-th
6334@@ -4139,7 +4132,7 @@ extend_buffers (re_match_context_t *mctx, int min_len)
6335 if (pstr->icase)
6336 {
6337 #ifdef RE_ENABLE_I18N
6338- if (pstr->mb_cur_max > 1)
6339+ if (string_mb_cur_max (pstr) > 1)
6340 {
6341 ret = build_wcs_upper_buffer (pstr);
6342 if (BE (ret != REG_NOERROR, 0))
6343@@ -4152,7 +4145,7 @@ extend_buffers (re_match_context_t *mctx, int min_len)
6344 else
6345 {
6346 #ifdef RE_ENABLE_I18N
6347- if (pstr->mb_cur_max > 1)
6348+ if (string_mb_cur_max (pstr) > 1)
6349 build_wcs_buffer (pstr);
6350 else
6351 #endif /* RE_ENABLE_I18N */
6352diff --git a/posix/xregex.c b/posix/xregex.c
6353new file mode 100644
6354index 0000000..d3f7ace
6355--- /dev/null
6356+++ b/posix/xregex.c
6357@@ -0,0 +1,8215 @@
6358+/* Extended regular expression matching and search library,
6359+ version 0.12.
6360+ (Implements POSIX draft P1003.2/D11.2, except for some of the
6361+ internationalization features.)
6362+
6363+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
6364+ 2002, 2005 Free Software Foundation, Inc.
6365+ This file is part of the GNU C Library.
6366+
6367+ The GNU C Library is free software; you can redistribute it and/or
6368+ modify it under the terms of the GNU Lesser General Public
6369+ License as published by the Free Software Foundation; either
6370+ version 2.1 of the License, or (at your option) any later version.
6371+
6372+ The GNU C Library is distributed in the hope that it will be useful,
6373+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6374+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6375+ Lesser General Public License for more details.
6376+
6377+ You should have received a copy of the GNU Lesser General Public
6378+ License along with the GNU C Library; if not, write to the Free
6379+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
6380+ 02110-1301 USA. */
6381+
6382+/* AIX requires this to be the first thing in the file. */
6383+#if defined _AIX && !defined __GNUC__ && !defined REGEX_MALLOC
6384+ #pragma alloca
6385+#endif
6386+
6387+#undef _GNU_SOURCE
6388+#define _GNU_SOURCE
6389+
6390+#ifndef INSIDE_RECURSION
6391+# ifdef HAVE_CONFIG_H
6392+# include <config.h>
6393+# endif
6394+#endif
6395+
6396+/*#include <ansidecl.h>*/
6397+
6398+
6399+#ifndef INSIDE_RECURSION
6400+
6401+# if defined STDC_HEADERS && !defined emacs
6402+# include <stddef.h>
6403+# else
6404+/* We need this for `regex.h', and perhaps for the Emacs include files. */
6405+# include <sys/types.h>
6406+# endif
6407+
6408+# if (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_BTOWC)
6409+# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
6410+# else
6411+# define WIDE_CHAR_SUPPORT 0
6412+# endif
6413+/* For platform which support the ISO C amendement 1 functionality we
6414+ support user defined character classes. */
6415+# if WIDE_CHAR_SUPPORT
6416+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
6417+# include <wchar.h>
6418+# include <wctype.h>
6419+# endif
6420+
6421+# ifdef _LIBC
6422+/* We have to keep the namespace clean. */
6423+# define regfree(preg) __regfree (preg)
6424+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
6425+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
6426+# define regerror(errcode, preg, errbuf, errbuf_size) \
6427+ __regerror(errcode, preg, errbuf, errbuf_size)
6428+# define re_set_registers(bu, re, nu, st, en) \
6429+ __re_set_registers (bu, re, nu, st, en)
6430+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
6431+ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
6432+# define re_match(bufp, string, size, pos, regs) \
6433+ __re_match (bufp, string, size, pos, regs)
6434+# define re_search(bufp, string, size, startpos, range, regs) \
6435+ __re_search (bufp, string, size, startpos, range, regs)
6436+# define re_compile_pattern(pattern, length, bufp) \
6437+ __re_compile_pattern (pattern, length, bufp)
6438+# define re_set_syntax(syntax) __re_set_syntax (syntax)
6439+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
6440+ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
6441+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
6442+
6443+# define btowc __btowc
6444+
6445+/* We are also using some library internals. */
6446+# include <locale/localeinfo.h>
6447+# include <locale/elem-hash.h>
6448+# include <langinfo.h>
6449+# include <locale/coll-lookup.h>
6450+# endif
6451+
6452+/* This is for other GNU distributions with internationalized messages. */
6453+# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
6454+# include <libintl.h>
6455+# ifdef _LIBC
6456+# undef gettext
6457+# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES)
6458+# endif
6459+# else
6460+# define gettext(msgid) (msgid)
6461+# endif
6462+
6463+# ifndef gettext_noop
6464+/* This define is so xgettext can find the internationalizable
6465+ strings. */
6466+# define gettext_noop(String) String
6467+# endif
6468+
6469+/* The `emacs' switch turns on certain matching commands
6470+ that make sense only in Emacs. */
6471+# ifdef emacs
6472+
6473+# include "lisp.h"
6474+# include "buffer.h"
6475+# include "syntax.h"
6476+
6477+# else /* not emacs */
6478+
6479+/* If we are not linking with Emacs proper,
6480+ we can't use the relocating allocator
6481+ even if config.h says that we can. */
6482+# undef REL_ALLOC
6483+
6484+# if defined STDC_HEADERS || defined _LIBC
6485+# include <stdlib.h>
6486+# else
6487+char *malloc ();
6488+char *realloc ();
6489+# endif
6490+
6491+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
6492+ If nothing else has been done, use the method below. */
6493+# ifdef INHIBIT_STRING_HEADER
6494+# if !(defined HAVE_BZERO && defined HAVE_BCOPY)
6495+# if !defined bzero && !defined bcopy
6496+# undef INHIBIT_STRING_HEADER
6497+# endif
6498+# endif
6499+# endif
6500+
6501+/* This is the normal way of making sure we have a bcopy and a bzero.
6502+ This is used in most programs--a few other programs avoid this
6503+ by defining INHIBIT_STRING_HEADER. */
6504+# ifndef INHIBIT_STRING_HEADER
6505+# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
6506+# include <string.h>
6507+# ifndef bzero
6508+# ifndef _LIBC
6509+# define bzero(s, n) (memset (s, '\0', n), (s))
6510+# else
6511+# define bzero(s, n) __bzero (s, n)
6512+# endif
6513+# endif
6514+# else
6515+# include <strings.h>
6516+# ifndef memcmp
6517+# define memcmp(s1, s2, n) bcmp (s1, s2, n)
6518+# endif
6519+# ifndef memcpy
6520+# define memcpy(d, s, n) (bcopy (s, d, n), (d))
6521+# endif
6522+# endif
6523+# endif
6524+
6525+/* Define the syntax stuff for \<, \>, etc. */
6526+
6527+/* This must be nonzero for the wordchar and notwordchar pattern
6528+ commands in re_match_2. */
6529+# ifndef Sword
6530+# define Sword 1
6531+# endif
6532+
6533+# ifdef SWITCH_ENUM_BUG
6534+# define SWITCH_ENUM_CAST(x) ((int)(x))
6535+# else
6536+# define SWITCH_ENUM_CAST(x) (x)
6537+# endif
6538+
6539+# endif /* not emacs */
6540+
6541+# if defined _LIBC || HAVE_LIMITS_H
6542+# include <limits.h>
6543+# endif
6544+
6545+# ifndef MB_LEN_MAX
6546+# define MB_LEN_MAX 1
6547+# endif
6548+
6549+/* Get the interface, including the syntax bits. */
6550+# include "regex.h"
6551+
6552+/* isalpha etc. are used for the character classes. */
6553+# include <ctype.h>
6554+
6555+/* Jim Meyering writes:
6556+
6557+ "... Some ctype macros are valid only for character codes that
6558+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
6559+ using /bin/cc or gcc but without giving an ansi option). So, all
6560+ ctype uses should be through macros like ISPRINT... If
6561+ STDC_HEADERS is defined, then autoconf has verified that the ctype
6562+ macros don't need to be guarded with references to isascii. ...
6563+ Defining isascii to 1 should let any compiler worth its salt
6564+ eliminate the && through constant folding."
6565+ Solaris defines some of these symbols so we must undefine them first. */
6566+
6567+# undef ISASCII
6568+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
6569+# define ISASCII(c) 1
6570+# else
6571+# define ISASCII(c) isascii(c)
6572+# endif
6573+
6574+# ifdef isblank
6575+# define ISBLANK(c) (ISASCII (c) && isblank (c))
6576+# else
6577+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
6578+# endif
6579+# ifdef isgraph
6580+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
6581+# else
6582+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
6583+# endif
6584+
6585+# undef ISPRINT
6586+# define ISPRINT(c) (ISASCII (c) && isprint (c))
6587+# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
6588+# define ISALNUM(c) (ISASCII (c) && isalnum (c))
6589+# define ISALPHA(c) (ISASCII (c) && isalpha (c))
6590+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
6591+# define ISLOWER(c) (ISASCII (c) && islower (c))
6592+# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
6593+# define ISSPACE(c) (ISASCII (c) && isspace (c))
6594+# define ISUPPER(c) (ISASCII (c) && isupper (c))
6595+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
6596+
6597+# ifdef _tolower
6598+# define TOLOWER(c) _tolower(c)
6599+# else
6600+# define TOLOWER(c) tolower(c)
6601+# endif
6602+
6603+# ifndef NULL
6604+# define NULL (void *)0
6605+# endif
6606+
6607+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
6608+ since ours (we hope) works properly with all combinations of
6609+ machines, compilers, `char' and `unsigned char' argument types.
6610+ (Per Bothner suggested the basic approach.) */
6611+# undef SIGN_EXTEND_CHAR
6612+# if __STDC__
6613+# define SIGN_EXTEND_CHAR(c) ((signed char) (c))
6614+# else /* not __STDC__ */
6615+/* As in Harbison and Steele. */
6616+# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
6617+# endif
6618+
6619+# ifndef emacs
6620+/* How many characters in the character set. */
6621+# define CHAR_SET_SIZE 256
6622+
6623+# ifdef SYNTAX_TABLE
6624+
6625+extern char *re_syntax_table;
6626+
6627+# else /* not SYNTAX_TABLE */
6628+
6629+static char re_syntax_table[CHAR_SET_SIZE];
6630+
6631+static void init_syntax_once (void);
6632+
6633+static void
6634+init_syntax_once (void)
6635+{
6636+ register int c;
6637+ static int done = 0;
6638+
6639+ if (done)
6640+ return;
6641+ bzero (re_syntax_table, sizeof re_syntax_table);
6642+
6643+ for (c = 0; c < CHAR_SET_SIZE; ++c)
6644+ if (ISALNUM (c))
6645+ re_syntax_table[c] = Sword;
6646+
6647+ re_syntax_table['_'] = Sword;
6648+
6649+ done = 1;
6650+}
6651+
6652+# endif /* not SYNTAX_TABLE */
6653+
6654+# define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
6655+
6656+# endif /* emacs */
6657+
6658+/* Integer type for pointers. */
6659+# if !defined _LIBC && !defined HAVE_UINTPTR_T
6660+typedef unsigned long int uintptr_t;
6661+# endif
6662+
6663+/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
6664+ use `alloca' instead of `malloc'. This is because using malloc in
6665+ re_search* or re_match* could cause memory leaks when C-g is used in
6666+ Emacs; also, malloc is slower and causes storage fragmentation. On
6667+ the other hand, malloc is more portable, and easier to debug.
6668+
6669+ Because we sometimes use alloca, some routines have to be macros,
6670+ not functions -- `alloca'-allocated space disappears at the end of the
6671+ function it is called in. */
6672+
6673+# ifdef REGEX_MALLOC
6674+
6675+# define REGEX_ALLOCATE malloc
6676+# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
6677+# define REGEX_FREE free
6678+
6679+# else /* not REGEX_MALLOC */
6680+
6681+/* Emacs already defines alloca, sometimes. */
6682+# ifndef alloca
6683+
6684+/* Make alloca work the best possible way. */
6685+# ifdef __GNUC__
6686+# define alloca __builtin_alloca
6687+# else /* not __GNUC__ */
6688+# if HAVE_ALLOCA_H
6689+# include <alloca.h>
6690+# endif /* HAVE_ALLOCA_H */
6691+# endif /* not __GNUC__ */
6692+
6693+# endif /* not alloca */
6694+
6695+# define REGEX_ALLOCATE alloca
6696+
6697+/* Assumes a `char *destination' variable. */
6698+# define REGEX_REALLOCATE(source, osize, nsize) \
6699+ (destination = (char *) alloca (nsize), \
6700+ memcpy (destination, source, osize))
6701+
6702+/* No need to do anything to free, after alloca. */
6703+# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */
6704+
6705+# endif /* not REGEX_MALLOC */
6706+
6707+/* Define how to allocate the failure stack. */
6708+
6709+# if defined REL_ALLOC && defined REGEX_MALLOC
6710+
6711+# define REGEX_ALLOCATE_STACK(size) \
6712+ r_alloc (&failure_stack_ptr, (size))
6713+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
6714+ r_re_alloc (&failure_stack_ptr, (nsize))
6715+# define REGEX_FREE_STACK(ptr) \
6716+ r_alloc_free (&failure_stack_ptr)
6717+
6718+# else /* not using relocating allocator */
6719+
6720+# ifdef REGEX_MALLOC
6721+
6722+# define REGEX_ALLOCATE_STACK malloc
6723+# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
6724+# define REGEX_FREE_STACK free
6725+
6726+# else /* not REGEX_MALLOC */
6727+
6728+# define REGEX_ALLOCATE_STACK alloca
6729+
6730+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
6731+ REGEX_REALLOCATE (source, osize, nsize)
6732+/* No need to explicitly free anything. */
6733+# define REGEX_FREE_STACK(arg)
6734+
6735+# endif /* not REGEX_MALLOC */
6736+# endif /* not using relocating allocator */
6737+
6738+
6739+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
6740+ `string1' or just past its end. This works if PTR is NULL, which is
6741+ a good thing. */
6742+# define FIRST_STRING_P(ptr) \
6743+ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
6744+
6745+/* (Re)Allocate N items of type T using malloc, or fail. */
6746+# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
6747+# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
6748+# define RETALLOC_IF(addr, n, t) \
6749+ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
6750+# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
6751+
6752+# define BYTEWIDTH 8 /* In bits. */
6753+
6754+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
6755+
6756+# undef MAX
6757+# undef MIN
6758+# define MAX(a, b) ((a) > (b) ? (a) : (b))
6759+# define MIN(a, b) ((a) < (b) ? (a) : (b))
6760+
6761+typedef char boolean;
6762+# define false 0
6763+# define true 1
6764+
6765+static reg_errcode_t byte_regex_compile (const char *pattern, size_t size,
6766+ reg_syntax_t syntax,
6767+ struct re_pattern_buffer *bufp);
6768+
6769+static int byte_re_match_2_internal (struct re_pattern_buffer *bufp,
6770+ const char *string1, int size1,
6771+ const char *string2, int size2,
6772+ int pos,
6773+ struct re_registers *regs,
6774+ int stop);
6775+static int byte_re_search_2 (struct re_pattern_buffer *bufp,
6776+ const char *string1, int size1,
6777+ const char *string2, int size2,
6778+ int startpos, int range,
6779+ struct re_registers *regs, int stop);
6780+static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp);
6781+
6782+#ifdef MBS_SUPPORT
6783+static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size,
6784+ reg_syntax_t syntax,
6785+ struct re_pattern_buffer *bufp);
6786+
6787+
6788+static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
6789+ const char *cstring1, int csize1,
6790+ const char *cstring2, int csize2,
6791+ int pos,
6792+ struct re_registers *regs,
6793+ int stop,
6794+ wchar_t *string1, int size1,
6795+ wchar_t *string2, int size2,
6796+ int *mbs_offset1, int *mbs_offset2);
6797+static int wcs_re_search_2 (struct re_pattern_buffer *bufp,
6798+ const char *string1, int size1,
6799+ const char *string2, int size2,
6800+ int startpos, int range,
6801+ struct re_registers *regs, int stop);
6802+static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp);
6803+#endif
6804+
6805+/* These are the command codes that appear in compiled regular
6806+ expressions. Some opcodes are followed by argument bytes. A
6807+ command code can specify any interpretation whatsoever for its
6808+ arguments. Zero bytes may appear in the compiled regular expression. */
6809+
6810+typedef enum
6811+{
6812+ no_op = 0,
6813+
6814+ /* Succeed right away--no more backtracking. */
6815+ succeed,
6816+
6817+ /* Followed by one byte giving n, then by n literal bytes. */
6818+ exactn,
6819+
6820+# ifdef MBS_SUPPORT
6821+ /* Same as exactn, but contains binary data. */
6822+ exactn_bin,
6823+# endif
6824+
6825+ /* Matches any (more or less) character. */
6826+ anychar,
6827+
6828+ /* Matches any one char belonging to specified set. First
6829+ following byte is number of bitmap bytes. Then come bytes
6830+ for a bitmap saying which chars are in. Bits in each byte
6831+ are ordered low-bit-first. A character is in the set if its
6832+ bit is 1. A character too large to have a bit in the map is
6833+ automatically not in the set. */
6834+ /* ifdef MBS_SUPPORT, following element is length of character
6835+ classes, length of collating symbols, length of equivalence
6836+ classes, length of character ranges, and length of characters.
6837+ Next, character class element, collating symbols elements,
6838+ equivalence class elements, range elements, and character
6839+ elements follow.
6840+ See regex_compile function. */
6841+ charset,
6842+
6843+ /* Same parameters as charset, but match any character that is
6844+ not one of those specified. */
6845+ charset_not,
6846+
6847+ /* Start remembering the text that is matched, for storing in a
6848+ register. Followed by one byte with the register number, in
6849+ the range 0 to one less than the pattern buffer's re_nsub
6850+ field. Then followed by one byte with the number of groups
6851+ inner to this one. (This last has to be part of the
6852+ start_memory only because we need it in the on_failure_jump
6853+ of re_match_2.) */
6854+ start_memory,
6855+
6856+ /* Stop remembering the text that is matched and store it in a
6857+ memory register. Followed by one byte with the register
6858+ number, in the range 0 to one less than `re_nsub' in the
6859+ pattern buffer, and one byte with the number of inner groups,
6860+ just like `start_memory'. (We need the number of inner
6861+ groups here because we don't have any easy way of finding the
6862+ corresponding start_memory when we're at a stop_memory.) */
6863+ stop_memory,
6864+
6865+ /* Match a duplicate of something remembered. Followed by one
6866+ byte containing the register number. */
6867+ duplicate,
6868+
6869+ /* Fail unless at beginning of line. */
6870+ begline,
6871+
6872+ /* Fail unless at end of line. */
6873+ endline,
6874+
6875+ /* Succeeds if at beginning of buffer (if emacs) or at beginning
6876+ of string to be matched (if not). */
6877+ begbuf,
6878+
6879+ /* Analogously, for end of buffer/string. */
6880+ endbuf,
6881+
6882+ /* Followed by two byte relative address to which to jump. */
6883+ jump,
6884+
6885+ /* Same as jump, but marks the end of an alternative. */
6886+ jump_past_alt,
6887+
6888+ /* Followed by two-byte relative address of place to resume at
6889+ in case of failure. */
6890+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6891+ on_failure_jump,
6892+
6893+ /* Like on_failure_jump, but pushes a placeholder instead of the
6894+ current string position when executed. */
6895+ on_failure_keep_string_jump,
6896+
6897+ /* Throw away latest failure point and then jump to following
6898+ two-byte relative address. */
6899+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6900+ pop_failure_jump,
6901+
6902+ /* Change to pop_failure_jump if know won't have to backtrack to
6903+ match; otherwise change to jump. This is used to jump
6904+ back to the beginning of a repeat. If what follows this jump
6905+ clearly won't match what the repeat does, such that we can be
6906+ sure that there is no use backtracking out of repetitions
6907+ already matched, then we change it to a pop_failure_jump.
6908+ Followed by two-byte address. */
6909+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6910+ maybe_pop_jump,
6911+
6912+ /* Jump to following two-byte address, and push a dummy failure
6913+ point. This failure point will be thrown away if an attempt
6914+ is made to use it for a failure. A `+' construct makes this
6915+ before the first repeat. Also used as an intermediary kind
6916+ of jump when compiling an alternative. */
6917+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6918+ dummy_failure_jump,
6919+
6920+ /* Push a dummy failure point and continue. Used at the end of
6921+ alternatives. */
6922+ push_dummy_failure,
6923+
6924+ /* Followed by two-byte relative address and two-byte number n.
6925+ After matching N times, jump to the address upon failure. */
6926+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6927+ succeed_n,
6928+
6929+ /* Followed by two-byte relative address, and two-byte number n.
6930+ Jump to the address N times, then fail. */
6931+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6932+ jump_n,
6933+
6934+ /* Set the following two-byte relative address to the
6935+ subsequent two-byte number. The address *includes* the two
6936+ bytes of number. */
6937+ /* ifdef MBS_SUPPORT, the size of address is 1. */
6938+ set_number_at,
6939+
6940+ wordchar, /* Matches any word-constituent character. */
6941+ notwordchar, /* Matches any char that is not a word-constituent. */
6942+
6943+ wordbeg, /* Succeeds if at word beginning. */
6944+ wordend, /* Succeeds if at word end. */
6945+
6946+ wordbound, /* Succeeds if at a word boundary. */
6947+ notwordbound /* Succeeds if not at a word boundary. */
6948+
6949+# ifdef emacs
6950+ ,before_dot, /* Succeeds if before point. */
6951+ at_dot, /* Succeeds if at point. */
6952+ after_dot, /* Succeeds if after point. */
6953+
6954+ /* Matches any character whose syntax is specified. Followed by
6955+ a byte which contains a syntax code, e.g., Sword. */
6956+ syntaxspec,
6957+
6958+ /* Matches any character whose syntax is not that specified. */
6959+ notsyntaxspec
6960+# endif /* emacs */
6961+} re_opcode_t;
6962+#endif /* not INSIDE_RECURSION */
6963+
6964+
6965+#ifdef BYTE
6966+# define CHAR_T char
6967+# define UCHAR_T unsigned char
6968+# define COMPILED_BUFFER_VAR bufp->buffer
6969+# define OFFSET_ADDRESS_SIZE 2
6970+# define PREFIX(name) byte_##name
6971+# define ARG_PREFIX(name) name
6972+# define PUT_CHAR(c) putchar (c)
6973+# include <locale/weight.h>
6974+# define FINDIDX findidx
6975+#else
6976+# ifdef WCHAR
6977+# define CHAR_T wchar_t
6978+# define UCHAR_T wchar_t
6979+# define COMPILED_BUFFER_VAR wc_buffer
6980+# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */
6981+# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1)
6982+# define PREFIX(name) wcs_##name
6983+# define ARG_PREFIX(name) c##name
6984+/* Should we use wide stream?? */
6985+# define PUT_CHAR(c) printf ("%C", c);
6986+# define TRUE 1
6987+# define FALSE 0
6988+# define findidx findidxwc
6989+# include <locale/weightwc.h>
6990+# undef findidx
6991+# define FINDIDX findidxwc
6992+# else
6993+# ifdef MBS_SUPPORT
6994+# define WCHAR
6995+# define INSIDE_RECURSION
6996+# include "xregex.c"
6997+# undef INSIDE_RECURSION
6998+# endif
6999+# define BYTE
7000+# define INSIDE_RECURSION
7001+# include "xregex.c"
7002+# undef INSIDE_RECURSION
7003+# endif
7004+#endif
7005+
7006+#ifdef INSIDE_RECURSION
7007+/* Common operations on the compiled pattern. */
7008+
7009+/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
7010+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */
7011+
7012+# ifdef WCHAR
7013+# define STORE_NUMBER(destination, number) \
7014+ do { \
7015+ *(destination) = (UCHAR_T)(number); \
7016+ } while (0)
7017+# else /* BYTE */
7018+# define STORE_NUMBER(destination, number) \
7019+ do { \
7020+ (destination)[0] = (number) & 0377; \
7021+ (destination)[1] = (number) >> 8; \
7022+ } while (0)
7023+# endif /* WCHAR */
7024+
7025+/* Same as STORE_NUMBER, except increment DESTINATION to
7026+ the byte after where the number is stored. Therefore, DESTINATION
7027+ must be an lvalue. */
7028+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */
7029+
7030+# define STORE_NUMBER_AND_INCR(destination, number) \
7031+ do { \
7032+ STORE_NUMBER (destination, number); \
7033+ (destination) += OFFSET_ADDRESS_SIZE; \
7034+ } while (0)
7035+
7036+/* Put into DESTINATION a number stored in two contiguous bytes starting
7037+ at SOURCE. */
7038+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */
7039+
7040+# ifdef WCHAR
7041+# define EXTRACT_NUMBER(destination, source) \
7042+ do { \
7043+ (destination) = *(source); \
7044+ } while (0)
7045+# else /* BYTE */
7046+# define EXTRACT_NUMBER(destination, source) \
7047+ do { \
7048+ (destination) = *(source) & 0377; \
7049+ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
7050+ } while (0)
7051+# endif
7052+
7053+# ifdef DEBUG
7054+static void PREFIX(extract_number) (int *dest, UCHAR_T *source);
7055+static void
7056+PREFIX(extract_number) (int *dest, UCHAR_T *source)
7057+{
7058+# ifdef WCHAR
7059+ *dest = *source;
7060+# else /* BYTE */
7061+ int temp = SIGN_EXTEND_CHAR (*(source + 1));
7062+ *dest = *source & 0377;
7063+ *dest += temp << 8;
7064+# endif
7065+}
7066+
7067+# ifndef EXTRACT_MACROS /* To debug the macros. */
7068+# undef EXTRACT_NUMBER
7069+# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src)
7070+# endif /* not EXTRACT_MACROS */
7071+
7072+# endif /* DEBUG */
7073+
7074+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
7075+ SOURCE must be an lvalue. */
7076+
7077+# define EXTRACT_NUMBER_AND_INCR(destination, source) \
7078+ do { \
7079+ EXTRACT_NUMBER (destination, source); \
7080+ (source) += OFFSET_ADDRESS_SIZE; \
7081+ } while (0)
7082+
7083+# ifdef DEBUG
7084+static void PREFIX(extract_number_and_incr) (int *destination,
7085+ UCHAR_T **source);
7086+static void
7087+PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source)
7088+{
7089+ PREFIX(extract_number) (destination, *source);
7090+ *source += OFFSET_ADDRESS_SIZE;
7091+}
7092+
7093+# ifndef EXTRACT_MACROS
7094+# undef EXTRACT_NUMBER_AND_INCR
7095+# define EXTRACT_NUMBER_AND_INCR(dest, src) \
7096+ PREFIX(extract_number_and_incr) (&dest, &src)
7097+# endif /* not EXTRACT_MACROS */
7098+
7099+# endif /* DEBUG */
7100+
7101+
7102+
7103+/* If DEBUG is defined, Regex prints many voluminous messages about what
7104+ it is doing (if the variable `debug' is nonzero). If linked with the
7105+ main program in `iregex.c', you can enter patterns and strings
7106+ interactively. And if linked with the main program in `main.c' and
7107+ the other test files, you can run the already-written tests. */
7108+
7109+# ifdef DEBUG
7110+
7111+# ifndef DEFINED_ONCE
7112+
7113+/* We use standard I/O for debugging. */
7114+# include <stdio.h>
7115+
7116+/* It is useful to test things that ``must'' be true when debugging. */
7117+# include <assert.h>
7118+
7119+static int debug;
7120+
7121+# define DEBUG_STATEMENT(e) e
7122+# define DEBUG_PRINT1(x) if (debug) printf (x)
7123+# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
7124+# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
7125+# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
7126+# endif /* not DEFINED_ONCE */
7127+
7128+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
7129+ if (debug) PREFIX(print_partial_compiled_pattern) (s, e)
7130+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
7131+ if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2)
7132+
7133+
7134+/* Print the fastmap in human-readable form. */
7135+
7136+# ifndef DEFINED_ONCE
7137+void
7138+print_fastmap (char *fastmap)
7139+{
7140+ unsigned was_a_range = 0;
7141+ unsigned i = 0;
7142+
7143+ while (i < (1 << BYTEWIDTH))
7144+ {
7145+ if (fastmap[i++])
7146+ {
7147+ was_a_range = 0;
7148+ putchar (i - 1);
7149+ while (i < (1 << BYTEWIDTH) && fastmap[i])
7150+ {
7151+ was_a_range = 1;
7152+ i++;
7153+ }
7154+ if (was_a_range)
7155+ {
7156+ printf ("-");
7157+ putchar (i - 1);
7158+ }
7159+ }
7160+ }
7161+ putchar ('\n');
7162+}
7163+# endif /* not DEFINED_ONCE */
7164+
7165+
7166+/* Print a compiled pattern string in human-readable form, starting at
7167+ the START pointer into it and ending just before the pointer END. */
7168+
7169+void
7170+PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end)
7171+{
7172+ int mcnt, mcnt2;
7173+ UCHAR_T *p1;
7174+ UCHAR_T *p = start;
7175+ UCHAR_T *pend = end;
7176+
7177+ if (start == NULL)
7178+ {
7179+ printf ("(null)\n");
7180+ return;
7181+ }
7182+
7183+ /* Loop over pattern commands. */
7184+ while (p < pend)
7185+ {
7186+# ifdef _LIBC
7187+ printf ("%td:\t", p - start);
7188+# else
7189+ printf ("%ld:\t", (long int) (p - start));
7190+# endif
7191+
7192+ switch ((re_opcode_t) *p++)
7193+ {
7194+ case no_op:
7195+ printf ("/no_op");
7196+ break;
7197+
7198+ case exactn:
7199+ mcnt = *p++;
7200+ printf ("/exactn/%d", mcnt);
7201+ do
7202+ {
7203+ putchar ('/');
7204+ PUT_CHAR (*p++);
7205+ }
7206+ while (--mcnt);
7207+ break;
7208+
7209+# ifdef MBS_SUPPORT
7210+ case exactn_bin:
7211+ mcnt = *p++;
7212+ printf ("/exactn_bin/%d", mcnt);
7213+ do
7214+ {
7215+ printf("/%lx", (long int) *p++);
7216+ }
7217+ while (--mcnt);
7218+ break;
7219+# endif /* MBS_SUPPORT */
7220+
7221+ case start_memory:
7222+ mcnt = *p++;
7223+ printf ("/start_memory/%d/%ld", mcnt, (long int) *p++);
7224+ break;
7225+
7226+ case stop_memory:
7227+ mcnt = *p++;
7228+ printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++);
7229+ break;
7230+
7231+ case duplicate:
7232+ printf ("/duplicate/%ld", (long int) *p++);
7233+ break;
7234+
7235+ case anychar:
7236+ printf ("/anychar");
7237+ break;
7238+
7239+ case charset:
7240+ case charset_not:
7241+ {
7242+# ifdef WCHAR
7243+ int i, length;
7244+ wchar_t *workp = p;
7245+ printf ("/charset [%s",
7246+ (re_opcode_t) *(workp - 1) == charset_not ? "^" : "");
7247+ p += 5;
7248+ length = *workp++; /* the length of char_classes */
7249+ for (i=0 ; i<length ; i++)
7250+ printf("[:%lx:]", (long int) *p++);
7251+ length = *workp++; /* the length of collating_symbol */
7252+ for (i=0 ; i<length ;)
7253+ {
7254+ printf("[.");
7255+ while(*p != 0)
7256+ PUT_CHAR((i++,*p++));
7257+ i++,p++;
7258+ printf(".]");
7259+ }
7260+ length = *workp++; /* the length of equivalence_class */
7261+ for (i=0 ; i<length ;)
7262+ {
7263+ printf("[=");
7264+ while(*p != 0)
7265+ PUT_CHAR((i++,*p++));
7266+ i++,p++;
7267+ printf("=]");
7268+ }
7269+ length = *workp++; /* the length of char_range */
7270+ for (i=0 ; i<length ; i++)
7271+ {
7272+ wchar_t range_start = *p++;
7273+ wchar_t range_end = *p++;
7274+ printf("%C-%C", range_start, range_end);
7275+ }
7276+ length = *workp++; /* the length of char */
7277+ for (i=0 ; i<length ; i++)
7278+ printf("%C", *p++);
7279+ putchar (']');
7280+# else
7281+ register int c, last = -100;
7282+ register int in_range = 0;
7283+
7284+ printf ("/charset [%s",
7285+ (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
7286+
7287+ assert (p + *p < pend);
7288+
7289+ for (c = 0; c < 256; c++)
7290+ if (c / 8 < *p
7291+ && (p[1 + (c/8)] & (1 << (c % 8))))
7292+ {
7293+ /* Are we starting a range? */
7294+ if (last + 1 == c && ! in_range)
7295+ {
7296+ putchar ('-');
7297+ in_range = 1;
7298+ }
7299+ /* Have we broken a range? */
7300+ else if (last + 1 != c && in_range)
7301+ {
7302+ putchar (last);
7303+ in_range = 0;
7304+ }
7305+
7306+ if (! in_range)
7307+ putchar (c);
7308+
7309+ last = c;
7310+ }
7311+
7312+ if (in_range)
7313+ putchar (last);
7314+
7315+ putchar (']');
7316+
7317+ p += 1 + *p;
7318+# endif /* WCHAR */
7319+ }
7320+ break;
7321+
7322+ case begline:
7323+ printf ("/begline");
7324+ break;
7325+
7326+ case endline:
7327+ printf ("/endline");
7328+ break;
7329+
7330+ case on_failure_jump:
7331+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7332+# ifdef _LIBC
7333+ printf ("/on_failure_jump to %td", p + mcnt - start);
7334+# else
7335+ printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start));
7336+# endif
7337+ break;
7338+
7339+ case on_failure_keep_string_jump:
7340+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7341+# ifdef _LIBC
7342+ printf ("/on_failure_keep_string_jump to %td", p + mcnt - start);
7343+# else
7344+ printf ("/on_failure_keep_string_jump to %ld",
7345+ (long int) (p + mcnt - start));
7346+# endif
7347+ break;
7348+
7349+ case dummy_failure_jump:
7350+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7351+# ifdef _LIBC
7352+ printf ("/dummy_failure_jump to %td", p + mcnt - start);
7353+# else
7354+ printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start));
7355+# endif
7356+ break;
7357+
7358+ case push_dummy_failure:
7359+ printf ("/push_dummy_failure");
7360+ break;
7361+
7362+ case maybe_pop_jump:
7363+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7364+# ifdef _LIBC
7365+ printf ("/maybe_pop_jump to %td", p + mcnt - start);
7366+# else
7367+ printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start));
7368+# endif
7369+ break;
7370+
7371+ case pop_failure_jump:
7372+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7373+# ifdef _LIBC
7374+ printf ("/pop_failure_jump to %td", p + mcnt - start);
7375+# else
7376+ printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start));
7377+# endif
7378+ break;
7379+
7380+ case jump_past_alt:
7381+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7382+# ifdef _LIBC
7383+ printf ("/jump_past_alt to %td", p + mcnt - start);
7384+# else
7385+ printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start));
7386+# endif
7387+ break;
7388+
7389+ case jump:
7390+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7391+# ifdef _LIBC
7392+ printf ("/jump to %td", p + mcnt - start);
7393+# else
7394+ printf ("/jump to %ld", (long int) (p + mcnt - start));
7395+# endif
7396+ break;
7397+
7398+ case succeed_n:
7399+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7400+ p1 = p + mcnt;
7401+ PREFIX(extract_number_and_incr) (&mcnt2, &p);
7402+# ifdef _LIBC
7403+ printf ("/succeed_n to %td, %d times", p1 - start, mcnt2);
7404+# else
7405+ printf ("/succeed_n to %ld, %d times",
7406+ (long int) (p1 - start), mcnt2);
7407+# endif
7408+ break;
7409+
7410+ case jump_n:
7411+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7412+ p1 = p + mcnt;
7413+ PREFIX(extract_number_and_incr) (&mcnt2, &p);
7414+ printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
7415+ break;
7416+
7417+ case set_number_at:
7418+ PREFIX(extract_number_and_incr) (&mcnt, &p);
7419+ p1 = p + mcnt;
7420+ PREFIX(extract_number_and_incr) (&mcnt2, &p);
7421+# ifdef _LIBC
7422+ printf ("/set_number_at location %td to %d", p1 - start, mcnt2);
7423+# else
7424+ printf ("/set_number_at location %ld to %d",
7425+ (long int) (p1 - start), mcnt2);
7426+# endif
7427+ break;
7428+
7429+ case wordbound:
7430+ printf ("/wordbound");
7431+ break;
7432+
7433+ case notwordbound:
7434+ printf ("/notwordbound");
7435+ break;
7436+
7437+ case wordbeg:
7438+ printf ("/wordbeg");
7439+ break;
7440+
7441+ case wordend:
7442+ printf ("/wordend");
7443+ break;
7444+
7445+# ifdef emacs
7446+ case before_dot:
7447+ printf ("/before_dot");
7448+ break;
7449+
7450+ case at_dot:
7451+ printf ("/at_dot");
7452+ break;
7453+
7454+ case after_dot:
7455+ printf ("/after_dot");
7456+ break;
7457+
7458+ case syntaxspec:
7459+ printf ("/syntaxspec");
7460+ mcnt = *p++;
7461+ printf ("/%d", mcnt);
7462+ break;
7463+
7464+ case notsyntaxspec:
7465+ printf ("/notsyntaxspec");
7466+ mcnt = *p++;
7467+ printf ("/%d", mcnt);
7468+ break;
7469+# endif /* emacs */
7470+
7471+ case wordchar:
7472+ printf ("/wordchar");
7473+ break;
7474+
7475+ case notwordchar:
7476+ printf ("/notwordchar");
7477+ break;
7478+
7479+ case begbuf:
7480+ printf ("/begbuf");
7481+ break;
7482+
7483+ case endbuf:
7484+ printf ("/endbuf");
7485+ break;
7486+
7487+ default:
7488+ printf ("?%ld", (long int) *(p-1));
7489+ }
7490+
7491+ putchar ('\n');
7492+ }
7493+
7494+# ifdef _LIBC
7495+ printf ("%td:\tend of pattern.\n", p - start);
7496+# else
7497+ printf ("%ld:\tend of pattern.\n", (long int) (p - start));
7498+# endif
7499+}
7500+
7501+
7502+void
7503+PREFIX(print_compiled_pattern) (struct re_pattern_buffer *bufp)
7504+{
7505+ UCHAR_T *buffer = (UCHAR_T*) bufp->buffer;
7506+
7507+ PREFIX(print_partial_compiled_pattern) (buffer, buffer
7508+ + bufp->used / sizeof(UCHAR_T));
7509+ printf ("%ld bytes used/%ld bytes allocated.\n",
7510+ bufp->used, bufp->allocated);
7511+
7512+ if (bufp->fastmap_accurate && bufp->fastmap)
7513+ {
7514+ printf ("fastmap: ");
7515+ print_fastmap (bufp->fastmap);
7516+ }
7517+
7518+# ifdef _LIBC
7519+ printf ("re_nsub: %Zd\t", bufp->re_nsub);
7520+# else
7521+ printf ("re_nsub: %ld\t", (long int) bufp->re_nsub);
7522+# endif
7523+ printf ("regs_alloc: %d\t", bufp->regs_allocated);
7524+ printf ("can_be_null: %d\t", bufp->can_be_null);
7525+ printf ("newline_anchor: %d\n", bufp->newline_anchor);
7526+ printf ("no_sub: %d\t", bufp->no_sub);
7527+ printf ("not_bol: %d\t", bufp->not_bol);
7528+ printf ("not_eol: %d\t", bufp->not_eol);
7529+ printf ("syntax: %lx\n", bufp->syntax);
7530+ /* Perhaps we should print the translate table? */
7531+}
7532+
7533+
7534+void
7535+PREFIX(print_double_string) (const CHAR_T *where, const CHAR_T *string1,
7536+ int size1, const CHAR_T *string2, int size2)
7537+{
7538+ int this_char;
7539+
7540+ if (where == NULL)
7541+ printf ("(null)");
7542+ else
7543+ {
7544+ int cnt;
7545+
7546+ if (FIRST_STRING_P (where))
7547+ {
7548+ for (this_char = where - string1; this_char < size1; this_char++)
7549+ PUT_CHAR (string1[this_char]);
7550+
7551+ where = string2;
7552+ }
7553+
7554+ cnt = 0;
7555+ for (this_char = where - string2; this_char < size2; this_char++)
7556+ {
7557+ PUT_CHAR (string2[this_char]);
7558+ if (++cnt > 100)
7559+ {
7560+ fputs ("...", stdout);
7561+ break;
7562+ }
7563+ }
7564+ }
7565+}
7566+
7567+# ifndef DEFINED_ONCE
7568+void
7569+printchar (int c)
7570+{
7571+ putc (c, stderr);
7572+}
7573+# endif
7574+
7575+# else /* not DEBUG */
7576+
7577+# ifndef DEFINED_ONCE
7578+# undef assert
7579+# define assert(e)
7580+
7581+# define DEBUG_STATEMENT(e)
7582+# define DEBUG_PRINT1(x)
7583+# define DEBUG_PRINT2(x1, x2)
7584+# define DEBUG_PRINT3(x1, x2, x3)
7585+# define DEBUG_PRINT4(x1, x2, x3, x4)
7586+# endif /* not DEFINED_ONCE */
7587+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
7588+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
7589+
7590+# endif /* not DEBUG */
7591+
7592+
7593+
7594+# ifdef WCHAR
7595+/* This convert a multibyte string to a wide character string.
7596+ And write their correspondances to offset_buffer(see below)
7597+ and write whether each wchar_t is binary data to is_binary.
7598+ This assume invalid multibyte sequences as binary data.
7599+ We assume offset_buffer and is_binary is already allocated
7600+ enough space. */
7601+
7602+static size_t convert_mbs_to_wcs (CHAR_T *dest, const unsigned char* src,
7603+ size_t len, int *offset_buffer,
7604+ char *is_binary);
7605+static size_t
7606+convert_mbs_to_wcs (CHAR_T *dest, const unsigned char*src, size_t len,
7607+ int *offset_buffer, char *is_binary)
7608+ /* It hold correspondances between src(char string) and
7609+ dest(wchar_t string) for optimization.
7610+ e.g. src = "xxxyzz"
7611+ dest = {'X', 'Y', 'Z'}
7612+ (each "xxx", "y" and "zz" represent one multibyte character
7613+ corresponding to 'X', 'Y' and 'Z'.)
7614+ offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")}
7615+ = {0, 3, 4, 6}
7616+ */
7617+{
7618+ wchar_t *pdest = dest;
7619+ const unsigned char *psrc = src;
7620+ size_t wc_count = 0;
7621+
7622+ mbstate_t mbs;
7623+ int i, consumed;
7624+ size_t mb_remain = len;
7625+ size_t mb_count = 0;
7626+
7627+ /* Initialize the conversion state. */
7628+ memset (&mbs, 0, sizeof (mbstate_t));
7629+
7630+ offset_buffer[0] = 0;
7631+ for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed,
7632+ psrc += consumed)
7633+ {
7634+#ifdef _LIBC
7635+ consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs);
7636+#else
7637+ consumed = mbrtowc (pdest, psrc, mb_remain, &mbs);
7638+#endif
7639+
7640+ if (consumed <= 0)
7641+ /* failed to convert. maybe src contains binary data.
7642+ So we consume 1 byte manualy. */
7643+ {
7644+ *pdest = *psrc;
7645+ consumed = 1;
7646+ is_binary[wc_count] = TRUE;
7647+ }
7648+ else
7649+ is_binary[wc_count] = FALSE;
7650+ /* In sjis encoding, we use yen sign as escape character in
7651+ place of reverse solidus. So we convert 0x5c(yen sign in
7652+ sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse
7653+ solidus in UCS2). */
7654+ if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5)
7655+ *pdest = (wchar_t) *psrc;
7656+
7657+ offset_buffer[wc_count + 1] = mb_count += consumed;
7658+ }
7659+
7660+ /* Fill remain of the buffer with sentinel. */
7661+ for (i = wc_count + 1 ; i <= len ; i++)
7662+ offset_buffer[i] = mb_count + 1;
7663+
7664+ return wc_count;
7665+}
7666+
7667+# endif /* WCHAR */
7668+
7669+#else /* not INSIDE_RECURSION */
7670+
7671+/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
7672+ also be assigned to arbitrarily: each pattern buffer stores its own
7673+ syntax, so it can be changed between regex compilations. */
7674+/* This has no initializer because initialized variables in Emacs
7675+ become read-only after dumping. */
7676+reg_syntax_t re_syntax_options;
7677+
7678+
7679+/* Specify the precise syntax of regexps for compilation. This provides
7680+ for compatibility for various utilities which historically have
7681+ different, incompatible syntaxes.
7682+
7683+ The argument SYNTAX is a bit mask comprised of the various bits
7684+ defined in regex.h. We return the old syntax. */
7685+
7686+reg_syntax_t
7687+re_set_syntax (reg_syntax_t syntax)
7688+{
7689+ reg_syntax_t ret = re_syntax_options;
7690+
7691+ re_syntax_options = syntax;
7692+# ifdef DEBUG
7693+ if (syntax & RE_DEBUG)
7694+ debug = 1;
7695+ else if (debug) /* was on but now is not */
7696+ debug = 0;
7697+# endif /* DEBUG */
7698+ return ret;
7699+}
7700+# ifdef _LIBC
7701+weak_alias (__re_set_syntax, re_set_syntax)
7702+# endif
7703+
7704+/* This table gives an error message for each of the error codes listed
7705+ in regex.h. Obviously the order here has to be same as there.
7706+ POSIX doesn't require that we do anything for REG_NOERROR,
7707+ but why not be nice? */
7708+
7709+static const char *re_error_msgid[] =
7710+ {
7711+ gettext_noop ("Success"), /* REG_NOERROR */
7712+ gettext_noop ("No match"), /* REG_NOMATCH */
7713+ gettext_noop ("Invalid regular expression"), /* REG_BADPAT */
7714+ gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */
7715+ gettext_noop ("Invalid character class name"), /* REG_ECTYPE */
7716+ gettext_noop ("Trailing backslash"), /* REG_EESCAPE */
7717+ gettext_noop ("Invalid back reference"), /* REG_ESUBREG */
7718+ gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */
7719+ gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */
7720+ gettext_noop ("Unmatched \\{"), /* REG_EBRACE */
7721+ gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */
7722+ gettext_noop ("Invalid range end"), /* REG_ERANGE */
7723+ gettext_noop ("Memory exhausted"), /* REG_ESPACE */
7724+ gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */
7725+ gettext_noop ("Premature end of regular expression"), /* REG_EEND */
7726+ gettext_noop ("Regular expression too big"), /* REG_ESIZE */
7727+ gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
7728+ };
7729+
7730+#endif /* INSIDE_RECURSION */
7731+
7732+#ifndef DEFINED_ONCE
7733+/* Avoiding alloca during matching, to placate r_alloc. */
7734+
7735+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
7736+ searching and matching functions should not call alloca. On some
7737+ systems, alloca is implemented in terms of malloc, and if we're
7738+ using the relocating allocator routines, then malloc could cause a
7739+ relocation, which might (if the strings being searched are in the
7740+ ralloc heap) shift the data out from underneath the regexp
7741+ routines.
7742+
7743+ Here's another reason to avoid allocation: Emacs
7744+ processes input from X in a signal handler; processing X input may
7745+ call malloc; if input arrives while a matching routine is calling
7746+ malloc, then we're scrod. But Emacs can't just block input while
7747+ calling matching routines; then we don't notice interrupts when
7748+ they come in. So, Emacs blocks input around all regexp calls
7749+ except the matching calls, which it leaves unprotected, in the
7750+ faith that they will not malloc. */
7751+
7752+/* Normally, this is fine. */
7753+# define MATCH_MAY_ALLOCATE
7754+
7755+/* When using GNU C, we are not REALLY using the C alloca, no matter
7756+ what config.h may say. So don't take precautions for it. */
7757+# ifdef __GNUC__
7758+# undef C_ALLOCA
7759+# endif
7760+
7761+/* The match routines may not allocate if (1) they would do it with malloc
7762+ and (2) it's not safe for them to use malloc.
7763+ Note that if REL_ALLOC is defined, matching would not use malloc for the
7764+ failure stack, but we would still use it for the register vectors;
7765+ so REL_ALLOC should not affect this. */
7766+# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
7767+# undef MATCH_MAY_ALLOCATE
7768+# endif
7769+#endif /* not DEFINED_ONCE */
7770+
7771+#ifdef INSIDE_RECURSION
7772+/* Failure stack declarations and macros; both re_compile_fastmap and
7773+ re_match_2 use a failure stack. These have to be macros because of
7774+ REGEX_ALLOCATE_STACK. */
7775+
7776+
7777+/* Number of failure points for which to initially allocate space
7778+ when matching. If this number is exceeded, we allocate more
7779+ space, so it is not a hard limit. */
7780+# ifndef INIT_FAILURE_ALLOC
7781+# define INIT_FAILURE_ALLOC 5
7782+# endif
7783+
7784+/* Roughly the maximum number of failure points on the stack. Would be
7785+ exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
7786+ This is a variable only so users of regex can assign to it; we never
7787+ change it ourselves. */
7788+
7789+
7790+# ifndef DEFINED_ONCE
7791+
7792+# ifdef INT_IS_16BIT
7793+# define RE_M_F_TYPE long int
7794+# else
7795+# define RE_M_F_TYPE int
7796+# endif /* INT_IS_16BIT */
7797+
7798+# ifdef MATCH_MAY_ALLOCATE
7799+/* 4400 was enough to cause a crash on Alpha OSF/1,
7800+ whose default stack limit is 2mb. */
7801+# define RE_M_F_DEFAULT 4000
7802+# else
7803+# define RE_M_F_DEFAULT 2000
7804+# endif /* MATCH_MAY_ALLOCATE */
7805+
7806+# include <shlib-compat.h>
7807+
7808+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
7809+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
7810+RE_M_F_TYPE re_max_failures = RE_M_F_DEFAULT;
7811+# else
7812+RE_M_F_TYPE re_max_failures attribute_hidden = RE_M_F_DEFAULT;
7813+# endif /* SHLIB_COMPAT */
7814+
7815+# undef RE_M_F_TYPE
7816+# undef RE_M_F_DEFAULT
7817+
7818+# endif /* DEFINED_ONCE */
7819+
7820+# ifdef INT_IS_16BIT
7821+
7822+union PREFIX(fail_stack_elt)
7823+{
7824+ UCHAR_T *pointer;
7825+ long int integer;
7826+};
7827+
7828+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
7829+
7830+typedef struct
7831+{
7832+ PREFIX(fail_stack_elt_t) *stack;
7833+ unsigned long int size;
7834+ unsigned long int avail; /* Offset of next open position. */
7835+} PREFIX(fail_stack_type);
7836+
7837+# else /* not INT_IS_16BIT */
7838+
7839+union PREFIX(fail_stack_elt)
7840+{
7841+ UCHAR_T *pointer;
7842+ int integer;
7843+};
7844+
7845+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
7846+
7847+typedef struct
7848+{
7849+ PREFIX(fail_stack_elt_t) *stack;
7850+ unsigned size;
7851+ unsigned avail; /* Offset of next open position. */
7852+} PREFIX(fail_stack_type);
7853+
7854+# endif /* INT_IS_16BIT */
7855+
7856+# ifndef DEFINED_ONCE
7857+# define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
7858+# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
7859+# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
7860+# endif
7861+
7862+
7863+/* Define macros to initialize and free the failure stack.
7864+ Do `return -2' if the alloc fails. */
7865+
7866+# ifdef MATCH_MAY_ALLOCATE
7867+# define INIT_FAIL_STACK() \
7868+ do { \
7869+ fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \
7870+ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \
7871+ \
7872+ if (fail_stack.stack == NULL) \
7873+ return -2; \
7874+ \
7875+ fail_stack.size = INIT_FAILURE_ALLOC; \
7876+ fail_stack.avail = 0; \
7877+ } while (0)
7878+
7879+# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack)
7880+# else
7881+# define INIT_FAIL_STACK() \
7882+ do { \
7883+ fail_stack.avail = 0; \
7884+ } while (0)
7885+
7886+# define RESET_FAIL_STACK()
7887+# endif
7888+
7889+
7890+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
7891+
7892+ Return 1 if succeeds, and 0 if either ran out of memory
7893+ allocating space for it or it was already too large.
7894+
7895+ REGEX_REALLOCATE_STACK requires `destination' be declared. */
7896+
7897+# define DOUBLE_FAIL_STACK(fail_stack) \
7898+ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \
7899+ ? 0 \
7900+ : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \
7901+ REGEX_REALLOCATE_STACK ((fail_stack).stack, \
7902+ (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \
7903+ ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\
7904+ \
7905+ (fail_stack).stack == NULL \
7906+ ? 0 \
7907+ : ((fail_stack).size <<= 1, \
7908+ 1)))
7909+
7910+
7911+/* Push pointer POINTER on FAIL_STACK.
7912+ Return 1 if was able to do so and 0 if ran out of memory allocating
7913+ space to do so. */
7914+# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \
7915+ ((FAIL_STACK_FULL () \
7916+ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \
7917+ ? 0 \
7918+ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \
7919+ 1))
7920+
7921+/* Push a pointer value onto the failure stack.
7922+ Assumes the variable `fail_stack'. Probably should only
7923+ be called from within `PUSH_FAILURE_POINT'. */
7924+# define PUSH_FAILURE_POINTER(item) \
7925+ fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item)
7926+
7927+/* This pushes an integer-valued item onto the failure stack.
7928+ Assumes the variable `fail_stack'. Probably should only
7929+ be called from within `PUSH_FAILURE_POINT'. */
7930+# define PUSH_FAILURE_INT(item) \
7931+ fail_stack.stack[fail_stack.avail++].integer = (item)
7932+
7933+/* Push a fail_stack_elt_t value onto the failure stack.
7934+ Assumes the variable `fail_stack'. Probably should only
7935+ be called from within `PUSH_FAILURE_POINT'. */
7936+# define PUSH_FAILURE_ELT(item) \
7937+ fail_stack.stack[fail_stack.avail++] = (item)
7938+
7939+/* These three POP... operations complement the three PUSH... operations.
7940+ All assume that `fail_stack' is nonempty. */
7941+# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
7942+# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
7943+# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
7944+
7945+/* Used to omit pushing failure point id's when we're not debugging. */
7946+# ifdef DEBUG
7947+# define DEBUG_PUSH PUSH_FAILURE_INT
7948+# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
7949+# else
7950+# define DEBUG_PUSH(item)
7951+# define DEBUG_POP(item_addr)
7952+# endif
7953+
7954+
7955+/* Push the information about the state we will need
7956+ if we ever fail back to it.
7957+
7958+ Requires variables fail_stack, regstart, regend, reg_info, and
7959+ num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination'
7960+ be declared.
7961+
7962+ Does `return FAILURE_CODE' if runs out of memory. */
7963+
7964+# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
7965+ do { \
7966+ char *destination; \
7967+ /* Must be int, so when we don't save any registers, the arithmetic \
7968+ of 0 + -1 isn't done as unsigned. */ \
7969+ /* Can't be int, since there is not a shred of a guarantee that int \
7970+ is wide enough to hold a value of something to which pointer can \
7971+ be assigned */ \
7972+ active_reg_t this_reg; \
7973+ \
7974+ DEBUG_STATEMENT (failure_id++); \
7975+ DEBUG_STATEMENT (nfailure_points_pushed++); \
7976+ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
7977+ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
7978+ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
7979+ \
7980+ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \
7981+ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
7982+ \
7983+ /* Ensure we have enough space allocated for what we will push. */ \
7984+ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
7985+ { \
7986+ if (!DOUBLE_FAIL_STACK (fail_stack)) \
7987+ return failure_code; \
7988+ \
7989+ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
7990+ (fail_stack).size); \
7991+ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
7992+ } \
7993+ \
7994+ /* Push the info, starting with the registers. */ \
7995+ DEBUG_PRINT1 ("\n"); \
7996+ \
7997+ if (1) \
7998+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
7999+ this_reg++) \
8000+ { \
8001+ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \
8002+ DEBUG_STATEMENT (num_regs_pushed++); \
8003+ \
8004+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
8005+ PUSH_FAILURE_POINTER (regstart[this_reg]); \
8006+ \
8007+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
8008+ PUSH_FAILURE_POINTER (regend[this_reg]); \
8009+ \
8010+ DEBUG_PRINT2 (" info: %p\n ", \
8011+ reg_info[this_reg].word.pointer); \
8012+ DEBUG_PRINT2 (" match_null=%d", \
8013+ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
8014+ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
8015+ DEBUG_PRINT2 (" matched_something=%d", \
8016+ MATCHED_SOMETHING (reg_info[this_reg])); \
8017+ DEBUG_PRINT2 (" ever_matched=%d", \
8018+ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
8019+ DEBUG_PRINT1 ("\n"); \
8020+ PUSH_FAILURE_ELT (reg_info[this_reg].word); \
8021+ } \
8022+ \
8023+ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\
8024+ PUSH_FAILURE_INT (lowest_active_reg); \
8025+ \
8026+ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\
8027+ PUSH_FAILURE_INT (highest_active_reg); \
8028+ \
8029+ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \
8030+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
8031+ PUSH_FAILURE_POINTER (pattern_place); \
8032+ \
8033+ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \
8034+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
8035+ size2); \
8036+ DEBUG_PRINT1 ("'\n"); \
8037+ PUSH_FAILURE_POINTER (string_place); \
8038+ \
8039+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
8040+ DEBUG_PUSH (failure_id); \
8041+ } while (0)
8042+
8043+# ifndef DEFINED_ONCE
8044+/* This is the number of items that are pushed and popped on the stack
8045+ for each register. */
8046+# define NUM_REG_ITEMS 3
8047+
8048+/* Individual items aside from the registers. */
8049+# ifdef DEBUG
8050+# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
8051+# else
8052+# define NUM_NONREG_ITEMS 4
8053+# endif
8054+
8055+/* We push at most this many items on the stack. */
8056+/* We used to use (num_regs - 1), which is the number of registers
8057+ this regexp will save; but that was changed to 5
8058+ to avoid stack overflow for a regexp with lots of parens. */
8059+# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
8060+
8061+/* We actually push this many items. */
8062+# define NUM_FAILURE_ITEMS \
8063+ (((0 \
8064+ ? 0 : highest_active_reg - lowest_active_reg + 1) \
8065+ * NUM_REG_ITEMS) \
8066+ + NUM_NONREG_ITEMS)
8067+
8068+/* How many items can still be added to the stack without overflowing it. */
8069+# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
8070+# endif /* not DEFINED_ONCE */
8071+
8072+
8073+/* Pops what PUSH_FAIL_STACK pushes.
8074+
8075+ We restore into the parameters, all of which should be lvalues:
8076+ STR -- the saved data position.
8077+ PAT -- the saved pattern position.
8078+ LOW_REG, HIGH_REG -- the highest and lowest active registers.
8079+ REGSTART, REGEND -- arrays of string positions.
8080+ REG_INFO -- array of information about each subexpression.
8081+
8082+ Also assumes the variables `fail_stack' and (if debugging), `bufp',
8083+ `pend', `string1', `size1', `string2', and `size2'. */
8084+# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
8085+{ \
8086+ DEBUG_STATEMENT (unsigned failure_id;) \
8087+ active_reg_t this_reg; \
8088+ const UCHAR_T *string_temp; \
8089+ \
8090+ assert (!FAIL_STACK_EMPTY ()); \
8091+ \
8092+ /* Remove failure points and point to how many regs pushed. */ \
8093+ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
8094+ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
8095+ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
8096+ \
8097+ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
8098+ \
8099+ DEBUG_POP (&failure_id); \
8100+ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
8101+ \
8102+ /* If the saved string location is NULL, it came from an \
8103+ on_failure_keep_string_jump opcode, and we want to throw away the \
8104+ saved NULL, thus retaining our current position in the string. */ \
8105+ string_temp = POP_FAILURE_POINTER (); \
8106+ if (string_temp != NULL) \
8107+ str = (const CHAR_T *) string_temp; \
8108+ \
8109+ DEBUG_PRINT2 (" Popping string %p: `", str); \
8110+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
8111+ DEBUG_PRINT1 ("'\n"); \
8112+ \
8113+ pat = (UCHAR_T *) POP_FAILURE_POINTER (); \
8114+ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \
8115+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
8116+ \
8117+ /* Restore register info. */ \
8118+ high_reg = (active_reg_t) POP_FAILURE_INT (); \
8119+ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \
8120+ \
8121+ low_reg = (active_reg_t) POP_FAILURE_INT (); \
8122+ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \
8123+ \
8124+ if (1) \
8125+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
8126+ { \
8127+ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \
8128+ \
8129+ reg_info[this_reg].word = POP_FAILURE_ELT (); \
8130+ DEBUG_PRINT2 (" info: %p\n", \
8131+ reg_info[this_reg].word.pointer); \
8132+ \
8133+ regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \
8134+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
8135+ \
8136+ regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \
8137+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
8138+ } \
8139+ else \
8140+ { \
8141+ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
8142+ { \
8143+ reg_info[this_reg].word.integer = 0; \
8144+ regend[this_reg] = 0; \
8145+ regstart[this_reg] = 0; \
8146+ } \
8147+ highest_active_reg = high_reg; \
8148+ } \
8149+ \
8150+ set_regs_matched_done = 0; \
8151+ DEBUG_STATEMENT (nfailure_points_popped++); \
8152+} /* POP_FAILURE_POINT */
8153+
8154+/* Structure for per-register (a.k.a. per-group) information.
8155+ Other register information, such as the
8156+ starting and ending positions (which are addresses), and the list of
8157+ inner groups (which is a bits list) are maintained in separate
8158+ variables.
8159+
8160+ We are making a (strictly speaking) nonportable assumption here: that
8161+ the compiler will pack our bit fields into something that fits into
8162+ the type of `word', i.e., is something that fits into one item on the
8163+ failure stack. */
8164+
8165+
8166+/* Declarations and macros for re_match_2. */
8167+
8168+typedef union
8169+{
8170+ PREFIX(fail_stack_elt_t) word;
8171+ struct
8172+ {
8173+ /* This field is one if this group can match the empty string,
8174+ zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
8175+# define MATCH_NULL_UNSET_VALUE 3
8176+ unsigned match_null_string_p : 2;
8177+ unsigned is_active : 1;
8178+ unsigned matched_something : 1;
8179+ unsigned ever_matched_something : 1;
8180+ } bits;
8181+} PREFIX(register_info_type);
8182+
8183+# ifndef DEFINED_ONCE
8184+# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
8185+# define IS_ACTIVE(R) ((R).bits.is_active)
8186+# define MATCHED_SOMETHING(R) ((R).bits.matched_something)
8187+# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
8188+
8189+
8190+/* Call this when have matched a real character; it sets `matched' flags
8191+ for the subexpressions which we are currently inside. Also records
8192+ that those subexprs have matched. */
8193+# define SET_REGS_MATCHED() \
8194+ do \
8195+ { \
8196+ if (!set_regs_matched_done) \
8197+ { \
8198+ active_reg_t r; \
8199+ set_regs_matched_done = 1; \
8200+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
8201+ { \
8202+ MATCHED_SOMETHING (reg_info[r]) \
8203+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
8204+ = 1; \
8205+ } \
8206+ } \
8207+ } \
8208+ while (0)
8209+# endif /* not DEFINED_ONCE */
8210+
8211+/* Registers are set to a sentinel when they haven't yet matched. */
8212+static CHAR_T PREFIX(reg_unset_dummy);
8213+# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy))
8214+# define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
8215+
8216+/* Subroutine declarations and macros for regex_compile. */
8217+static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg);
8218+static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc,
8219+ int arg1, int arg2);
8220+static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc,
8221+ int arg, UCHAR_T *end);
8222+static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc,
8223+ int arg1, int arg2, UCHAR_T *end);
8224+static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern,
8225+ const CHAR_T *p,
8226+ reg_syntax_t syntax);
8227+static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p,
8228+ const CHAR_T *pend,
8229+ reg_syntax_t syntax);
8230+# ifdef WCHAR
8231+static reg_errcode_t wcs_compile_range (CHAR_T range_start,
8232+ const CHAR_T **p_ptr,
8233+ const CHAR_T *pend,
8234+ char *translate,
8235+ reg_syntax_t syntax,
8236+ UCHAR_T *b,
8237+ CHAR_T *char_set);
8238+static void insert_space (int num, CHAR_T *loc, CHAR_T *end);
8239+# else /* BYTE */
8240+static reg_errcode_t byte_compile_range (unsigned int range_start,
8241+ const char **p_ptr,
8242+ const char *pend,
8243+ RE_TRANSLATE_TYPE translate,
8244+ reg_syntax_t syntax,
8245+ unsigned char *b);
8246+# endif /* WCHAR */
8247+
8248+/* Fetch the next character in the uncompiled pattern---translating it
8249+ if necessary. Also cast from a signed character in the constant
8250+ string passed to us by the user to an unsigned char that we can use
8251+ as an array index (in, e.g., `translate'). */
8252+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
8253+ because it is impossible to allocate 4GB array for some encodings
8254+ which have 4 byte character_set like UCS4. */
8255+# ifndef PATFETCH
8256+# ifdef WCHAR
8257+# define PATFETCH(c) \
8258+ do {if (p == pend) return REG_EEND; \
8259+ c = (UCHAR_T) *p++; \
8260+ if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \
8261+ } while (0)
8262+# else /* BYTE */
8263+# define PATFETCH(c) \
8264+ do {if (p == pend) return REG_EEND; \
8265+ c = (unsigned char) *p++; \
8266+ if (translate) c = (unsigned char) translate[c]; \
8267+ } while (0)
8268+# endif /* WCHAR */
8269+# endif
8270+
8271+/* Fetch the next character in the uncompiled pattern, with no
8272+ translation. */
8273+# define PATFETCH_RAW(c) \
8274+ do {if (p == pend) return REG_EEND; \
8275+ c = (UCHAR_T) *p++; \
8276+ } while (0)
8277+
8278+/* Go backwards one character in the pattern. */
8279+# define PATUNFETCH p--
8280+
8281+
8282+/* If `translate' is non-null, return translate[D], else just D. We
8283+ cast the subscript to translate because some data is declared as
8284+ `char *', to avoid warnings when a string constant is passed. But
8285+ when we use a character as a subscript we must make it unsigned. */
8286+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
8287+ because it is impossible to allocate 4GB array for some encodings
8288+ which have 4 byte character_set like UCS4. */
8289+
8290+# ifndef TRANSLATE
8291+# ifdef WCHAR
8292+# define TRANSLATE(d) \
8293+ ((translate && ((UCHAR_T) (d)) <= 0xff) \
8294+ ? (char) translate[(unsigned char) (d)] : (d))
8295+# else /* BYTE */
8296+# define TRANSLATE(d) \
8297+ (translate ? (char) translate[(unsigned char) (d)] : (char) (d))
8298+# endif /* WCHAR */
8299+# endif
8300+
8301+
8302+/* Macros for outputting the compiled pattern into `buffer'. */
8303+
8304+/* If the buffer isn't allocated when it comes in, use this. */
8305+# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T))
8306+
8307+/* Make sure we have at least N more bytes of space in buffer. */
8308+# ifdef WCHAR
8309+# define GET_BUFFER_SPACE(n) \
8310+ while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \
8311+ + (n)*sizeof(CHAR_T)) > bufp->allocated) \
8312+ EXTEND_BUFFER ()
8313+# else /* BYTE */
8314+# define GET_BUFFER_SPACE(n) \
8315+ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \
8316+ EXTEND_BUFFER ()
8317+# endif /* WCHAR */
8318+
8319+/* Make sure we have one more byte of buffer space and then add C to it. */
8320+# define BUF_PUSH(c) \
8321+ do { \
8322+ GET_BUFFER_SPACE (1); \
8323+ *b++ = (UCHAR_T) (c); \
8324+ } while (0)
8325+
8326+
8327+/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
8328+# define BUF_PUSH_2(c1, c2) \
8329+ do { \
8330+ GET_BUFFER_SPACE (2); \
8331+ *b++ = (UCHAR_T) (c1); \
8332+ *b++ = (UCHAR_T) (c2); \
8333+ } while (0)
8334+
8335+
8336+/* As with BUF_PUSH_2, except for three bytes. */
8337+# define BUF_PUSH_3(c1, c2, c3) \
8338+ do { \
8339+ GET_BUFFER_SPACE (3); \
8340+ *b++ = (UCHAR_T) (c1); \
8341+ *b++ = (UCHAR_T) (c2); \
8342+ *b++ = (UCHAR_T) (c3); \
8343+ } while (0)
8344+
8345+/* Store a jump with opcode OP at LOC to location TO. We store a
8346+ relative address offset by the three bytes the jump itself occupies. */
8347+# define STORE_JUMP(op, loc, to) \
8348+ PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)))
8349+
8350+/* Likewise, for a two-argument jump. */
8351+# define STORE_JUMP2(op, loc, to, arg) \
8352+ PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg)
8353+
8354+/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
8355+# define INSERT_JUMP(op, loc, to) \
8356+ PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b)
8357+
8358+/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
8359+# define INSERT_JUMP2(op, loc, to, arg) \
8360+ PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\
8361+ arg, b)
8362+
8363+/* This is not an arbitrary limit: the arguments which represent offsets
8364+ into the pattern are two bytes long. So if 2^16 bytes turns out to
8365+ be too small, many things would have to change. */
8366+/* Any other compiler which, like MSC, has allocation limit below 2^16
8367+ bytes will have to use approach similar to what was done below for
8368+ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up
8369+ reallocating to 0 bytes. Such thing is not going to work too well.
8370+ You have been warned!! */
8371+# ifndef DEFINED_ONCE
8372+# if defined _MSC_VER && !defined WIN32
8373+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
8374+ The REALLOC define eliminates a flurry of conversion warnings,
8375+ but is not required. */
8376+# define MAX_BUF_SIZE 65500L
8377+# define REALLOC(p,s) realloc ((p), (size_t) (s))
8378+# else
8379+# define MAX_BUF_SIZE (1L << 16)
8380+# define REALLOC(p,s) realloc ((p), (s))
8381+# endif
8382+
8383+/* Extend the buffer by twice its current size via realloc and
8384+ reset the pointers that pointed into the old block to point to the
8385+ correct places in the new one. If extending the buffer results in it
8386+ being larger than MAX_BUF_SIZE, then flag memory exhausted. */
8387+# ifndef __BOUNDED_POINTERS__
8388+# define __BOUNDED_POINTERS__ 0
8389+# endif
8390+# if __BOUNDED_POINTERS__
8391+# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated)
8392+# define MOVE_BUFFER_POINTER(P) \
8393+ (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr)
8394+# define ELSE_EXTEND_BUFFER_HIGH_BOUND \
8395+ else \
8396+ { \
8397+ SET_HIGH_BOUND (b); \
8398+ SET_HIGH_BOUND (begalt); \
8399+ if (fixup_alt_jump) \
8400+ SET_HIGH_BOUND (fixup_alt_jump); \
8401+ if (laststart) \
8402+ SET_HIGH_BOUND (laststart); \
8403+ if (pending_exact) \
8404+ SET_HIGH_BOUND (pending_exact); \
8405+ }
8406+# else
8407+# define MOVE_BUFFER_POINTER(P) (P) += incr
8408+# define ELSE_EXTEND_BUFFER_HIGH_BOUND
8409+# endif
8410+# endif /* not DEFINED_ONCE */
8411+
8412+# ifdef WCHAR
8413+# define EXTEND_BUFFER() \
8414+ do { \
8415+ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \
8416+ int wchar_count; \
8417+ if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \
8418+ return REG_ESIZE; \
8419+ bufp->allocated <<= 1; \
8420+ if (bufp->allocated > MAX_BUF_SIZE) \
8421+ bufp->allocated = MAX_BUF_SIZE; \
8422+ /* How many characters the new buffer can have? */ \
8423+ wchar_count = bufp->allocated / sizeof(UCHAR_T); \
8424+ if (wchar_count == 0) wchar_count = 1; \
8425+ /* Truncate the buffer to CHAR_T align. */ \
8426+ bufp->allocated = wchar_count * sizeof(UCHAR_T); \
8427+ RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \
8428+ bufp->buffer = (char*)COMPILED_BUFFER_VAR; \
8429+ if (COMPILED_BUFFER_VAR == NULL) \
8430+ return REG_ESPACE; \
8431+ /* If the buffer moved, move all the pointers into it. */ \
8432+ if (old_buffer != COMPILED_BUFFER_VAR) \
8433+ { \
8434+ int incr = COMPILED_BUFFER_VAR - old_buffer; \
8435+ MOVE_BUFFER_POINTER (b); \
8436+ MOVE_BUFFER_POINTER (begalt); \
8437+ if (fixup_alt_jump) \
8438+ MOVE_BUFFER_POINTER (fixup_alt_jump); \
8439+ if (laststart) \
8440+ MOVE_BUFFER_POINTER (laststart); \
8441+ if (pending_exact) \
8442+ MOVE_BUFFER_POINTER (pending_exact); \
8443+ } \
8444+ ELSE_EXTEND_BUFFER_HIGH_BOUND \
8445+ } while (0)
8446+# else /* BYTE */
8447+# define EXTEND_BUFFER() \
8448+ do { \
8449+ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \
8450+ if (bufp->allocated == MAX_BUF_SIZE) \
8451+ return REG_ESIZE; \
8452+ bufp->allocated <<= 1; \
8453+ if (bufp->allocated > MAX_BUF_SIZE) \
8454+ bufp->allocated = MAX_BUF_SIZE; \
8455+ bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \
8456+ bufp->allocated); \
8457+ if (COMPILED_BUFFER_VAR == NULL) \
8458+ return REG_ESPACE; \
8459+ /* If the buffer moved, move all the pointers into it. */ \
8460+ if (old_buffer != COMPILED_BUFFER_VAR) \
8461+ { \
8462+ int incr = COMPILED_BUFFER_VAR - old_buffer; \
8463+ MOVE_BUFFER_POINTER (b); \
8464+ MOVE_BUFFER_POINTER (begalt); \
8465+ if (fixup_alt_jump) \
8466+ MOVE_BUFFER_POINTER (fixup_alt_jump); \
8467+ if (laststart) \
8468+ MOVE_BUFFER_POINTER (laststart); \
8469+ if (pending_exact) \
8470+ MOVE_BUFFER_POINTER (pending_exact); \
8471+ } \
8472+ ELSE_EXTEND_BUFFER_HIGH_BOUND \
8473+ } while (0)
8474+# endif /* WCHAR */
8475+
8476+# ifndef DEFINED_ONCE
8477+/* Since we have one byte reserved for the register number argument to
8478+ {start,stop}_memory, the maximum number of groups we can report
8479+ things about is what fits in that byte. */
8480+# define MAX_REGNUM 255
8481+
8482+/* But patterns can have more than `MAX_REGNUM' registers. We just
8483+ ignore the excess. */
8484+typedef unsigned regnum_t;
8485+
8486+
8487+/* Macros for the compile stack. */
8488+
8489+/* Since offsets can go either forwards or backwards, this type needs to
8490+ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
8491+/* int may be not enough when sizeof(int) == 2. */
8492+typedef long pattern_offset_t;
8493+
8494+typedef struct
8495+{
8496+ pattern_offset_t begalt_offset;
8497+ pattern_offset_t fixup_alt_jump;
8498+ pattern_offset_t inner_group_offset;
8499+ pattern_offset_t laststart_offset;
8500+ regnum_t regnum;
8501+} compile_stack_elt_t;
8502+
8503+
8504+typedef struct
8505+{
8506+ compile_stack_elt_t *stack;
8507+ unsigned size;
8508+ unsigned avail; /* Offset of next open position. */
8509+} compile_stack_type;
8510+
8511+
8512+# define INIT_COMPILE_STACK_SIZE 32
8513+
8514+# define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
8515+# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
8516+
8517+/* The next available element. */
8518+# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
8519+
8520+# endif /* not DEFINED_ONCE */
8521+
8522+/* Set the bit for character C in a list. */
8523+# ifndef DEFINED_ONCE
8524+# define SET_LIST_BIT(c) \
8525+ (b[((unsigned char) (c)) / BYTEWIDTH] \
8526+ |= 1 << (((unsigned char) c) % BYTEWIDTH))
8527+# endif /* DEFINED_ONCE */
8528+
8529+/* Get the next unsigned number in the uncompiled pattern. */
8530+# define GET_UNSIGNED_NUMBER(num) \
8531+ { \
8532+ while (p != pend) \
8533+ { \
8534+ PATFETCH (c); \
8535+ if (c < '0' || c > '9') \
8536+ break; \
8537+ if (num <= RE_DUP_MAX) \
8538+ { \
8539+ if (num < 0) \
8540+ num = 0; \
8541+ num = num * 10 + c - '0'; \
8542+ } \
8543+ } \
8544+ }
8545+
8546+# ifndef DEFINED_ONCE
8547+# if WIDE_CHAR_SUPPORT
8548+/* The GNU C library provides support for user-defined character classes
8549+ and the functions from ISO C amendement 1. */
8550+# ifdef CHARCLASS_NAME_MAX
8551+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
8552+# else
8553+/* This shouldn't happen but some implementation might still have this
8554+ problem. Use a reasonable default value. */
8555+# define CHAR_CLASS_MAX_LENGTH 256
8556+# endif
8557+
8558+# ifdef _LIBC
8559+# define IS_CHAR_CLASS(string) __wctype (string)
8560+# else
8561+# define IS_CHAR_CLASS(string) wctype (string)
8562+# endif
8563+# else
8564+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
8565+
8566+# define IS_CHAR_CLASS(string) \
8567+ (STREQ (string, "alpha") || STREQ (string, "upper") \
8568+ || STREQ (string, "lower") || STREQ (string, "digit") \
8569+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
8570+ || STREQ (string, "space") || STREQ (string, "print") \
8571+ || STREQ (string, "punct") || STREQ (string, "graph") \
8572+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
8573+# endif
8574+# endif /* DEFINED_ONCE */
8575+
8576+# ifndef MATCH_MAY_ALLOCATE
8577+
8578+/* If we cannot allocate large objects within re_match_2_internal,
8579+ we make the fail stack and register vectors global.
8580+ The fail stack, we grow to the maximum size when a regexp
8581+ is compiled.
8582+ The register vectors, we adjust in size each time we
8583+ compile a regexp, according to the number of registers it needs. */
8584+
8585+static PREFIX(fail_stack_type) fail_stack;
8586+
8587+/* Size with which the following vectors are currently allocated.
8588+ That is so we can make them bigger as needed,
8589+ but never make them smaller. */
8590+# ifdef DEFINED_ONCE
8591+static int regs_allocated_size;
8592+
8593+static const char ** regstart, ** regend;
8594+static const char ** old_regstart, ** old_regend;
8595+static const char **best_regstart, **best_regend;
8596+static const char **reg_dummy;
8597+# endif /* DEFINED_ONCE */
8598+
8599+static PREFIX(register_info_type) *PREFIX(reg_info);
8600+static PREFIX(register_info_type) *PREFIX(reg_info_dummy);
8601+
8602+/* Make the register vectors big enough for NUM_REGS registers,
8603+ but don't make them smaller. */
8604+
8605+static void
8606+PREFIX(regex_grow_registers) (int num_regs)
8607+{
8608+ if (num_regs > regs_allocated_size)
8609+ {
8610+ RETALLOC_IF (regstart, num_regs, const char *);
8611+ RETALLOC_IF (regend, num_regs, const char *);
8612+ RETALLOC_IF (old_regstart, num_regs, const char *);
8613+ RETALLOC_IF (old_regend, num_regs, const char *);
8614+ RETALLOC_IF (best_regstart, num_regs, const char *);
8615+ RETALLOC_IF (best_regend, num_regs, const char *);
8616+ RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type));
8617+ RETALLOC_IF (reg_dummy, num_regs, const char *);
8618+ RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type));
8619+
8620+ regs_allocated_size = num_regs;
8621+ }
8622+}
8623+
8624+# endif /* not MATCH_MAY_ALLOCATE */
8625+
8626+# ifndef DEFINED_ONCE
8627+static boolean group_in_compile_stack (compile_stack_type compile_stack,
8628+ regnum_t regnum);
8629+# endif /* not DEFINED_ONCE */
8630+
8631+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
8632+ Returns one of error codes defined in `regex.h', or zero for success.
8633+
8634+ Assumes the `allocated' (and perhaps `buffer') and `translate'
8635+ fields are set in BUFP on entry.
8636+
8637+ If it succeeds, results are put in BUFP (if it returns an error, the
8638+ contents of BUFP are undefined):
8639+ `buffer' is the compiled pattern;
8640+ `syntax' is set to SYNTAX;
8641+ `used' is set to the length of the compiled pattern;
8642+ `fastmap_accurate' is zero;
8643+ `re_nsub' is the number of subexpressions in PATTERN;
8644+ `not_bol' and `not_eol' are zero;
8645+
8646+ The `fastmap' and `newline_anchor' fields are neither
8647+ examined nor set. */
8648+
8649+/* Return, freeing storage we allocated. */
8650+# ifdef WCHAR
8651+# define FREE_STACK_RETURN(value) \
8652+ return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value)
8653+# else
8654+# define FREE_STACK_RETURN(value) \
8655+ return (free (compile_stack.stack), value)
8656+# endif /* WCHAR */
8657+
8658+static reg_errcode_t
8659+PREFIX(regex_compile) (const char *ARG_PREFIX(pattern),
8660+ size_t ARG_PREFIX(size), reg_syntax_t syntax,
8661+ struct re_pattern_buffer *bufp)
8662+{
8663+ /* We fetch characters from PATTERN here. Even though PATTERN is
8664+ `char *' (i.e., signed), we declare these variables as unsigned, so
8665+ they can be reliably used as array indices. */
8666+ register UCHAR_T c, c1;
8667+
8668+#ifdef WCHAR
8669+ /* A temporary space to keep wchar_t pattern and compiled pattern. */
8670+ CHAR_T *pattern, *COMPILED_BUFFER_VAR;
8671+ size_t size;
8672+ /* offset buffer for optimization. See convert_mbs_to_wc. */
8673+ int *mbs_offset = NULL;
8674+ /* It hold whether each wchar_t is binary data or not. */
8675+ char *is_binary = NULL;
8676+ /* A flag whether exactn is handling binary data or not. */
8677+ char is_exactn_bin = FALSE;
8678+#endif /* WCHAR */
8679+
8680+ /* A random temporary spot in PATTERN. */
8681+ const CHAR_T *p1;
8682+
8683+ /* Points to the end of the buffer, where we should append. */
8684+ register UCHAR_T *b;
8685+
8686+ /* Keeps track of unclosed groups. */
8687+ compile_stack_type compile_stack;
8688+
8689+ /* Points to the current (ending) position in the pattern. */
8690+#ifdef WCHAR
8691+ const CHAR_T *p;
8692+ const CHAR_T *pend;
8693+#else /* BYTE */
8694+ const CHAR_T *p = pattern;
8695+ const CHAR_T *pend = pattern + size;
8696+#endif /* WCHAR */
8697+
8698+ /* How to translate the characters in the pattern. */
8699+ RE_TRANSLATE_TYPE translate = bufp->translate;
8700+
8701+ /* Address of the count-byte of the most recently inserted `exactn'
8702+ command. This makes it possible to tell if a new exact-match
8703+ character can be added to that command or if the character requires
8704+ a new `exactn' command. */
8705+ UCHAR_T *pending_exact = 0;
8706+
8707+ /* Address of start of the most recently finished expression.
8708+ This tells, e.g., postfix * where to find the start of its
8709+ operand. Reset at the beginning of groups and alternatives. */
8710+ UCHAR_T *laststart = 0;
8711+
8712+ /* Address of beginning of regexp, or inside of last group. */
8713+ UCHAR_T *begalt;
8714+
8715+ /* Address of the place where a forward jump should go to the end of
8716+ the containing expression. Each alternative of an `or' -- except the
8717+ last -- ends with a forward jump of this sort. */
8718+ UCHAR_T *fixup_alt_jump = 0;
8719+
8720+ /* Counts open-groups as they are encountered. Remembered for the
8721+ matching close-group on the compile stack, so the same register
8722+ number is put in the stop_memory as the start_memory. */
8723+ regnum_t regnum = 0;
8724+
8725+#ifdef WCHAR
8726+ /* Initialize the wchar_t PATTERN and offset_buffer. */
8727+ p = pend = pattern = TALLOC(csize + 1, CHAR_T);
8728+ mbs_offset = TALLOC(csize + 1, int);
8729+ is_binary = TALLOC(csize + 1, char);
8730+ if (pattern == NULL || mbs_offset == NULL || is_binary == NULL)
8731+ {
8732+ free(pattern);
8733+ free(mbs_offset);
8734+ free(is_binary);
8735+ return REG_ESPACE;
8736+ }
8737+ pattern[csize] = L'\0'; /* sentinel */
8738+ size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary);
8739+ pend = p + size;
8740+ if (size < 0)
8741+ {
8742+ free(pattern);
8743+ free(mbs_offset);
8744+ free(is_binary);
8745+ return REG_BADPAT;
8746+ }
8747+#endif
8748+
8749+#ifdef DEBUG
8750+ DEBUG_PRINT1 ("\nCompiling pattern: ");
8751+ if (debug)
8752+ {
8753+ unsigned debug_count;
8754+
8755+ for (debug_count = 0; debug_count < size; debug_count++)
8756+ PUT_CHAR (pattern[debug_count]);
8757+ putchar ('\n');
8758+ }
8759+#endif /* DEBUG */
8760+
8761+ /* Initialize the compile stack. */
8762+ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
8763+ if (compile_stack.stack == NULL)
8764+ {
8765+#ifdef WCHAR
8766+ free(pattern);
8767+ free(mbs_offset);
8768+ free(is_binary);
8769+#endif
8770+ return REG_ESPACE;
8771+ }
8772+
8773+ compile_stack.size = INIT_COMPILE_STACK_SIZE;
8774+ compile_stack.avail = 0;
8775+
8776+ /* Initialize the pattern buffer. */
8777+ bufp->syntax = syntax;
8778+ bufp->fastmap_accurate = 0;
8779+ bufp->not_bol = bufp->not_eol = 0;
8780+
8781+ /* Set `used' to zero, so that if we return an error, the pattern
8782+ printer (for debugging) will think there's no pattern. We reset it
8783+ at the end. */
8784+ bufp->used = 0;
8785+
8786+ /* Always count groups, whether or not bufp->no_sub is set. */
8787+ bufp->re_nsub = 0;
8788+
8789+#if !defined emacs && !defined SYNTAX_TABLE
8790+ /* Initialize the syntax table. */
8791+ init_syntax_once ();
8792+#endif
8793+
8794+ if (bufp->allocated == 0)
8795+ {
8796+ if (bufp->buffer)
8797+ { /* If zero allocated, but buffer is non-null, try to realloc
8798+ enough space. This loses if buffer's address is bogus, but
8799+ that is the user's responsibility. */
8800+#ifdef WCHAR
8801+ /* Free bufp->buffer and allocate an array for wchar_t pattern
8802+ buffer. */
8803+ free(bufp->buffer);
8804+ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T),
8805+ UCHAR_T);
8806+#else
8807+ RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T);
8808+#endif /* WCHAR */
8809+ }
8810+ else
8811+ { /* Caller did not allocate a buffer. Do it for them. */
8812+ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T),
8813+ UCHAR_T);
8814+ }
8815+
8816+ if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE);
8817+#ifdef WCHAR
8818+ bufp->buffer = (char*)COMPILED_BUFFER_VAR;
8819+#endif /* WCHAR */
8820+ bufp->allocated = INIT_BUF_SIZE;
8821+ }
8822+#ifdef WCHAR
8823+ else
8824+ COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer;
8825+#endif
8826+
8827+ begalt = b = COMPILED_BUFFER_VAR;
8828+
8829+ /* Loop through the uncompiled pattern until we're at the end. */
8830+ while (p != pend)
8831+ {
8832+ PATFETCH (c);
8833+
8834+ switch (c)
8835+ {
8836+ case '^':
8837+ {
8838+ if ( /* If at start of pattern, it's an operator. */
8839+ p == pattern + 1
8840+ /* If context independent, it's an operator. */
8841+ || syntax & RE_CONTEXT_INDEP_ANCHORS
8842+ /* Otherwise, depends on what's come before. */
8843+ || PREFIX(at_begline_loc_p) (pattern, p, syntax))
8844+ BUF_PUSH (begline);
8845+ else
8846+ goto normal_char;
8847+ }
8848+ break;
8849+
8850+
8851+ case '$':
8852+ {
8853+ if ( /* If at end of pattern, it's an operator. */
8854+ p == pend
8855+ /* If context independent, it's an operator. */
8856+ || syntax & RE_CONTEXT_INDEP_ANCHORS
8857+ /* Otherwise, depends on what's next. */
8858+ || PREFIX(at_endline_loc_p) (p, pend, syntax))
8859+ BUF_PUSH (endline);
8860+ else
8861+ goto normal_char;
8862+ }
8863+ break;
8864+
8865+
8866+ case '+':
8867+ case '?':
8868+ if ((syntax & RE_BK_PLUS_QM)
8869+ || (syntax & RE_LIMITED_OPS))
8870+ goto normal_char;
8871+ handle_plus:
8872+ case '*':
8873+ /* If there is no previous pattern... */
8874+ if (!laststart)
8875+ {
8876+ if (syntax & RE_CONTEXT_INVALID_OPS)
8877+ FREE_STACK_RETURN (REG_BADRPT);
8878+ else if (!(syntax & RE_CONTEXT_INDEP_OPS))
8879+ goto normal_char;
8880+ }
8881+
8882+ {
8883+ /* Are we optimizing this jump? */
8884+ boolean keep_string_p = false;
8885+
8886+ /* 1 means zero (many) matches is allowed. */
8887+ char zero_times_ok = 0, many_times_ok = 0;
8888+
8889+ /* If there is a sequence of repetition chars, collapse it
8890+ down to just one (the right one). We can't combine
8891+ interval operators with these because of, e.g., `a{2}*',
8892+ which should only match an even number of `a's. */
8893+
8894+ for (;;)
8895+ {
8896+ zero_times_ok |= c != '+';
8897+ many_times_ok |= c != '?';
8898+
8899+ if (p == pend)
8900+ break;
8901+
8902+ PATFETCH (c);
8903+
8904+ if (c == '*'
8905+ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
8906+ ;
8907+
8908+ else if (syntax & RE_BK_PLUS_QM && c == '\\')
8909+ {
8910+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
8911+
8912+ PATFETCH (c1);
8913+ if (!(c1 == '+' || c1 == '?'))
8914+ {
8915+ PATUNFETCH;
8916+ PATUNFETCH;
8917+ break;
8918+ }
8919+
8920+ c = c1;
8921+ }
8922+ else
8923+ {
8924+ PATUNFETCH;
8925+ break;
8926+ }
8927+
8928+ /* If we get here, we found another repeat character. */
8929+ }
8930+
8931+ /* Star, etc. applied to an empty pattern is equivalent
8932+ to an empty pattern. */
8933+ if (!laststart)
8934+ break;
8935+
8936+ /* Now we know whether or not zero matches is allowed
8937+ and also whether or not two or more matches is allowed. */
8938+ if (many_times_ok)
8939+ { /* More than one repetition is allowed, so put in at the
8940+ end a backward relative jump from `b' to before the next
8941+ jump we're going to put in below (which jumps from
8942+ laststart to after this jump).
8943+
8944+ But if we are at the `*' in the exact sequence `.*\n',
8945+ insert an unconditional jump backwards to the .,
8946+ instead of the beginning of the loop. This way we only
8947+ push a failure point once, instead of every time
8948+ through the loop. */
8949+ assert (p - 1 > pattern);
8950+
8951+ /* Allocate the space for the jump. */
8952+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
8953+
8954+ /* We know we are not at the first character of the pattern,
8955+ because laststart was nonzero. And we've already
8956+ incremented `p', by the way, to be the character after
8957+ the `*'. Do we have to do something analogous here
8958+ for null bytes, because of RE_DOT_NOT_NULL? */
8959+ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
8960+ && zero_times_ok
8961+ && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
8962+ && !(syntax & RE_DOT_NEWLINE))
8963+ { /* We have .*\n. */
8964+ STORE_JUMP (jump, b, laststart);
8965+ keep_string_p = true;
8966+ }
8967+ else
8968+ /* Anything else. */
8969+ STORE_JUMP (maybe_pop_jump, b, laststart -
8970+ (1 + OFFSET_ADDRESS_SIZE));
8971+
8972+ /* We've added more stuff to the buffer. */
8973+ b += 1 + OFFSET_ADDRESS_SIZE;
8974+ }
8975+
8976+ /* On failure, jump from laststart to b + 3, which will be the
8977+ end of the buffer after this jump is inserted. */
8978+ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of
8979+ 'b + 3'. */
8980+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
8981+ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
8982+ : on_failure_jump,
8983+ laststart, b + 1 + OFFSET_ADDRESS_SIZE);
8984+ pending_exact = 0;
8985+ b += 1 + OFFSET_ADDRESS_SIZE;
8986+
8987+ if (!zero_times_ok)
8988+ {
8989+ /* At least one repetition is required, so insert a
8990+ `dummy_failure_jump' before the initial
8991+ `on_failure_jump' instruction of the loop. This
8992+ effects a skip over that instruction the first time
8993+ we hit that loop. */
8994+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
8995+ INSERT_JUMP (dummy_failure_jump, laststart, laststart +
8996+ 2 + 2 * OFFSET_ADDRESS_SIZE);
8997+ b += 1 + OFFSET_ADDRESS_SIZE;
8998+ }
8999+ }
9000+ break;
9001+
9002+
9003+ case '.':
9004+ laststart = b;
9005+ BUF_PUSH (anychar);
9006+ break;
9007+
9008+
9009+ case '[':
9010+ {
9011+ boolean had_char_class = false;
9012+#ifdef WCHAR
9013+ CHAR_T range_start = 0xffffffff;
9014+#else
9015+ unsigned int range_start = 0xffffffff;
9016+#endif
9017+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9018+
9019+#ifdef WCHAR
9020+ /* We assume a charset(_not) structure as a wchar_t array.
9021+ charset[0] = (re_opcode_t) charset(_not)
9022+ charset[1] = l (= length of char_classes)
9023+ charset[2] = m (= length of collating_symbols)
9024+ charset[3] = n (= length of equivalence_classes)
9025+ charset[4] = o (= length of char_ranges)
9026+ charset[5] = p (= length of chars)
9027+
9028+ charset[6] = char_class (wctype_t)
9029+ charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t)
9030+ ...
9031+ charset[l+5] = char_class (wctype_t)
9032+
9033+ charset[l+6] = collating_symbol (wchar_t)
9034+ ...
9035+ charset[l+m+5] = collating_symbol (wchar_t)
9036+ ifdef _LIBC we use the index if
9037+ _NL_COLLATE_SYMB_EXTRAMB instead of
9038+ wchar_t string.
9039+
9040+ charset[l+m+6] = equivalence_classes (wchar_t)
9041+ ...
9042+ charset[l+m+n+5] = equivalence_classes (wchar_t)
9043+ ifdef _LIBC we use the index in
9044+ _NL_COLLATE_WEIGHT instead of
9045+ wchar_t string.
9046+
9047+ charset[l+m+n+6] = range_start
9048+ charset[l+m+n+7] = range_end
9049+ ...
9050+ charset[l+m+n+2o+4] = range_start
9051+ charset[l+m+n+2o+5] = range_end
9052+ ifdef _LIBC we use the value looked up
9053+ in _NL_COLLATE_COLLSEQ instead of
9054+ wchar_t character.
9055+
9056+ charset[l+m+n+2o+6] = char
9057+ ...
9058+ charset[l+m+n+2o+p+5] = char
9059+
9060+ */
9061+
9062+ /* We need at least 6 spaces: the opcode, the length of
9063+ char_classes, the length of collating_symbols, the length of
9064+ equivalence_classes, the length of char_ranges, the length of
9065+ chars. */
9066+ GET_BUFFER_SPACE (6);
9067+
9068+ /* Save b as laststart. And We use laststart as the pointer
9069+ to the first element of the charset here.
9070+ In other words, laststart[i] indicates charset[i]. */
9071+ laststart = b;
9072+
9073+ /* We test `*p == '^' twice, instead of using an if
9074+ statement, so we only need one BUF_PUSH. */
9075+ BUF_PUSH (*p == '^' ? charset_not : charset);
9076+ if (*p == '^')
9077+ p++;
9078+
9079+ /* Push the length of char_classes, the length of
9080+ collating_symbols, the length of equivalence_classes, the
9081+ length of char_ranges and the length of chars. */
9082+ BUF_PUSH_3 (0, 0, 0);
9083+ BUF_PUSH_2 (0, 0);
9084+
9085+ /* Remember the first position in the bracket expression. */
9086+ p1 = p;
9087+
9088+ /* charset_not matches newline according to a syntax bit. */
9089+ if ((re_opcode_t) b[-6] == charset_not
9090+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
9091+ {
9092+ BUF_PUSH('\n');
9093+ laststart[5]++; /* Update the length of characters */
9094+ }
9095+
9096+ /* Read in characters and ranges, setting map bits. */
9097+ for (;;)
9098+ {
9099+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9100+
9101+ PATFETCH (c);
9102+
9103+ /* \ might escape characters inside [...] and [^...]. */
9104+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
9105+ {
9106+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
9107+
9108+ PATFETCH (c1);
9109+ BUF_PUSH(c1);
9110+ laststart[5]++; /* Update the length of chars */
9111+ range_start = c1;
9112+ continue;
9113+ }
9114+
9115+ /* Could be the end of the bracket expression. If it's
9116+ not (i.e., when the bracket expression is `[]' so
9117+ far), the ']' character bit gets set way below. */
9118+ if (c == ']' && p != p1 + 1)
9119+ break;
9120+
9121+ /* Look ahead to see if it's a range when the last thing
9122+ was a character class. */
9123+ if (had_char_class && c == '-' && *p != ']')
9124+ FREE_STACK_RETURN (REG_ERANGE);
9125+
9126+ /* Look ahead to see if it's a range when the last thing
9127+ was a character: if this is a hyphen not at the
9128+ beginning or the end of a list, then it's the range
9129+ operator. */
9130+ if (c == '-'
9131+ && !(p - 2 >= pattern && p[-2] == '[')
9132+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
9133+ && *p != ']')
9134+ {
9135+ reg_errcode_t ret;
9136+ /* Allocate the space for range_start and range_end. */
9137+ GET_BUFFER_SPACE (2);
9138+ /* Update the pointer to indicate end of buffer. */
9139+ b += 2;
9140+ ret = wcs_compile_range (range_start, &p, pend, translate,
9141+ syntax, b, laststart);
9142+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
9143+ range_start = 0xffffffff;
9144+ }
9145+ else if (p[0] == '-' && p[1] != ']')
9146+ { /* This handles ranges made up of characters only. */
9147+ reg_errcode_t ret;
9148+
9149+ /* Move past the `-'. */
9150+ PATFETCH (c1);
9151+ /* Allocate the space for range_start and range_end. */
9152+ GET_BUFFER_SPACE (2);
9153+ /* Update the pointer to indicate end of buffer. */
9154+ b += 2;
9155+ ret = wcs_compile_range (c, &p, pend, translate, syntax, b,
9156+ laststart);
9157+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
9158+ range_start = 0xffffffff;
9159+ }
9160+
9161+ /* See if we're at the beginning of a possible character
9162+ class. */
9163+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
9164+ { /* Leave room for the null. */
9165+ char str[CHAR_CLASS_MAX_LENGTH + 1];
9166+
9167+ PATFETCH (c);
9168+ c1 = 0;
9169+
9170+ /* If pattern is `[[:'. */
9171+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9172+
9173+ for (;;)
9174+ {
9175+ PATFETCH (c);
9176+ if ((c == ':' && *p == ']') || p == pend)
9177+ break;
9178+ if (c1 < CHAR_CLASS_MAX_LENGTH)
9179+ str[c1++] = c;
9180+ else
9181+ /* This is in any case an invalid class name. */
9182+ str[0] = '\0';
9183+ }
9184+ str[c1] = '\0';
9185+
9186+ /* If isn't a word bracketed by `[:' and `:]':
9187+ undo the ending character, the letters, and leave
9188+ the leading `:' and `[' (but store them as character). */
9189+ if (c == ':' && *p == ']')
9190+ {
9191+ wctype_t wt;
9192+ uintptr_t alignedp;
9193+
9194+ /* Query the character class as wctype_t. */
9195+ wt = IS_CHAR_CLASS (str);
9196+ if (wt == 0)
9197+ FREE_STACK_RETURN (REG_ECTYPE);
9198+
9199+ /* Throw away the ] at the end of the character
9200+ class. */
9201+ PATFETCH (c);
9202+
9203+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9204+
9205+ /* Allocate the space for character class. */
9206+ GET_BUFFER_SPACE(CHAR_CLASS_SIZE);
9207+ /* Update the pointer to indicate end of buffer. */
9208+ b += CHAR_CLASS_SIZE;
9209+ /* Move data which follow character classes
9210+ not to violate the data. */
9211+ insert_space(CHAR_CLASS_SIZE,
9212+ laststart + 6 + laststart[1],
9213+ b - 1);
9214+ alignedp = ((uintptr_t)(laststart + 6 + laststart[1])
9215+ + __alignof__(wctype_t) - 1)
9216+ & ~(uintptr_t)(__alignof__(wctype_t) - 1);
9217+ /* Store the character class. */
9218+ *((wctype_t*)alignedp) = wt;
9219+ /* Update length of char_classes */
9220+ laststart[1] += CHAR_CLASS_SIZE;
9221+
9222+ had_char_class = true;
9223+ }
9224+ else
9225+ {
9226+ c1++;
9227+ while (c1--)
9228+ PATUNFETCH;
9229+ BUF_PUSH ('[');
9230+ BUF_PUSH (':');
9231+ laststart[5] += 2; /* Update the length of characters */
9232+ range_start = ':';
9233+ had_char_class = false;
9234+ }
9235+ }
9236+ else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '='
9237+ || *p == '.'))
9238+ {
9239+ CHAR_T str[128]; /* Should be large enough. */
9240+ CHAR_T delim = *p; /* '=' or '.' */
9241+# ifdef _LIBC
9242+ uint32_t nrules =
9243+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
9244+# endif
9245+ PATFETCH (c);
9246+ c1 = 0;
9247+
9248+ /* If pattern is `[[=' or '[[.'. */
9249+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9250+
9251+ for (;;)
9252+ {
9253+ PATFETCH (c);
9254+ if ((c == delim && *p == ']') || p == pend)
9255+ break;
9256+ if (c1 < sizeof (str) - 1)
9257+ str[c1++] = c;
9258+ else
9259+ /* This is in any case an invalid class name. */
9260+ str[0] = '\0';
9261+ }
9262+ str[c1] = '\0';
9263+
9264+ if (c == delim && *p == ']' && str[0] != '\0')
9265+ {
9266+ unsigned int i, offset;
9267+ /* If we have no collation data we use the default
9268+ collation in which each character is in a class
9269+ by itself. It also means that ASCII is the
9270+ character set and therefore we cannot have character
9271+ with more than one byte in the multibyte
9272+ representation. */
9273+
9274+ /* If not defined _LIBC, we push the name and
9275+ `\0' for the sake of matching performance. */
9276+ int datasize = c1 + 1;
9277+
9278+# ifdef _LIBC
9279+ int32_t idx = 0;
9280+ if (nrules == 0)
9281+# endif
9282+ {
9283+ if (c1 != 1)
9284+ FREE_STACK_RETURN (REG_ECOLLATE);
9285+ }
9286+# ifdef _LIBC
9287+ else
9288+ {
9289+ const int32_t *table;
9290+ const int32_t *weights;
9291+ const int32_t *extra;
9292+ const int32_t *indirect;
9293+ wint_t *cp;
9294+
9295+ if(delim == '=')
9296+ {
9297+ /* We push the index for equivalence class. */
9298+ cp = (wint_t*)str;
9299+
9300+ table = (const int32_t *)
9301+ _NL_CURRENT (LC_COLLATE,
9302+ _NL_COLLATE_TABLEWC);
9303+ weights = (const int32_t *)
9304+ _NL_CURRENT (LC_COLLATE,
9305+ _NL_COLLATE_WEIGHTWC);
9306+ extra = (const wint_t *)
9307+ _NL_CURRENT (LC_COLLATE,
9308+ _NL_COLLATE_EXTRAWC);
9309+ indirect = (const int32_t *)
9310+ _NL_CURRENT (LC_COLLATE,
9311+ _NL_COLLATE_INDIRECTWC);
9312+
9313+ idx = FINDIDX (table, indirect, extra, &cp, 1);
9314+ if (idx == 0 || cp < (wint_t*) str + c1)
9315+ /* This is no valid character. */
9316+ FREE_STACK_RETURN (REG_ECOLLATE);
9317+
9318+ str[0] = (wchar_t)idx;
9319+ }
9320+ else /* delim == '.' */
9321+ {
9322+ /* We push collation sequence value
9323+ for collating symbol. */
9324+ int32_t table_size;
9325+ const int32_t *symb_table;
9326+ const unsigned char *extra;
9327+ int32_t idx;
9328+ int32_t elem;
9329+ int32_t second;
9330+ int32_t hash;
9331+ char char_str[c1];
9332+
9333+ /* We have to convert the name to a single-byte
9334+ string. This is possible since the names
9335+ consist of ASCII characters and the internal
9336+ representation is UCS4. */
9337+ for (i = 0; i < c1; ++i)
9338+ char_str[i] = str[i];
9339+
9340+ table_size =
9341+ _NL_CURRENT_WORD (LC_COLLATE,
9342+ _NL_COLLATE_SYMB_HASH_SIZEMB);
9343+ symb_table = (const int32_t *)
9344+ _NL_CURRENT (LC_COLLATE,
9345+ _NL_COLLATE_SYMB_TABLEMB);
9346+ extra = (const unsigned char *)
9347+ _NL_CURRENT (LC_COLLATE,
9348+ _NL_COLLATE_SYMB_EXTRAMB);
9349+
9350+ /* Locate the character in the hashing table. */
9351+ hash = elem_hash (char_str, c1);
9352+
9353+ idx = 0;
9354+ elem = hash % table_size;
9355+ second = hash % (table_size - 2);
9356+ while (symb_table[2 * elem] != 0)
9357+ {
9358+ /* First compare the hashing value. */
9359+ if (symb_table[2 * elem] == hash
9360+ && c1 == extra[symb_table[2 * elem + 1]]
9361+ && memcmp (char_str,
9362+ &extra[symb_table[2 * elem + 1]
9363+ + 1], c1) == 0)
9364+ {
9365+ /* Yep, this is the entry. */
9366+ idx = symb_table[2 * elem + 1];
9367+ idx += 1 + extra[idx];
9368+ break;
9369+ }
9370+
9371+ /* Next entry. */
9372+ elem += second;
9373+ }
9374+
9375+ if (symb_table[2 * elem] != 0)
9376+ {
9377+ /* Compute the index of the byte sequence
9378+ in the table. */
9379+ idx += 1 + extra[idx];
9380+ /* Adjust for the alignment. */
9381+ idx = (idx + 3) & ~3;
9382+
9383+ str[0] = (wchar_t) idx + 4;
9384+ }
9385+ else if (symb_table[2 * elem] == 0 && c1 == 1)
9386+ {
9387+ /* No valid character. Match it as a
9388+ single byte character. */
9389+ had_char_class = false;
9390+ BUF_PUSH(str[0]);
9391+ /* Update the length of characters */
9392+ laststart[5]++;
9393+ range_start = str[0];
9394+
9395+ /* Throw away the ] at the end of the
9396+ collating symbol. */
9397+ PATFETCH (c);
9398+ /* exit from the switch block. */
9399+ continue;
9400+ }
9401+ else
9402+ FREE_STACK_RETURN (REG_ECOLLATE);
9403+ }
9404+ datasize = 1;
9405+ }
9406+# endif
9407+ /* Throw away the ] at the end of the equivalence
9408+ class (or collating symbol). */
9409+ PATFETCH (c);
9410+
9411+ /* Allocate the space for the equivalence class
9412+ (or collating symbol) (and '\0' if needed). */
9413+ GET_BUFFER_SPACE(datasize);
9414+ /* Update the pointer to indicate end of buffer. */
9415+ b += datasize;
9416+
9417+ if (delim == '=')
9418+ { /* equivalence class */
9419+ /* Calculate the offset of char_ranges,
9420+ which is next to equivalence_classes. */
9421+ offset = laststart[1] + laststart[2]
9422+ + laststart[3] +6;
9423+ /* Insert space. */
9424+ insert_space(datasize, laststart + offset, b - 1);
9425+
9426+ /* Write the equivalence_class and \0. */
9427+ for (i = 0 ; i < datasize ; i++)
9428+ laststart[offset + i] = str[i];
9429+
9430+ /* Update the length of equivalence_classes. */
9431+ laststart[3] += datasize;
9432+ had_char_class = true;
9433+ }
9434+ else /* delim == '.' */
9435+ { /* collating symbol */
9436+ /* Calculate the offset of the equivalence_classes,
9437+ which is next to collating_symbols. */
9438+ offset = laststart[1] + laststart[2] + 6;
9439+ /* Insert space and write the collationg_symbol
9440+ and \0. */
9441+ insert_space(datasize, laststart + offset, b-1);
9442+ for (i = 0 ; i < datasize ; i++)
9443+ laststart[offset + i] = str[i];
9444+
9445+ /* In re_match_2_internal if range_start < -1, we
9446+ assume -range_start is the offset of the
9447+ collating symbol which is specified as
9448+ the character of the range start. So we assign
9449+ -(laststart[1] + laststart[2] + 6) to
9450+ range_start. */
9451+ range_start = -(laststart[1] + laststart[2] + 6);
9452+ /* Update the length of collating_symbol. */
9453+ laststart[2] += datasize;
9454+ had_char_class = false;
9455+ }
9456+ }
9457+ else
9458+ {
9459+ c1++;
9460+ while (c1--)
9461+ PATUNFETCH;
9462+ BUF_PUSH ('[');
9463+ BUF_PUSH (delim);
9464+ laststart[5] += 2; /* Update the length of characters */
9465+ range_start = delim;
9466+ had_char_class = false;
9467+ }
9468+ }
9469+ else
9470+ {
9471+ had_char_class = false;
9472+ BUF_PUSH(c);
9473+ laststart[5]++; /* Update the length of characters */
9474+ range_start = c;
9475+ }
9476+ }
9477+
9478+#else /* BYTE */
9479+ /* Ensure that we have enough space to push a charset: the
9480+ opcode, the length count, and the bitset; 34 bytes in all. */
9481+ GET_BUFFER_SPACE (34);
9482+
9483+ laststart = b;
9484+
9485+ /* We test `*p == '^' twice, instead of using an if
9486+ statement, so we only need one BUF_PUSH. */
9487+ BUF_PUSH (*p == '^' ? charset_not : charset);
9488+ if (*p == '^')
9489+ p++;
9490+
9491+ /* Remember the first position in the bracket expression. */
9492+ p1 = p;
9493+
9494+ /* Push the number of bytes in the bitmap. */
9495+ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
9496+
9497+ /* Clear the whole map. */
9498+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
9499+
9500+ /* charset_not matches newline according to a syntax bit. */
9501+ if ((re_opcode_t) b[-2] == charset_not
9502+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
9503+ SET_LIST_BIT ('\n');
9504+
9505+ /* Read in characters and ranges, setting map bits. */
9506+ for (;;)
9507+ {
9508+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9509+
9510+ PATFETCH (c);
9511+
9512+ /* \ might escape characters inside [...] and [^...]. */
9513+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
9514+ {
9515+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
9516+
9517+ PATFETCH (c1);
9518+ SET_LIST_BIT (c1);
9519+ range_start = c1;
9520+ continue;
9521+ }
9522+
9523+ /* Could be the end of the bracket expression. If it's
9524+ not (i.e., when the bracket expression is `[]' so
9525+ far), the ']' character bit gets set way below. */
9526+ if (c == ']' && p != p1 + 1)
9527+ break;
9528+
9529+ /* Look ahead to see if it's a range when the last thing
9530+ was a character class. */
9531+ if (had_char_class && c == '-' && *p != ']')
9532+ FREE_STACK_RETURN (REG_ERANGE);
9533+
9534+ /* Look ahead to see if it's a range when the last thing
9535+ was a character: if this is a hyphen not at the
9536+ beginning or the end of a list, then it's the range
9537+ operator. */
9538+ if (c == '-'
9539+ && !(p - 2 >= pattern && p[-2] == '[')
9540+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
9541+ && *p != ']')
9542+ {
9543+ reg_errcode_t ret
9544+ = byte_compile_range (range_start, &p, pend, translate,
9545+ syntax, b);
9546+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
9547+ range_start = 0xffffffff;
9548+ }
9549+
9550+ else if (p[0] == '-' && p[1] != ']')
9551+ { /* This handles ranges made up of characters only. */
9552+ reg_errcode_t ret;
9553+
9554+ /* Move past the `-'. */
9555+ PATFETCH (c1);
9556+
9557+ ret = byte_compile_range (c, &p, pend, translate, syntax, b);
9558+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
9559+ range_start = 0xffffffff;
9560+ }
9561+
9562+ /* See if we're at the beginning of a possible character
9563+ class. */
9564+
9565+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
9566+ { /* Leave room for the null. */
9567+ char str[CHAR_CLASS_MAX_LENGTH + 1];
9568+
9569+ PATFETCH (c);
9570+ c1 = 0;
9571+
9572+ /* If pattern is `[[:'. */
9573+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9574+
9575+ for (;;)
9576+ {
9577+ PATFETCH (c);
9578+ if ((c == ':' && *p == ']') || p == pend)
9579+ break;
9580+ if (((int) c1) < CHAR_CLASS_MAX_LENGTH)
9581+ str[c1++] = c;
9582+ else
9583+ /* This is in any case an invalid class name. */
9584+ str[0] = '\0';
9585+ }
9586+ str[c1] = '\0';
9587+
9588+ /* If isn't a word bracketed by `[:' and `:]':
9589+ undo the ending character, the letters, and leave
9590+ the leading `:' and `[' (but set bits for them). */
9591+ if (c == ':' && *p == ']')
9592+ {
9593+# if WIDE_CHAR_SUPPORT
9594+ boolean is_lower = STREQ (str, "lower");
9595+ boolean is_upper = STREQ (str, "upper");
9596+ wctype_t wt;
9597+ int ch;
9598+
9599+ wt = IS_CHAR_CLASS (str);
9600+ if (wt == 0)
9601+ FREE_STACK_RETURN (REG_ECTYPE);
9602+
9603+ /* Throw away the ] at the end of the character
9604+ class. */
9605+ PATFETCH (c);
9606+
9607+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9608+
9609+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
9610+ {
9611+# ifdef _LIBC
9612+ if (__iswctype (__btowc (ch), wt))
9613+ SET_LIST_BIT (ch);
9614+# else
9615+ if (iswctype (btowc (ch), wt))
9616+ SET_LIST_BIT (ch);
9617+# endif
9618+
9619+ if (translate && (is_upper || is_lower)
9620+ && (ISUPPER (ch) || ISLOWER (ch)))
9621+ SET_LIST_BIT (ch);
9622+ }
9623+
9624+ had_char_class = true;
9625+# else
9626+ int ch;
9627+ boolean is_alnum = STREQ (str, "alnum");
9628+ boolean is_alpha = STREQ (str, "alpha");
9629+ boolean is_blank = STREQ (str, "blank");
9630+ boolean is_cntrl = STREQ (str, "cntrl");
9631+ boolean is_digit = STREQ (str, "digit");
9632+ boolean is_graph = STREQ (str, "graph");
9633+ boolean is_lower = STREQ (str, "lower");
9634+ boolean is_print = STREQ (str, "print");
9635+ boolean is_punct = STREQ (str, "punct");
9636+ boolean is_space = STREQ (str, "space");
9637+ boolean is_upper = STREQ (str, "upper");
9638+ boolean is_xdigit = STREQ (str, "xdigit");
9639+
9640+ if (!IS_CHAR_CLASS (str))
9641+ FREE_STACK_RETURN (REG_ECTYPE);
9642+
9643+ /* Throw away the ] at the end of the character
9644+ class. */
9645+ PATFETCH (c);
9646+
9647+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9648+
9649+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
9650+ {
9651+ /* This was split into 3 if's to
9652+ avoid an arbitrary limit in some compiler. */
9653+ if ( (is_alnum && ISALNUM (ch))
9654+ || (is_alpha && ISALPHA (ch))
9655+ || (is_blank && ISBLANK (ch))
9656+ || (is_cntrl && ISCNTRL (ch)))
9657+ SET_LIST_BIT (ch);
9658+ if ( (is_digit && ISDIGIT (ch))
9659+ || (is_graph && ISGRAPH (ch))
9660+ || (is_lower && ISLOWER (ch))
9661+ || (is_print && ISPRINT (ch)))
9662+ SET_LIST_BIT (ch);
9663+ if ( (is_punct && ISPUNCT (ch))
9664+ || (is_space && ISSPACE (ch))
9665+ || (is_upper && ISUPPER (ch))
9666+ || (is_xdigit && ISXDIGIT (ch)))
9667+ SET_LIST_BIT (ch);
9668+ if ( translate && (is_upper || is_lower)
9669+ && (ISUPPER (ch) || ISLOWER (ch)))
9670+ SET_LIST_BIT (ch);
9671+ }
9672+ had_char_class = true;
9673+# endif /* libc || wctype.h */
9674+ }
9675+ else
9676+ {
9677+ c1++;
9678+ while (c1--)
9679+ PATUNFETCH;
9680+ SET_LIST_BIT ('[');
9681+ SET_LIST_BIT (':');
9682+ range_start = ':';
9683+ had_char_class = false;
9684+ }
9685+ }
9686+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=')
9687+ {
9688+ unsigned char str[MB_LEN_MAX + 1];
9689+# ifdef _LIBC
9690+ uint32_t nrules =
9691+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
9692+# endif
9693+
9694+ PATFETCH (c);
9695+ c1 = 0;
9696+
9697+ /* If pattern is `[[='. */
9698+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9699+
9700+ for (;;)
9701+ {
9702+ PATFETCH (c);
9703+ if ((c == '=' && *p == ']') || p == pend)
9704+ break;
9705+ if (c1 < MB_LEN_MAX)
9706+ str[c1++] = c;
9707+ else
9708+ /* This is in any case an invalid class name. */
9709+ str[0] = '\0';
9710+ }
9711+ str[c1] = '\0';
9712+
9713+ if (c == '=' && *p == ']' && str[0] != '\0')
9714+ {
9715+ /* If we have no collation data we use the default
9716+ collation in which each character is in a class
9717+ by itself. It also means that ASCII is the
9718+ character set and therefore we cannot have character
9719+ with more than one byte in the multibyte
9720+ representation. */
9721+# ifdef _LIBC
9722+ if (nrules == 0)
9723+# endif
9724+ {
9725+ if (c1 != 1)
9726+ FREE_STACK_RETURN (REG_ECOLLATE);
9727+
9728+ /* Throw away the ] at the end of the equivalence
9729+ class. */
9730+ PATFETCH (c);
9731+
9732+ /* Set the bit for the character. */
9733+ SET_LIST_BIT (str[0]);
9734+ }
9735+# ifdef _LIBC
9736+ else
9737+ {
9738+ /* Try to match the byte sequence in `str' against
9739+ those known to the collate implementation.
9740+ First find out whether the bytes in `str' are
9741+ actually from exactly one character. */
9742+ const int32_t *table;
9743+ const unsigned char *weights;
9744+ const unsigned char *extra;
9745+ const int32_t *indirect;
9746+ int32_t idx;
9747+ const unsigned char *cp = str;
9748+ int ch;
9749+
9750+ table = (const int32_t *)
9751+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
9752+ weights = (const unsigned char *)
9753+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
9754+ extra = (const unsigned char *)
9755+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
9756+ indirect = (const int32_t *)
9757+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
9758+ idx = FINDIDX (table, indirect, extra, &cp, 1);
9759+ if (idx == 0 || cp < str + c1)
9760+ /* This is no valid character. */
9761+ FREE_STACK_RETURN (REG_ECOLLATE);
9762+
9763+ /* Throw away the ] at the end of the equivalence
9764+ class. */
9765+ PATFETCH (c);
9766+
9767+ /* Now we have to go throught the whole table
9768+ and find all characters which have the same
9769+ first level weight.
9770+
9771+ XXX Note that this is not entirely correct.
9772+ we would have to match multibyte sequences
9773+ but this is not possible with the current
9774+ implementation. */
9775+ for (ch = 1; ch < 256; ++ch)
9776+ /* XXX This test would have to be changed if we
9777+ would allow matching multibyte sequences. */
9778+ if (table[ch] > 0)
9779+ {
9780+ int32_t idx2 = table[ch];
9781+ size_t len = weights[idx2];
9782+
9783+ /* Test whether the lenghts match. */
9784+ if (weights[idx] == len)
9785+ {
9786+ /* They do. New compare the bytes of
9787+ the weight. */
9788+ size_t cnt = 0;
9789+
9790+ while (cnt < len
9791+ && (weights[idx + 1 + cnt]
9792+ == weights[idx2 + 1 + cnt]))
9793+ ++cnt;
9794+
9795+ if (cnt == len)
9796+ /* They match. Mark the character as
9797+ acceptable. */
9798+ SET_LIST_BIT (ch);
9799+ }
9800+ }
9801+ }
9802+# endif
9803+ had_char_class = true;
9804+ }
9805+ else
9806+ {
9807+ c1++;
9808+ while (c1--)
9809+ PATUNFETCH;
9810+ SET_LIST_BIT ('[');
9811+ SET_LIST_BIT ('=');
9812+ range_start = '=';
9813+ had_char_class = false;
9814+ }
9815+ }
9816+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.')
9817+ {
9818+ unsigned char str[128]; /* Should be large enough. */
9819+# ifdef _LIBC
9820+ uint32_t nrules =
9821+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
9822+# endif
9823+
9824+ PATFETCH (c);
9825+ c1 = 0;
9826+
9827+ /* If pattern is `[[.'. */
9828+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
9829+
9830+ for (;;)
9831+ {
9832+ PATFETCH (c);
9833+ if ((c == '.' && *p == ']') || p == pend)
9834+ break;
9835+ if (c1 < sizeof (str))
9836+ str[c1++] = c;
9837+ else
9838+ /* This is in any case an invalid class name. */
9839+ str[0] = '\0';
9840+ }
9841+ str[c1] = '\0';
9842+
9843+ if (c == '.' && *p == ']' && str[0] != '\0')
9844+ {
9845+ /* If we have no collation data we use the default
9846+ collation in which each character is the name
9847+ for its own class which contains only the one
9848+ character. It also means that ASCII is the
9849+ character set and therefore we cannot have character
9850+ with more than one byte in the multibyte
9851+ representation. */
9852+# ifdef _LIBC
9853+ if (nrules == 0)
9854+# endif
9855+ {
9856+ if (c1 != 1)
9857+ FREE_STACK_RETURN (REG_ECOLLATE);
9858+
9859+ /* Throw away the ] at the end of the equivalence
9860+ class. */
9861+ PATFETCH (c);
9862+
9863+ /* Set the bit for the character. */
9864+ SET_LIST_BIT (str[0]);
9865+ range_start = ((const unsigned char *) str)[0];
9866+ }
9867+# ifdef _LIBC
9868+ else
9869+ {
9870+ /* Try to match the byte sequence in `str' against
9871+ those known to the collate implementation.
9872+ First find out whether the bytes in `str' are
9873+ actually from exactly one character. */
9874+ int32_t table_size;
9875+ const int32_t *symb_table;
9876+ const unsigned char *extra;
9877+ int32_t idx;
9878+ int32_t elem;
9879+ int32_t second;
9880+ int32_t hash;
9881+
9882+ table_size =
9883+ _NL_CURRENT_WORD (LC_COLLATE,
9884+ _NL_COLLATE_SYMB_HASH_SIZEMB);
9885+ symb_table = (const int32_t *)
9886+ _NL_CURRENT (LC_COLLATE,
9887+ _NL_COLLATE_SYMB_TABLEMB);
9888+ extra = (const unsigned char *)
9889+ _NL_CURRENT (LC_COLLATE,
9890+ _NL_COLLATE_SYMB_EXTRAMB);
9891+
9892+ /* Locate the character in the hashing table. */
9893+ hash = elem_hash ((const char *) str, c1);
9894+
9895+ idx = 0;
9896+ elem = hash % table_size;
9897+ second = hash % (table_size - 2);
9898+ while (symb_table[2 * elem] != 0)
9899+ {
9900+ /* First compare the hashing value. */
9901+ if (symb_table[2 * elem] == hash
9902+ && c1 == extra[symb_table[2 * elem + 1]]
9903+ && memcmp (str,
9904+ &extra[symb_table[2 * elem + 1]
9905+ + 1],
9906+ c1) == 0)
9907+ {
9908+ /* Yep, this is the entry. */
9909+ idx = symb_table[2 * elem + 1];
9910+ idx += 1 + extra[idx];
9911+ break;
9912+ }
9913+
9914+ /* Next entry. */
9915+ elem += second;
9916+ }
9917+
9918+ if (symb_table[2 * elem] == 0)
9919+ /* This is no valid character. */
9920+ FREE_STACK_RETURN (REG_ECOLLATE);
9921+
9922+ /* Throw away the ] at the end of the equivalence
9923+ class. */
9924+ PATFETCH (c);
9925+
9926+ /* Now add the multibyte character(s) we found
9927+ to the accept list.
9928+
9929+ XXX Note that this is not entirely correct.
9930+ we would have to match multibyte sequences
9931+ but this is not possible with the current
9932+ implementation. Also, we have to match
9933+ collating symbols, which expand to more than
9934+ one file, as a whole and not allow the
9935+ individual bytes. */
9936+ c1 = extra[idx++];
9937+ if (c1 == 1)
9938+ range_start = extra[idx];
9939+ while (c1-- > 0)
9940+ {
9941+ SET_LIST_BIT (extra[idx]);
9942+ ++idx;
9943+ }
9944+ }
9945+# endif
9946+ had_char_class = false;
9947+ }
9948+ else
9949+ {
9950+ c1++;
9951+ while (c1--)
9952+ PATUNFETCH;
9953+ SET_LIST_BIT ('[');
9954+ SET_LIST_BIT ('.');
9955+ range_start = '.';
9956+ had_char_class = false;
9957+ }
9958+ }
9959+ else
9960+ {
9961+ had_char_class = false;
9962+ SET_LIST_BIT (c);
9963+ range_start = c;
9964+ }
9965+ }
9966+
9967+ /* Discard any (non)matching list bytes that are all 0 at the
9968+ end of the map. Decrease the map-length byte too. */
9969+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
9970+ b[-1]--;
9971+ b += b[-1];
9972+#endif /* WCHAR */
9973+ }
9974+ break;
9975+
9976+
9977+ case '(':
9978+ if (syntax & RE_NO_BK_PARENS)
9979+ goto handle_open;
9980+ else
9981+ goto normal_char;
9982+
9983+
9984+ case ')':
9985+ if (syntax & RE_NO_BK_PARENS)
9986+ goto handle_close;
9987+ else
9988+ goto normal_char;
9989+
9990+
9991+ case '\n':
9992+ if (syntax & RE_NEWLINE_ALT)
9993+ goto handle_alt;
9994+ else
9995+ goto normal_char;
9996+
9997+
9998+ case '|':
9999+ if (syntax & RE_NO_BK_VBAR)
10000+ goto handle_alt;
10001+ else
10002+ goto normal_char;
10003+
10004+
10005+ case '{':
10006+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
10007+ goto handle_interval;
10008+ else
10009+ goto normal_char;
10010+
10011+
10012+ case '\\':
10013+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
10014+
10015+ /* Do not translate the character after the \, so that we can
10016+ distinguish, e.g., \B from \b, even if we normally would
10017+ translate, e.g., B to b. */
10018+ PATFETCH_RAW (c);
10019+
10020+ switch (c)
10021+ {
10022+ case '(':
10023+ if (syntax & RE_NO_BK_PARENS)
10024+ goto normal_backslash;
10025+
10026+ handle_open:
10027+ bufp->re_nsub++;
10028+ regnum++;
10029+
10030+ if (COMPILE_STACK_FULL)
10031+ {
10032+ RETALLOC (compile_stack.stack, compile_stack.size << 1,
10033+ compile_stack_elt_t);
10034+ if (compile_stack.stack == NULL) return REG_ESPACE;
10035+
10036+ compile_stack.size <<= 1;
10037+ }
10038+
10039+ /* These are the values to restore when we hit end of this
10040+ group. They are all relative offsets, so that if the
10041+ whole pattern moves because of realloc, they will still
10042+ be valid. */
10043+ COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR;
10044+ COMPILE_STACK_TOP.fixup_alt_jump
10045+ = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0;
10046+ COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR;
10047+ COMPILE_STACK_TOP.regnum = regnum;
10048+
10049+ /* We will eventually replace the 0 with the number of
10050+ groups inner to this one. But do not push a
10051+ start_memory for groups beyond the last one we can
10052+ represent in the compiled pattern. */
10053+ if (regnum <= MAX_REGNUM)
10054+ {
10055+ COMPILE_STACK_TOP.inner_group_offset = b
10056+ - COMPILED_BUFFER_VAR + 2;
10057+ BUF_PUSH_3 (start_memory, regnum, 0);
10058+ }
10059+
10060+ compile_stack.avail++;
10061+
10062+ fixup_alt_jump = 0;
10063+ laststart = 0;
10064+ begalt = b;
10065+ /* If we've reached MAX_REGNUM groups, then this open
10066+ won't actually generate any code, so we'll have to
10067+ clear pending_exact explicitly. */
10068+ pending_exact = 0;
10069+ break;
10070+
10071+
10072+ case ')':
10073+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
10074+
10075+ if (COMPILE_STACK_EMPTY)
10076+ {
10077+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
10078+ goto normal_backslash;
10079+ else
10080+ FREE_STACK_RETURN (REG_ERPAREN);
10081+ }
10082+
10083+ handle_close:
10084+ if (fixup_alt_jump)
10085+ { /* Push a dummy failure point at the end of the
10086+ alternative for a possible future
10087+ `pop_failure_jump' to pop. See comments at
10088+ `push_dummy_failure' in `re_match_2'. */
10089+ BUF_PUSH (push_dummy_failure);
10090+
10091+ /* We allocated space for this jump when we assigned
10092+ to `fixup_alt_jump', in the `handle_alt' case below. */
10093+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
10094+ }
10095+
10096+ /* See similar code for backslashed left paren above. */
10097+ if (COMPILE_STACK_EMPTY)
10098+ {
10099+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
10100+ goto normal_char;
10101+ else
10102+ FREE_STACK_RETURN (REG_ERPAREN);
10103+ }
10104+
10105+ /* Since we just checked for an empty stack above, this
10106+ ``can't happen''. */
10107+ assert (compile_stack.avail != 0);
10108+ {
10109+ /* We don't just want to restore into `regnum', because
10110+ later groups should continue to be numbered higher,
10111+ as in `(ab)c(de)' -- the second group is #2. */
10112+ regnum_t this_group_regnum;
10113+
10114+ compile_stack.avail--;
10115+ begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset;
10116+ fixup_alt_jump
10117+ = COMPILE_STACK_TOP.fixup_alt_jump
10118+ ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1
10119+ : 0;
10120+ laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset;
10121+ this_group_regnum = COMPILE_STACK_TOP.regnum;
10122+ /* If we've reached MAX_REGNUM groups, then this open
10123+ won't actually generate any code, so we'll have to
10124+ clear pending_exact explicitly. */
10125+ pending_exact = 0;
10126+
10127+ /* We're at the end of the group, so now we know how many
10128+ groups were inside this one. */
10129+ if (this_group_regnum <= MAX_REGNUM)
10130+ {
10131+ UCHAR_T *inner_group_loc
10132+ = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset;
10133+
10134+ *inner_group_loc = regnum - this_group_regnum;
10135+ BUF_PUSH_3 (stop_memory, this_group_regnum,
10136+ regnum - this_group_regnum);
10137+ }
10138+ }
10139+ break;
10140+
10141+
10142+ case '|': /* `\|'. */
10143+ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
10144+ goto normal_backslash;
10145+ handle_alt:
10146+ if (syntax & RE_LIMITED_OPS)
10147+ goto normal_char;
10148+
10149+ /* Insert before the previous alternative a jump which
10150+ jumps to this alternative if the former fails. */
10151+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
10152+ INSERT_JUMP (on_failure_jump, begalt,
10153+ b + 2 + 2 * OFFSET_ADDRESS_SIZE);
10154+ pending_exact = 0;
10155+ b += 1 + OFFSET_ADDRESS_SIZE;
10156+
10157+ /* The alternative before this one has a jump after it
10158+ which gets executed if it gets matched. Adjust that
10159+ jump so it will jump to this alternative's analogous
10160+ jump (put in below, which in turn will jump to the next
10161+ (if any) alternative's such jump, etc.). The last such
10162+ jump jumps to the correct final destination. A picture:
10163+ _____ _____
10164+ | | | |
10165+ | v | v
10166+ a | b | c
10167+
10168+ If we are at `b', then fixup_alt_jump right now points to a
10169+ three-byte space after `a'. We'll put in the jump, set
10170+ fixup_alt_jump to right after `b', and leave behind three
10171+ bytes which we'll fill in when we get to after `c'. */
10172+
10173+ if (fixup_alt_jump)
10174+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
10175+
10176+ /* Mark and leave space for a jump after this alternative,
10177+ to be filled in later either by next alternative or
10178+ when know we're at the end of a series of alternatives. */
10179+ fixup_alt_jump = b;
10180+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
10181+ b += 1 + OFFSET_ADDRESS_SIZE;
10182+
10183+ laststart = 0;
10184+ begalt = b;
10185+ break;
10186+
10187+
10188+ case '{':
10189+ /* If \{ is a literal. */
10190+ if (!(syntax & RE_INTERVALS)
10191+ /* If we're at `\{' and it's not the open-interval
10192+ operator. */
10193+ || (syntax & RE_NO_BK_BRACES))
10194+ goto normal_backslash;
10195+
10196+ handle_interval:
10197+ {
10198+ /* If got here, then the syntax allows intervals. */
10199+
10200+ /* At least (most) this many matches must be made. */
10201+ int lower_bound = -1, upper_bound = -1;
10202+
10203+ /* Place in the uncompiled pattern (i.e., just after
10204+ the '{') to go back to if the interval is invalid. */
10205+ const CHAR_T *beg_interval = p;
10206+
10207+ if (p == pend)
10208+ goto invalid_interval;
10209+
10210+ GET_UNSIGNED_NUMBER (lower_bound);
10211+
10212+ if (c == ',')
10213+ {
10214+ GET_UNSIGNED_NUMBER (upper_bound);
10215+ if (upper_bound < 0)
10216+ upper_bound = RE_DUP_MAX;
10217+ }
10218+ else
10219+ /* Interval such as `{1}' => match exactly once. */
10220+ upper_bound = lower_bound;
10221+
10222+ if (! (0 <= lower_bound && lower_bound <= upper_bound))
10223+ goto invalid_interval;
10224+
10225+ if (!(syntax & RE_NO_BK_BRACES))
10226+ {
10227+ if (c != '\\' || p == pend)
10228+ goto invalid_interval;
10229+ PATFETCH (c);
10230+ }
10231+
10232+ if (c != '}')
10233+ goto invalid_interval;
10234+
10235+ /* If it's invalid to have no preceding re. */
10236+ if (!laststart)
10237+ {
10238+ if (syntax & RE_CONTEXT_INVALID_OPS
10239+ && !(syntax & RE_INVALID_INTERVAL_ORD))
10240+ FREE_STACK_RETURN (REG_BADRPT);
10241+ else if (syntax & RE_CONTEXT_INDEP_OPS)
10242+ laststart = b;
10243+ else
10244+ goto unfetch_interval;
10245+ }
10246+
10247+ /* We just parsed a valid interval. */
10248+
10249+ if (RE_DUP_MAX < upper_bound)
10250+ FREE_STACK_RETURN (REG_BADBR);
10251+
10252+ /* If the upper bound is zero, don't want to succeed at
10253+ all; jump from `laststart' to `b + 3', which will be
10254+ the end of the buffer after we insert the jump. */
10255+ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE'
10256+ instead of 'b + 3'. */
10257+ if (upper_bound == 0)
10258+ {
10259+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
10260+ INSERT_JUMP (jump, laststart, b + 1
10261+ + OFFSET_ADDRESS_SIZE);
10262+ b += 1 + OFFSET_ADDRESS_SIZE;
10263+ }
10264+
10265+ /* Otherwise, we have a nontrivial interval. When
10266+ we're all done, the pattern will look like:
10267+ set_number_at <jump count> <upper bound>
10268+ set_number_at <succeed_n count> <lower bound>
10269+ succeed_n <after jump addr> <succeed_n count>
10270+ <body of loop>
10271+ jump_n <succeed_n addr> <jump count>
10272+ (The upper bound and `jump_n' are omitted if
10273+ `upper_bound' is 1, though.) */
10274+ else
10275+ { /* If the upper bound is > 1, we need to insert
10276+ more at the end of the loop. */
10277+ unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE +
10278+ (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE);
10279+
10280+ GET_BUFFER_SPACE (nbytes);
10281+
10282+ /* Initialize lower bound of the `succeed_n', even
10283+ though it will be set during matching by its
10284+ attendant `set_number_at' (inserted next),
10285+ because `re_compile_fastmap' needs to know.
10286+ Jump to the `jump_n' we might insert below. */
10287+ INSERT_JUMP2 (succeed_n, laststart,
10288+ b + 1 + 2 * OFFSET_ADDRESS_SIZE
10289+ + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE)
10290+ , lower_bound);
10291+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
10292+
10293+ /* Code to initialize the lower bound. Insert
10294+ before the `succeed_n'. The `5' is the last two
10295+ bytes of this `set_number_at', plus 3 bytes of
10296+ the following `succeed_n'. */
10297+ /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE'
10298+ is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE'
10299+ of the following `succeed_n'. */
10300+ PREFIX(insert_op2) (set_number_at, laststart, 1
10301+ + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b);
10302+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
10303+
10304+ if (upper_bound > 1)
10305+ { /* More than one repetition is allowed, so
10306+ append a backward jump to the `succeed_n'
10307+ that starts this interval.
10308+
10309+ When we've reached this during matching,
10310+ we'll have matched the interval once, so
10311+ jump back only `upper_bound - 1' times. */
10312+ STORE_JUMP2 (jump_n, b, laststart
10313+ + 2 * OFFSET_ADDRESS_SIZE + 1,
10314+ upper_bound - 1);
10315+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
10316+
10317+ /* The location we want to set is the second
10318+ parameter of the `jump_n'; that is `b-2' as
10319+ an absolute address. `laststart' will be
10320+ the `set_number_at' we're about to insert;
10321+ `laststart+3' the number to set, the source
10322+ for the relative address. But we are
10323+ inserting into the middle of the pattern --
10324+ so everything is getting moved up by 5.
10325+ Conclusion: (b - 2) - (laststart + 3) + 5,
10326+ i.e., b - laststart.
10327+
10328+ We insert this at the beginning of the loop
10329+ so that if we fail during matching, we'll
10330+ reinitialize the bounds. */
10331+ PREFIX(insert_op2) (set_number_at, laststart,
10332+ b - laststart,
10333+ upper_bound - 1, b);
10334+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
10335+ }
10336+ }
10337+ pending_exact = 0;
10338+ break;
10339+
10340+ invalid_interval:
10341+ if (!(syntax & RE_INVALID_INTERVAL_ORD))
10342+ FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR);
10343+ unfetch_interval:
10344+ /* Match the characters as literals. */
10345+ p = beg_interval;
10346+ c = '{';
10347+ if (syntax & RE_NO_BK_BRACES)
10348+ goto normal_char;
10349+ else
10350+ goto normal_backslash;
10351+ }
10352+
10353+#ifdef emacs
10354+ /* There is no way to specify the before_dot and after_dot
10355+ operators. rms says this is ok. --karl */
10356+ case '=':
10357+ BUF_PUSH (at_dot);
10358+ break;
10359+
10360+ case 's':
10361+ laststart = b;
10362+ PATFETCH (c);
10363+ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
10364+ break;
10365+
10366+ case 'S':
10367+ laststart = b;
10368+ PATFETCH (c);
10369+ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
10370+ break;
10371+#endif /* emacs */
10372+
10373+
10374+ case 'w':
10375+ if (syntax & RE_NO_GNU_OPS)
10376+ goto normal_char;
10377+ laststart = b;
10378+ BUF_PUSH (wordchar);
10379+ break;
10380+
10381+
10382+ case 'W':
10383+ if (syntax & RE_NO_GNU_OPS)
10384+ goto normal_char;
10385+ laststart = b;
10386+ BUF_PUSH (notwordchar);
10387+ break;
10388+
10389+
10390+ case '<':
10391+ if (syntax & RE_NO_GNU_OPS)
10392+ goto normal_char;
10393+ BUF_PUSH (wordbeg);
10394+ break;
10395+
10396+ case '>':
10397+ if (syntax & RE_NO_GNU_OPS)
10398+ goto normal_char;
10399+ BUF_PUSH (wordend);
10400+ break;
10401+
10402+ case 'b':
10403+ if (syntax & RE_NO_GNU_OPS)
10404+ goto normal_char;
10405+ BUF_PUSH (wordbound);
10406+ break;
10407+
10408+ case 'B':
10409+ if (syntax & RE_NO_GNU_OPS)
10410+ goto normal_char;
10411+ BUF_PUSH (notwordbound);
10412+ break;
10413+
10414+ case '`':
10415+ if (syntax & RE_NO_GNU_OPS)
10416+ goto normal_char;
10417+ BUF_PUSH (begbuf);
10418+ break;
10419+
10420+ case '\'':
10421+ if (syntax & RE_NO_GNU_OPS)
10422+ goto normal_char;
10423+ BUF_PUSH (endbuf);
10424+ break;
10425+
10426+ case '1': case '2': case '3': case '4': case '5':
10427+ case '6': case '7': case '8': case '9':
10428+ if (syntax & RE_NO_BK_REFS)
10429+ goto normal_char;
10430+
10431+ c1 = c - '0';
10432+
10433+ if (c1 > regnum)
10434+ FREE_STACK_RETURN (REG_ESUBREG);
10435+
10436+ /* Can't back reference to a subexpression if inside of it. */
10437+ if (group_in_compile_stack (compile_stack, (regnum_t) c1))
10438+ goto normal_char;
10439+
10440+ laststart = b;
10441+ BUF_PUSH_2 (duplicate, c1);
10442+ break;
10443+
10444+
10445+ case '+':
10446+ case '?':
10447+ if (syntax & RE_BK_PLUS_QM)
10448+ goto handle_plus;
10449+ else
10450+ goto normal_backslash;
10451+
10452+ default:
10453+ normal_backslash:
10454+ /* You might think it would be useful for \ to mean
10455+ not to translate; but if we don't translate it
10456+ it will never match anything. */
10457+ c = TRANSLATE (c);
10458+ goto normal_char;
10459+ }
10460+ break;
10461+
10462+
10463+ default:
10464+ /* Expects the character in `c'. */
10465+ normal_char:
10466+ /* If no exactn currently being built. */
10467+ if (!pending_exact
10468+#ifdef WCHAR
10469+ /* If last exactn handle binary(or character) and
10470+ new exactn handle character(or binary). */
10471+ || is_exactn_bin != is_binary[p - 1 - pattern]
10472+#endif /* WCHAR */
10473+
10474+ /* If last exactn not at current position. */
10475+ || pending_exact + *pending_exact + 1 != b
10476+
10477+ /* We have only one byte following the exactn for the count. */
10478+ || *pending_exact == (1 << BYTEWIDTH) - 1
10479+
10480+ /* If followed by a repetition operator. */
10481+ || *p == '*' || *p == '^'
10482+ || ((syntax & RE_BK_PLUS_QM)
10483+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
10484+ : (*p == '+' || *p == '?'))
10485+ || ((syntax & RE_INTERVALS)
10486+ && ((syntax & RE_NO_BK_BRACES)
10487+ ? *p == '{'
10488+ : (p[0] == '\\' && p[1] == '{'))))
10489+ {
10490+ /* Start building a new exactn. */
10491+
10492+ laststart = b;
10493+
10494+#ifdef WCHAR
10495+ /* Is this exactn binary data or character? */
10496+ is_exactn_bin = is_binary[p - 1 - pattern];
10497+ if (is_exactn_bin)
10498+ BUF_PUSH_2 (exactn_bin, 0);
10499+ else
10500+ BUF_PUSH_2 (exactn, 0);
10501+#else
10502+ BUF_PUSH_2 (exactn, 0);
10503+#endif /* WCHAR */
10504+ pending_exact = b - 1;
10505+ }
10506+
10507+ BUF_PUSH (c);
10508+ (*pending_exact)++;
10509+ break;
10510+ } /* switch (c) */
10511+ } /* while p != pend */
10512+
10513+
10514+ /* Through the pattern now. */
10515+
10516+ if (fixup_alt_jump)
10517+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
10518+
10519+ if (!COMPILE_STACK_EMPTY)
10520+ FREE_STACK_RETURN (REG_EPAREN);
10521+
10522+ /* If we don't want backtracking, force success
10523+ the first time we reach the end of the compiled pattern. */
10524+ if (syntax & RE_NO_POSIX_BACKTRACKING)
10525+ BUF_PUSH (succeed);
10526+
10527+#ifdef WCHAR
10528+ free (pattern);
10529+ free (mbs_offset);
10530+ free (is_binary);
10531+#endif
10532+ free (compile_stack.stack);
10533+
10534+ /* We have succeeded; set the length of the buffer. */
10535+#ifdef WCHAR
10536+ bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR;
10537+#else
10538+ bufp->used = b - bufp->buffer;
10539+#endif
10540+
10541+#ifdef DEBUG
10542+ if (debug)
10543+ {
10544+ DEBUG_PRINT1 ("\nCompiled pattern: \n");
10545+ PREFIX(print_compiled_pattern) (bufp);
10546+ }
10547+#endif /* DEBUG */
10548+
10549+#ifndef MATCH_MAY_ALLOCATE
10550+ /* Initialize the failure stack to the largest possible stack. This
10551+ isn't necessary unless we're trying to avoid calling alloca in
10552+ the search and match routines. */
10553+ {
10554+ int num_regs = bufp->re_nsub + 1;
10555+
10556+ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
10557+ is strictly greater than re_max_failures, the largest possible stack
10558+ is 2 * re_max_failures failure points. */
10559+ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
10560+ {
10561+ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
10562+
10563+# ifdef emacs
10564+ if (! fail_stack.stack)
10565+ fail_stack.stack
10566+ = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size
10567+ * sizeof (PREFIX(fail_stack_elt_t)));
10568+ else
10569+ fail_stack.stack
10570+ = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack,
10571+ (fail_stack.size
10572+ * sizeof (PREFIX(fail_stack_elt_t))));
10573+# else /* not emacs */
10574+ if (! fail_stack.stack)
10575+ fail_stack.stack
10576+ = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size
10577+ * sizeof (PREFIX(fail_stack_elt_t)));
10578+ else
10579+ fail_stack.stack
10580+ = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack,
10581+ (fail_stack.size
10582+ * sizeof (PREFIX(fail_stack_elt_t))));
10583+# endif /* not emacs */
10584+ }
10585+
10586+ PREFIX(regex_grow_registers) (num_regs);
10587+ }
10588+#endif /* not MATCH_MAY_ALLOCATE */
10589+
10590+ return REG_NOERROR;
10591+} /* regex_compile */
10592+
10593+/* Subroutines for `regex_compile'. */
10594+
10595+/* Store OP at LOC followed by two-byte integer parameter ARG. */
10596+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
10597+
10598+static void
10599+PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg)
10600+{
10601+ *loc = (UCHAR_T) op;
10602+ STORE_NUMBER (loc + 1, arg);
10603+}
10604+
10605+
10606+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
10607+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
10608+
10609+static void
10610+PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2)
10611+{
10612+ *loc = (UCHAR_T) op;
10613+ STORE_NUMBER (loc + 1, arg1);
10614+ STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2);
10615+}
10616+
10617+
10618+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
10619+ for OP followed by two-byte integer parameter ARG. */
10620+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
10621+
10622+static void
10623+PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end)
10624+{
10625+ register UCHAR_T *pfrom = end;
10626+ register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE;
10627+
10628+ while (pfrom != loc)
10629+ *--pto = *--pfrom;
10630+
10631+ PREFIX(store_op1) (op, loc, arg);
10632+}
10633+
10634+
10635+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
10636+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
10637+
10638+static void
10639+PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1,
10640+ int arg2, UCHAR_T *end)
10641+{
10642+ register UCHAR_T *pfrom = end;
10643+ register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE;
10644+
10645+ while (pfrom != loc)
10646+ *--pto = *--pfrom;
10647+
10648+ PREFIX(store_op2) (op, loc, arg1, arg2);
10649+}
10650+
10651+
10652+/* P points to just after a ^ in PATTERN. Return true if that ^ comes
10653+ after an alternative or a begin-subexpression. We assume there is at
10654+ least one character before the ^. */
10655+
10656+static boolean
10657+PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p,
10658+ reg_syntax_t syntax)
10659+{
10660+ const CHAR_T *prev = p - 2;
10661+ boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
10662+
10663+ return
10664+ /* After a subexpression? */
10665+ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
10666+ /* After an alternative? */
10667+ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
10668+}
10669+
10670+
10671+/* The dual of at_begline_loc_p. This one is for $. We assume there is
10672+ at least one character after the $, i.e., `P < PEND'. */
10673+
10674+static boolean
10675+PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend,
10676+ reg_syntax_t syntax)
10677+{
10678+ const CHAR_T *next = p;
10679+ boolean next_backslash = *next == '\\';
10680+ const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0;
10681+
10682+ return
10683+ /* Before a subexpression? */
10684+ (syntax & RE_NO_BK_PARENS ? *next == ')'
10685+ : next_backslash && next_next && *next_next == ')')
10686+ /* Before an alternative? */
10687+ || (syntax & RE_NO_BK_VBAR ? *next == '|'
10688+ : next_backslash && next_next && *next_next == '|');
10689+}
10690+
10691+#else /* not INSIDE_RECURSION */
10692+
10693+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
10694+ false if it's not. */
10695+
10696+static boolean
10697+group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
10698+{
10699+ int this_element;
10700+
10701+ for (this_element = compile_stack.avail - 1;
10702+ this_element >= 0;
10703+ this_element--)
10704+ if (compile_stack.stack[this_element].regnum == regnum)
10705+ return true;
10706+
10707+ return false;
10708+}
10709+#endif /* not INSIDE_RECURSION */
10710+
10711+#ifdef INSIDE_RECURSION
10712+
10713+#ifdef WCHAR
10714+/* This insert space, which size is "num", into the pattern at "loc".
10715+ "end" must point the end of the allocated buffer. */
10716+static void
10717+insert_space (int num, CHAR_T *loc, CHAR_T *end)
10718+{
10719+ register CHAR_T *pto = end;
10720+ register CHAR_T *pfrom = end - num;
10721+
10722+ while (pfrom >= loc)
10723+ *pto-- = *pfrom--;
10724+}
10725+#endif /* WCHAR */
10726+
10727+#ifdef WCHAR
10728+static reg_errcode_t
10729+wcs_compile_range (CHAR_T range_start_char, const CHAR_T **p_ptr,
10730+ const CHAR_T *pend, RE_TRANSLATE_TYPE translate,
10731+ reg_syntax_t syntax, CHAR_T *b, CHAR_T *char_set)
10732+{
10733+ const CHAR_T *p = *p_ptr;
10734+ CHAR_T range_start, range_end;
10735+ reg_errcode_t ret;
10736+# ifdef _LIBC
10737+ uint32_t nrules;
10738+ uint32_t start_val, end_val;
10739+# endif
10740+ if (p == pend)
10741+ return REG_ERANGE;
10742+
10743+# ifdef _LIBC
10744+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
10745+ if (nrules != 0)
10746+ {
10747+ const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE,
10748+ _NL_COLLATE_COLLSEQWC);
10749+ const unsigned char *extra = (const unsigned char *)
10750+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
10751+
10752+ if (range_start_char < -1)
10753+ {
10754+ /* range_start is a collating symbol. */
10755+ int32_t *wextra;
10756+ /* Retreive the index and get collation sequence value. */
10757+ wextra = (int32_t*)(extra + char_set[-range_start_char]);
10758+ start_val = wextra[1 + *wextra];
10759+ }
10760+ else
10761+ start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char));
10762+
10763+ end_val = collseq_table_lookup (collseq, TRANSLATE (p[0]));
10764+
10765+ /* Report an error if the range is empty and the syntax prohibits
10766+ this. */
10767+ ret = ((syntax & RE_NO_EMPTY_RANGES)
10768+ && (start_val > end_val))? REG_ERANGE : REG_NOERROR;
10769+
10770+ /* Insert space to the end of the char_ranges. */
10771+ insert_space(2, b - char_set[5] - 2, b - 1);
10772+ *(b - char_set[5] - 2) = (wchar_t)start_val;
10773+ *(b - char_set[5] - 1) = (wchar_t)end_val;
10774+ char_set[4]++; /* ranges_index */
10775+ }
10776+ else
10777+# endif
10778+ {
10779+ range_start = (range_start_char >= 0)? TRANSLATE (range_start_char):
10780+ range_start_char;
10781+ range_end = TRANSLATE (p[0]);
10782+ /* Report an error if the range is empty and the syntax prohibits
10783+ this. */
10784+ ret = ((syntax & RE_NO_EMPTY_RANGES)
10785+ && (range_start > range_end))? REG_ERANGE : REG_NOERROR;
10786+
10787+ /* Insert space to the end of the char_ranges. */
10788+ insert_space(2, b - char_set[5] - 2, b - 1);
10789+ *(b - char_set[5] - 2) = range_start;
10790+ *(b - char_set[5] - 1) = range_end;
10791+ char_set[4]++; /* ranges_index */
10792+ }
10793+ /* Have to increment the pointer into the pattern string, so the
10794+ caller isn't still at the ending character. */
10795+ (*p_ptr)++;
10796+
10797+ return ret;
10798+}
10799+#else /* BYTE */
10800+/* Read the ending character of a range (in a bracket expression) from the
10801+ uncompiled pattern *P_PTR (which ends at PEND). We assume the
10802+ starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
10803+ Then we set the translation of all bits between the starting and
10804+ ending characters (inclusive) in the compiled pattern B.
10805+
10806+ Return an error code.
10807+
10808+ We use these short variable names so we can use the same macros as
10809+ `regex_compile' itself. */
10810+
10811+static reg_errcode_t
10812+byte_compile_range (unsigned int range_start_char, const char **p_ptr,
10813+ const char *pend, RE_TRANSLATE_TYPE translate,
10814+ reg_syntax_t syntax, unsigned char *b)
10815+{
10816+ unsigned this_char;
10817+ const char *p = *p_ptr;
10818+ reg_errcode_t ret;
10819+# if _LIBC
10820+ const unsigned char *collseq;
10821+ unsigned int start_colseq;
10822+ unsigned int end_colseq;
10823+# else
10824+ unsigned end_char;
10825+# endif
10826+
10827+ if (p == pend)
10828+ return REG_ERANGE;
10829+
10830+ /* Have to increment the pointer into the pattern string, so the
10831+ caller isn't still at the ending character. */
10832+ (*p_ptr)++;
10833+
10834+ /* Report an error if the range is empty and the syntax prohibits this. */
10835+ ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
10836+
10837+# if _LIBC
10838+ collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
10839+ _NL_COLLATE_COLLSEQMB);
10840+
10841+ start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)];
10842+ end_colseq = collseq[(unsigned char) TRANSLATE (p[0])];
10843+ for (this_char = 0; this_char <= (unsigned char) -1; ++this_char)
10844+ {
10845+ unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)];
10846+
10847+ if (start_colseq <= this_colseq && this_colseq <= end_colseq)
10848+ {
10849+ SET_LIST_BIT (TRANSLATE (this_char));
10850+ ret = REG_NOERROR;
10851+ }
10852+ }
10853+# else
10854+ /* Here we see why `this_char' has to be larger than an `unsigned
10855+ char' -- we would otherwise go into an infinite loop, since all
10856+ characters <= 0xff. */
10857+ range_start_char = TRANSLATE (range_start_char);
10858+ /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE,
10859+ and some compilers cast it to int implicitly, so following for_loop
10860+ may fall to (almost) infinite loop.
10861+ e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff.
10862+ To avoid this, we cast p[0] to unsigned int and truncate it. */
10863+ end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1));
10864+
10865+ for (this_char = range_start_char; this_char <= end_char; ++this_char)
10866+ {
10867+ SET_LIST_BIT (TRANSLATE (this_char));
10868+ ret = REG_NOERROR;
10869+ }
10870+# endif
10871+
10872+ return ret;
10873+}
10874+#endif /* WCHAR */
10875+
10876+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
10877+ BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
10878+ characters can start a string that matches the pattern. This fastmap
10879+ is used by re_search to skip quickly over impossible starting points.
10880+
10881+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data
10882+ area as BUFP->fastmap.
10883+
10884+ We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
10885+ the pattern buffer.
10886+
10887+ Returns 0 if we succeed, -2 if an internal error. */
10888+
10889+#ifdef WCHAR
10890+/* local function for re_compile_fastmap.
10891+ truncate wchar_t character to char. */
10892+static unsigned char truncate_wchar (CHAR_T c);
10893+
10894+static unsigned char
10895+truncate_wchar (CHAR_T c)
10896+{
10897+ unsigned char buf[MB_CUR_MAX];
10898+ mbstate_t state;
10899+ int retval;
10900+ memset (&state, '\0', sizeof (state));
10901+# ifdef _LIBC
10902+ retval = __wcrtomb (buf, c, &state);
10903+# else
10904+ retval = wcrtomb (buf, c, &state);
10905+# endif
10906+ return retval > 0 ? buf[0] : (unsigned char) c;
10907+}
10908+#endif /* WCHAR */
10909+
10910+static int
10911+PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp)
10912+{
10913+ int j, k;
10914+#ifdef MATCH_MAY_ALLOCATE
10915+ PREFIX(fail_stack_type) fail_stack;
10916+#endif
10917+#ifndef REGEX_MALLOC
10918+ char *destination;
10919+#endif
10920+
10921+ register char *fastmap = bufp->fastmap;
10922+
10923+#ifdef WCHAR
10924+ /* We need to cast pattern to (wchar_t*), because we casted this compiled
10925+ pattern to (char*) in regex_compile. */
10926+ UCHAR_T *pattern = (UCHAR_T*)bufp->buffer;
10927+ register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used);
10928+#else /* BYTE */
10929+ UCHAR_T *pattern = bufp->buffer;
10930+ register UCHAR_T *pend = pattern + bufp->used;
10931+#endif /* WCHAR */
10932+ UCHAR_T *p = pattern;
10933+
10934+#ifdef REL_ALLOC
10935+ /* This holds the pointer to the failure stack, when
10936+ it is allocated relocatably. */
10937+ fail_stack_elt_t *failure_stack_ptr;
10938+#endif
10939+
10940+ /* Assume that each path through the pattern can be null until
10941+ proven otherwise. We set this false at the bottom of switch
10942+ statement, to which we get only if a particular path doesn't
10943+ match the empty string. */
10944+ boolean path_can_be_null = true;
10945+
10946+ /* We aren't doing a `succeed_n' to begin with. */
10947+ boolean succeed_n_p = false;
10948+
10949+ assert (fastmap != NULL && p != NULL);
10950+
10951+ INIT_FAIL_STACK ();
10952+ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
10953+ bufp->fastmap_accurate = 1; /* It will be when we're done. */
10954+ bufp->can_be_null = 0;
10955+
10956+ while (1)
10957+ {
10958+ if (p == pend || *p == (UCHAR_T) succeed)
10959+ {
10960+ /* We have reached the (effective) end of pattern. */
10961+ if (!FAIL_STACK_EMPTY ())
10962+ {
10963+ bufp->can_be_null |= path_can_be_null;
10964+
10965+ /* Reset for next path. */
10966+ path_can_be_null = true;
10967+
10968+ p = fail_stack.stack[--fail_stack.avail].pointer;
10969+
10970+ continue;
10971+ }
10972+ else
10973+ break;
10974+ }
10975+
10976+ /* We should never be about to go beyond the end of the pattern. */
10977+ assert (p < pend);
10978+
10979+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
10980+ {
10981+
10982+ /* I guess the idea here is to simply not bother with a fastmap
10983+ if a backreference is used, since it's too hard to figure out
10984+ the fastmap for the corresponding group. Setting
10985+ `can_be_null' stops `re_search_2' from using the fastmap, so
10986+ that is all we do. */
10987+ case duplicate:
10988+ bufp->can_be_null = 1;
10989+ goto done;
10990+
10991+
10992+ /* Following are the cases which match a character. These end
10993+ with `break'. */
10994+
10995+#ifdef WCHAR
10996+ case exactn:
10997+ fastmap[truncate_wchar(p[1])] = 1;
10998+ break;
10999+#else /* BYTE */
11000+ case exactn:
11001+ fastmap[p[1]] = 1;
11002+ break;
11003+#endif /* WCHAR */
11004+#ifdef MBS_SUPPORT
11005+ case exactn_bin:
11006+ fastmap[p[1]] = 1;
11007+ break;
11008+#endif
11009+
11010+#ifdef WCHAR
11011+ /* It is hard to distinguish fastmap from (multi byte) characters
11012+ which depends on current locale. */
11013+ case charset:
11014+ case charset_not:
11015+ case wordchar:
11016+ case notwordchar:
11017+ bufp->can_be_null = 1;
11018+ goto done;
11019+#else /* BYTE */
11020+ case charset:
11021+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
11022+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
11023+ fastmap[j] = 1;
11024+ break;
11025+
11026+
11027+ case charset_not:
11028+ /* Chars beyond end of map must be allowed. */
11029+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
11030+ fastmap[j] = 1;
11031+
11032+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
11033+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
11034+ fastmap[j] = 1;
11035+ break;
11036+
11037+
11038+ case wordchar:
11039+ for (j = 0; j < (1 << BYTEWIDTH); j++)
11040+ if (SYNTAX (j) == Sword)
11041+ fastmap[j] = 1;
11042+ break;
11043+
11044+
11045+ case notwordchar:
11046+ for (j = 0; j < (1 << BYTEWIDTH); j++)
11047+ if (SYNTAX (j) != Sword)
11048+ fastmap[j] = 1;
11049+ break;
11050+#endif /* WCHAR */
11051+
11052+ case anychar:
11053+ {
11054+ int fastmap_newline = fastmap['\n'];
11055+
11056+ /* `.' matches anything ... */
11057+ for (j = 0; j < (1 << BYTEWIDTH); j++)
11058+ fastmap[j] = 1;
11059+
11060+ /* ... except perhaps newline. */
11061+ if (!(bufp->syntax & RE_DOT_NEWLINE))
11062+ fastmap['\n'] = fastmap_newline;
11063+
11064+ /* Return if we have already set `can_be_null'; if we have,
11065+ then the fastmap is irrelevant. Something's wrong here. */
11066+ else if (bufp->can_be_null)
11067+ goto done;
11068+
11069+ /* Otherwise, have to check alternative paths. */
11070+ break;
11071+ }
11072+
11073+#ifdef emacs
11074+ case syntaxspec:
11075+ k = *p++;
11076+ for (j = 0; j < (1 << BYTEWIDTH); j++)
11077+ if (SYNTAX (j) == (enum syntaxcode) k)
11078+ fastmap[j] = 1;
11079+ break;
11080+
11081+
11082+ case notsyntaxspec:
11083+ k = *p++;
11084+ for (j = 0; j < (1 << BYTEWIDTH); j++)
11085+ if (SYNTAX (j) != (enum syntaxcode) k)
11086+ fastmap[j] = 1;
11087+ break;
11088+
11089+
11090+ /* All cases after this match the empty string. These end with
11091+ `continue'. */
11092+
11093+
11094+ case before_dot:
11095+ case at_dot:
11096+ case after_dot:
11097+ continue;
11098+#endif /* emacs */
11099+
11100+
11101+ case no_op:
11102+ case begline:
11103+ case endline:
11104+ case begbuf:
11105+ case endbuf:
11106+ case wordbound:
11107+ case notwordbound:
11108+ case wordbeg:
11109+ case wordend:
11110+ case push_dummy_failure:
11111+ continue;
11112+
11113+
11114+ case jump_n:
11115+ case pop_failure_jump:
11116+ case maybe_pop_jump:
11117+ case jump:
11118+ case jump_past_alt:
11119+ case dummy_failure_jump:
11120+ EXTRACT_NUMBER_AND_INCR (j, p);
11121+ p += j;
11122+ if (j > 0)
11123+ continue;
11124+
11125+ /* Jump backward implies we just went through the body of a
11126+ loop and matched nothing. Opcode jumped to should be
11127+ `on_failure_jump' or `succeed_n'. Just treat it like an
11128+ ordinary jump. For a * loop, it has pushed its failure
11129+ point already; if so, discard that as redundant. */
11130+ if ((re_opcode_t) *p != on_failure_jump
11131+ && (re_opcode_t) *p != succeed_n)
11132+ continue;
11133+
11134+ p++;
11135+ EXTRACT_NUMBER_AND_INCR (j, p);
11136+ p += j;
11137+
11138+ /* If what's on the stack is where we are now, pop it. */
11139+ if (!FAIL_STACK_EMPTY ()
11140+ && fail_stack.stack[fail_stack.avail - 1].pointer == p)
11141+ fail_stack.avail--;
11142+
11143+ continue;
11144+
11145+
11146+ case on_failure_jump:
11147+ case on_failure_keep_string_jump:
11148+ handle_on_failure_jump:
11149+ EXTRACT_NUMBER_AND_INCR (j, p);
11150+
11151+ /* For some patterns, e.g., `(a?)?', `p+j' here points to the
11152+ end of the pattern. We don't want to push such a point,
11153+ since when we restore it above, entering the switch will
11154+ increment `p' past the end of the pattern. We don't need
11155+ to push such a point since we obviously won't find any more
11156+ fastmap entries beyond `pend'. Such a pattern can match
11157+ the null string, though. */
11158+ if (p + j < pend)
11159+ {
11160+ if (!PUSH_PATTERN_OP (p + j, fail_stack))
11161+ {
11162+ RESET_FAIL_STACK ();
11163+ return -2;
11164+ }
11165+ }
11166+ else
11167+ bufp->can_be_null = 1;
11168+
11169+ if (succeed_n_p)
11170+ {
11171+ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
11172+ succeed_n_p = false;
11173+ }
11174+
11175+ continue;
11176+
11177+
11178+ case succeed_n:
11179+ /* Get to the number of times to succeed. */
11180+ p += OFFSET_ADDRESS_SIZE;
11181+
11182+ /* Increment p past the n for when k != 0. */
11183+ EXTRACT_NUMBER_AND_INCR (k, p);
11184+ if (k == 0)
11185+ {
11186+ p -= 2 * OFFSET_ADDRESS_SIZE;
11187+ succeed_n_p = true; /* Spaghetti code alert. */
11188+ goto handle_on_failure_jump;
11189+ }
11190+ continue;
11191+
11192+
11193+ case set_number_at:
11194+ p += 2 * OFFSET_ADDRESS_SIZE;
11195+ continue;
11196+
11197+
11198+ case start_memory:
11199+ case stop_memory:
11200+ p += 2;
11201+ continue;
11202+
11203+
11204+ default:
11205+ abort (); /* We have listed all the cases. */
11206+ } /* switch *p++ */
11207+
11208+ /* Getting here means we have found the possible starting
11209+ characters for one path of the pattern -- and that the empty
11210+ string does not match. We need not follow this path further.
11211+ Instead, look at the next alternative (remembered on the
11212+ stack), or quit if no more. The test at the top of the loop
11213+ does these things. */
11214+ path_can_be_null = false;
11215+ p = pend;
11216+ } /* while p */
11217+
11218+ /* Set `can_be_null' for the last path (also the first path, if the
11219+ pattern is empty). */
11220+ bufp->can_be_null |= path_can_be_null;
11221+
11222+ done:
11223+ RESET_FAIL_STACK ();
11224+ return 0;
11225+}
11226+
11227+#else /* not INSIDE_RECURSION */
11228+
11229+int
11230+re_compile_fastmap (struct re_pattern_buffer *bufp)
11231+{
11232+# ifdef MBS_SUPPORT
11233+ if (MB_CUR_MAX != 1)
11234+ return wcs_re_compile_fastmap(bufp);
11235+ else
11236+# endif
11237+ return byte_re_compile_fastmap(bufp);
11238+} /* re_compile_fastmap */
11239+#ifdef _LIBC
11240+weak_alias (__re_compile_fastmap, re_compile_fastmap)
11241+#endif
11242+
11243+
11244+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
11245+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
11246+ this memory for recording register information. STARTS and ENDS
11247+ must be allocated using the malloc library routine, and must each
11248+ be at least NUM_REGS * sizeof (regoff_t) bytes long.
11249+
11250+ If NUM_REGS == 0, then subsequent matches should allocate their own
11251+ register data.
11252+
11253+ Unless this function is called, the first search or match using
11254+ PATTERN_BUFFER will allocate its own register data, without
11255+ freeing the old data. */
11256+
11257+void
11258+re_set_registers (struct re_pattern_buffer *bufp,
11259+ struct re_registers *regs, unsigned num_regs,
11260+ regoff_t *starts, regoff_t *ends)
11261+{
11262+ if (num_regs)
11263+ {
11264+ bufp->regs_allocated = REGS_REALLOCATE;
11265+ regs->num_regs = num_regs;
11266+ regs->start = starts;
11267+ regs->end = ends;
11268+ }
11269+ else
11270+ {
11271+ bufp->regs_allocated = REGS_UNALLOCATED;
11272+ regs->num_regs = 0;
11273+ regs->start = regs->end = (regoff_t *) 0;
11274+ }
11275+}
11276+#ifdef _LIBC
11277+weak_alias (__re_set_registers, re_set_registers)
11278+#endif
11279+
11280+/* Searching routines. */
11281+
11282+/* Like re_search_2, below, but only one string is specified, and
11283+ doesn't let you say where to stop matching. */
11284+
11285+int
11286+re_search (struct re_pattern_buffer *bufp, const char *string, int size,
11287+ int startpos, int range, struct re_registers *regs)
11288+{
11289+ return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
11290+ regs, size);
11291+}
11292+#ifdef _LIBC
11293+weak_alias (__re_search, re_search)
11294+#endif
11295+
11296+
11297+/* Using the compiled pattern in BUFP->buffer, first tries to match the
11298+ virtual concatenation of STRING1 and STRING2, starting first at index
11299+ STARTPOS, then at STARTPOS + 1, and so on.
11300+
11301+ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
11302+
11303+ RANGE is how far to scan while trying to match. RANGE = 0 means try
11304+ only at STARTPOS; in general, the last start tried is STARTPOS +
11305+ RANGE.
11306+
11307+ In REGS, return the indices of the virtual concatenation of STRING1
11308+ and STRING2 that matched the entire BUFP->buffer and its contained
11309+ subexpressions.
11310+
11311+ Do not consider matching one past the index STOP in the virtual
11312+ concatenation of STRING1 and STRING2.
11313+
11314+ We return either the position in the strings at which the match was
11315+ found, -1 if no match, or -2 if error (such as failure
11316+ stack overflow). */
11317+
11318+int
11319+re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int size1,
11320+ const char *string2, int size2, int startpos, int range,
11321+ struct re_registers *regs, int stop)
11322+{
11323+# ifdef MBS_SUPPORT
11324+ if (MB_CUR_MAX != 1)
11325+ return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos,
11326+ range, regs, stop);
11327+ else
11328+# endif
11329+ return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos,
11330+ range, regs, stop);
11331+} /* re_search_2 */
11332+#ifdef _LIBC
11333+weak_alias (__re_search_2, re_search_2)
11334+#endif
11335+
11336+#endif /* not INSIDE_RECURSION */
11337+
11338+#ifdef INSIDE_RECURSION
11339+
11340+#ifdef MATCH_MAY_ALLOCATE
11341+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
11342+#else
11343+# define FREE_VAR(var) if (var) free (var); var = NULL
11344+#endif
11345+
11346+#ifdef WCHAR
11347+# define MAX_ALLOCA_SIZE 2000
11348+
11349+# define FREE_WCS_BUFFERS() \
11350+ do { \
11351+ if (size1 > MAX_ALLOCA_SIZE) \
11352+ { \
11353+ free (wcs_string1); \
11354+ free (mbs_offset1); \
11355+ } \
11356+ else \
11357+ { \
11358+ FREE_VAR (wcs_string1); \
11359+ FREE_VAR (mbs_offset1); \
11360+ } \
11361+ if (size2 > MAX_ALLOCA_SIZE) \
11362+ { \
11363+ free (wcs_string2); \
11364+ free (mbs_offset2); \
11365+ } \
11366+ else \
11367+ { \
11368+ FREE_VAR (wcs_string2); \
11369+ FREE_VAR (mbs_offset2); \
11370+ } \
11371+ } while (0)
11372+
11373+#endif
11374+
11375+
11376+static int
11377+PREFIX(re_search_2) (struct re_pattern_buffer *bufp, const char *string1,
11378+ int size1, const char *string2, int size2,
11379+ int startpos, int range,
11380+ struct re_registers *regs, int stop)
11381+{
11382+ int val;
11383+ register char *fastmap = bufp->fastmap;
11384+ register RE_TRANSLATE_TYPE translate = bufp->translate;
11385+ int total_size = size1 + size2;
11386+ int endpos = startpos + range;
11387+#ifdef WCHAR
11388+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */
11389+ wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL;
11390+ /* We need the size of wchar_t buffers correspond to csize1, csize2. */
11391+ int wcs_size1 = 0, wcs_size2 = 0;
11392+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */
11393+ int *mbs_offset1 = NULL, *mbs_offset2 = NULL;
11394+ /* They hold whether each wchar_t is binary data or not. */
11395+ char *is_binary = NULL;
11396+#endif /* WCHAR */
11397+
11398+ /* Check for out-of-range STARTPOS. */
11399+ if (startpos < 0 || startpos > total_size)
11400+ return -1;
11401+
11402+ /* Fix up RANGE if it might eventually take us outside
11403+ the virtual concatenation of STRING1 and STRING2.
11404+ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */
11405+ if (endpos < 0)
11406+ range = 0 - startpos;
11407+ else if (endpos > total_size)
11408+ range = total_size - startpos;
11409+
11410+ /* If the search isn't to be a backwards one, don't waste time in a
11411+ search for a pattern that must be anchored. */
11412+ if (bufp->used > 0 && range > 0
11413+ && ((re_opcode_t) bufp->buffer[0] == begbuf
11414+ /* `begline' is like `begbuf' if it cannot match at newlines. */
11415+ || ((re_opcode_t) bufp->buffer[0] == begline
11416+ && !bufp->newline_anchor)))
11417+ {
11418+ if (startpos > 0)
11419+ return -1;
11420+ else
11421+ range = 1;
11422+ }
11423+
11424+#ifdef emacs
11425+ /* In a forward search for something that starts with \=.
11426+ don't keep searching past point. */
11427+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
11428+ {
11429+ range = PT - startpos;
11430+ if (range <= 0)
11431+ return -1;
11432+ }
11433+#endif /* emacs */
11434+
11435+ /* Update the fastmap now if not correct already. */
11436+ if (fastmap && !bufp->fastmap_accurate)
11437+ if (re_compile_fastmap (bufp) == -2)
11438+ return -2;
11439+
11440+#ifdef WCHAR
11441+ /* Allocate wchar_t array for wcs_string1 and wcs_string2 and
11442+ fill them with converted string. */
11443+ if (size1 != 0)
11444+ {
11445+ if (size1 > MAX_ALLOCA_SIZE)
11446+ {
11447+ wcs_string1 = TALLOC (size1 + 1, CHAR_T);
11448+ mbs_offset1 = TALLOC (size1 + 1, int);
11449+ is_binary = TALLOC (size1 + 1, char);
11450+ }
11451+ else
11452+ {
11453+ wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T);
11454+ mbs_offset1 = REGEX_TALLOC (size1 + 1, int);
11455+ is_binary = REGEX_TALLOC (size1 + 1, char);
11456+ }
11457+ if (!wcs_string1 || !mbs_offset1 || !is_binary)
11458+ {
11459+ if (size1 > MAX_ALLOCA_SIZE)
11460+ {
11461+ free (wcs_string1);
11462+ free (mbs_offset1);
11463+ free (is_binary);
11464+ }
11465+ else
11466+ {
11467+ FREE_VAR (wcs_string1);
11468+ FREE_VAR (mbs_offset1);
11469+ FREE_VAR (is_binary);
11470+ }
11471+ return -2;
11472+ }
11473+ wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1,
11474+ mbs_offset1, is_binary);
11475+ wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */
11476+ if (size1 > MAX_ALLOCA_SIZE)
11477+ free (is_binary);
11478+ else
11479+ FREE_VAR (is_binary);
11480+ }
11481+ if (size2 != 0)
11482+ {
11483+ if (size2 > MAX_ALLOCA_SIZE)
11484+ {
11485+ wcs_string2 = TALLOC (size2 + 1, CHAR_T);
11486+ mbs_offset2 = TALLOC (size2 + 1, int);
11487+ is_binary = TALLOC (size2 + 1, char);
11488+ }
11489+ else
11490+ {
11491+ wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T);
11492+ mbs_offset2 = REGEX_TALLOC (size2 + 1, int);
11493+ is_binary = REGEX_TALLOC (size2 + 1, char);
11494+ }
11495+ if (!wcs_string2 || !mbs_offset2 || !is_binary)
11496+ {
11497+ FREE_WCS_BUFFERS ();
11498+ if (size2 > MAX_ALLOCA_SIZE)
11499+ free (is_binary);
11500+ else
11501+ FREE_VAR (is_binary);
11502+ return -2;
11503+ }
11504+ wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2,
11505+ mbs_offset2, is_binary);
11506+ wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */
11507+ if (size2 > MAX_ALLOCA_SIZE)
11508+ free (is_binary);
11509+ else
11510+ FREE_VAR (is_binary);
11511+ }
11512+#endif /* WCHAR */
11513+
11514+
11515+ /* Loop through the string, looking for a place to start matching. */
11516+ for (;;)
11517+ {
11518+ /* If a fastmap is supplied, skip quickly over characters that
11519+ cannot be the start of a match. If the pattern can match the
11520+ null string, however, we don't need to skip characters; we want
11521+ the first null string. */
11522+ if (fastmap && startpos < total_size && !bufp->can_be_null)
11523+ {
11524+ if (range > 0) /* Searching forwards. */
11525+ {
11526+ register const char *d;
11527+ register int lim = 0;
11528+ int irange = range;
11529+
11530+ if (startpos < size1 && startpos + range >= size1)
11531+ lim = range - (size1 - startpos);
11532+
11533+ d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
11534+
11535+ /* Written out as an if-else to avoid testing `translate'
11536+ inside the loop. */
11537+ if (translate)
11538+ while (range > lim
11539+ && !fastmap[(unsigned char)
11540+ translate[(unsigned char) *d++]])
11541+ range--;
11542+ else
11543+ while (range > lim && !fastmap[(unsigned char) *d++])
11544+ range--;
11545+
11546+ startpos += irange - range;
11547+ }
11548+ else /* Searching backwards. */
11549+ {
11550+ register CHAR_T c = (size1 == 0 || startpos >= size1
11551+ ? string2[startpos - size1]
11552+ : string1[startpos]);
11553+
11554+ if (!fastmap[(unsigned char) TRANSLATE (c)])
11555+ goto advance;
11556+ }
11557+ }
11558+
11559+ /* If can't match the null string, and that's all we have left, fail. */
11560+ if (range >= 0 && startpos == total_size && fastmap
11561+ && !bufp->can_be_null)
11562+ {
11563+#ifdef WCHAR
11564+ FREE_WCS_BUFFERS ();
11565+#endif
11566+ return -1;
11567+ }
11568+
11569+#ifdef WCHAR
11570+ val = wcs_re_match_2_internal (bufp, string1, size1, string2,
11571+ size2, startpos, regs, stop,
11572+ wcs_string1, wcs_size1,
11573+ wcs_string2, wcs_size2,
11574+ mbs_offset1, mbs_offset2);
11575+#else /* BYTE */
11576+ val = byte_re_match_2_internal (bufp, string1, size1, string2,
11577+ size2, startpos, regs, stop);
11578+#endif /* BYTE */
11579+
11580+#ifndef REGEX_MALLOC
11581+# ifdef C_ALLOCA
11582+ alloca (0);
11583+# endif
11584+#endif
11585+
11586+ if (val >= 0)
11587+ {
11588+#ifdef WCHAR
11589+ FREE_WCS_BUFFERS ();
11590+#endif
11591+ return startpos;
11592+ }
11593+
11594+ if (val == -2)
11595+ {
11596+#ifdef WCHAR
11597+ FREE_WCS_BUFFERS ();
11598+#endif
11599+ return -2;
11600+ }
11601+
11602+ advance:
11603+ if (!range)
11604+ break;
11605+ else if (range > 0)
11606+ {
11607+ range--;
11608+ startpos++;
11609+ }
11610+ else
11611+ {
11612+ range++;
11613+ startpos--;
11614+ }
11615+ }
11616+#ifdef WCHAR
11617+ FREE_WCS_BUFFERS ();
11618+#endif
11619+ return -1;
11620+}
11621+
11622+#ifdef WCHAR
11623+/* This converts PTR, a pointer into one of the search wchar_t strings
11624+ `string1' and `string2' into an multibyte string offset from the
11625+ beginning of that string. We use mbs_offset to optimize.
11626+ See convert_mbs_to_wcs. */
11627+# define POINTER_TO_OFFSET(ptr) \
11628+ (FIRST_STRING_P (ptr) \
11629+ ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \
11630+ : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \
11631+ + csize1)))
11632+#else /* BYTE */
11633+/* This converts PTR, a pointer into one of the search strings `string1'
11634+ and `string2' into an offset from the beginning of that string. */
11635+# define POINTER_TO_OFFSET(ptr) \
11636+ (FIRST_STRING_P (ptr) \
11637+ ? ((regoff_t) ((ptr) - string1)) \
11638+ : ((regoff_t) ((ptr) - string2 + size1)))
11639+#endif /* WCHAR */
11640+
11641+/* Macros for dealing with the split strings in re_match_2. */
11642+
11643+#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
11644+
11645+/* Call before fetching a character with *d. This switches over to
11646+ string2 if necessary. */
11647+#define PREFETCH() \
11648+ while (d == dend) \
11649+ { \
11650+ /* End of string2 => fail. */ \
11651+ if (dend == end_match_2) \
11652+ goto fail; \
11653+ /* End of string1 => advance to string2. */ \
11654+ d = string2; \
11655+ dend = end_match_2; \
11656+ }
11657+
11658+/* Test if at very beginning or at very end of the virtual concatenation
11659+ of `string1' and `string2'. If only one string, it's `string2'. */
11660+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
11661+#define AT_STRINGS_END(d) ((d) == end2)
11662+
11663+
11664+/* Test if D points to a character which is word-constituent. We have
11665+ two special cases to check for: if past the end of string1, look at
11666+ the first character in string2; and if before the beginning of
11667+ string2, look at the last character in string1. */
11668+#ifdef WCHAR
11669+/* Use internationalized API instead of SYNTAX. */
11670+# define WORDCHAR_P(d) \
11671+ (iswalnum ((wint_t)((d) == end1 ? *string2 \
11672+ : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \
11673+ || ((d) == end1 ? *string2 \
11674+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_')
11675+#else /* BYTE */
11676+# define WORDCHAR_P(d) \
11677+ (SYNTAX ((d) == end1 ? *string2 \
11678+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
11679+ == Sword)
11680+#endif /* WCHAR */
11681+
11682+/* Disabled due to a compiler bug -- see comment at case wordbound */
11683+#if 0
11684+/* Test if the character before D and the one at D differ with respect
11685+ to being word-constituent. */
11686+#define AT_WORD_BOUNDARY(d) \
11687+ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
11688+ || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
11689+#endif
11690+
11691+/* Free everything we malloc. */
11692+#ifdef MATCH_MAY_ALLOCATE
11693+# ifdef WCHAR
11694+# define FREE_VARIABLES() \
11695+ do { \
11696+ REGEX_FREE_STACK (fail_stack.stack); \
11697+ FREE_VAR (regstart); \
11698+ FREE_VAR (regend); \
11699+ FREE_VAR (old_regstart); \
11700+ FREE_VAR (old_regend); \
11701+ FREE_VAR (best_regstart); \
11702+ FREE_VAR (best_regend); \
11703+ FREE_VAR (reg_info); \
11704+ FREE_VAR (reg_dummy); \
11705+ FREE_VAR (reg_info_dummy); \
11706+ if (!cant_free_wcs_buf) \
11707+ { \
11708+ FREE_VAR (string1); \
11709+ FREE_VAR (string2); \
11710+ FREE_VAR (mbs_offset1); \
11711+ FREE_VAR (mbs_offset2); \
11712+ } \
11713+ } while (0)
11714+# else /* BYTE */
11715+# define FREE_VARIABLES() \
11716+ do { \
11717+ REGEX_FREE_STACK (fail_stack.stack); \
11718+ FREE_VAR (regstart); \
11719+ FREE_VAR (regend); \
11720+ FREE_VAR (old_regstart); \
11721+ FREE_VAR (old_regend); \
11722+ FREE_VAR (best_regstart); \
11723+ FREE_VAR (best_regend); \
11724+ FREE_VAR (reg_info); \
11725+ FREE_VAR (reg_dummy); \
11726+ FREE_VAR (reg_info_dummy); \
11727+ } while (0)
11728+# endif /* WCHAR */
11729+#else
11730+# ifdef WCHAR
11731+# define FREE_VARIABLES() \
11732+ do { \
11733+ if (!cant_free_wcs_buf) \
11734+ { \
11735+ FREE_VAR (string1); \
11736+ FREE_VAR (string2); \
11737+ FREE_VAR (mbs_offset1); \
11738+ FREE_VAR (mbs_offset2); \
11739+ } \
11740+ } while (0)
11741+# else /* BYTE */
11742+# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
11743+# endif /* WCHAR */
11744+#endif /* not MATCH_MAY_ALLOCATE */
11745+
11746+/* These values must meet several constraints. They must not be valid
11747+ register values; since we have a limit of 255 registers (because
11748+ we use only one byte in the pattern for the register number), we can
11749+ use numbers larger than 255. They must differ by 1, because of
11750+ NUM_FAILURE_ITEMS above. And the value for the lowest register must
11751+ be larger than the value for the highest register, so we do not try
11752+ to actually save any registers when none are active. */
11753+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
11754+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
11755+
11756+#else /* not INSIDE_RECURSION */
11757+/* Matching routines. */
11758+
11759+#ifndef emacs /* Emacs never uses this. */
11760+/* re_match is like re_match_2 except it takes only a single string. */
11761+
11762+int
11763+re_match (struct re_pattern_buffer *bufp, const char *string,
11764+ int size, int pos, struct re_registers *regs)
11765+{
11766+ int result;
11767+# ifdef MBS_SUPPORT
11768+ if (MB_CUR_MAX != 1)
11769+ result = wcs_re_match_2_internal (bufp, NULL, 0, string, size,
11770+ pos, regs, size,
11771+ NULL, 0, NULL, 0, NULL, NULL);
11772+ else
11773+# endif
11774+ result = byte_re_match_2_internal (bufp, NULL, 0, string, size,
11775+ pos, regs, size);
11776+# ifndef REGEX_MALLOC
11777+# ifdef C_ALLOCA
11778+ alloca (0);
11779+# endif
11780+# endif
11781+ return result;
11782+}
11783+# ifdef _LIBC
11784+weak_alias (__re_match, re_match)
11785+# endif
11786+#endif /* not emacs */
11787+
11788+#endif /* not INSIDE_RECURSION */
11789+
11790+#ifdef INSIDE_RECURSION
11791+static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p,
11792+ UCHAR_T *end,
11793+ PREFIX(register_info_type) *reg_info);
11794+static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p,
11795+ UCHAR_T *end,
11796+ PREFIX(register_info_type) *reg_info);
11797+static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p,
11798+ UCHAR_T *end,
11799+ PREFIX(register_info_type) *reg_info);
11800+static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2,
11801+ register int len,
11802+ RE_TRANSLATE_TYPE translate);
11803+#else /* not INSIDE_RECURSION */
11804+
11805+/* re_match_2 matches the compiled pattern in BUFP against the
11806+ the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
11807+ and SIZE2, respectively). We start matching at POS, and stop
11808+ matching at STOP.
11809+
11810+ If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
11811+ store offsets for the substring each group matched in REGS. See the
11812+ documentation for exactly how many groups we fill.
11813+
11814+ We return -1 if no match, -2 if an internal error (such as the
11815+ failure stack overflowing). Otherwise, we return the length of the
11816+ matched substring. */
11817+
11818+int
11819+re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int size1,
11820+ const char *string2, int size2, int pos,
11821+ struct re_registers *regs, int stop)
11822+{
11823+ int result;
11824+# ifdef MBS_SUPPORT
11825+ if (MB_CUR_MAX != 1)
11826+ result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2,
11827+ pos, regs, stop,
11828+ NULL, 0, NULL, 0, NULL, NULL);
11829+ else
11830+# endif
11831+ result = byte_re_match_2_internal (bufp, string1, size1, string2, size2,
11832+ pos, regs, stop);
11833+
11834+#ifndef REGEX_MALLOC
11835+# ifdef C_ALLOCA
11836+ alloca (0);
11837+# endif
11838+#endif
11839+ return result;
11840+}
11841+#ifdef _LIBC
11842+weak_alias (__re_match_2, re_match_2)
11843+#endif
11844+
11845+#endif /* not INSIDE_RECURSION */
11846+
11847+#ifdef INSIDE_RECURSION
11848+
11849+#ifdef WCHAR
11850+static int count_mbs_length (int *, int);
11851+
11852+/* This check the substring (from 0, to length) of the multibyte string,
11853+ to which offset_buffer correspond. And count how many wchar_t_characters
11854+ the substring occupy. We use offset_buffer to optimization.
11855+ See convert_mbs_to_wcs. */
11856+
11857+static int
11858+count_mbs_length(int *offset_buffer, int length)
11859+{
11860+ int upper, lower;
11861+
11862+ /* Check whether the size is valid. */
11863+ if (length < 0)
11864+ return -1;
11865+
11866+ if (offset_buffer == NULL)
11867+ return 0;
11868+
11869+ /* If there are no multibyte character, offset_buffer[i] == i.
11870+ Optmize for this case. */
11871+ if (offset_buffer[length] == length)
11872+ return length;
11873+
11874+ /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */
11875+ upper = length;
11876+ lower = 0;
11877+
11878+ while (true)
11879+ {
11880+ int middle = (lower + upper) / 2;
11881+ if (middle == lower || middle == upper)
11882+ break;
11883+ if (offset_buffer[middle] > length)
11884+ upper = middle;
11885+ else if (offset_buffer[middle] < length)
11886+ lower = middle;
11887+ else
11888+ return middle;
11889+ }
11890+
11891+ return -1;
11892+}
11893+#endif /* WCHAR */
11894+
11895+/* This is a separate function so that we can force an alloca cleanup
11896+ afterwards. */
11897+#ifdef WCHAR
11898+static int
11899+wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
11900+ const char *cstring1, int csize1,
11901+ const char *cstring2, int csize2,
11902+ int pos,
11903+ struct re_registers *regs,
11904+ int stop,
11905+ /* string1 == string2 == NULL means string1/2, size1/2 and
11906+ mbs_offset1/2 need seting up in this function. */
11907+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */
11908+ wchar_t *string1, int size1,
11909+ wchar_t *string2, int size2,
11910+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */
11911+ int *mbs_offset1, int *mbs_offset2)
11912+#else /* BYTE */
11913+static int
11914+byte_re_match_2_internal (struct re_pattern_buffer *bufp,
11915+ const char *string1, int size1,
11916+ const char *string2, int size2,
11917+ int pos,
11918+ struct re_registers *regs, int stop)
11919+#endif /* BYTE */
11920+{
11921+ /* General temporaries. */
11922+ int mcnt;
11923+ UCHAR_T *p1;
11924+#ifdef WCHAR
11925+ /* They hold whether each wchar_t is binary data or not. */
11926+ char *is_binary = NULL;
11927+ /* If true, we can't free string1/2, mbs_offset1/2. */
11928+ int cant_free_wcs_buf = 1;
11929+#endif /* WCHAR */
11930+
11931+ /* Just past the end of the corresponding string. */
11932+ const CHAR_T *end1, *end2;
11933+
11934+ /* Pointers into string1 and string2, just past the last characters in
11935+ each to consider matching. */
11936+ const CHAR_T *end_match_1, *end_match_2;
11937+
11938+ /* Where we are in the data, and the end of the current string. */
11939+ const CHAR_T *d, *dend;
11940+
11941+ /* Where we are in the pattern, and the end of the pattern. */
11942+#ifdef WCHAR
11943+ UCHAR_T *pattern, *p;
11944+ register UCHAR_T *pend;
11945+#else /* BYTE */
11946+ UCHAR_T *p = bufp->buffer;
11947+ register UCHAR_T *pend = p + bufp->used;
11948+#endif /* WCHAR */
11949+
11950+ /* Mark the opcode just after a start_memory, so we can test for an
11951+ empty subpattern when we get to the stop_memory. */
11952+ UCHAR_T *just_past_start_mem = 0;
11953+
11954+ /* We use this to map every character in the string. */
11955+ RE_TRANSLATE_TYPE translate = bufp->translate;
11956+
11957+ /* Failure point stack. Each place that can handle a failure further
11958+ down the line pushes a failure point on this stack. It consists of
11959+ restart, regend, and reg_info for all registers corresponding to
11960+ the subexpressions we're currently inside, plus the number of such
11961+ registers, and, finally, two char *'s. The first char * is where
11962+ to resume scanning the pattern; the second one is where to resume
11963+ scanning the strings. If the latter is zero, the failure point is
11964+ a ``dummy''; if a failure happens and the failure point is a dummy,
11965+ it gets discarded and the next next one is tried. */
11966+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
11967+ PREFIX(fail_stack_type) fail_stack;
11968+#endif
11969+#ifdef DEBUG
11970+ static unsigned failure_id;
11971+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
11972+#endif
11973+
11974+#ifdef REL_ALLOC
11975+ /* This holds the pointer to the failure stack, when
11976+ it is allocated relocatably. */
11977+ fail_stack_elt_t *failure_stack_ptr;
11978+#endif
11979+
11980+ /* We fill all the registers internally, independent of what we
11981+ return, for use in backreferences. The number here includes
11982+ an element for register zero. */
11983+ size_t num_regs = bufp->re_nsub + 1;
11984+
11985+ /* The currently active registers. */
11986+ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
11987+ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
11988+
11989+ /* Information on the contents of registers. These are pointers into
11990+ the input strings; they record just what was matched (on this
11991+ attempt) by a subexpression part of the pattern, that is, the
11992+ regnum-th regstart pointer points to where in the pattern we began
11993+ matching and the regnum-th regend points to right after where we
11994+ stopped matching the regnum-th subexpression. (The zeroth register
11995+ keeps track of what the whole pattern matches.) */
11996+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
11997+ const CHAR_T **regstart, **regend;
11998+#endif
11999+
12000+ /* If a group that's operated upon by a repetition operator fails to
12001+ match anything, then the register for its start will need to be
12002+ restored because it will have been set to wherever in the string we
12003+ are when we last see its open-group operator. Similarly for a
12004+ register's end. */
12005+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
12006+ const CHAR_T **old_regstart, **old_regend;
12007+#endif
12008+
12009+ /* The is_active field of reg_info helps us keep track of which (possibly
12010+ nested) subexpressions we are currently in. The matched_something
12011+ field of reg_info[reg_num] helps us tell whether or not we have
12012+ matched any of the pattern so far this time through the reg_num-th
12013+ subexpression. These two fields get reset each time through any
12014+ loop their register is in. */
12015+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
12016+ PREFIX(register_info_type) *reg_info;
12017+#endif
12018+
12019+ /* The following record the register info as found in the above
12020+ variables when we find a match better than any we've seen before.
12021+ This happens as we backtrack through the failure points, which in
12022+ turn happens only if we have not yet matched the entire string. */
12023+ unsigned best_regs_set = false;
12024+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
12025+ const CHAR_T **best_regstart, **best_regend;
12026+#endif
12027+
12028+ /* Logically, this is `best_regend[0]'. But we don't want to have to
12029+ allocate space for that if we're not allocating space for anything
12030+ else (see below). Also, we never need info about register 0 for
12031+ any of the other register vectors, and it seems rather a kludge to
12032+ treat `best_regend' differently than the rest. So we keep track of
12033+ the end of the best match so far in a separate variable. We
12034+ initialize this to NULL so that when we backtrack the first time
12035+ and need to test it, it's not garbage. */
12036+ const CHAR_T *match_end = NULL;
12037+
12038+ /* This helps SET_REGS_MATCHED avoid doing redundant work. */
12039+ int set_regs_matched_done = 0;
12040+
12041+ /* Used when we pop values we don't care about. */
12042+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
12043+ const CHAR_T **reg_dummy;
12044+ PREFIX(register_info_type) *reg_info_dummy;
12045+#endif
12046+
12047+#ifdef DEBUG
12048+ /* Counts the total number of registers pushed. */
12049+ unsigned num_regs_pushed = 0;
12050+#endif
12051+
12052+ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
12053+
12054+ INIT_FAIL_STACK ();
12055+
12056+#ifdef MATCH_MAY_ALLOCATE
12057+ /* Do not bother to initialize all the register variables if there are
12058+ no groups in the pattern, as it takes a fair amount of time. If
12059+ there are groups, we include space for register 0 (the whole
12060+ pattern), even though we never use it, since it simplifies the
12061+ array indexing. We should fix this. */
12062+ if (bufp->re_nsub)
12063+ {
12064+ regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
12065+ regend = REGEX_TALLOC (num_regs, const CHAR_T *);
12066+ old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
12067+ old_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
12068+ best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
12069+ best_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
12070+ reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
12071+ reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *);
12072+ reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
12073+
12074+ if (!(regstart && regend && old_regstart && old_regend && reg_info
12075+ && best_regstart && best_regend && reg_dummy && reg_info_dummy))
12076+ {
12077+ FREE_VARIABLES ();
12078+ return -2;
12079+ }
12080+ }
12081+ else
12082+ {
12083+ /* We must initialize all our variables to NULL, so that
12084+ `FREE_VARIABLES' doesn't try to free them. */
12085+ regstart = regend = old_regstart = old_regend = best_regstart
12086+ = best_regend = reg_dummy = NULL;
12087+ reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL;
12088+ }
12089+#endif /* MATCH_MAY_ALLOCATE */
12090+
12091+ /* The starting position is bogus. */
12092+#ifdef WCHAR
12093+ if (pos < 0 || pos > csize1 + csize2)
12094+#else /* BYTE */
12095+ if (pos < 0 || pos > size1 + size2)
12096+#endif
12097+ {
12098+ FREE_VARIABLES ();
12099+ return -1;
12100+ }
12101+
12102+#ifdef WCHAR
12103+ /* Allocate wchar_t array for string1 and string2 and
12104+ fill them with converted string. */
12105+ if (string1 == NULL && string2 == NULL)
12106+ {
12107+ /* We need seting up buffers here. */
12108+
12109+ /* We must free wcs buffers in this function. */
12110+ cant_free_wcs_buf = 0;
12111+
12112+ if (csize1 != 0)
12113+ {
12114+ string1 = REGEX_TALLOC (csize1 + 1, CHAR_T);
12115+ mbs_offset1 = REGEX_TALLOC (csize1 + 1, int);
12116+ is_binary = REGEX_TALLOC (csize1 + 1, char);
12117+ if (!string1 || !mbs_offset1 || !is_binary)
12118+ {
12119+ FREE_VAR (string1);
12120+ FREE_VAR (mbs_offset1);
12121+ FREE_VAR (is_binary);
12122+ return -2;
12123+ }
12124+ }
12125+ if (csize2 != 0)
12126+ {
12127+ string2 = REGEX_TALLOC (csize2 + 1, CHAR_T);
12128+ mbs_offset2 = REGEX_TALLOC (csize2 + 1, int);
12129+ is_binary = REGEX_TALLOC (csize2 + 1, char);
12130+ if (!string2 || !mbs_offset2 || !is_binary)
12131+ {
12132+ FREE_VAR (string1);
12133+ FREE_VAR (mbs_offset1);
12134+ FREE_VAR (string2);
12135+ FREE_VAR (mbs_offset2);
12136+ FREE_VAR (is_binary);
12137+ return -2;
12138+ }
12139+ size2 = convert_mbs_to_wcs(string2, cstring2, csize2,
12140+ mbs_offset2, is_binary);
12141+ string2[size2] = L'\0'; /* for a sentinel */
12142+ FREE_VAR (is_binary);
12143+ }
12144+ }
12145+
12146+ /* We need to cast pattern to (wchar_t*), because we casted this compiled
12147+ pattern to (char*) in regex_compile. */
12148+ p = pattern = (CHAR_T*)bufp->buffer;
12149+ pend = (CHAR_T*)(bufp->buffer + bufp->used);
12150+
12151+#endif /* WCHAR */
12152+
12153+ /* Initialize subexpression text positions to -1 to mark ones that no
12154+ start_memory/stop_memory has been seen for. Also initialize the
12155+ register information struct. */
12156+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
12157+ {
12158+ regstart[mcnt] = regend[mcnt]
12159+ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
12160+
12161+ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
12162+ IS_ACTIVE (reg_info[mcnt]) = 0;
12163+ MATCHED_SOMETHING (reg_info[mcnt]) = 0;
12164+ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
12165+ }
12166+
12167+ /* We move `string1' into `string2' if the latter's empty -- but not if
12168+ `string1' is null. */
12169+ if (size2 == 0 && string1 != NULL)
12170+ {
12171+ string2 = string1;
12172+ size2 = size1;
12173+ string1 = 0;
12174+ size1 = 0;
12175+#ifdef WCHAR
12176+ mbs_offset2 = mbs_offset1;
12177+ csize2 = csize1;
12178+ mbs_offset1 = NULL;
12179+ csize1 = 0;
12180+#endif
12181+ }
12182+ end1 = string1 + size1;
12183+ end2 = string2 + size2;
12184+
12185+ /* Compute where to stop matching, within the two strings. */
12186+#ifdef WCHAR
12187+ if (stop <= csize1)
12188+ {
12189+ mcnt = count_mbs_length(mbs_offset1, stop);
12190+ end_match_1 = string1 + mcnt;
12191+ end_match_2 = string2;
12192+ }
12193+ else
12194+ {
12195+ if (stop > csize1 + csize2)
12196+ stop = csize1 + csize2;
12197+ end_match_1 = end1;
12198+ mcnt = count_mbs_length(mbs_offset2, stop-csize1);
12199+ end_match_2 = string2 + mcnt;
12200+ }
12201+ if (mcnt < 0)
12202+ { /* count_mbs_length return error. */
12203+ FREE_VARIABLES ();
12204+ return -1;
12205+ }
12206+#else
12207+ if (stop <= size1)
12208+ {
12209+ end_match_1 = string1 + stop;
12210+ end_match_2 = string2;
12211+ }
12212+ else
12213+ {
12214+ end_match_1 = end1;
12215+ end_match_2 = string2 + stop - size1;
12216+ }
12217+#endif /* WCHAR */
12218+
12219+ /* `p' scans through the pattern as `d' scans through the data.
12220+ `dend' is the end of the input string that `d' points within. `d'
12221+ is advanced into the following input string whenever necessary, but
12222+ this happens before fetching; therefore, at the beginning of the
12223+ loop, `d' can be pointing at the end of a string, but it cannot
12224+ equal `string2'. */
12225+#ifdef WCHAR
12226+ if (size1 > 0 && pos <= csize1)
12227+ {
12228+ mcnt = count_mbs_length(mbs_offset1, pos);
12229+ d = string1 + mcnt;
12230+ dend = end_match_1;
12231+ }
12232+ else
12233+ {
12234+ mcnt = count_mbs_length(mbs_offset2, pos-csize1);
12235+ d = string2 + mcnt;
12236+ dend = end_match_2;
12237+ }
12238+
12239+ if (mcnt < 0)
12240+ { /* count_mbs_length return error. */
12241+ FREE_VARIABLES ();
12242+ return -1;
12243+ }
12244+#else
12245+ if (size1 > 0 && pos <= size1)
12246+ {
12247+ d = string1 + pos;
12248+ dend = end_match_1;
12249+ }
12250+ else
12251+ {
12252+ d = string2 + pos - size1;
12253+ dend = end_match_2;
12254+ }
12255+#endif /* WCHAR */
12256+
12257+ DEBUG_PRINT1 ("The compiled pattern is:\n");
12258+ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
12259+ DEBUG_PRINT1 ("The string to match is: `");
12260+ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
12261+ DEBUG_PRINT1 ("'\n");
12262+
12263+ /* This loops over pattern commands. It exits by returning from the
12264+ function if the match is complete, or it drops through if the match
12265+ fails at this starting point in the input data. */
12266+ for (;;)
12267+ {
12268+#ifdef _LIBC
12269+ DEBUG_PRINT2 ("\n%p: ", p);
12270+#else
12271+ DEBUG_PRINT2 ("\n0x%x: ", p);
12272+#endif
12273+
12274+ if (p == pend)
12275+ { /* End of pattern means we might have succeeded. */
12276+ DEBUG_PRINT1 ("end of pattern ... ");
12277+
12278+ /* If we haven't matched the entire string, and we want the
12279+ longest match, try backtracking. */
12280+ if (d != end_match_2)
12281+ {
12282+ /* 1 if this match ends in the same string (string1 or string2)
12283+ as the best previous match. */
12284+ boolean same_str_p = (FIRST_STRING_P (match_end)
12285+ == MATCHING_IN_FIRST_STRING);
12286+ /* 1 if this match is the best seen so far. */
12287+ boolean best_match_p;
12288+
12289+ /* AIX compiler got confused when this was combined
12290+ with the previous declaration. */
12291+ if (same_str_p)
12292+ best_match_p = d > match_end;
12293+ else
12294+ best_match_p = !MATCHING_IN_FIRST_STRING;
12295+
12296+ DEBUG_PRINT1 ("backtracking.\n");
12297+
12298+ if (!FAIL_STACK_EMPTY ())
12299+ { /* More failure points to try. */
12300+
12301+ /* If exceeds best match so far, save it. */
12302+ if (!best_regs_set || best_match_p)
12303+ {
12304+ best_regs_set = true;
12305+ match_end = d;
12306+
12307+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
12308+
12309+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
12310+ {
12311+ best_regstart[mcnt] = regstart[mcnt];
12312+ best_regend[mcnt] = regend[mcnt];
12313+ }
12314+ }
12315+ goto fail;
12316+ }
12317+
12318+ /* If no failure points, don't restore garbage. And if
12319+ last match is real best match, don't restore second
12320+ best one. */
12321+ else if (best_regs_set && !best_match_p)
12322+ {
12323+ restore_best_regs:
12324+ /* Restore best match. It may happen that `dend ==
12325+ end_match_1' while the restored d is in string2.
12326+ For example, the pattern `x.*y.*z' against the
12327+ strings `x-' and `y-z-', if the two strings are
12328+ not consecutive in memory. */
12329+ DEBUG_PRINT1 ("Restoring best registers.\n");
12330+
12331+ d = match_end;
12332+ dend = ((d >= string1 && d <= end1)
12333+ ? end_match_1 : end_match_2);
12334+
12335+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
12336+ {
12337+ regstart[mcnt] = best_regstart[mcnt];
12338+ regend[mcnt] = best_regend[mcnt];
12339+ }
12340+ }
12341+ } /* d != end_match_2 */
12342+
12343+ succeed_label:
12344+ DEBUG_PRINT1 ("Accepting match.\n");
12345+ /* If caller wants register contents data back, do it. */
12346+ if (regs && !bufp->no_sub)
12347+ {
12348+ /* Have the register data arrays been allocated? */
12349+ if (bufp->regs_allocated == REGS_UNALLOCATED)
12350+ { /* No. So allocate them with malloc. We need one
12351+ extra element beyond `num_regs' for the `-1' marker
12352+ GNU code uses. */
12353+ regs->num_regs = MAX (RE_NREGS, num_regs + 1);
12354+ regs->start = TALLOC (regs->num_regs, regoff_t);
12355+ regs->end = TALLOC (regs->num_regs, regoff_t);
12356+ if (regs->start == NULL || regs->end == NULL)
12357+ {
12358+ FREE_VARIABLES ();
12359+ return -2;
12360+ }
12361+ bufp->regs_allocated = REGS_REALLOCATE;
12362+ }
12363+ else if (bufp->regs_allocated == REGS_REALLOCATE)
12364+ { /* Yes. If we need more elements than were already
12365+ allocated, reallocate them. If we need fewer, just
12366+ leave it alone. */
12367+ if (regs->num_regs < num_regs + 1)
12368+ {
12369+ regs->num_regs = num_regs + 1;
12370+ RETALLOC (regs->start, regs->num_regs, regoff_t);
12371+ RETALLOC (regs->end, regs->num_regs, regoff_t);
12372+ if (regs->start == NULL || regs->end == NULL)
12373+ {
12374+ FREE_VARIABLES ();
12375+ return -2;
12376+ }
12377+ }
12378+ }
12379+ else
12380+ {
12381+ /* These braces fend off a "empty body in an else-statement"
12382+ warning under GCC when assert expands to nothing. */
12383+ assert (bufp->regs_allocated == REGS_FIXED);
12384+ }
12385+
12386+ /* Convert the pointer data in `regstart' and `regend' to
12387+ indices. Register zero has to be set differently,
12388+ since we haven't kept track of any info for it. */
12389+ if (regs->num_regs > 0)
12390+ {
12391+ regs->start[0] = pos;
12392+#ifdef WCHAR
12393+ if (MATCHING_IN_FIRST_STRING)
12394+ regs->end[0] = mbs_offset1 != NULL ?
12395+ mbs_offset1[d-string1] : 0;
12396+ else
12397+ regs->end[0] = csize1 + (mbs_offset2 != NULL ?
12398+ mbs_offset2[d-string2] : 0);
12399+#else
12400+ regs->end[0] = (MATCHING_IN_FIRST_STRING
12401+ ? ((regoff_t) (d - string1))
12402+ : ((regoff_t) (d - string2 + size1)));
12403+#endif /* WCHAR */
12404+ }
12405+
12406+ /* Go through the first `min (num_regs, regs->num_regs)'
12407+ registers, since that is all we initialized. */
12408+ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
12409+ mcnt++)
12410+ {
12411+ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
12412+ regs->start[mcnt] = regs->end[mcnt] = -1;
12413+ else
12414+ {
12415+ regs->start[mcnt]
12416+ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
12417+ regs->end[mcnt]
12418+ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
12419+ }
12420+ }
12421+
12422+ /* If the regs structure we return has more elements than
12423+ were in the pattern, set the extra elements to -1. If
12424+ we (re)allocated the registers, this is the case,
12425+ because we always allocate enough to have at least one
12426+ -1 at the end. */
12427+ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
12428+ regs->start[mcnt] = regs->end[mcnt] = -1;
12429+ } /* regs && !bufp->no_sub */
12430+
12431+ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
12432+ nfailure_points_pushed, nfailure_points_popped,
12433+ nfailure_points_pushed - nfailure_points_popped);
12434+ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
12435+
12436+#ifdef WCHAR
12437+ if (MATCHING_IN_FIRST_STRING)
12438+ mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0;
12439+ else
12440+ mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) +
12441+ csize1;
12442+ mcnt -= pos;
12443+#else
12444+ mcnt = d - pos - (MATCHING_IN_FIRST_STRING
12445+ ? string1
12446+ : string2 - size1);
12447+#endif /* WCHAR */
12448+
12449+ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
12450+
12451+ FREE_VARIABLES ();
12452+ return mcnt;
12453+ }
12454+
12455+ /* Otherwise match next pattern command. */
12456+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
12457+ {
12458+ /* Ignore these. Used to ignore the n of succeed_n's which
12459+ currently have n == 0. */
12460+ case no_op:
12461+ DEBUG_PRINT1 ("EXECUTING no_op.\n");
12462+ break;
12463+
12464+ case succeed:
12465+ DEBUG_PRINT1 ("EXECUTING succeed.\n");
12466+ goto succeed_label;
12467+
12468+ /* Match the next n pattern characters exactly. The following
12469+ byte in the pattern defines n, and the n bytes after that
12470+ are the characters to match. */
12471+ case exactn:
12472+#ifdef MBS_SUPPORT
12473+ case exactn_bin:
12474+#endif
12475+ mcnt = *p++;
12476+ DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
12477+
12478+ /* This is written out as an if-else so we don't waste time
12479+ testing `translate' inside the loop. */
12480+ if (translate)
12481+ {
12482+ do
12483+ {
12484+ PREFETCH ();
12485+#ifdef WCHAR
12486+ if (*d <= 0xff)
12487+ {
12488+ if ((UCHAR_T) translate[(unsigned char) *d++]
12489+ != (UCHAR_T) *p++)
12490+ goto fail;
12491+ }
12492+ else
12493+ {
12494+ if (*d++ != (CHAR_T) *p++)
12495+ goto fail;
12496+ }
12497+#else
12498+ if ((UCHAR_T) translate[(unsigned char) *d++]
12499+ != (UCHAR_T) *p++)
12500+ goto fail;
12501+#endif /* WCHAR */
12502+ }
12503+ while (--mcnt);
12504+ }
12505+ else
12506+ {
12507+ do
12508+ {
12509+ PREFETCH ();
12510+ if (*d++ != (CHAR_T) *p++) goto fail;
12511+ }
12512+ while (--mcnt);
12513+ }
12514+ SET_REGS_MATCHED ();
12515+ break;
12516+
12517+
12518+ /* Match any character except possibly a newline or a null. */
12519+ case anychar:
12520+ DEBUG_PRINT1 ("EXECUTING anychar.\n");
12521+
12522+ PREFETCH ();
12523+
12524+ if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
12525+ || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
12526+ goto fail;
12527+
12528+ SET_REGS_MATCHED ();
12529+ DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d);
12530+ d++;
12531+ break;
12532+
12533+
12534+ case charset:
12535+ case charset_not:
12536+ {
12537+ register UCHAR_T c;
12538+#ifdef WCHAR
12539+ unsigned int i, char_class_length, coll_symbol_length,
12540+ equiv_class_length, ranges_length, chars_length, length;
12541+ CHAR_T *workp, *workp2, *charset_top;
12542+#define WORK_BUFFER_SIZE 128
12543+ CHAR_T str_buf[WORK_BUFFER_SIZE];
12544+# ifdef _LIBC
12545+ uint32_t nrules;
12546+# endif /* _LIBC */
12547+#endif /* WCHAR */
12548+ boolean negate = (re_opcode_t) *(p - 1) == charset_not;
12549+
12550+ DEBUG_PRINT2 ("EXECUTING charset%s.\n", negate ? "_not" : "");
12551+ PREFETCH ();
12552+ c = TRANSLATE (*d); /* The character to match. */
12553+#ifdef WCHAR
12554+# ifdef _LIBC
12555+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
12556+# endif /* _LIBC */
12557+ charset_top = p - 1;
12558+ char_class_length = *p++;
12559+ coll_symbol_length = *p++;
12560+ equiv_class_length = *p++;
12561+ ranges_length = *p++;
12562+ chars_length = *p++;
12563+ /* p points charset[6], so the address of the next instruction
12564+ (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'],
12565+ where l=length of char_classes, m=length of collating_symbol,
12566+ n=equivalence_class, o=length of char_range,
12567+ p'=length of character. */
12568+ workp = p;
12569+ /* Update p to indicate the next instruction. */
12570+ p += char_class_length + coll_symbol_length+ equiv_class_length +
12571+ 2*ranges_length + chars_length;
12572+
12573+ /* match with char_class? */
12574+ for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE)
12575+ {
12576+ wctype_t wctype;
12577+ uintptr_t alignedp = ((uintptr_t)workp
12578+ + __alignof__(wctype_t) - 1)
12579+ & ~(uintptr_t)(__alignof__(wctype_t) - 1);
12580+ wctype = *((wctype_t*)alignedp);
12581+ workp += CHAR_CLASS_SIZE;
12582+# ifdef _LIBC
12583+ if (__iswctype((wint_t)c, wctype))
12584+ goto char_set_matched;
12585+# else
12586+ if (iswctype((wint_t)c, wctype))
12587+ goto char_set_matched;
12588+# endif
12589+ }
12590+
12591+ /* match with collating_symbol? */
12592+# ifdef _LIBC
12593+ if (nrules != 0)
12594+ {
12595+ const unsigned char *extra = (const unsigned char *)
12596+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
12597+
12598+ for (workp2 = workp + coll_symbol_length ; workp < workp2 ;
12599+ workp++)
12600+ {
12601+ int32_t *wextra;
12602+ wextra = (int32_t*)(extra + *workp++);
12603+ for (i = 0; i < *wextra; ++i)
12604+ if (TRANSLATE(d[i]) != wextra[1 + i])
12605+ break;
12606+
12607+ if (i == *wextra)
12608+ {
12609+ /* Update d, however d will be incremented at
12610+ char_set_matched:, we decrement d here. */
12611+ d += i - 1;
12612+ goto char_set_matched;
12613+ }
12614+ }
12615+ }
12616+ else /* (nrules == 0) */
12617+# endif
12618+ /* If we can't look up collation data, we use wcscoll
12619+ instead. */
12620+ {
12621+ for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
12622+ {
12623+ const CHAR_T *backup_d = d, *backup_dend = dend;
12624+# ifdef _LIBC
12625+ length = __wcslen (workp);
12626+# else
12627+ length = wcslen (workp);
12628+# endif
12629+
12630+ /* If wcscoll(the collating symbol, whole string) > 0,
12631+ any substring of the string never match with the
12632+ collating symbol. */
12633+# ifdef _LIBC
12634+ if (__wcscoll (workp, d) > 0)
12635+# else
12636+ if (wcscoll (workp, d) > 0)
12637+# endif
12638+ {
12639+ workp += length + 1;
12640+ continue;
12641+ }
12642+
12643+ /* First, we compare the collating symbol with
12644+ the first character of the string.
12645+ If it don't match, we add the next character to
12646+ the compare buffer in turn. */
12647+ for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++)
12648+ {
12649+ int match;
12650+ if (d == dend)
12651+ {
12652+ if (dend == end_match_2)
12653+ break;
12654+ d = string2;
12655+ dend = end_match_2;
12656+ }
12657+
12658+ /* add next character to the compare buffer. */
12659+ str_buf[i] = TRANSLATE(*d);
12660+ str_buf[i+1] = '\0';
12661+
12662+# ifdef _LIBC
12663+ match = __wcscoll (workp, str_buf);
12664+# else
12665+ match = wcscoll (workp, str_buf);
12666+# endif
12667+ if (match == 0)
12668+ goto char_set_matched;
12669+
12670+ if (match < 0)
12671+ /* (str_buf > workp) indicate (str_buf + X > workp),
12672+ because for all X (str_buf + X > str_buf).
12673+ So we don't need continue this loop. */
12674+ break;
12675+
12676+ /* Otherwise(str_buf < workp),
12677+ (str_buf+next_character) may equals (workp).
12678+ So we continue this loop. */
12679+ }
12680+ /* not matched */
12681+ d = backup_d;
12682+ dend = backup_dend;
12683+ workp += length + 1;
12684+ }
12685+ }
12686+ /* match with equivalence_class? */
12687+# ifdef _LIBC
12688+ if (nrules != 0)
12689+ {
12690+ const CHAR_T *backup_d = d, *backup_dend = dend;
12691+ /* Try to match the equivalence class against
12692+ those known to the collate implementation. */
12693+ const int32_t *table;
12694+ const int32_t *weights;
12695+ const int32_t *extra;
12696+ const int32_t *indirect;
12697+ int32_t idx, idx2;
12698+ wint_t *cp;
12699+ size_t len;
12700+
12701+ table = (const int32_t *)
12702+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
12703+ weights = (const wint_t *)
12704+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
12705+ extra = (const wint_t *)
12706+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
12707+ indirect = (const int32_t *)
12708+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
12709+
12710+ /* Write 1 collating element to str_buf, and
12711+ get its index. */
12712+ idx2 = 0;
12713+
12714+ for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++)
12715+ {
12716+ cp = (wint_t*)str_buf;
12717+ if (d == dend)
12718+ {
12719+ if (dend == end_match_2)
12720+ break;
12721+ d = string2;
12722+ dend = end_match_2;
12723+ }
12724+ str_buf[i] = TRANSLATE(*(d+i));
12725+ str_buf[i+1] = '\0'; /* sentinel */
12726+ idx2 = FINDIDX (table, indirect, extra, &cp, 1);
12727+ }
12728+
12729+ /* Update d, however d will be incremented at
12730+ char_set_matched:, we decrement d here. */
12731+ d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1);
12732+ if (d >= dend)
12733+ {
12734+ if (dend == end_match_2)
12735+ d = dend;
12736+ else
12737+ {
12738+ d = string2;
12739+ dend = end_match_2;
12740+ }
12741+ }
12742+
12743+ len = weights[idx2];
12744+
12745+ for (workp2 = workp + equiv_class_length ; workp < workp2 ;
12746+ workp++)
12747+ {
12748+ idx = (int32_t)*workp;
12749+ /* We already checked idx != 0 in regex_compile. */
12750+
12751+ if (idx2 != 0 && len == weights[idx])
12752+ {
12753+ int cnt = 0;
12754+ while (cnt < len && (weights[idx + 1 + cnt]
12755+ == weights[idx2 + 1 + cnt]))
12756+ ++cnt;
12757+
12758+ if (cnt == len)
12759+ goto char_set_matched;
12760+ }
12761+ }
12762+ /* not matched */
12763+ d = backup_d;
12764+ dend = backup_dend;
12765+ }
12766+ else /* (nrules == 0) */
12767+# endif
12768+ /* If we can't look up collation data, we use wcscoll
12769+ instead. */
12770+ {
12771+ for (workp2 = workp + equiv_class_length ; workp < workp2 ;)
12772+ {
12773+ const CHAR_T *backup_d = d, *backup_dend = dend;
12774+# ifdef _LIBC
12775+ length = __wcslen (workp);
12776+# else
12777+ length = wcslen (workp);
12778+# endif
12779+
12780+ /* If wcscoll(the collating symbol, whole string) > 0,
12781+ any substring of the string never match with the
12782+ collating symbol. */
12783+# ifdef _LIBC
12784+ if (__wcscoll (workp, d) > 0)
12785+# else
12786+ if (wcscoll (workp, d) > 0)
12787+# endif
12788+ {
12789+ workp += length + 1;
12790+ break;
12791+ }
12792+
12793+ /* First, we compare the equivalence class with
12794+ the first character of the string.
12795+ If it don't match, we add the next character to
12796+ the compare buffer in turn. */
12797+ for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++)
12798+ {
12799+ int match;
12800+ if (d == dend)
12801+ {
12802+ if (dend == end_match_2)
12803+ break;
12804+ d = string2;
12805+ dend = end_match_2;
12806+ }
12807+
12808+ /* add next character to the compare buffer. */
12809+ str_buf[i] = TRANSLATE(*d);
12810+ str_buf[i+1] = '\0';
12811+
12812+# ifdef _LIBC
12813+ match = __wcscoll (workp, str_buf);
12814+# else
12815+ match = wcscoll (workp, str_buf);
12816+# endif
12817+
12818+ if (match == 0)
12819+ goto char_set_matched;
12820+
12821+ if (match < 0)
12822+ /* (str_buf > workp) indicate (str_buf + X > workp),
12823+ because for all X (str_buf + X > str_buf).
12824+ So we don't need continue this loop. */
12825+ break;
12826+
12827+ /* Otherwise(str_buf < workp),
12828+ (str_buf+next_character) may equals (workp).
12829+ So we continue this loop. */
12830+ }
12831+ /* not matched */
12832+ d = backup_d;
12833+ dend = backup_dend;
12834+ workp += length + 1;
12835+ }
12836+ }
12837+
12838+ /* match with char_range? */
12839+# ifdef _LIBC
12840+ if (nrules != 0)
12841+ {
12842+ uint32_t collseqval;
12843+ const char *collseq = (const char *)
12844+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
12845+
12846+ collseqval = collseq_table_lookup (collseq, c);
12847+
12848+ for (; workp < p - chars_length ;)
12849+ {
12850+ uint32_t start_val, end_val;
12851+
12852+ /* We already compute the collation sequence value
12853+ of the characters (or collating symbols). */
12854+ start_val = (uint32_t) *workp++; /* range_start */
12855+ end_val = (uint32_t) *workp++; /* range_end */
12856+
12857+ if (start_val <= collseqval && collseqval <= end_val)
12858+ goto char_set_matched;
12859+ }
12860+ }
12861+ else
12862+# endif
12863+ {
12864+ /* We set range_start_char at str_buf[0], range_end_char
12865+ at str_buf[4], and compared char at str_buf[2]. */
12866+ str_buf[1] = 0;
12867+ str_buf[2] = c;
12868+ str_buf[3] = 0;
12869+ str_buf[5] = 0;
12870+ for (; workp < p - chars_length ;)
12871+ {
12872+ wchar_t *range_start_char, *range_end_char;
12873+
12874+ /* match if (range_start_char <= c <= range_end_char). */
12875+
12876+ /* If range_start(or end) < 0, we assume -range_start(end)
12877+ is the offset of the collating symbol which is specified
12878+ as the character of the range start(end). */
12879+
12880+ /* range_start */
12881+ if (*workp < 0)
12882+ range_start_char = charset_top - (*workp++);
12883+ else
12884+ {
12885+ str_buf[0] = *workp++;
12886+ range_start_char = str_buf;
12887+ }
12888+
12889+ /* range_end */
12890+ if (*workp < 0)
12891+ range_end_char = charset_top - (*workp++);
12892+ else
12893+ {
12894+ str_buf[4] = *workp++;
12895+ range_end_char = str_buf + 4;
12896+ }
12897+
12898+# ifdef _LIBC
12899+ if (__wcscoll (range_start_char, str_buf+2) <= 0
12900+ && __wcscoll (str_buf+2, range_end_char) <= 0)
12901+# else
12902+ if (wcscoll (range_start_char, str_buf+2) <= 0
12903+ && wcscoll (str_buf+2, range_end_char) <= 0)
12904+# endif
12905+ goto char_set_matched;
12906+ }
12907+ }
12908+
12909+ /* match with char? */
12910+ for (; workp < p ; workp++)
12911+ if (c == *workp)
12912+ goto char_set_matched;
12913+
12914+ negate = !negate;
12915+
12916+ char_set_matched:
12917+ if (negate) goto fail;
12918+#else
12919+ /* Cast to `unsigned' instead of `unsigned char' in case the
12920+ bit list is a full 32 bytes long. */
12921+ if (c < (unsigned) (*p * BYTEWIDTH)
12922+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
12923+ negate = !negate;
12924+
12925+ p += 1 + *p;
12926+
12927+ if (!negate) goto fail;
12928+#undef WORK_BUFFER_SIZE
12929+#endif /* WCHAR */
12930+ SET_REGS_MATCHED ();
12931+ d++;
12932+ break;
12933+ }
12934+
12935+
12936+ /* The beginning of a group is represented by start_memory.
12937+ The arguments are the register number in the next byte, and the
12938+ number of groups inner to this one in the next. The text
12939+ matched within the group is recorded (in the internal
12940+ registers data structure) under the register number. */
12941+ case start_memory:
12942+ DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n",
12943+ (long int) *p, (long int) p[1]);
12944+
12945+ /* Find out if this group can match the empty string. */
12946+ p1 = p; /* To send to group_match_null_string_p. */
12947+
12948+ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
12949+ REG_MATCH_NULL_STRING_P (reg_info[*p])
12950+ = PREFIX(group_match_null_string_p) (&p1, pend, reg_info);
12951+
12952+ /* Save the position in the string where we were the last time
12953+ we were at this open-group operator in case the group is
12954+ operated upon by a repetition operator, e.g., with `(a*)*b'
12955+ against `ab'; then we want to ignore where we are now in
12956+ the string in case this attempt to match fails. */
12957+ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
12958+ ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
12959+ : regstart[*p];
12960+ DEBUG_PRINT2 (" old_regstart: %d\n",
12961+ POINTER_TO_OFFSET (old_regstart[*p]));
12962+
12963+ regstart[*p] = d;
12964+ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
12965+
12966+ IS_ACTIVE (reg_info[*p]) = 1;
12967+ MATCHED_SOMETHING (reg_info[*p]) = 0;
12968+
12969+ /* Clear this whenever we change the register activity status. */
12970+ set_regs_matched_done = 0;
12971+
12972+ /* This is the new highest active register. */
12973+ highest_active_reg = *p;
12974+
12975+ /* If nothing was active before, this is the new lowest active
12976+ register. */
12977+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
12978+ lowest_active_reg = *p;
12979+
12980+ /* Move past the register number and inner group count. */
12981+ p += 2;
12982+ just_past_start_mem = p;
12983+
12984+ break;
12985+
12986+
12987+ /* The stop_memory opcode represents the end of a group. Its
12988+ arguments are the same as start_memory's: the register
12989+ number, and the number of inner groups. */
12990+ case stop_memory:
12991+ DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n",
12992+ (long int) *p, (long int) p[1]);
12993+
12994+ /* We need to save the string position the last time we were at
12995+ this close-group operator in case the group is operated
12996+ upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
12997+ against `aba'; then we want to ignore where we are now in
12998+ the string in case this attempt to match fails. */
12999+ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
13000+ ? REG_UNSET (regend[*p]) ? d : regend[*p]
13001+ : regend[*p];
13002+ DEBUG_PRINT2 (" old_regend: %d\n",
13003+ POINTER_TO_OFFSET (old_regend[*p]));
13004+
13005+ regend[*p] = d;
13006+ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
13007+
13008+ /* This register isn't active anymore. */
13009+ IS_ACTIVE (reg_info[*p]) = 0;
13010+
13011+ /* Clear this whenever we change the register activity status. */
13012+ set_regs_matched_done = 0;
13013+
13014+ /* If this was the only register active, nothing is active
13015+ anymore. */
13016+ if (lowest_active_reg == highest_active_reg)
13017+ {
13018+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
13019+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
13020+ }
13021+ else
13022+ { /* We must scan for the new highest active register, since
13023+ it isn't necessarily one less than now: consider
13024+ (a(b)c(d(e)f)g). When group 3 ends, after the f), the
13025+ new highest active register is 1. */
13026+ UCHAR_T r = *p - 1;
13027+ while (r > 0 && !IS_ACTIVE (reg_info[r]))
13028+ r--;
13029+
13030+ /* If we end up at register zero, that means that we saved
13031+ the registers as the result of an `on_failure_jump', not
13032+ a `start_memory', and we jumped to past the innermost
13033+ `stop_memory'. For example, in ((.)*) we save
13034+ registers 1 and 2 as a result of the *, but when we pop
13035+ back to the second ), we are at the stop_memory 1.
13036+ Thus, nothing is active. */
13037+ if (r == 0)
13038+ {
13039+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
13040+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
13041+ }
13042+ else
13043+ highest_active_reg = r;
13044+ }
13045+
13046+ /* If just failed to match something this time around with a
13047+ group that's operated on by a repetition operator, try to
13048+ force exit from the ``loop'', and restore the register
13049+ information for this group that we had before trying this
13050+ last match. */
13051+ if ((!MATCHED_SOMETHING (reg_info[*p])
13052+ || just_past_start_mem == p - 1)
13053+ && (p + 2) < pend)
13054+ {
13055+ boolean is_a_jump_n = false;
13056+
13057+ p1 = p + 2;
13058+ mcnt = 0;
13059+ switch ((re_opcode_t) *p1++)
13060+ {
13061+ case jump_n:
13062+ is_a_jump_n = true;
13063+ case pop_failure_jump:
13064+ case maybe_pop_jump:
13065+ case jump:
13066+ case dummy_failure_jump:
13067+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
13068+ if (is_a_jump_n)
13069+ p1 += OFFSET_ADDRESS_SIZE;
13070+ break;
13071+
13072+ default:
13073+ /* do nothing */ ;
13074+ }
13075+ p1 += mcnt;
13076+
13077+ /* If the next operation is a jump backwards in the pattern
13078+ to an on_failure_jump right before the start_memory
13079+ corresponding to this stop_memory, exit from the loop
13080+ by forcing a failure after pushing on the stack the
13081+ on_failure_jump's jump in the pattern, and d. */
13082+ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
13083+ && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory
13084+ && p1[2+OFFSET_ADDRESS_SIZE] == *p)
13085+ {
13086+ /* If this group ever matched anything, then restore
13087+ what its registers were before trying this last
13088+ failed match, e.g., with `(a*)*b' against `ab' for
13089+ regstart[1], and, e.g., with `((a*)*(b*)*)*'
13090+ against `aba' for regend[3].
13091+
13092+ Also restore the registers for inner groups for,
13093+ e.g., `((a*)(b*))*' against `aba' (register 3 would
13094+ otherwise get trashed). */
13095+
13096+ if (EVER_MATCHED_SOMETHING (reg_info[*p]))
13097+ {
13098+ unsigned r;
13099+
13100+ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
13101+
13102+ /* Restore this and inner groups' (if any) registers. */
13103+ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
13104+ r++)
13105+ {
13106+ regstart[r] = old_regstart[r];
13107+
13108+ /* xx why this test? */
13109+ if (old_regend[r] >= regstart[r])
13110+ regend[r] = old_regend[r];
13111+ }
13112+ }
13113+ p1++;
13114+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
13115+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
13116+
13117+ goto fail;
13118+ }
13119+ }
13120+
13121+ /* Move past the register number and the inner group count. */
13122+ p += 2;
13123+ break;
13124+
13125+
13126+ /* \<digit> has been turned into a `duplicate' command which is
13127+ followed by the numeric value of <digit> as the register number. */
13128+ case duplicate:
13129+ {
13130+ register const CHAR_T *d2, *dend2;
13131+ int regno = *p++; /* Get which register to match against. */
13132+ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
13133+
13134+ /* Can't back reference a group which we've never matched. */
13135+ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
13136+ goto fail;
13137+
13138+ /* Where in input to try to start matching. */
13139+ d2 = regstart[regno];
13140+
13141+ /* Where to stop matching; if both the place to start and
13142+ the place to stop matching are in the same string, then
13143+ set to the place to stop, otherwise, for now have to use
13144+ the end of the first string. */
13145+
13146+ dend2 = ((FIRST_STRING_P (regstart[regno])
13147+ == FIRST_STRING_P (regend[regno]))
13148+ ? regend[regno] : end_match_1);
13149+ for (;;)
13150+ {
13151+ /* If necessary, advance to next segment in register
13152+ contents. */
13153+ while (d2 == dend2)
13154+ {
13155+ if (dend2 == end_match_2) break;
13156+ if (dend2 == regend[regno]) break;
13157+
13158+ /* End of string1 => advance to string2. */
13159+ d2 = string2;
13160+ dend2 = regend[regno];
13161+ }
13162+ /* At end of register contents => success */
13163+ if (d2 == dend2) break;
13164+
13165+ /* If necessary, advance to next segment in data. */
13166+ PREFETCH ();
13167+
13168+ /* How many characters left in this segment to match. */
13169+ mcnt = dend - d;
13170+
13171+ /* Want how many consecutive characters we can match in
13172+ one shot, so, if necessary, adjust the count. */
13173+ if (mcnt > dend2 - d2)
13174+ mcnt = dend2 - d2;
13175+
13176+ /* Compare that many; failure if mismatch, else move
13177+ past them. */
13178+ if (translate
13179+ ? PREFIX(bcmp_translate) (d, d2, mcnt, translate)
13180+ : memcmp (d, d2, mcnt*sizeof(UCHAR_T)))
13181+ goto fail;
13182+ d += mcnt, d2 += mcnt;
13183+
13184+ /* Do this because we've match some characters. */
13185+ SET_REGS_MATCHED ();
13186+ }
13187+ }
13188+ break;
13189+
13190+
13191+ /* begline matches the empty string at the beginning of the string
13192+ (unless `not_bol' is set in `bufp'), and, if
13193+ `newline_anchor' is set, after newlines. */
13194+ case begline:
13195+ DEBUG_PRINT1 ("EXECUTING begline.\n");
13196+
13197+ if (AT_STRINGS_BEG (d))
13198+ {
13199+ if (!bufp->not_bol) break;
13200+ }
13201+ else if (d[-1] == '\n' && bufp->newline_anchor)
13202+ {
13203+ break;
13204+ }
13205+ /* In all other cases, we fail. */
13206+ goto fail;
13207+
13208+
13209+ /* endline is the dual of begline. */
13210+ case endline:
13211+ DEBUG_PRINT1 ("EXECUTING endline.\n");
13212+
13213+ if (AT_STRINGS_END (d))
13214+ {
13215+ if (!bufp->not_eol) break;
13216+ }
13217+
13218+ /* We have to ``prefetch'' the next character. */
13219+ else if ((d == end1 ? *string2 : *d) == '\n'
13220+ && bufp->newline_anchor)
13221+ {
13222+ break;
13223+ }
13224+ goto fail;
13225+
13226+
13227+ /* Match at the very beginning of the data. */
13228+ case begbuf:
13229+ DEBUG_PRINT1 ("EXECUTING begbuf.\n");
13230+ if (AT_STRINGS_BEG (d))
13231+ break;
13232+ goto fail;
13233+
13234+
13235+ /* Match at the very end of the data. */
13236+ case endbuf:
13237+ DEBUG_PRINT1 ("EXECUTING endbuf.\n");
13238+ if (AT_STRINGS_END (d))
13239+ break;
13240+ goto fail;
13241+
13242+
13243+ /* on_failure_keep_string_jump is used to optimize `.*\n'. It
13244+ pushes NULL as the value for the string on the stack. Then
13245+ `pop_failure_point' will keep the current value for the
13246+ string, instead of restoring it. To see why, consider
13247+ matching `foo\nbar' against `.*\n'. The .* matches the foo;
13248+ then the . fails against the \n. But the next thing we want
13249+ to do is match the \n against the \n; if we restored the
13250+ string value, we would be back at the foo.
13251+
13252+ Because this is used only in specific cases, we don't need to
13253+ check all the things that `on_failure_jump' does, to make
13254+ sure the right things get saved on the stack. Hence we don't
13255+ share its code. The only reason to push anything on the
13256+ stack at all is that otherwise we would have to change
13257+ `anychar's code to do something besides goto fail in this
13258+ case; that seems worse than this. */
13259+ case on_failure_keep_string_jump:
13260+ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
13261+
13262+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
13263+#ifdef _LIBC
13264+ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
13265+#else
13266+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
13267+#endif
13268+
13269+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
13270+ break;
13271+
13272+
13273+ /* Uses of on_failure_jump:
13274+
13275+ Each alternative starts with an on_failure_jump that points
13276+ to the beginning of the next alternative. Each alternative
13277+ except the last ends with a jump that in effect jumps past
13278+ the rest of the alternatives. (They really jump to the
13279+ ending jump of the following alternative, because tensioning
13280+ these jumps is a hassle.)
13281+
13282+ Repeats start with an on_failure_jump that points past both
13283+ the repetition text and either the following jump or
13284+ pop_failure_jump back to this on_failure_jump. */
13285+ case on_failure_jump:
13286+ on_failure:
13287+ DEBUG_PRINT1 ("EXECUTING on_failure_jump");
13288+
13289+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
13290+#ifdef _LIBC
13291+ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
13292+#else
13293+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
13294+#endif
13295+
13296+ /* If this on_failure_jump comes right before a group (i.e.,
13297+ the original * applied to a group), save the information
13298+ for that group and all inner ones, so that if we fail back
13299+ to this point, the group's information will be correct.
13300+ For example, in \(a*\)*\1, we need the preceding group,
13301+ and in \(zz\(a*\)b*\)\2, we need the inner group. */
13302+
13303+ /* We can't use `p' to check ahead because we push
13304+ a failure point to `p + mcnt' after we do this. */
13305+ p1 = p;
13306+
13307+ /* We need to skip no_op's before we look for the
13308+ start_memory in case this on_failure_jump is happening as
13309+ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
13310+ against aba. */
13311+ while (p1 < pend && (re_opcode_t) *p1 == no_op)
13312+ p1++;
13313+
13314+ if (p1 < pend && (re_opcode_t) *p1 == start_memory)
13315+ {
13316+ /* We have a new highest active register now. This will
13317+ get reset at the start_memory we are about to get to,
13318+ but we will have saved all the registers relevant to
13319+ this repetition op, as described above. */
13320+ highest_active_reg = *(p1 + 1) + *(p1 + 2);
13321+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
13322+ lowest_active_reg = *(p1 + 1);
13323+ }
13324+
13325+ DEBUG_PRINT1 (":\n");
13326+ PUSH_FAILURE_POINT (p + mcnt, d, -2);
13327+ break;
13328+
13329+
13330+ /* A smart repeat ends with `maybe_pop_jump'.
13331+ We change it to either `pop_failure_jump' or `jump'. */
13332+ case maybe_pop_jump:
13333+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
13334+ DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
13335+ {
13336+ register UCHAR_T *p2 = p;
13337+
13338+ /* Compare the beginning of the repeat with what in the
13339+ pattern follows its end. If we can establish that there
13340+ is nothing that they would both match, i.e., that we
13341+ would have to backtrack because of (as in, e.g., `a*a')
13342+ then we can change to pop_failure_jump, because we'll
13343+ never have to backtrack.
13344+
13345+ This is not true in the case of alternatives: in
13346+ `(a|ab)*' we do need to backtrack to the `ab' alternative
13347+ (e.g., if the string was `ab'). But instead of trying to
13348+ detect that here, the alternative has put on a dummy
13349+ failure point which is what we will end up popping. */
13350+
13351+ /* Skip over open/close-group commands.
13352+ If what follows this loop is a ...+ construct,
13353+ look at what begins its body, since we will have to
13354+ match at least one of that. */
13355+ while (1)
13356+ {
13357+ if (p2 + 2 < pend
13358+ && ((re_opcode_t) *p2 == stop_memory
13359+ || (re_opcode_t) *p2 == start_memory))
13360+ p2 += 3;
13361+ else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend
13362+ && (re_opcode_t) *p2 == dummy_failure_jump)
13363+ p2 += 2 + 2 * OFFSET_ADDRESS_SIZE;
13364+ else
13365+ break;
13366+ }
13367+
13368+ p1 = p + mcnt;
13369+ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
13370+ to the `maybe_finalize_jump' of this case. Examine what
13371+ follows. */
13372+
13373+ /* If we're at the end of the pattern, we can change. */
13374+ if (p2 == pend)
13375+ {
13376+ /* Consider what happens when matching ":\(.*\)"
13377+ against ":/". I don't really understand this code
13378+ yet. */
13379+ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
13380+ pop_failure_jump;
13381+ DEBUG_PRINT1
13382+ (" End of pattern: change to `pop_failure_jump'.\n");
13383+ }
13384+
13385+ else if ((re_opcode_t) *p2 == exactn
13386+#ifdef MBS_SUPPORT
13387+ || (re_opcode_t) *p2 == exactn_bin
13388+#endif
13389+ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
13390+ {
13391+ register UCHAR_T c
13392+ = *p2 == (UCHAR_T) endline ? '\n' : p2[2];
13393+
13394+ if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn
13395+#ifdef MBS_SUPPORT
13396+ || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin
13397+#endif
13398+ ) && p1[3+OFFSET_ADDRESS_SIZE] != c)
13399+ {
13400+ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
13401+ pop_failure_jump;
13402+#ifdef WCHAR
13403+ DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n",
13404+ (wint_t) c,
13405+ (wint_t) p1[3+OFFSET_ADDRESS_SIZE]);
13406+#else
13407+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
13408+ (char) c,
13409+ (char) p1[3+OFFSET_ADDRESS_SIZE]);
13410+#endif
13411+ }
13412+
13413+#ifndef WCHAR
13414+ else if ((re_opcode_t) p1[3] == charset
13415+ || (re_opcode_t) p1[3] == charset_not)
13416+ {
13417+ int negate = (re_opcode_t) p1[3] == charset_not;
13418+
13419+ if (c < (unsigned) (p1[4] * BYTEWIDTH)
13420+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
13421+ negate = !negate;
13422+
13423+ /* `negate' is equal to 1 if c would match, which means
13424+ that we can't change to pop_failure_jump. */
13425+ if (!negate)
13426+ {
13427+ p[-3] = (unsigned char) pop_failure_jump;
13428+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
13429+ }
13430+ }
13431+#endif /* not WCHAR */
13432+ }
13433+#ifndef WCHAR
13434+ else if ((re_opcode_t) *p2 == charset)
13435+ {
13436+ /* We win if the first character of the loop is not part
13437+ of the charset. */
13438+ if ((re_opcode_t) p1[3] == exactn
13439+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
13440+ && (p2[2 + p1[5] / BYTEWIDTH]
13441+ & (1 << (p1[5] % BYTEWIDTH)))))
13442+ {
13443+ p[-3] = (unsigned char) pop_failure_jump;
13444+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
13445+ }
13446+
13447+ else if ((re_opcode_t) p1[3] == charset_not)
13448+ {
13449+ int idx;
13450+ /* We win if the charset_not inside the loop
13451+ lists every character listed in the charset after. */
13452+ for (idx = 0; idx < (int) p2[1]; idx++)
13453+ if (! (p2[2 + idx] == 0
13454+ || (idx < (int) p1[4]
13455+ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
13456+ break;
13457+
13458+ if (idx == p2[1])
13459+ {
13460+ p[-3] = (unsigned char) pop_failure_jump;
13461+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
13462+ }
13463+ }
13464+ else if ((re_opcode_t) p1[3] == charset)
13465+ {
13466+ int idx;
13467+ /* We win if the charset inside the loop
13468+ has no overlap with the one after the loop. */
13469+ for (idx = 0;
13470+ idx < (int) p2[1] && idx < (int) p1[4];
13471+ idx++)
13472+ if ((p2[2 + idx] & p1[5 + idx]) != 0)
13473+ break;
13474+
13475+ if (idx == p2[1] || idx == p1[4])
13476+ {
13477+ p[-3] = (unsigned char) pop_failure_jump;
13478+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
13479+ }
13480+ }
13481+ }
13482+#endif /* not WCHAR */
13483+ }
13484+ p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */
13485+ if ((re_opcode_t) p[-1] != pop_failure_jump)
13486+ {
13487+ p[-1] = (UCHAR_T) jump;
13488+ DEBUG_PRINT1 (" Match => jump.\n");
13489+ goto unconditional_jump;
13490+ }
13491+ /* Note fall through. */
13492+
13493+
13494+ /* The end of a simple repeat has a pop_failure_jump back to
13495+ its matching on_failure_jump, where the latter will push a
13496+ failure point. The pop_failure_jump takes off failure
13497+ points put on by this pop_failure_jump's matching
13498+ on_failure_jump; we got through the pattern to here from the
13499+ matching on_failure_jump, so didn't fail. */
13500+ case pop_failure_jump:
13501+ {
13502+ /* We need to pass separate storage for the lowest and
13503+ highest registers, even though we don't care about the
13504+ actual values. Otherwise, we will restore only one
13505+ register from the stack, since lowest will == highest in
13506+ `pop_failure_point'. */
13507+ active_reg_t dummy_low_reg, dummy_high_reg;
13508+ UCHAR_T *pdummy __attribute__ ((unused)) = NULL;
13509+ const CHAR_T *sdummy __attribute__ ((unused)) = NULL;
13510+
13511+ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
13512+ POP_FAILURE_POINT (sdummy, pdummy,
13513+ dummy_low_reg, dummy_high_reg,
13514+ reg_dummy, reg_dummy, reg_info_dummy);
13515+ }
13516+ /* Note fall through. */
13517+
13518+ unconditional_jump:
13519+#ifdef _LIBC
13520+ DEBUG_PRINT2 ("\n%p: ", p);
13521+#else
13522+ DEBUG_PRINT2 ("\n0x%x: ", p);
13523+#endif
13524+ /* Note fall through. */
13525+
13526+ /* Unconditionally jump (without popping any failure points). */
13527+ case jump:
13528+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
13529+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
13530+ p += mcnt; /* Do the jump. */
13531+#ifdef _LIBC
13532+ DEBUG_PRINT2 ("(to %p).\n", p);
13533+#else
13534+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
13535+#endif
13536+ break;
13537+
13538+
13539+ /* We need this opcode so we can detect where alternatives end
13540+ in `group_match_null_string_p' et al. */
13541+ case jump_past_alt:
13542+ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
13543+ goto unconditional_jump;
13544+
13545+
13546+ /* Normally, the on_failure_jump pushes a failure point, which
13547+ then gets popped at pop_failure_jump. We will end up at
13548+ pop_failure_jump, also, and with a pattern of, say, `a+', we
13549+ are skipping over the on_failure_jump, so we have to push
13550+ something meaningless for pop_failure_jump to pop. */
13551+ case dummy_failure_jump:
13552+ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
13553+ /* It doesn't matter what we push for the string here. What
13554+ the code at `fail' tests is the value for the pattern. */
13555+ PUSH_FAILURE_POINT (NULL, NULL, -2);
13556+ goto unconditional_jump;
13557+
13558+
13559+ /* At the end of an alternative, we need to push a dummy failure
13560+ point in case we are followed by a `pop_failure_jump', because
13561+ we don't want the failure point for the alternative to be
13562+ popped. For example, matching `(a|ab)*' against `aab'
13563+ requires that we match the `ab' alternative. */
13564+ case push_dummy_failure:
13565+ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
13566+ /* See comments just above at `dummy_failure_jump' about the
13567+ two zeroes. */
13568+ PUSH_FAILURE_POINT (NULL, NULL, -2);
13569+ break;
13570+
13571+ /* Have to succeed matching what follows at least n times.
13572+ After that, handle like `on_failure_jump'. */
13573+ case succeed_n:
13574+ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
13575+ DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
13576+
13577+ assert (mcnt >= 0);
13578+ /* Originally, this is how many times we HAVE to succeed. */
13579+ if (mcnt > 0)
13580+ {
13581+ mcnt--;
13582+ p += OFFSET_ADDRESS_SIZE;
13583+ STORE_NUMBER_AND_INCR (p, mcnt);
13584+#ifdef _LIBC
13585+ DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE
13586+ , mcnt);
13587+#else
13588+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE
13589+ , mcnt);
13590+#endif
13591+ }
13592+ else if (mcnt == 0)
13593+ {
13594+#ifdef _LIBC
13595+ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n",
13596+ p + OFFSET_ADDRESS_SIZE);
13597+#else
13598+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n",
13599+ p + OFFSET_ADDRESS_SIZE);
13600+#endif /* _LIBC */
13601+
13602+#ifdef WCHAR
13603+ p[1] = (UCHAR_T) no_op;
13604+#else
13605+ p[2] = (UCHAR_T) no_op;
13606+ p[3] = (UCHAR_T) no_op;
13607+#endif /* WCHAR */
13608+ goto on_failure;
13609+ }
13610+ break;
13611+
13612+ case jump_n:
13613+ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
13614+ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
13615+
13616+ /* Originally, this is how many times we CAN jump. */
13617+ if (mcnt)
13618+ {
13619+ mcnt--;
13620+ STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt);
13621+
13622+#ifdef _LIBC
13623+ DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE,
13624+ mcnt);
13625+#else
13626+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE,
13627+ mcnt);
13628+#endif /* _LIBC */
13629+ goto unconditional_jump;
13630+ }
13631+ /* If don't have to jump any more, skip over the rest of command. */
13632+ else
13633+ p += 2 * OFFSET_ADDRESS_SIZE;
13634+ break;
13635+
13636+ case set_number_at:
13637+ {
13638+ DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
13639+
13640+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
13641+ p1 = p + mcnt;
13642+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
13643+#ifdef _LIBC
13644+ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt);
13645+#else
13646+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
13647+#endif
13648+ STORE_NUMBER (p1, mcnt);
13649+ break;
13650+ }
13651+
13652+#if 0
13653+ /* The DEC Alpha C compiler 3.x generates incorrect code for the
13654+ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of
13655+ AT_WORD_BOUNDARY, so this code is disabled. Expanding the
13656+ macro and introducing temporary variables works around the bug. */
13657+
13658+ case wordbound:
13659+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
13660+ if (AT_WORD_BOUNDARY (d))
13661+ break;
13662+ goto fail;
13663+
13664+ case notwordbound:
13665+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
13666+ if (AT_WORD_BOUNDARY (d))
13667+ goto fail;
13668+ break;
13669+#else
13670+ case wordbound:
13671+ {
13672+ boolean prevchar, thischar;
13673+
13674+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
13675+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
13676+ break;
13677+
13678+ prevchar = WORDCHAR_P (d - 1);
13679+ thischar = WORDCHAR_P (d);
13680+ if (prevchar != thischar)
13681+ break;
13682+ goto fail;
13683+ }
13684+
13685+ case notwordbound:
13686+ {
13687+ boolean prevchar, thischar;
13688+
13689+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
13690+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
13691+ goto fail;
13692+
13693+ prevchar = WORDCHAR_P (d - 1);
13694+ thischar = WORDCHAR_P (d);
13695+ if (prevchar != thischar)
13696+ goto fail;
13697+ break;
13698+ }
13699+#endif
13700+
13701+ case wordbeg:
13702+ DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
13703+ if (!AT_STRINGS_END (d) && WORDCHAR_P (d)
13704+ && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
13705+ break;
13706+ goto fail;
13707+
13708+ case wordend:
13709+ DEBUG_PRINT1 ("EXECUTING wordend.\n");
13710+ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
13711+ && (AT_STRINGS_END (d) || !WORDCHAR_P (d)))
13712+ break;
13713+ goto fail;
13714+
13715+#ifdef emacs
13716+ case before_dot:
13717+ DEBUG_PRINT1 ("EXECUTING before_dot.\n");
13718+ if (PTR_CHAR_POS ((unsigned char *) d) >= point)
13719+ goto fail;
13720+ break;
13721+
13722+ case at_dot:
13723+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
13724+ if (PTR_CHAR_POS ((unsigned char *) d) != point)
13725+ goto fail;
13726+ break;
13727+
13728+ case after_dot:
13729+ DEBUG_PRINT1 ("EXECUTING after_dot.\n");
13730+ if (PTR_CHAR_POS ((unsigned char *) d) <= point)
13731+ goto fail;
13732+ break;
13733+
13734+ case syntaxspec:
13735+ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
13736+ mcnt = *p++;
13737+ goto matchsyntax;
13738+
13739+ case wordchar:
13740+ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
13741+ mcnt = (int) Sword;
13742+ matchsyntax:
13743+ PREFETCH ();
13744+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
13745+ d++;
13746+ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
13747+ goto fail;
13748+ SET_REGS_MATCHED ();
13749+ break;
13750+
13751+ case notsyntaxspec:
13752+ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
13753+ mcnt = *p++;
13754+ goto matchnotsyntax;
13755+
13756+ case notwordchar:
13757+ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
13758+ mcnt = (int) Sword;
13759+ matchnotsyntax:
13760+ PREFETCH ();
13761+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
13762+ d++;
13763+ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
13764+ goto fail;
13765+ SET_REGS_MATCHED ();
13766+ break;
13767+
13768+#else /* not emacs */
13769+ case wordchar:
13770+ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
13771+ PREFETCH ();
13772+ if (!WORDCHAR_P (d))
13773+ goto fail;
13774+ SET_REGS_MATCHED ();
13775+ d++;
13776+ break;
13777+
13778+ case notwordchar:
13779+ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
13780+ PREFETCH ();
13781+ if (WORDCHAR_P (d))
13782+ goto fail;
13783+ SET_REGS_MATCHED ();
13784+ d++;
13785+ break;
13786+#endif /* not emacs */
13787+
13788+ default:
13789+ abort ();
13790+ }
13791+ continue; /* Successfully executed one pattern command; keep going. */
13792+
13793+
13794+ /* We goto here if a matching operation fails. */
13795+ fail:
13796+ if (!FAIL_STACK_EMPTY ())
13797+ { /* A restart point is known. Restore to that state. */
13798+ DEBUG_PRINT1 ("\nFAIL:\n");
13799+ POP_FAILURE_POINT (d, p,
13800+ lowest_active_reg, highest_active_reg,
13801+ regstart, regend, reg_info);
13802+
13803+ /* If this failure point is a dummy, try the next one. */
13804+ if (!p)
13805+ goto fail;
13806+
13807+ /* If we failed to the end of the pattern, don't examine *p. */
13808+ assert (p <= pend);
13809+ if (p < pend)
13810+ {
13811+ boolean is_a_jump_n = false;
13812+
13813+ /* If failed to a backwards jump that's part of a repetition
13814+ loop, need to pop this failure point and use the next one. */
13815+ switch ((re_opcode_t) *p)
13816+ {
13817+ case jump_n:
13818+ is_a_jump_n = true;
13819+ case maybe_pop_jump:
13820+ case pop_failure_jump:
13821+ case jump:
13822+ p1 = p + 1;
13823+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
13824+ p1 += mcnt;
13825+
13826+ if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
13827+ || (!is_a_jump_n
13828+ && (re_opcode_t) *p1 == on_failure_jump))
13829+ goto fail;
13830+ break;
13831+ default:
13832+ /* do nothing */ ;
13833+ }
13834+ }
13835+
13836+ if (d >= string1 && d <= end1)
13837+ dend = end_match_1;
13838+ }
13839+ else
13840+ break; /* Matching at this starting point really fails. */
13841+ } /* for (;;) */
13842+
13843+ if (best_regs_set)
13844+ goto restore_best_regs;
13845+
13846+ FREE_VARIABLES ();
13847+
13848+ return -1; /* Failure to match. */
13849+} /* re_match_2 */
13850+
13851+/* Subroutine definitions for re_match_2. */
13852+
13853+
13854+/* We are passed P pointing to a register number after a start_memory.
13855+
13856+ Return true if the pattern up to the corresponding stop_memory can
13857+ match the empty string, and false otherwise.
13858+
13859+ If we find the matching stop_memory, sets P to point to one past its number.
13860+ Otherwise, sets P to an undefined byte less than or equal to END.
13861+
13862+ We don't handle duplicates properly (yet). */
13863+
13864+static boolean
13865+PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end,
13866+ PREFIX(register_info_type) *reg_info)
13867+{
13868+ int mcnt;
13869+ /* Point to after the args to the start_memory. */
13870+ UCHAR_T *p1 = *p + 2;
13871+
13872+ while (p1 < end)
13873+ {
13874+ /* Skip over opcodes that can match nothing, and return true or
13875+ false, as appropriate, when we get to one that can't, or to the
13876+ matching stop_memory. */
13877+
13878+ switch ((re_opcode_t) *p1)
13879+ {
13880+ /* Could be either a loop or a series of alternatives. */
13881+ case on_failure_jump:
13882+ p1++;
13883+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
13884+
13885+ /* If the next operation is not a jump backwards in the
13886+ pattern. */
13887+
13888+ if (mcnt >= 0)
13889+ {
13890+ /* Go through the on_failure_jumps of the alternatives,
13891+ seeing if any of the alternatives cannot match nothing.
13892+ The last alternative starts with only a jump,
13893+ whereas the rest start with on_failure_jump and end
13894+ with a jump, e.g., here is the pattern for `a|b|c':
13895+
13896+ /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
13897+ /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
13898+ /exactn/1/c
13899+
13900+ So, we have to first go through the first (n-1)
13901+ alternatives and then deal with the last one separately. */
13902+
13903+
13904+ /* Deal with the first (n-1) alternatives, which start
13905+ with an on_failure_jump (see above) that jumps to right
13906+ past a jump_past_alt. */
13907+
13908+ while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] ==
13909+ jump_past_alt)
13910+ {
13911+ /* `mcnt' holds how many bytes long the alternative
13912+ is, including the ending `jump_past_alt' and
13913+ its number. */
13914+
13915+ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt -
13916+ (1 + OFFSET_ADDRESS_SIZE),
13917+ reg_info))
13918+ return false;
13919+
13920+ /* Move to right after this alternative, including the
13921+ jump_past_alt. */
13922+ p1 += mcnt;
13923+
13924+ /* Break if it's the beginning of an n-th alternative
13925+ that doesn't begin with an on_failure_jump. */
13926+ if ((re_opcode_t) *p1 != on_failure_jump)
13927+ break;
13928+
13929+ /* Still have to check that it's not an n-th
13930+ alternative that starts with an on_failure_jump. */
13931+ p1++;
13932+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
13933+ if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] !=
13934+ jump_past_alt)
13935+ {
13936+ /* Get to the beginning of the n-th alternative. */
13937+ p1 -= 1 + OFFSET_ADDRESS_SIZE;
13938+ break;
13939+ }
13940+ }
13941+
13942+ /* Deal with the last alternative: go back and get number
13943+ of the `jump_past_alt' just before it. `mcnt' contains
13944+ the length of the alternative. */
13945+ EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE);
13946+
13947+ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info))
13948+ return false;
13949+
13950+ p1 += mcnt; /* Get past the n-th alternative. */
13951+ } /* if mcnt > 0 */
13952+ break;
13953+
13954+
13955+ case stop_memory:
13956+ assert (p1[1] == **p);
13957+ *p = p1 + 2;
13958+ return true;
13959+
13960+
13961+ default:
13962+ if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info))
13963+ return false;
13964+ }
13965+ } /* while p1 < end */
13966+
13967+ return false;
13968+} /* group_match_null_string_p */
13969+
13970+
13971+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
13972+ It expects P to be the first byte of a single alternative and END one
13973+ byte past the last. The alternative can contain groups. */
13974+
13975+static boolean
13976+PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end,
13977+ PREFIX(register_info_type) *reg_info)
13978+{
13979+ int mcnt;
13980+ UCHAR_T *p1 = p;
13981+
13982+ while (p1 < end)
13983+ {
13984+ /* Skip over opcodes that can match nothing, and break when we get
13985+ to one that can't. */
13986+
13987+ switch ((re_opcode_t) *p1)
13988+ {
13989+ /* It's a loop. */
13990+ case on_failure_jump:
13991+ p1++;
13992+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
13993+ p1 += mcnt;
13994+ break;
13995+
13996+ default:
13997+ if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info))
13998+ return false;
13999+ }
14000+ } /* while p1 < end */
14001+
14002+ return true;
14003+} /* alt_match_null_string_p */
14004+
14005+
14006+/* Deals with the ops common to group_match_null_string_p and
14007+ alt_match_null_string_p.
14008+
14009+ Sets P to one after the op and its arguments, if any. */
14010+
14011+static boolean
14012+PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end,
14013+ PREFIX(register_info_type) *reg_info)
14014+{
14015+ int mcnt;
14016+ boolean ret;
14017+ int reg_no;
14018+ UCHAR_T *p1 = *p;
14019+
14020+ switch ((re_opcode_t) *p1++)
14021+ {
14022+ case no_op:
14023+ case begline:
14024+ case endline:
14025+ case begbuf:
14026+ case endbuf:
14027+ case wordbeg:
14028+ case wordend:
14029+ case wordbound:
14030+ case notwordbound:
14031+#ifdef emacs
14032+ case before_dot:
14033+ case at_dot:
14034+ case after_dot:
14035+#endif
14036+ break;
14037+
14038+ case start_memory:
14039+ reg_no = *p1;
14040+ assert (reg_no > 0 && reg_no <= MAX_REGNUM);
14041+ ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info);
14042+
14043+ /* Have to set this here in case we're checking a group which
14044+ contains a group and a back reference to it. */
14045+
14046+ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
14047+ REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
14048+
14049+ if (!ret)
14050+ return false;
14051+ break;
14052+
14053+ /* If this is an optimized succeed_n for zero times, make the jump. */
14054+ case jump:
14055+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
14056+ if (mcnt >= 0)
14057+ p1 += mcnt;
14058+ else
14059+ return false;
14060+ break;
14061+
14062+ case succeed_n:
14063+ /* Get to the number of times to succeed. */
14064+ p1 += OFFSET_ADDRESS_SIZE;
14065+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
14066+
14067+ if (mcnt == 0)
14068+ {
14069+ p1 -= 2 * OFFSET_ADDRESS_SIZE;
14070+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
14071+ p1 += mcnt;
14072+ }
14073+ else
14074+ return false;
14075+ break;
14076+
14077+ case duplicate:
14078+ if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
14079+ return false;
14080+ break;
14081+
14082+ case set_number_at:
14083+ p1 += 2 * OFFSET_ADDRESS_SIZE;
14084+
14085+ default:
14086+ /* All other opcodes mean we cannot match the empty string. */
14087+ return false;
14088+ }
14089+
14090+ *p = p1;
14091+ return true;
14092+} /* common_op_match_null_string_p */
14093+
14094+
14095+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
14096+ bytes; nonzero otherwise. */
14097+
14098+static int
14099+PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, register int len,
14100+ RE_TRANSLATE_TYPE translate)
14101+{
14102+ register const UCHAR_T *p1 = (const UCHAR_T *) s1;
14103+ register const UCHAR_T *p2 = (const UCHAR_T *) s2;
14104+ while (len)
14105+ {
14106+#ifdef WCHAR
14107+ if (((*p1<=0xff)?translate[*p1++]:*p1++)
14108+ != ((*p2<=0xff)?translate[*p2++]:*p2++))
14109+ return 1;
14110+#else /* BYTE */
14111+ if (translate[*p1++] != translate[*p2++]) return 1;
14112+#endif /* WCHAR */
14113+ len--;
14114+ }
14115+ return 0;
14116+}
14117+
14118+
14119+#else /* not INSIDE_RECURSION */
14120+
14121+/* Entry points for GNU code. */
14122+
14123+/* re_compile_pattern is the GNU regular expression compiler: it
14124+ compiles PATTERN (of length SIZE) and puts the result in BUFP.
14125+ Returns 0 if the pattern was valid, otherwise an error string.
14126+
14127+ Assumes the `allocated' (and perhaps `buffer') and `translate' fields
14128+ are set in BUFP on entry.
14129+
14130+ We call regex_compile to do the actual compilation. */
14131+
14132+const char *
14133+re_compile_pattern (const char *pattern, size_t length,
14134+ struct re_pattern_buffer *bufp)
14135+{
14136+ reg_errcode_t ret;
14137+
14138+ /* GNU code is written to assume at least RE_NREGS registers will be set
14139+ (and at least one extra will be -1). */
14140+ bufp->regs_allocated = REGS_UNALLOCATED;
14141+
14142+ /* And GNU code determines whether or not to get register information
14143+ by passing null for the REGS argument to re_match, etc., not by
14144+ setting no_sub. */
14145+ bufp->no_sub = 0;
14146+
14147+ /* Match anchors at newline. */
14148+ bufp->newline_anchor = 1;
14149+
14150+# ifdef MBS_SUPPORT
14151+ if (MB_CUR_MAX != 1)
14152+ ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp);
14153+ else
14154+# endif
14155+ ret = byte_regex_compile (pattern, length, re_syntax_options, bufp);
14156+
14157+ if (!ret)
14158+ return NULL;
14159+ return gettext (re_error_msgid[(int) ret]);
14160+}
14161+#ifdef _LIBC
14162+weak_alias (__re_compile_pattern, re_compile_pattern)
14163+#endif
14164+
14165+/* Entry points compatible with 4.2 BSD regex library. We don't define
14166+ them unless specifically requested. */
14167+
14168+#if defined _REGEX_RE_COMP || defined _LIBC
14169+
14170+/* BSD has one and only one pattern buffer. */
14171+static struct re_pattern_buffer re_comp_buf;
14172+
14173+char *
14174+#ifdef _LIBC
14175+/* Make these definitions weak in libc, so POSIX programs can redefine
14176+ these names if they don't use our functions, and still use
14177+ regcomp/regexec below without link errors. */
14178+weak_function
14179+#endif
14180+re_comp (const char *s)
14181+{
14182+ reg_errcode_t ret;
14183+
14184+ if (!s)
14185+ {
14186+ if (!re_comp_buf.buffer)
14187+ return (char *) gettext ("No previous regular expression");
14188+ return 0;
14189+ }
14190+
14191+ if (!re_comp_buf.buffer)
14192+ {
14193+ re_comp_buf.buffer = (unsigned char *) malloc (200);
14194+ if (re_comp_buf.buffer == NULL)
14195+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
14196+ re_comp_buf.allocated = 200;
14197+
14198+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
14199+ if (re_comp_buf.fastmap == NULL)
14200+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
14201+ }
14202+
14203+ /* Since `re_exec' always passes NULL for the `regs' argument, we
14204+ don't need to initialize the pattern buffer fields which affect it. */
14205+
14206+ /* Match anchors at newlines. */
14207+ re_comp_buf.newline_anchor = 1;
14208+
14209+# ifdef MBS_SUPPORT
14210+ if (MB_CUR_MAX != 1)
14211+ ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
14212+ else
14213+# endif
14214+ ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
14215+
14216+ if (!ret)
14217+ return NULL;
14218+
14219+ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
14220+ return (char *) gettext (re_error_msgid[(int) ret]);
14221+}
14222+
14223+
14224+int
14225+#ifdef _LIBC
14226+weak_function
14227+#endif
14228+re_exec (const char *s)
14229+{
14230+ const int len = strlen (s);
14231+ return
14232+ 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
14233+}
14234+
14235+#endif /* _REGEX_RE_COMP */
14236+
14237+/* POSIX.2 functions. Don't define these for Emacs. */
14238+
14239+#ifndef emacs
14240+
14241+/* regcomp takes a regular expression as a string and compiles it.
14242+
14243+ PREG is a regex_t *. We do not expect any fields to be initialized,
14244+ since POSIX says we shouldn't. Thus, we set
14245+
14246+ `buffer' to the compiled pattern;
14247+ `used' to the length of the compiled pattern;
14248+ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
14249+ REG_EXTENDED bit in CFLAGS is set; otherwise, to
14250+ RE_SYNTAX_POSIX_BASIC;
14251+ `newline_anchor' to REG_NEWLINE being set in CFLAGS;
14252+ `fastmap' to an allocated space for the fastmap;
14253+ `fastmap_accurate' to zero;
14254+ `re_nsub' to the number of subexpressions in PATTERN.
14255+
14256+ PATTERN is the address of the pattern string.
14257+
14258+ CFLAGS is a series of bits which affect compilation.
14259+
14260+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
14261+ use POSIX basic syntax.
14262+
14263+ If REG_NEWLINE is set, then . and [^...] don't match newline.
14264+ Also, regexec will try a match beginning after every newline.
14265+
14266+ If REG_ICASE is set, then we considers upper- and lowercase
14267+ versions of letters to be equivalent when matching.
14268+
14269+ If REG_NOSUB is set, then when PREG is passed to regexec, that
14270+ routine will report only success or failure, and nothing about the
14271+ registers.
14272+
14273+ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
14274+ the return codes and their meanings.) */
14275+
14276+int
14277+regcomp (regex_t *preg, const char *pattern, int cflags)
14278+{
14279+ reg_errcode_t ret;
14280+ reg_syntax_t syntax
14281+ = (cflags & REG_EXTENDED) ?
14282+ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
14283+
14284+ /* regex_compile will allocate the space for the compiled pattern. */
14285+ preg->buffer = 0;
14286+ preg->allocated = 0;
14287+ preg->used = 0;
14288+
14289+ /* Try to allocate space for the fastmap. */
14290+ preg->fastmap = (char *) malloc (1 << BYTEWIDTH);
14291+
14292+ if (cflags & REG_ICASE)
14293+ {
14294+ int i;
14295+
14296+ preg->translate
14297+ = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
14298+ * sizeof (*(RE_TRANSLATE_TYPE)0));
14299+ if (preg->translate == NULL)
14300+ return (int) REG_ESPACE;
14301+
14302+ /* Map uppercase characters to corresponding lowercase ones. */
14303+ for (i = 0; i < CHAR_SET_SIZE; i++)
14304+ preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
14305+ }
14306+ else
14307+ preg->translate = NULL;
14308+
14309+ /* If REG_NEWLINE is set, newlines are treated differently. */
14310+ if (cflags & REG_NEWLINE)
14311+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */
14312+ syntax &= ~RE_DOT_NEWLINE;
14313+ syntax |= RE_HAT_LISTS_NOT_NEWLINE;
14314+ /* It also changes the matching behavior. */
14315+ preg->newline_anchor = 1;
14316+ }
14317+ else
14318+ preg->newline_anchor = 0;
14319+
14320+ preg->no_sub = !!(cflags & REG_NOSUB);
14321+
14322+ /* POSIX says a null character in the pattern terminates it, so we
14323+ can use strlen here in compiling the pattern. */
14324+# ifdef MBS_SUPPORT
14325+ if (MB_CUR_MAX != 1)
14326+ ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg);
14327+ else
14328+# endif
14329+ ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg);
14330+
14331+ /* POSIX doesn't distinguish between an unmatched open-group and an
14332+ unmatched close-group: both are REG_EPAREN. */
14333+ if (ret == REG_ERPAREN) ret = REG_EPAREN;
14334+
14335+ if (ret == REG_NOERROR && preg->fastmap)
14336+ {
14337+ /* Compute the fastmap now, since regexec cannot modify the pattern
14338+ buffer. */
14339+ if (re_compile_fastmap (preg) == -2)
14340+ {
14341+ /* Some error occurred while computing the fastmap, just forget
14342+ about it. */
14343+ free (preg->fastmap);
14344+ preg->fastmap = NULL;
14345+ }
14346+ }
14347+
14348+ return (int) ret;
14349+}
14350+#ifdef _LIBC
14351+weak_alias (__regcomp, regcomp)
14352+#endif
14353+
14354+
14355+/* regexec searches for a given pattern, specified by PREG, in the
14356+ string STRING.
14357+
14358+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to
14359+ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
14360+ least NMATCH elements, and we set them to the offsets of the
14361+ corresponding matched substrings.
14362+
14363+ EFLAGS specifies `execution flags' which affect matching: if
14364+ REG_NOTBOL is set, then ^ does not match at the beginning of the
14365+ string; if REG_NOTEOL is set, then $ does not match at the end.
14366+
14367+ We return 0 if we find a match and REG_NOMATCH if not. */
14368+
14369+int
14370+regexec (const regex_t *preg, const char *string, size_t nmatch,
14371+ regmatch_t pmatch[], int eflags)
14372+{
14373+ int ret;
14374+ struct re_registers regs;
14375+ regex_t private_preg;
14376+ int len = strlen (string);
14377+ boolean want_reg_info = !preg->no_sub && nmatch > 0;
14378+
14379+ private_preg = *preg;
14380+
14381+ private_preg.not_bol = !!(eflags & REG_NOTBOL);
14382+ private_preg.not_eol = !!(eflags & REG_NOTEOL);
14383+
14384+ /* The user has told us exactly how many registers to return
14385+ information about, via `nmatch'. We have to pass that on to the
14386+ matching routines. */
14387+ private_preg.regs_allocated = REGS_FIXED;
14388+
14389+ if (want_reg_info)
14390+ {
14391+ regs.num_regs = nmatch;
14392+ regs.start = TALLOC (nmatch * 2, regoff_t);
14393+ if (regs.start == NULL)
14394+ return (int) REG_NOMATCH;
14395+ regs.end = regs.start + nmatch;
14396+ }
14397+
14398+ /* Perform the searching operation. */
14399+ ret = re_search (&private_preg, string, len,
14400+ /* start: */ 0, /* range: */ len,
14401+ want_reg_info ? &regs : (struct re_registers *) 0);
14402+
14403+ /* Copy the register information to the POSIX structure. */
14404+ if (want_reg_info)
14405+ {
14406+ if (ret >= 0)
14407+ {
14408+ unsigned r;
14409+
14410+ for (r = 0; r < nmatch; r++)
14411+ {
14412+ pmatch[r].rm_so = regs.start[r];
14413+ pmatch[r].rm_eo = regs.end[r];
14414+ }
14415+ }
14416+
14417+ /* If we needed the temporary register info, free the space now. */
14418+ free (regs.start);
14419+ }
14420+
14421+ /* We want zero return to mean success, unlike `re_search'. */
14422+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
14423+}
14424+#ifdef _LIBC
14425+/* EGLIBC: This is handled in regexec-compat.c. */
14426+/*weak_alias (__regexec, regexec)*/
14427+#include "regexec-compat.c"
14428+#endif
14429+
14430+
14431+/* Returns a message corresponding to an error code, ERRCODE, returned
14432+ from either regcomp or regexec. We don't use PREG here. */
14433+
14434+size_t
14435+regerror (int errcode, const regex_t *preg __attribute__ ((unused)),
14436+ char *errbuf, size_t errbuf_size)
14437+{
14438+ const char *msg;
14439+ size_t msg_size;
14440+
14441+ if (errcode < 0
14442+ || errcode >= (int) (sizeof (re_error_msgid)
14443+ / sizeof (re_error_msgid[0])))
14444+ /* Only error codes returned by the rest of the code should be passed
14445+ to this routine. If we are given anything else, or if other regex
14446+ code generates an invalid error code, then the program has a bug.
14447+ Dump core so we can fix it. */
14448+ abort ();
14449+
14450+ msg = gettext (re_error_msgid[errcode]);
14451+
14452+ msg_size = strlen (msg) + 1; /* Includes the null. */
14453+
14454+ if (errbuf_size != 0)
14455+ {
14456+ if (msg_size > errbuf_size)
14457+ {
14458+#if defined HAVE_MEMPCPY || defined _LIBC
14459+ *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
14460+#else
14461+ memcpy (errbuf, msg, errbuf_size - 1);
14462+ errbuf[errbuf_size - 1] = 0;
14463+#endif
14464+ }
14465+ else
14466+ memcpy (errbuf, msg, msg_size);
14467+ }
14468+
14469+ return msg_size;
14470+}
14471+#ifdef _LIBC
14472+weak_alias (__regerror, regerror)
14473+#endif
14474+
14475+
14476+/* Free dynamically allocated space used by PREG. */
14477+
14478+void
14479+regfree (regex_t *preg)
14480+{
14481+ if (preg->buffer != NULL)
14482+ free (preg->buffer);
14483+ preg->buffer = NULL;
14484+
14485+ preg->allocated = 0;
14486+ preg->used = 0;
14487+
14488+ if (preg->fastmap != NULL)
14489+ free (preg->fastmap);
14490+ preg->fastmap = NULL;
14491+ preg->fastmap_accurate = 0;
14492+
14493+ if (preg->translate != NULL)
14494+ free (preg->translate);
14495+ preg->translate = NULL;
14496+}
14497+#ifdef _LIBC
14498+weak_alias (__regfree, regfree)
14499+#endif
14500+
14501+#endif /* not emacs */
14502+
14503+#endif /* not INSIDE_RECURSION */
14504+
14505+
14506+#undef STORE_NUMBER
14507+#undef STORE_NUMBER_AND_INCR
14508+#undef EXTRACT_NUMBER
14509+#undef EXTRACT_NUMBER_AND_INCR
14510+
14511+#undef DEBUG_PRINT_COMPILED_PATTERN
14512+#undef DEBUG_PRINT_DOUBLE_STRING
14513+
14514+#undef INIT_FAIL_STACK
14515+#undef RESET_FAIL_STACK
14516+#undef DOUBLE_FAIL_STACK
14517+#undef PUSH_PATTERN_OP
14518+#undef PUSH_FAILURE_POINTER
14519+#undef PUSH_FAILURE_INT
14520+#undef PUSH_FAILURE_ELT
14521+#undef POP_FAILURE_POINTER
14522+#undef POP_FAILURE_INT
14523+#undef POP_FAILURE_ELT
14524+#undef DEBUG_PUSH
14525+#undef DEBUG_POP
14526+#undef PUSH_FAILURE_POINT
14527+#undef POP_FAILURE_POINT
14528+
14529+#undef REG_UNSET_VALUE
14530+#undef REG_UNSET
14531+
14532+#undef PATFETCH
14533+#undef PATFETCH_RAW
14534+#undef PATUNFETCH
14535+#undef TRANSLATE
14536+
14537+#undef INIT_BUF_SIZE
14538+#undef GET_BUFFER_SPACE
14539+#undef BUF_PUSH
14540+#undef BUF_PUSH_2
14541+#undef BUF_PUSH_3
14542+#undef STORE_JUMP
14543+#undef STORE_JUMP2
14544+#undef INSERT_JUMP
14545+#undef INSERT_JUMP2
14546+#undef EXTEND_BUFFER
14547+#undef GET_UNSIGNED_NUMBER
14548+#undef FREE_STACK_RETURN
14549+
14550+# undef POINTER_TO_OFFSET
14551+# undef MATCHING_IN_FRST_STRING
14552+# undef PREFETCH
14553+# undef AT_STRINGS_BEG
14554+# undef AT_STRINGS_END
14555+# undef WORDCHAR_P
14556+# undef FREE_VAR
14557+# undef FREE_VARIABLES
14558+# undef NO_HIGHEST_ACTIVE_REG
14559+# undef NO_LOWEST_ACTIVE_REG
14560+
14561+# undef CHAR_T
14562+# undef UCHAR_T
14563+# undef COMPILED_BUFFER_VAR
14564+# undef OFFSET_ADDRESS_SIZE
14565+# undef CHAR_CLASS_SIZE
14566+# undef PREFIX
14567+# undef ARG_PREFIX
14568+# undef PUT_CHAR
14569+# undef BYTE
14570+# undef WCHAR
14571+
14572+# define DEFINED_ONCE
14573diff --git a/pwd/Makefile b/pwd/Makefile
14574index 7f6de03..916d546 100644
14575--- a/pwd/Makefile
14576+++ b/pwd/Makefile
14577@@ -18,6 +18,8 @@
14578 #
14579 # Sub-makefile for pwd portion of the library.
14580 #
14581+include ../option-groups.mak
14582+
14583 subdir := pwd
14584
14585 include ../Makeconfig
14586diff --git a/resolv/Makefile b/resolv/Makefile
14587index 1dcb75f..2e4b630 100644
14588--- a/resolv/Makefile
14589+++ b/resolv/Makefile
14590@@ -18,6 +18,8 @@
14591 #
14592 # Sub-makefile for resolv portion of the library.
14593 #
14594+include ../option-groups.mak
14595+
14596 subdir := resolv
14597
14598 include ../Makeconfig
14599@@ -27,21 +29,22 @@ headers := resolv.h \
14600 arpa/nameser.h arpa/nameser_compat.h \
14601 sys/bitypes.h
14602
14603-routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
14604- res_hconf res_libc res-state
14605+routines-$(OPTION_EGLIBC_INET) \
14606+ += herror inet_addr inet_ntop inet_pton nsap_addr res_init \
14607+ res_hconf res_libc res-state
14608
14609-tests = tst-aton tst-leaks tst-inet_ntop
14610-xtests = tst-leaks2
14611+tests-$(OPTION_EGLIBC_INET) += tst-aton tst-leaks tst-inet_ntop
14612+xtests-$(OPTION_EGLIBC_INET) += tst-leaks2
14613
14614 generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace
14615
14616-extra-libs := libresolv libnss_dns
14617+extra-libs-$(OPTION_EGLIBC_INET) += libresolv libnss_dns
14618 ifeq ($(have-thread-library),yes)
14619-extra-libs += libanl
14620-routines += gai_sigqueue
14621+extra-libs-$(OPTION_EGLIBC_INET_ANL) += libanl
14622+routines-$(OPTION_EGLIBC_INET) += gai_sigqueue
14623 tests += tst-res_hconf_reorder
14624 endif
14625-extra-libs-others = $(extra-libs)
14626+extra-libs-others-y += $(extra-libs-y)
14627 libresolv-routines := gethnamaddr res_comp res_debug \
14628 res_data res_mkquery res_query res_send \
14629 inet_net_ntop inet_net_pton inet_neta base64 \
14630@@ -61,7 +64,7 @@ routines += $(libnss_dns-routines) $(libresolv-routines)
14631 static-only-routines += $(libnss_dns-routines) $(libresolv-routines)
14632 endif
14633
14634-ifeq (yesyes,$(build-shared)$(have-thread-library))
14635+ifeq (yesyesy,$(build-shared)$(have-thread-library)$(OPTION_EGLIBC_INET_ANL))
14636 tests: $(objpfx)ga_test
14637 endif
14638
14639diff --git a/stdio-common/Makefile b/stdio-common/Makefile
14640index d0bf0e1..8655801 100644
14641--- a/stdio-common/Makefile
14642+++ b/stdio-common/Makefile
14643@@ -18,6 +18,8 @@
14644 #
14645 # Specific makefile for stdio-common.
14646 #
14647+include ../option-groups.mak
14648+
14649 subdir := stdio-common
14650
14651 include ../Makeconfig
14652@@ -30,7 +32,7 @@ routines := \
14653 vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \
14654 reg-modifier reg-type \
14655 printf_size fprintf printf snprintf sprintf asprintf dprintf \
14656- vfwprintf vfscanf vfwscanf \
14657+ vfscanf \
14658 fscanf scanf sscanf \
14659 perror psignal \
14660 tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
14661@@ -41,23 +43,36 @@ routines := \
14662 isoc99_vsscanf \
14663 psiginfo
14664
14665-aux := errlist siglist printf-parsemb printf-parsewc fxprintf
14666+# Ideally, _itowa and itowa-digits would be in this option group as
14667+# well, but it is used unconditionally by printf_fp and printf_fphex,
14668+# and it didn't seem straightforward to disentangle it.
14669+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
14670+ += vfwprintf vfwscanf
14671+
14672+aux := errlist siglist printf-parsemb fxprintf
14673+aux-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += printf-parsewc
14674
14675 tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
14676 temptest tst-fileno test-fwrite tst-ungetc tst-ferror \
14677 xbug errnobug \
14678 bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \
14679- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \
14680+ tfformat tiformat tllformat tstdiomisc tst-printfsz \
14681 scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \
14682- scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
14683- tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
14684- tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \
14685+ scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf \
14686+ tst-fseek tst-fmemopen tst-gets \
14687+ tst-sprintf tst-rndseek tst-fdopen tst-fphex \
14688 tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
14689- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
14690- bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
14691- scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
14692- bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
14693+ tst-fwrite bug16 bug17 tst-sprintf2 bug18 \
14694+ bug19 tst-popen2 scanf14 scanf15 bug21 bug22 \
14695+ scanf16 scanf17 tst-setvbuf1 bug23 bug24 \
14696+ bug-vfprintf-nargs tst-sprintf3 \
14697 bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3
14698+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
14699+ += tst-sscanf tst-swprintf test-vfprintf bug14 scanf13 tst-grouping
14700+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
14701+ += tst-perror bug19a bug20 tst-long-dbl-fphex tst-fphex-wide
14702+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
14703+ += bug18a tst-swscanf tst-wc-printf
14704
14705 test-srcs = tst-unbputc tst-printf
14706
14707diff --git a/stdio-common/_i18n_number.h b/stdio-common/_i18n_number.h
14708index 3c73044..ac62b3a 100644
14709--- a/stdio-common/_i18n_number.h
14710+++ b/stdio-common/_i18n_number.h
14711@@ -19,10 +19,13 @@
14712 #include <stdbool.h>
14713 #include <wchar.h>
14714 #include <wctype.h>
14715+#include <gnu/option-groups.h>
14716
14717 #include "../locale/outdigits.h"
14718 #include "../locale/outdigitswc.h"
14719
14720+#if __OPTION_EGLIBC_LOCALE_CODE
14721+
14722 static CHAR_T *
14723 _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
14724 {
14725@@ -115,3 +118,13 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
14726
14727 return w;
14728 }
14729+
14730+#else
14731+
14732+static CHAR_T *
14733+_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
14734+{
14735+ return w;
14736+}
14737+
14738+#endif
14739diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c
14740index 7b2eb94..8476076 100644
14741--- a/stdio-common/fxprintf.c
14742+++ b/stdio-common/fxprintf.c
14743@@ -23,6 +23,7 @@
14744 #include <wchar.h>
14745 #include <string.h>
14746 #include <libioP.h>
14747+#include <gnu/option-groups.h>
14748
14749
14750 int
14751@@ -37,6 +38,7 @@ __fxprintf (FILE *fp, const char *fmt, ...)
14752 int res;
14753 if (_IO_fwide (fp, 0) > 0)
14754 {
14755+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
14756 size_t len = strlen (fmt) + 1;
14757 wchar_t wfmt[len];
14758 for (size_t i = 0; i < len; ++i)
14759@@ -45,6 +47,9 @@ __fxprintf (FILE *fp, const char *fmt, ...)
14760 wfmt[i] = fmt[i];
14761 }
14762 res = __vfwprintf (fp, wfmt, ap);
14763+#else
14764+ abort();
14765+#endif
14766 }
14767 else
14768 res = _IO_vfprintf (fp, fmt, ap);
14769diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
14770index 3023b20..bd0df66 100644
14771--- a/stdio-common/printf_fp.c
14772+++ b/stdio-common/printf_fp.c
14773@@ -39,6 +39,7 @@
14774 #include <unistd.h>
14775 #include <stdlib.h>
14776 #include <wchar.h>
14777+#include <gnu/option-groups.h>
14778 #include <stdbool.h>
14779 #include <rounding-mode.h>
14780
14781@@ -142,6 +143,10 @@ extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
14782 extern unsigned int __guess_grouping (unsigned int intdig_max,
14783 const char *grouping);
14784
14785+/* Ideally, when OPTION_EGLIBC_LOCALE_CODE is disabled, this should do
14786+ all its work in ordinary characters, rather than doing it in wide
14787+ characters and then converting at the end. But that is a challenge
14788+ for another day. */
14789
14790 static wchar_t *group_number (wchar_t *buf, wchar_t *bufend,
14791 unsigned int intdig_no, const char *grouping,
14792@@ -251,7 +256,14 @@ ___printf_fp (FILE *fp,
14793 mp_limb_t cy;
14794
14795 /* Nonzero if this is output on a wide character stream. */
14796+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
14797 int wide = info->wide;
14798+#else
14799+ /* This should never be called on a wide-oriented stream when
14800+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
14801+ be trusted to figure that out. */
14802+ const int wide = 0;
14803+#endif
14804
14805 /* Buffer in which we produce the output. */
14806 wchar_t *wbuffer = NULL;
14807@@ -261,6 +273,7 @@ ___printf_fp (FILE *fp,
14808 p.expsign = 0;
14809
14810 /* Figure out the decimal point character. */
14811+#if __OPTION_EGLIBC_LOCALE_CODE
14812 if (info->extra == 0)
14813 {
14814 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
14815@@ -280,7 +293,13 @@ ___printf_fp (FILE *fp,
14816 /* The decimal point character must not be zero. */
14817 assert (*decimal != '\0');
14818 assert (decimalwc != L'\0');
14819+#else
14820+ /* Hard-code values from 'C' locale. */
14821+ decimal = ".";
14822+ decimalwc = L'.';
14823+#endif
14824
14825+#if __OPTION_EGLIBC_LOCALE_CODE
14826 if (info->group)
14827 {
14828 if (info->extra == 0)
14829@@ -324,6 +343,9 @@ ___printf_fp (FILE *fp,
14830 }
14831 else
14832 grouping = NULL;
14833+#else
14834+ grouping = NULL;
14835+#endif
14836
14837 /* Fetch the argument value. */
14838 #ifndef __NO_LONG_DOUBLE_MATH
14839diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c
14840index 6c3b5e9..f660ce0 100644
14841--- a/stdio-common/printf_fphex.c
14842+++ b/stdio-common/printf_fphex.c
14843@@ -28,6 +28,7 @@
14844 #include <_itoa.h>
14845 #include <_itowa.h>
14846 #include <locale/localeinfo.h>
14847+#include <gnu/option-groups.h>
14848 #include <stdbool.h>
14849 #include <rounding-mode.h>
14850
14851@@ -139,10 +140,18 @@ __printf_fphex (FILE *fp,
14852 int done = 0;
14853
14854 /* Nonzero if this is output on a wide character stream. */
14855+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
14856 int wide = info->wide;
14857+#else
14858+ /* This should never be called on a wide-oriented stream when
14859+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
14860+ be trusted to figure that out. */
14861+ const int wide = 0;
14862+#endif
14863
14864
14865 /* Figure out the decimal point character. */
14866+#if __OPTION_EGLIBC_LOCALE_CODE
14867 if (info->extra == 0)
14868 {
14869 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
14870@@ -156,6 +165,10 @@ __printf_fphex (FILE *fp,
14871 }
14872 /* The decimal point character must never be zero. */
14873 assert (*decimal != '\0' && decimalwc != L'\0');
14874+#else
14875+ decimal = ".";
14876+ decimalwc = L'.';
14877+#endif
14878
14879
14880 /* Fetch the argument value. */
14881diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c
14882index 7dcd58e..6fb7491 100644
14883--- a/stdio-common/printf_size.c
14884+++ b/stdio-common/printf_size.c
14885@@ -23,6 +23,7 @@
14886 #include <math.h>
14887 #include <printf.h>
14888 #include <libioP.h>
14889+#include <gnu/option-groups.h>
14890
14891
14892 /* This defines make it possible to use the same code for GNU C library and
14893@@ -116,7 +117,14 @@ __printf_size (FILE *fp, const struct printf_info *info,
14894
14895 struct printf_info fp_info;
14896 int done = 0;
14897+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
14898 int wide = info->wide;
14899+#else
14900+ /* This should never be called on a wide-oriented stream when
14901+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
14902+ be trusted to figure that out. */
14903+ const int wide = 0;
14904+#endif
14905 int res;
14906
14907 /* Fetch the argument value. */
14908diff --git a/stdio-common/scanf14.c b/stdio-common/scanf14.c
14909index cffccb0..6cc260a 100644
14910--- a/stdio-common/scanf14.c
14911+++ b/stdio-common/scanf14.c
14912@@ -3,6 +3,7 @@
14913 #include <string.h>
14914 #include <wchar.h>
14915 #include <libc-internal.h>
14916+#include <gnu/option-groups.h>
14917
14918 #define FAIL() \
14919 do { \
14920@@ -48,6 +49,7 @@ main (void)
14921 /* See explanation above. */
14922 DIAG_PUSH_NEEDS_COMMENT;
14923 DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
14924+#if __OPTION_EGLIBC_LOCALE_CODE
14925 if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
14926 FAIL ();
14927 else
14928@@ -57,6 +59,7 @@ main (void)
14929 memset (lsp, 'x', sizeof L"3.25");
14930 free (lsp);
14931 }
14932+#endif
14933 if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
14934 FAIL ();
14935 else
14936diff --git a/stdio-common/tst-popen.c b/stdio-common/tst-popen.c
14937index 5def27f..7c9b91e 100644
14938--- a/stdio-common/tst-popen.c
14939+++ b/stdio-common/tst-popen.c
14940@@ -19,6 +19,7 @@
14941 #include <stdio.h>
14942 #include <string.h>
14943 #include <wchar.h>
14944+#include <gnu/option-groups.h>
14945
14946 static int
14947 do_test (void)
14948@@ -34,12 +35,14 @@ do_test (void)
14949 return 1;
14950 }
14951
14952+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
14953 /* POSIX says that pipe streams are byte-oriented. */
14954 if (fwide (f, 0) >= 0)
14955 {
14956 puts ("popen did not return byte-oriented stream");
14957 result = 1;
14958 }
14959+#endif
14960
14961 if (getline (&line, &len, f) != 5)
14962 {
14963diff --git a/stdio-common/tst-sprintf.c b/stdio-common/tst-sprintf.c
14964index d5284b9..f1e3d21 100644
14965--- a/stdio-common/tst-sprintf.c
14966+++ b/stdio-common/tst-sprintf.c
14967@@ -3,7 +3,7 @@
14968 #include <locale.h>
14969 #include <string.h>
14970 #include <libc-internal.h>
14971-
14972+#include <gnu/option-groups.h>
14973
14974 static int
14975 do_test (void)
14976@@ -11,12 +11,14 @@ do_test (void)
14977 char buf[100];
14978 int result = 0;
14979
14980+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
14981 if (sprintf (buf, "%.0ls", L"foo") != 0
14982 || strlen (buf) != 0)
14983 {
14984 puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output");
14985 result = 1;
14986 }
14987+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
14988
14989 #define SIZE (1024*70000)
14990 #define STR(x) #x
14991diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c
14992index 5548a71..31ed024 100644
14993--- a/stdio-common/tstdiomisc.c
14994+++ b/stdio-common/tstdiomisc.c
14995@@ -4,6 +4,7 @@
14996 #include <string.h>
14997 #include <wchar.h>
14998 #include <libc-internal.h>
14999+#include <gnu/option-groups.h>
15000
15001 static int
15002 t1 (void)
15003@@ -134,6 +135,7 @@ F (void)
15004 printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n",
15005 buf);
15006
15007+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
15008 swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
15009 qnanval, qnanval, qnanval, qnanval,
15010 qnanval, qnanval, qnanval, qnanval);
15011@@ -171,6 +173,7 @@ F (void)
15012 result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0;
15013 printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n",
15014 wbuf);
15015+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
15016
15017 lqnanval = NAN;
15018
15019@@ -215,6 +218,7 @@ F (void)
15020 printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n",
15021 buf);
15022
15023+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
15024 swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
15025 L"%La %LA %Le %LE %Lf %LF %Lg %LG",
15026 lqnanval, lqnanval, lqnanval, lqnanval,
15027@@ -259,6 +263,7 @@ F (void)
15028 result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0;
15029 printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n",
15030 wbuf);
15031+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
15032
15033 return result;
15034 }
15035diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
15036index 0592e70..f21d973 100644
15037--- a/stdio-common/vfprintf.c
15038+++ b/stdio-common/vfprintf.c
15039@@ -29,6 +29,7 @@
15040 #include <_itoa.h>
15041 #include <locale/localeinfo.h>
15042 #include <stdio.h>
15043+#include <gnu/option-groups.h>
15044
15045 /* This code is shared between the standard stdio implementation found
15046 in GNU C library and the libio implementation originally found in
15047@@ -140,6 +141,18 @@ typedef wchar_t THOUSANDS_SEP_T;
15048 # define EOF WEOF
15049 #endif
15050
15051+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
15052+# define MULTIBYTE_SUPPORT (1)
15053+#else
15054+# define MULTIBYTE_SUPPORT (0)
15055+#endif
15056+
15057+#if __OPTION_EGLIBC_LOCALE_CODE
15058+# define LOCALE_SUPPORT (1)
15059+#else
15060+# define LOCALE_SUPPORT (0)
15061+#endif
15062+
15063 #include "_i18n_number.h"
15064
15065 /* Include the shared code for parsing the format string. */
15066@@ -1065,8 +1078,11 @@ static const uint8_t jump_table[] =
15067 # define process_string_arg(fspec) \
15068 LABEL (form_character): \
15069 /* Character. */ \
15070- if (is_long) \
15071- goto LABEL (form_wcharacter); \
15072+ if (is_long) \
15073+ { \
15074+ assert (MULTIBYTE_SUPPORT); \
15075+ goto LABEL (form_wcharacter); \
15076+ } \
15077 --width; /* Account for the character itself. */ \
15078 if (!left) \
15079 PAD (' '); \
15080@@ -1079,6 +1095,7 @@ static const uint8_t jump_table[] =
15081 break; \
15082 \
15083 LABEL (form_wcharacter): \
15084+ assert (MULTIBYTE_SUPPORT); \
15085 { \
15086 /* Wide character. */ \
15087 char buf[MB_CUR_MAX]; \
15088@@ -1145,6 +1162,7 @@ static const uint8_t jump_table[] =
15089 } \
15090 else \
15091 { \
15092+ assert (MULTIBYTE_SUPPORT); \
15093 const wchar_t *s2 = (const wchar_t *) string; \
15094 mbstate_t mbstate; \
15095 \
15096@@ -1399,7 +1417,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
15097 LABEL (flag_quote):
15098 group = 1;
15099
15100- if (grouping == (const char *) -1)
15101+ if (! LOCALE_SUPPORT)
15102+ grouping = NULL;
15103+ else if (grouping == (const char *) -1)
15104 {
15105 #ifdef COMPILE_WPRINTF
15106 thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
15107@@ -1728,8 +1748,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
15108 size_t cnt;
15109
15110 CHAR_T *workstart = NULL;
15111-
15112- if (grouping == (const char *) -1)
15113+ if (! LOCALE_SUPPORT)
15114+ grouping = NULL;
15115+ else if (grouping == (const char *) -1)
15116 {
15117 #ifdef COMPILE_WPRINTF
15118 thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
15119diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
15120index 0e204e7..66cc0af 100644
15121--- a/stdio-common/vfscanf.c
15122+++ b/stdio-common/vfscanf.c
15123@@ -29,6 +29,7 @@
15124 #include <wctype.h>
15125 #include <bits/libc-lock.h>
15126 #include <locale/localeinfo.h>
15127+#include <gnu/option-groups.h>
15128
15129 #ifdef __GNUC__
15130 # define HAVE_LONGLONG
15131@@ -133,6 +134,12 @@
15132 # define WINT_T int
15133 #endif
15134
15135+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
15136+# define MULTIBYTE_SUPPORT (1)
15137+#else
15138+# define MULTIBYTE_SUPPORT (0)
15139+#endif
15140+
15141 #define encode_error() do { \
15142 errval = 4; \
15143 __set_errno (EILSEQ); \
15144@@ -316,24 +323,35 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15145 ARGCHECK (s, format);
15146
15147 {
15148-#ifndef COMPILE_WSCANF
15149+#if __OPTION_EGLIBC_LOCALE_CODE && !defined (COMPILE_WSCANF)
15150 struct __locale_data *const curnumeric = loc->__locales[LC_NUMERIC];
15151 #endif
15152
15153+#if __OPTION_EGLIBC_LOCALE_CODE
15154 /* Figure out the decimal point character. */
15155-#ifdef COMPILE_WSCANF
15156+# ifdef COMPILE_WSCANF
15157 decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
15158-#else
15159+# else
15160 decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string;
15161-#endif
15162+# endif
15163 /* Figure out the thousands separator character. */
15164-#ifdef COMPILE_WSCANF
15165+# ifdef COMPILE_WSCANF
15166 thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
15167-#else
15168+# else
15169 thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string;
15170 if (*thousands == '\0')
15171 thousands = NULL;
15172-#endif
15173+# endif
15174+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */
15175+ /* Hard-code values from the C locale. */
15176+# ifdef COMPILE_WSCANF
15177+ decimal = L'.';
15178+ thousands = L'\0';
15179+# else
15180+ decimal = ".";
15181+ thousands = NULL;
15182+# endif
15183+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
15184 }
15185
15186 /* Lock the stream. */
15187@@ -385,6 +403,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15188 #ifndef COMPILE_WSCANF
15189 if (!isascii ((unsigned char) *f))
15190 {
15191+ assert (MULTIBYTE_SUPPORT);
15192+
15193 /* Non-ASCII, may be a multibyte. */
15194 int len = __mbrlen (f, strlen (f), &state);
15195 if (len > 0)
15196@@ -830,6 +850,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15197 }
15198 /* FALLTHROUGH */
15199 case L_('C'):
15200+ assert (MULTIBYTE_SUPPORT);
15201+
15202 if (width == -1)
15203 width = 1;
15204
15205@@ -1172,6 +1194,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15206 /* FALLTHROUGH */
15207
15208 case L_('S'):
15209+ assert (MULTIBYTE_SUPPORT);
15210+
15211 {
15212 #ifndef COMPILE_WSCANF
15213 mbstate_t cstate;
15214@@ -1419,10 +1443,17 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15215 const char *mbdigits[10];
15216 const char *mbdigits_extended[10];
15217 #endif
15218+#if __OPTION_EGLIBC_LOCALE_CODE
15219 /* "to_inpunct" is a map from ASCII digits to their
15220 equivalent in locale. This is defined for locales
15221 which use an extra digits set. */
15222 wctrans_t map = __wctrans ("to_inpunct");
15223+#else
15224+ /* This will always be the case when
15225+ OPTION_EGLIBC_LOCALE_CODE is disabled, but the
15226+ compiler can't figure that out. */
15227+ wctrans_t map = NULL;
15228+#endif
15229 int n;
15230
15231 from_level = 0;
15232@@ -2088,6 +2119,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15233 --width;
15234 }
15235
15236+#if __OPTION_EGLIBC_LOCALE_CODE
15237 wctrans_t map;
15238 if (__builtin_expect ((flags & I18N) != 0, 0)
15239 /* Hexadecimal floats make no sense, fixing localized
15240@@ -2304,6 +2336,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15241 ;
15242 #endif
15243 }
15244+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
15245
15246 /* Have we read any character? If we try to read a number
15247 in hexadecimal notation and we have read only the `0x'
15248@@ -2343,7 +2376,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15249
15250 case L_('['): /* Character class. */
15251 if (flags & LONG)
15252- STRING_ARG (wstr, wchar_t, 100);
15253+ {
15254+ assert (MULTIBYTE_SUPPORT);
15255+ STRING_ARG (wstr, wchar_t, 100);
15256+ }
15257 else
15258 STRING_ARG (str, char, 100);
15259
15260@@ -2417,6 +2453,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
15261 if (flags & LONG)
15262 {
15263 size_t now = read_in;
15264+ assert (MULTIBYTE_SUPPORT);
15265 #ifdef COMPILE_WSCANF
15266 if (__glibc_unlikely (inchar () == WEOF))
15267 input_error ();
15268diff --git a/stdlib/Makefile b/stdlib/Makefile
15269index 402466a..7e7e304 100644
15270--- a/stdlib/Makefile
15271+++ b/stdlib/Makefile
15272@@ -18,6 +18,8 @@
15273 #
15274 # Makefile for stdlib routines
15275 #
15276+include ../option-groups.mak
15277+
15278 subdir := stdlib
15279
15280 include ../Makeconfig
15281@@ -30,7 +32,7 @@ headers := stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h \
15282 alloca.h fmtmsg.h \
15283 bits/stdlib-bsearch.h
15284
15285-routines := \
15286+routines-y := \
15287 atof atoi atol atoll \
15288 abort \
15289 bsearch qsort msort \
15290@@ -39,7 +41,6 @@ routines := \
15291 quick_exit at_quick_exit cxa_at_quick_exit cxa_thread_atexit_impl \
15292 abs labs llabs \
15293 div ldiv lldiv \
15294- mblen mbstowcs mbtowc wcstombs wctomb \
15295 random random_r rand rand_r \
15296 drand48 erand48 lrand48 nrand48 mrand48 jrand48 \
15297 srand48 seed48 lcong48 \
15298@@ -52,9 +53,18 @@ routines := \
15299 strtof_l strtod_l strtold_l \
15300 system canonicalize \
15301 a64l l64a \
15302- rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \
15303- strtoimax strtoumax wcstoimax wcstoumax \
15304+ getsubopt xpg_basename \
15305+ strtoimax strtoumax \
15306 getcontext setcontext makecontext swapcontext
15307+routines-$(OPTION_EGLIBC_LOCALE_CODE) += \
15308+ strfmon strfmon_l
15309+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \
15310+ mblen mbstowcs mbtowc wcstombs wctomb \
15311+ wcstoimax wcstoumax
15312+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP))
15313+routines-y += rpmatch
15314+endif
15315+routines-$(OPTION_EGLIBC_FMTMSG) += fmtmsg
15316 aux = grouping groupingwc tens_in_limb
15317
15318 # These routines will be omitted from the libc shared object.
15319@@ -62,20 +72,24 @@ aux = grouping groupingwc tens_in_limb
15320 # linked against when the shared library will be used.
15321 static-only-routines = atexit at_quick_exit
15322
15323-test-srcs := tst-fmtmsg
15324-tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
15325+test-srcs-$(OPTION_EGLIBC_FMTMSG) := tst-fmtmsg
15326+tests := tst-strtol tst-strtod testrand testsort testdiv \
15327 test-canon test-canon2 tst-strtoll tst-environ \
15328 tst-xpg-basename tst-random tst-random2 tst-bsearch \
15329 tst-limits tst-rand48 bug-strtod tst-setcontext \
15330- tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \
15331- bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 \
15332- tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5 \
15333+ tst-setcontext2 test-a64l tst-qsort tst-system \
15334+ bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \
15335+ tst-rand48-2 tst-makecontext \
15336 tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
15337 tst-makecontext3 bug-getcontext bug-fmtmsg1 \
15338 tst-secure-getenv tst-strtod-overflow tst-strtod-round \
15339 tst-tininess tst-strtod-underflow tst-tls-atexit \
15340 tst-setcontext3 tst-tls-atexit-nodelete
15341 tests-static := tst-secure-getenv
15342+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
15343+ += tst-strtod3 tst-strtod4 tst-strtod5 testmb2
15344+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
15345+ += testmb
15346
15347 modules-names = tst-tls-atexit-lib
15348
15349@@ -116,8 +130,10 @@ CFLAGS-tst-makecontext2.c = $(stack-align-test-flags)
15350 tests-special += $(objpfx)isomac.out
15351
15352 ifeq ($(run-built-tests),yes)
15353+ifeq (y,$(OPTION_EGLIBC_FMTMSG))
15354 tests-special += $(objpfx)tst-fmtmsg.out
15355 endif
15356+endif
15357
15358 include ../Rules
15359
15360diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
15361index e13ab1e..63efe41 100644
15362--- a/stdlib/strtod_l.c
15363+++ b/stdlib/strtod_l.c
15364@@ -17,6 +17,7 @@
15365 License along with the GNU C Library; if not, see
15366 <http://www.gnu.org/licenses/>. */
15367
15368+#include <gnu/option-groups.h>
15369 #include <xlocale.h>
15370
15371 extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
15372@@ -548,6 +549,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
15373 /* Used in several places. */
15374 int cnt;
15375
15376+#if __OPTION_EGLIBC_LOCALE_CODE
15377 struct __locale_data *current = loc->__locales[LC_NUMERIC];
15378
15379 if (__glibc_unlikely (group))
15380@@ -586,6 +588,17 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
15381 decimal_len = strlen (decimal);
15382 assert (decimal_len > 0);
15383 #endif
15384+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */
15385+ /* Hard-code values from the 'C' locale. */
15386+ grouping = NULL;
15387+#ifdef USE_WIDE_CHAR
15388+ decimal = L'.';
15389+# define decimal_len 1
15390+#else
15391+ decimal = ".";
15392+ decimal_len = 1;
15393+#endif
15394+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
15395
15396 /* Prepare number representation. */
15397 exponent = 0;
15398diff --git a/stdlib/tst-strtod.c b/stdlib/tst-strtod.c
15399index a469208..28fb423 100644
15400--- a/stdlib/tst-strtod.c
15401+++ b/stdlib/tst-strtod.c
15402@@ -23,6 +23,7 @@
15403 #include <errno.h>
15404 #include <string.h>
15405 #include <math.h>
15406+#include <gnu/option-groups.h>
15407
15408 struct ltest
15409 {
15410@@ -176,7 +177,9 @@ main (int argc, char ** argv)
15411
15412 status |= long_dbl ();
15413
15414+#if __OPTION_EGLIBC_LOCALE_CODE
15415 status |= locale_test ();
15416+#endif
15417
15418 return status ? EXIT_FAILURE : EXIT_SUCCESS;
15419 }
15420@@ -219,6 +222,7 @@ long_dbl (void)
15421 return 0;
15422 }
15423
15424+#if __OPTION_EGLIBC_LOCALE_CODE
15425 /* Perform a few tests in a locale with thousands separators. */
15426 static int
15427 locale_test (void)
15428@@ -276,3 +280,4 @@ locale_test (void)
15429
15430 return result;
15431 }
15432+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
15433diff --git a/streams/Makefile b/streams/Makefile
15434index a8a6162..ceb423f 100644
15435--- a/streams/Makefile
15436+++ b/streams/Makefile
15437@@ -18,11 +18,14 @@
15438 #
15439 # Makefile for streams.
15440 #
15441+include ../option-groups.mak
15442+
15443 subdir := streams
15444
15445 include ../Makeconfig
15446
15447 headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
15448-routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
15449+routines-$(OPTION_EGLIBC_STREAMS) \
15450+ += isastream getmsg getpmsg putmsg putpmsg fattach fdetach
15451
15452 include ../Rules
15453diff --git a/string/Makefile b/string/Makefile
15454index 8424a61..5988834 100644
15455--- a/string/Makefile
15456+++ b/string/Makefile
15457@@ -18,6 +18,8 @@
15458 #
15459 # Sub-makefile for string portion of library.
15460 #
15461+include ../option-groups.mak
15462+
15463 subdir := string
15464
15465 include ../Makeconfig
15466@@ -39,10 +41,12 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \
15467 $(addprefix argz-,append count create ctsep next \
15468 delete extract insert stringify \
15469 addsep replace) \
15470- envz basename \
15471+ basename \
15472 strcoll_l strxfrm_l string-inlines memrchr \
15473 xpg-strerror strerror_l
15474
15475+routines-$(OPTION_EGLIBC_ENVZ) += envz
15476+
15477 strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \
15478 stpcpy stpncpy strcat strchr strcmp strcpy strcspn \
15479 strlen strncmp strncpy strpbrk strrchr strspn memmem \
15480@@ -51,10 +55,12 @@ strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \
15481 tests := tester inl-tester noinl-tester testcopy test-ffs \
15482 tst-strlen stratcliff tst-svc tst-inlcall \
15483 bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
15484- tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \
15485+ tst-strtok tst-strfry \
15486 bug-strtok1 $(addprefix test-,$(strop-tests)) \
15487- bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \
15488- tst-strtok_r
15489+ tst-strxfrm2 tst-endian tst-svc2 tst-strtok_r
15490+tests-$(OPTION_EGLIBC_ENVZ) += bug-envz1
15491+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
15492+ += tst-strxfrm bug-strcoll1
15493
15494 xtests = tst-strcoll-overflow
15495
15496diff --git a/string/strcoll_l.c b/string/strcoll_l.c
15497index 8f1225f..b36b18c 100644
15498--- a/string/strcoll_l.c
15499+++ b/string/strcoll_l.c
15500@@ -24,6 +24,7 @@
15501 #include <stdint.h>
15502 #include <string.h>
15503 #include <sys/param.h>
15504+#include <gnu/option-groups.h>
15505
15506 #ifndef STRING_TYPE
15507 # define STRING_TYPE char
15508@@ -260,7 +261,11 @@ int
15509 STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
15510 {
15511 struct __locale_data *current = l->__locales[LC_COLLATE];
15512+#if __OPTION_EGLIBC_LOCALE_CODE
15513 uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
15514+#else
15515+ const uint_fast32_t nrules = 0;
15516+#endif
15517 /* We don't assign the following values right away since it might be
15518 unnecessary in case there are no rules. */
15519 const unsigned char *rulesets;
15520diff --git a/string/strerror_l.c b/string/strerror_l.c
15521index 2ed78b5..6584813 100644
15522--- a/string/strerror_l.c
15523+++ b/string/strerror_l.c
15524@@ -21,6 +21,7 @@
15525 #include <stdlib.h>
15526 #include <string.h>
15527 #include <sys/param.h>
15528+#include <gnu/option-groups.h>
15529
15530
15531 static __thread char *last_value;
15532@@ -29,10 +30,14 @@ static __thread char *last_value;
15533 static const char *
15534 translate (const char *str, locale_t loc)
15535 {
15536+#if __OPTION_EGLIBC_LOCALE_CODE
15537 locale_t oldloc = __uselocale (loc);
15538 const char *res = _(str);
15539 __uselocale (oldloc);
15540 return res;
15541+#else
15542+ return str;
15543+#endif
15544 }
15545
15546
15547diff --git a/string/strxfrm_l.c b/string/strxfrm_l.c
15548index 8b61ea2..41fdc22 100644
15549--- a/string/strxfrm_l.c
15550+++ b/string/strxfrm_l.c
15551@@ -24,6 +24,7 @@
15552 #include <stdlib.h>
15553 #include <string.h>
15554 #include <sys/param.h>
15555+#include <gnu/option-groups.h>
15556
15557 #ifndef STRING_TYPE
15558 # define STRING_TYPE char
15559@@ -669,7 +670,11 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
15560 {
15561 locale_data_t l_data;
15562 struct __locale_data *current = l->__locales[LC_COLLATE];
15563+#if __OPTION_EGLIBC_LOCALE_CODE
15564 l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
15565+#else
15566+ l_data.nrules = 0;
15567+#endif
15568
15569 /* Handle byte comparison case. */
15570 if (l_data.nrules == 0)
15571diff --git a/string/test-strcmp.c b/string/test-strcmp.c
15572index dc4ba6f..a978656 100644
15573--- a/string/test-strcmp.c
15574+++ b/string/test-strcmp.c
15575@@ -329,34 +329,6 @@ check (void)
15576 FOR_EACH_IMPL (impl, 0)
15577 check_result (impl, s1 + i1, s2 + i2, exp_result);
15578 }
15579-
15580- /* Test cases where there are multiple zero bytes after the first. */
15581-
15582- for (size_t i = 0; i < 16 + 1; i++)
15583- {
15584- s1[i] = 0x00;
15585- s2[i] = 0x00;
15586- }
15587-
15588- for (size_t i = 0; i < 16; i++)
15589- {
15590- int exp_result;
15591-
15592- for (int val = 0x01; val < 0x100; val++)
15593- {
15594- for (size_t j = 0; j < i; j++)
15595- {
15596- s1[j] = val;
15597- s2[j] = val;
15598- }
15599-
15600- s2[i] = val;
15601-
15602- exp_result = SIMPLE_STRCMP (s1, s2);
15603- FOR_EACH_IMPL (impl, 0)
15604- check_result (impl, s1, s2, exp_result);
15605- }
15606- }
15607 }
15608
15609
15610diff --git a/string/tst-strxfrm.c b/string/tst-strxfrm.c
15611index f48cfc0..c3a51f9 100644
15612--- a/string/tst-strxfrm.c
15613+++ b/string/tst-strxfrm.c
15614@@ -3,6 +3,7 @@
15615 #include <stdio.h>
15616 #include <stdlib.h>
15617 #include <string.h>
15618+#include <gnu/option-groups.h>
15619
15620
15621 char const string[] = "";
15622@@ -64,8 +65,10 @@ do_test (void)
15623 int result = 0;
15624
15625 result |= test ("C");
15626+#if __OPTION_EGLIBC_LOCALE_CODE
15627 result |= test ("en_US.ISO-8859-1");
15628 result |= test ("de_DE.UTF-8");
15629+#endif
15630
15631 return result;
15632 }
15633diff --git a/string/tst-strxfrm2.c b/string/tst-strxfrm2.c
15634index d5a1115..19c7f30 100644
15635--- a/string/tst-strxfrm2.c
15636+++ b/string/tst-strxfrm2.c
15637@@ -1,6 +1,7 @@
15638 #include <locale.h>
15639 #include <stdio.h>
15640 #include <string.h>
15641+#include <gnu/option-groups.h>
15642
15643 static int
15644 do_test (void)
15645@@ -38,6 +39,7 @@ do_test (void)
15646 res = 1;
15647 }
15648
15649+#if __OPTION_EGLIBC_LOCALE_CODE
15650 if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
15651 {
15652 puts ("setlocale failed");
15653@@ -75,6 +77,7 @@ do_test (void)
15654 res = 1;
15655 }
15656 }
15657+#endif
15658
15659 return res;
15660 }
15661diff --git a/sunrpc/Makefile b/sunrpc/Makefile
15662index 60caa0a..5bc70ab 100644
15663--- a/sunrpc/Makefile
15664+++ b/sunrpc/Makefile
15665@@ -18,6 +18,8 @@
15666 #
15667 # Sub-makefile for sunrpc portion of the library.
15668 #
15669+include ../option-groups.mak
15670+
15671 subdir := sunrpc
15672
15673 include ../Makeconfig
15674@@ -55,7 +57,6 @@ headers-in-tirpc = $(addprefix rpc/,auth.h auth_unix.h clnt.h pmap_clnt.h \
15675 headers-not-in-tirpc = $(addprefix rpc/,key_prot.h rpc_des.h) \
15676 $(rpcsvc:%=rpcsvc/%) rpcsvc/bootparam.h
15677 headers = rpc/netdb.h
15678-install-others = $(inst_sysconfdir)/rpc
15679 generated += $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \
15680 $(rpcsvc:%.x=rpcsvc/%.stmp) rpcgen
15681 generated-dirs += rpcsvc
15682@@ -65,20 +66,28 @@ headers += $(headers-in-tirpc) $(headers-not-in-tirpc)
15683 endif
15684
15685 ifeq ($(build-shared),yes)
15686-need-export-routines := auth_des auth_unix clnt_gen clnt_perr clnt_tcp \
15687+need-export-routines-$(OPTION_EGLIBC_SUNRPC) := \
15688+ auth_des auth_unix clnt_gen clnt_perr clnt_tcp \
15689 clnt_udp get_myaddr key_call netname pm_getport \
15690- rpc_thread svc svc_tcp svc_udp xcrypt xdr_array xdr \
15691+ rpc_thread svc svc_tcp svc_udp xdr_array xdr \
15692 xdr_intXX_t xdr_mem xdr_ref xdr_sizeof xdr_stdio \
15693 svc_run
15694+need-export-routines-y += xcrypt
15695+need-export-routines := $(need-export-routines-y)
15696
15697-routines := auth_none authuxprot bindrsvprt clnt_raw clnt_simp \
15698+routines-$(OPTION_EGLIBC_SUNRPC) := \
15699+ auth_none authuxprot bindrsvprt clnt_raw clnt_simp \
15700 rpc_dtable getrpcport pmap_clnt pm_getmaps pmap_prot pmap_prot2 \
15701 pmap_rmt rpc_prot rpc_common rpc_cmsg svc_auth svc_authux svc_raw \
15702 svc_simple xdr_float xdr_rec publickey authdes_prot \
15703- des_crypt des_impl des_soft key_prot openchild rtime svcauth_des \
15704+ key_prot openchild rtime svcauth_des \
15705 getrpcent getrpcbyname getrpcbynumber \
15706 getrpcent_r getrpcbyname_r getrpcbynumber_r \
15707- clnt_unix svc_unix create_xid $(need-export-routines)
15708+ clnt_unix svc_unix create_xid
15709+
15710+# xdecrypt is also used by nss/nss_files/files-key.c.
15711+routines-y += des_crypt des_impl des_soft $(need-export-routines)
15712+
15713 ifneq ($(link-obsolete-rpc),yes)
15714 # We only add the RPC for compatibility to libc.so.
15715 shared-only-routines = $(routines)
15716@@ -87,25 +96,28 @@ endif
15717
15718 # We do not build rpcinfo anymore. It is not needed for a bootstrap
15719 # and not wanted on complete systems.
15720-# others := rpcinfo
15721-# install-sbin := rpcinfo
15722-install-bin := rpcgen
15723+# others-$(OPTION_EGLIBC_SUNRPC) += rpcinfo
15724+# install-sbin-$(OPTION_EGLIBC_SUNRPC) += rpcinfo
15725+install-bin-$(OPTION_EGLIBC_SUNRPC) += rpcgen
15726 rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \
15727 rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \
15728 rpc_tblout.o rpc_sample.o
15729-extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs))
15730-others += rpcgen
15731+extra-objs-$(OPTION_EGLIBC_SUNRPC) = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs))
15732+others-$(OPTION_EGLIBC_SUNRPC) += rpcgen
15733+
15734+install-others-$(OPTION_EGLIBC_SUNRPC) += $(inst_sysconfdir)/rpc
15735
15736-tests = tst-xdrmem tst-xdrmem2 test-rpcent
15737-xtests := tst-getmyaddr
15738+tests-$(OPTION_EGLIBC_SUNRPC) = tst-xdrmem tst-xdrmem2 test-rpcent
15739+xtests-$(OPTION_EGLIBC_SUNRPC) := tst-getmyaddr
15740
15741 ifeq ($(have-thread-library),yes)
15742-xtests += thrsvc
15743+xtests-$(OPTION_EGLIBC_SUNRPC) += thrsvc
15744 endif
15745
15746 headers += $(rpcsvc:%.x=rpcsvc/%.h)
15747-extra-libs := librpcsvc
15748-extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass.
15749+extra-libs-$(OPTION_EGLIBC_SUNRPC) += librpcsvc
15750+# Make it in `others' pass, not `lib' pass.
15751+extra-libs-others-y += $(extra-libs-y)
15752 librpcsvc-routines = $(rpcsvc:%.x=x%)
15753 librpcsvc-inhibit-o = .os # Build no shared rpcsvc library.
15754 omit-deps = $(librpcsvc-routines)
15755diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile
15756index 17c129b..543791a 100644
15757--- a/sysdeps/arm/Makefile
15758+++ b/sysdeps/arm/Makefile
15759@@ -37,10 +37,13 @@ ifeq ($(subdir),csu)
15760 # get offset to rtld_global._dl_hwcap
15761 gen-as-const-headers += rtld-global-offsets.sym tlsdesc.sym
15762 aeabi_constants = aeabi_lcsts aeabi_sighandlers aeabi_math
15763-aeabi_routines = aeabi_assert aeabi_localeconv aeabi_errno_addr \
15764+aeabi_routines = aeabi_assert aeabi_errno_addr \
15765 aeabi_mb_cur_max aeabi_atexit aeabi_memclr aeabi_memcpy \
15766 aeabi_memmove aeabi_memset \
15767 aeabi_read_tp libc-aeabi_read_tp
15768+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
15769+aeabi_routines += aeabi_localeconv
15770+endif
15771
15772 sysdep_routines += $(aeabi_constants) $(aeabi_routines)
15773 static-only-routines += $(aeabi_constants) aeabi_read_tp
15774diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
15775index 7a0fe8d..a3e2c0a 100644
15776--- a/sysdeps/generic/ldsodefs.h
15777+++ b/sysdeps/generic/ldsodefs.h
15778@@ -435,6 +435,12 @@ extern struct rtld_global _rtld_global __rtld_global_attribute__;
15779 # undef __rtld_global_attribute__
15780 #endif
15781
15782+#if __OPTION_EGLIBC_RTLD_DEBUG
15783+# define GLRO_dl_debug_mask GLRO(dl_debug_mask)
15784+#else
15785+# define GLRO_dl_debug_mask 0
15786+#endif
15787+
15788 #ifndef SHARED
15789 # define GLRO(name) _##name
15790 #else
15791@@ -447,8 +453,10 @@ struct rtld_global_ro
15792 {
15793 #endif
15794
15795+#if __OPTION_EGLIBC_RTLD_DEBUG
15796 /* If nonzero the appropriate debug information is printed. */
15797 EXTERN int _dl_debug_mask;
15798+#endif
15799 #define DL_DEBUG_LIBS (1 << 0)
15800 #define DL_DEBUG_IMPCALLS (1 << 1)
15801 #define DL_DEBUG_BINDINGS (1 << 2)
15802diff --git a/sysdeps/gnu/Makefile b/sysdeps/gnu/Makefile
15803index ea68037..3175cc3 100644
15804--- a/sysdeps/gnu/Makefile
15805+++ b/sysdeps/gnu/Makefile
15806@@ -59,7 +59,8 @@ $(foreach o,$(object-suffixes) $(object-suffixes:=.d),\
15807 endif
15808
15809 ifeq ($(subdir),login)
15810-sysdep_routines += setutxent getutxent endutxent getutxid getutxline \
15811+sysdep_routines-$(OPTION_EGLIBC_UTMPX) \
15812+ += setutxent getutxent endutxent getutxid getutxline \
15813 pututxline utmpxname updwtmpx getutmpx getutmp
15814
15815 sysdep_headers += utmpx.h bits/utmpx.h
15816diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile
15817index 222122d..4509357 100644
15818--- a/sysdeps/ieee754/ldbl-opt/Makefile
15819+++ b/sysdeps/ieee754/ldbl-opt/Makefile
15820@@ -11,19 +11,18 @@ libm-routines += s_nexttowardfd
15821 routines += math_ldbl_opt nldbl-compat
15822
15823 extra-libs += libnldbl
15824-libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \
15825+libnldbl-calls = asprintf dprintf fprintf fscanf iovfscanf \
15826 obstack_printf obstack_vprintf printf scanf snprintf \
15827- sprintf sscanf swprintf swscanf vasprintf vdprintf vfprintf \
15828- vfscanf vfwprintf vfwscanf vprintf vscanf vsnprintf \
15829- vsprintf vsscanf vswprintf vswscanf vwprintf vwscanf \
15830- wprintf wscanf printf_fp printf_size \
15831- fprintf_chk fwprintf_chk printf_chk snprintf_chk sprintf_chk \
15832- swprintf_chk vfprintf_chk vfwprintf_chk vprintf_chk \
15833- vsnprintf_chk vsprintf_chk vswprintf_chk vwprintf_chk \
15834- wprintf_chk asprintf_chk vasprintf_chk dprintf_chk \
15835+ sprintf sscanf vasprintf vdprintf vfprintf \
15836+ vfscanf vprintf vscanf vsnprintf \
15837+ vsprintf vsscanf \
15838+ printf_fp printf_size \
15839+ fprintf_chk printf_chk snprintf_chk sprintf_chk \
15840+ vfprintf_chk vprintf_chk \
15841+ vsnprintf_chk vsprintf_chk \
15842+ asprintf_chk vasprintf_chk dprintf_chk \
15843 vdprintf_chk obstack_printf_chk obstack_vprintf_chk \
15844 syslog syslog_chk vsyslog vsyslog_chk \
15845- strfmon strfmon_l \
15846 strtold strtold_l strtoldint wcstold wcstold_l wcstoldint \
15847 qecvt qfcvt qgcvt qecvt_r qfcvt_r \
15848 isinf isnan finite signbit scalb log2 lgamma_r ceil \
15849@@ -38,9 +37,15 @@ libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \
15850 casinh cexp clog cproj csin csinh csqrt ctan ctanh cpow \
15851 cabs carg cimag creal clog10 \
15852 isoc99_scanf isoc99_fscanf isoc99_sscanf \
15853- isoc99_vscanf isoc99_vfscanf isoc99_vsscanf \
15854+ isoc99_vscanf isoc99_vfscanf isoc99_vsscanf
15855+libnldbl-calls-$(OPTION_EGLIBC_LOCALE_CODE) += strfmon strfmon_l
15856+libnldbl-calls-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += fwprintf fwscanf \
15857+ swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf \
15858+ vwprintf vwscanf wprintf wscanf fwprintf_chk swprintf_chk \
15859+ vfwprintf_chk vswprintf_chk vwprintf_chk wprintf_chk \
15860 isoc99_wscanf isoc99_fwscanf isoc99_swscanf \
15861 isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf
15862+libnldbl-calls += $(libnldbl-calls-y)
15863 libnldbl-routines = $(libnldbl-calls:%=nldbl-%)
15864 libnldbl-inhibit-o = $(object-suffixes)
15865 libnldbl-static-only-routines = $(libnldbl-routines)
15866diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
15867index 0198886..55501cd 100644
15868--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
15869+++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
15870@@ -26,6 +26,7 @@
15871 #include <locale/localeinfo.h>
15872 #include <sys/syslog.h>
15873 #include <bits/libc-lock.h>
15874+#include <gnu/option-groups.h>
15875
15876 #include "nldbl-compat.h"
15877
15878@@ -33,20 +34,14 @@ libc_hidden_proto (__nldbl_vfprintf)
15879 libc_hidden_proto (__nldbl_vsscanf)
15880 libc_hidden_proto (__nldbl_vsprintf)
15881 libc_hidden_proto (__nldbl_vfscanf)
15882-libc_hidden_proto (__nldbl_vfwscanf)
15883 libc_hidden_proto (__nldbl_vdprintf)
15884-libc_hidden_proto (__nldbl_vswscanf)
15885-libc_hidden_proto (__nldbl_vfwprintf)
15886-libc_hidden_proto (__nldbl_vswprintf)
15887 libc_hidden_proto (__nldbl_vsnprintf)
15888 libc_hidden_proto (__nldbl_vasprintf)
15889 libc_hidden_proto (__nldbl_obstack_vprintf)
15890-libc_hidden_proto (__nldbl___vfwprintf_chk)
15891 libc_hidden_proto (__nldbl___vsnprintf_chk)
15892 libc_hidden_proto (__nldbl___vfprintf_chk)
15893 libc_hidden_proto (__nldbl___vsyslog_chk)
15894 libc_hidden_proto (__nldbl___vsprintf_chk)
15895-libc_hidden_proto (__nldbl___vswprintf_chk)
15896 libc_hidden_proto (__nldbl___vasprintf_chk)
15897 libc_hidden_proto (__nldbl___vdprintf_chk)
15898 libc_hidden_proto (__nldbl___obstack_vprintf_chk)
15899@@ -54,8 +49,17 @@ libc_hidden_proto (__nldbl___vstrfmon)
15900 libc_hidden_proto (__nldbl___vstrfmon_l)
15901 libc_hidden_proto (__nldbl___isoc99_vsscanf)
15902 libc_hidden_proto (__nldbl___isoc99_vfscanf)
15903+
15904+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
15905+libc_hidden_proto (__nldbl_vfwscanf)
15906+libc_hidden_proto (__nldbl_vswscanf)
15907+libc_hidden_proto (__nldbl_vfwprintf)
15908+libc_hidden_proto (__nldbl_vswprintf)
15909+libc_hidden_proto (__nldbl___vfwprintf_chk)
15910+libc_hidden_proto (__nldbl___vswprintf_chk)
15911 libc_hidden_proto (__nldbl___isoc99_vswscanf)
15912 libc_hidden_proto (__nldbl___isoc99_vfwscanf)
15913+#endif
15914
15915 static void
15916 __nldbl_cleanup (void *arg)
15917@@ -117,6 +121,7 @@ __nldbl_fprintf (FILE *stream, const char *fmt, ...)
15918 }
15919 weak_alias (__nldbl_fprintf, __nldbl__IO_fprintf)
15920
15921+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
15922 int
15923 attribute_compat_text_section weak_function
15924 __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...)
15925@@ -130,6 +135,7 @@ __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...)
15926
15927 return done;
15928 }
15929+#endif
15930
15931 int
15932 attribute_compat_text_section
15933@@ -226,6 +232,7 @@ __nldbl_snprintf (char *s, size_t maxlen, const char *fmt, ...)
15934 return done;
15935 }
15936
15937+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
15938 int
15939 attribute_compat_text_section
15940 __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...)
15941@@ -239,6 +246,7 @@ __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...)
15942
15943 return done;
15944 }
15945+#endif
15946
15947 int
15948 attribute_compat_text_section weak_function
15949@@ -264,6 +272,7 @@ __nldbl_vdprintf (int d, const char *fmt, va_list arg)
15950 }
15951 libc_hidden_def (__nldbl_vdprintf)
15952
15953+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
15954 int
15955 attribute_compat_text_section weak_function
15956 __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap)
15957@@ -275,6 +284,7 @@ __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap)
15958 return res;
15959 }
15960 libc_hidden_def (__nldbl_vfwprintf)
15961+#endif
15962
15963 int
15964 attribute_compat_text_section
15965@@ -297,6 +307,7 @@ __nldbl_vsnprintf (char *string, size_t maxlen, const char *fmt,
15966 libc_hidden_def (__nldbl_vsnprintf)
15967 weak_alias (__nldbl_vsnprintf, __nldbl___vsnprintf)
15968
15969+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
15970 int
15971 attribute_compat_text_section weak_function
15972 __nldbl_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *fmt,
15973@@ -330,6 +341,7 @@ __nldbl_wprintf (const wchar_t *fmt, ...)
15974
15975 return done;
15976 }
15977+#endif
15978
15979 int
15980 attribute_compat_text_section
15981@@ -419,6 +431,7 @@ __nldbl_scanf (const char *fmt, ...)
15982 return done;
15983 }
15984
15985+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
15986 int
15987 attribute_compat_text_section
15988 __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap)
15989@@ -491,6 +504,7 @@ __nldbl_wscanf (const wchar_t *fmt, ...)
15990
15991 return done;
15992 }
15993+#endif
15994
15995 int
15996 attribute_compat_text_section
15997@@ -506,6 +520,7 @@ __nldbl___fprintf_chk (FILE *stream, int flag, const char *fmt, ...)
15998 return done;
15999 }
16000
16001+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16002 int
16003 attribute_compat_text_section
16004 __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...)
16005@@ -519,6 +534,7 @@ __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...)
16006
16007 return done;
16008 }
16009+#endif
16010
16011 int
16012 attribute_compat_text_section
16013@@ -563,6 +579,7 @@ __nldbl___sprintf_chk (char *s, int flag, size_t slen, const char *fmt, ...)
16014 return done;
16015 }
16016
16017+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16018 int
16019 attribute_compat_text_section
16020 __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen,
16021@@ -577,6 +594,7 @@ __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen,
16022
16023 return done;
16024 }
16025+#endif
16026
16027 int
16028 attribute_compat_text_section
16029@@ -590,6 +608,7 @@ __nldbl___vfprintf_chk (FILE *s, int flag, const char *fmt, va_list ap)
16030 }
16031 libc_hidden_def (__nldbl___vfprintf_chk)
16032
16033+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16034 int
16035 attribute_compat_text_section
16036 __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap)
16037@@ -601,6 +620,7 @@ __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap)
16038 return res;
16039 }
16040 libc_hidden_def (__nldbl___vfwprintf_chk)
16041+#endif
16042
16043 int
16044 attribute_compat_text_section
16045@@ -635,6 +655,7 @@ __nldbl___vsprintf_chk (char *string, int flag, size_t slen, const char *fmt,
16046 }
16047 libc_hidden_def (__nldbl___vsprintf_chk)
16048
16049+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16050 int
16051 attribute_compat_text_section
16052 __nldbl___vswprintf_chk (wchar_t *string, size_t maxlen, int flag, size_t slen,
16053@@ -668,6 +689,7 @@ __nldbl___wprintf_chk (int flag, const wchar_t *fmt, ...)
16054
16055 return done;
16056 }
16057+#endif
16058
16059 int
16060 attribute_compat_text_section
16061@@ -775,6 +797,7 @@ __nldbl___printf_fp (FILE *fp, const struct printf_info *info,
16062 return ___printf_fp (fp, &info_no_ldbl, args);
16063 }
16064
16065+#if __OPTION_EGLIBC_LOCALE_CODE
16066 ssize_t
16067 attribute_compat_text_section
16068 __nldbl_strfmon (char *s, size_t maxsize, const char *format, ...)
16069@@ -829,6 +852,7 @@ __nldbl___vstrfmon_l (char *s, size_t maxsize, __locale_t loc,
16070 return res;
16071 }
16072 libc_hidden_def (__nldbl___vstrfmon_l)
16073+#endif
16074
16075 void
16076 attribute_compat_text_section
16077@@ -941,6 +965,7 @@ __nldbl___isoc99_scanf (const char *fmt, ...)
16078 return done;
16079 }
16080
16081+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16082 int
16083 attribute_compat_text_section
16084 __nldbl___isoc99_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap)
16085@@ -1014,6 +1039,7 @@ __nldbl___isoc99_wscanf (const wchar_t *fmt, ...)
16086
16087 return done;
16088 }
16089+#endif
16090
16091 #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
16092 compat_symbol (libc, __nldbl__IO_printf, _IO_printf, GLIBC_2_0);
16093@@ -1057,6 +1083,7 @@ compat_symbol (libc, __nldbl_printf_size, printf_size, GLIBC_2_1);
16094 compat_symbol (libc, __nldbl___strfmon_l, __strfmon_l, GLIBC_2_1);
16095 #endif
16096 #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_2)
16097+# if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16098 compat_symbol (libc, __nldbl_swprintf, swprintf, GLIBC_2_2);
16099 compat_symbol (libc, __nldbl_vwprintf, vwprintf, GLIBC_2_2);
16100 compat_symbol (libc, __nldbl_wprintf, wprintf, GLIBC_2_2);
16101@@ -1069,6 +1096,7 @@ compat_symbol (libc, __nldbl_vfwscanf, vfwscanf, GLIBC_2_2);
16102 compat_symbol (libc, __nldbl_vswscanf, vswscanf, GLIBC_2_2);
16103 compat_symbol (libc, __nldbl_vwscanf, vwscanf, GLIBC_2_2);
16104 compat_symbol (libc, __nldbl_wscanf, wscanf, GLIBC_2_2);
16105+# endif
16106 #endif
16107 #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_3)
16108 compat_symbol (libc, __nldbl_strfmon_l, strfmon_l, GLIBC_2_3);
16109diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
16110index 0d2c8af..f4cea50 100644
16111--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
16112+++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
16113@@ -30,6 +30,7 @@
16114 #include <math.h>
16115 #include <monetary.h>
16116 #include <sys/syslog.h>
16117+#include <gnu/option-groups.h>
16118
16119
16120 /* Declare the __nldbl_NAME function the wrappers call that's in libc.so. */
16121@@ -37,19 +38,15 @@
16122
16123 NLDBL_DECL (_IO_vfscanf);
16124 NLDBL_DECL (vfscanf);
16125-NLDBL_DECL (vfwscanf);
16126 NLDBL_DECL (obstack_vprintf);
16127 NLDBL_DECL (vasprintf);
16128 NLDBL_DECL (dprintf);
16129 NLDBL_DECL (vdprintf);
16130 NLDBL_DECL (fprintf);
16131 NLDBL_DECL (vfprintf);
16132-NLDBL_DECL (vfwprintf);
16133 NLDBL_DECL (vsnprintf);
16134 NLDBL_DECL (vsprintf);
16135 NLDBL_DECL (vsscanf);
16136-NLDBL_DECL (vswprintf);
16137-NLDBL_DECL (vswscanf);
16138 NLDBL_DECL (__asprintf);
16139 NLDBL_DECL (asprintf);
16140 NLDBL_DECL (__printf_fp);
16141@@ -66,12 +63,18 @@ NLDBL_DECL (__isoc99_sscanf);
16142 NLDBL_DECL (__isoc99_vscanf);
16143 NLDBL_DECL (__isoc99_vfscanf);
16144 NLDBL_DECL (__isoc99_vsscanf);
16145+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16146+NLDBL_DECL (vfwscanf);
16147+NLDBL_DECL (vfwprintf);
16148+NLDBL_DECL (vswprintf);
16149+NLDBL_DECL (vswscanf);
16150 NLDBL_DECL (__isoc99_wscanf);
16151 NLDBL_DECL (__isoc99_fwscanf);
16152 NLDBL_DECL (__isoc99_swscanf);
16153 NLDBL_DECL (__isoc99_vwscanf);
16154 NLDBL_DECL (__isoc99_vfwscanf);
16155 NLDBL_DECL (__isoc99_vswscanf);
16156+#endif
16157
16158 /* This one does not exist in the normal interface, only
16159 __nldbl___vstrfmon really exists. */
16160@@ -82,22 +85,23 @@ extern ssize_t __nldbl___vstrfmon (char *, size_t, const char *, va_list)
16161 since we don't compile with _FORTIFY_SOURCE. */
16162 extern int __nldbl___vfprintf_chk (FILE *__restrict, int,
16163 const char *__restrict, _G_va_list);
16164-extern int __nldbl___vfwprintf_chk (FILE *__restrict, int,
16165- const wchar_t *__restrict, __gnuc_va_list);
16166 extern int __nldbl___vsprintf_chk (char *__restrict, int, size_t,
16167 const char *__restrict, _G_va_list) __THROW;
16168 extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t,
16169 const char *__restrict, _G_va_list)
16170 __THROW;
16171-extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t,
16172- const wchar_t *__restrict, __gnuc_va_list)
16173- __THROW;
16174 extern int __nldbl___vasprintf_chk (char **, int, const char *, _G_va_list)
16175 __THROW;
16176 extern int __nldbl___vdprintf_chk (int, int, const char *, _G_va_list);
16177 extern int __nldbl___obstack_vprintf_chk (struct obstack *, int, const char *,
16178 _G_va_list) __THROW;
16179 extern void __nldbl___vsyslog_chk (int, int, const char *, va_list);
16180-
16181+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
16182+extern int __nldbl___vfwprintf_chk (FILE *__restrict, int,
16183+ const wchar_t *__restrict, __gnuc_va_list);
16184+extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t,
16185+ const wchar_t *__restrict, __gnuc_va_list)
16186+ __THROW;
16187+#endif
16188
16189 #endif /* __NLDBL_COMPAT_H */
16190diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile
16191index e9339a3..782009b 100644
16192--- a/sysdeps/nptl/Makefile
16193+++ b/sysdeps/nptl/Makefile
16194@@ -18,6 +18,9 @@
16195
16196 ifeq ($(subdir),nptl)
16197 libpthread-sysdep_routines += errno-loc
16198+ifeq ($(OPTION_EGLIBC_BIG_MACROS),n)
16199+sysdep_routines += small-macros-fns
16200+endif
16201 endif
16202
16203 ifeq ($(subdir),rt)
16204diff --git a/sysdeps/nptl/bits/libc-lock.h b/sysdeps/nptl/bits/libc-lock.h
16205index 5599cf1..b839378 100644
16206--- a/sysdeps/nptl/bits/libc-lock.h
16207+++ b/sysdeps/nptl/bits/libc-lock.h
16208@@ -24,6 +24,14 @@
16209 #include <stddef.h>
16210
16211
16212+#ifdef _LIBC
16213+# include <lowlevellock.h>
16214+# include <tls.h>
16215+# include <pthread-functions.h>
16216+# include <errno.h> /* For EBUSY. */
16217+# include <gnu/option-groups.h> /* For __OPTION_EGLIBC_BIG_MACROS. */
16218+#endif
16219+
16220 /* Mutex type. */
16221 #if defined _LIBC || defined _IO_MTSAFE_IO
16222 # if (!IS_IN (libc) && !IS_IN (libpthread)) || !defined _LIBC
16223@@ -87,6 +95,15 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
16224
16225 /* Lock the recursive named lock variable. */
16226 #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
16227+# if __OPTION_EGLIBC_BIG_MACROS != 1
16228+/* EGLIBC: Declare wrapper function for a big macro if either
16229+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
16230+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */
16231+extern void __libc_lock_lock_recursive_fn (__libc_lock_recursive_t *);
16232+libc_hidden_proto (__libc_lock_lock_recursive_fn);
16233+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
16234+# if __OPTION_EGLIBC_BIG_MACROS
16235+
16236 # define __libc_lock_lock_recursive(NAME) \
16237 do { \
16238 void *self = THREAD_SELF; \
16239@@ -97,6 +114,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
16240 } \
16241 ++(NAME).cnt; \
16242 } while (0)
16243+# else
16244+# define __libc_lock_lock_recursive(NAME) \
16245+ __libc_lock_lock_recursive_fn (&(NAME))
16246+# endif /* __OPTION_EGLIBC_BIG_MACROS */
16247 #else
16248 # define __libc_lock_lock_recursive(NAME) \
16249 __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
16250@@ -104,6 +125,14 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
16251
16252 /* Try to lock the recursive named lock variable. */
16253 #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
16254+# if __OPTION_EGLIBC_BIG_MACROS != 1
16255+/* EGLIBC: Declare wrapper function for a big macro if either
16256+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
16257+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */
16258+extern int __libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *);
16259+libc_hidden_proto (__libc_lock_trylock_recursive_fn);
16260+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
16261+# if __OPTION_EGLIBC_BIG_MACROS
16262 # define __libc_lock_trylock_recursive(NAME) \
16263 ({ \
16264 int result = 0; \
16265@@ -122,6 +151,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
16266 ++(NAME).cnt; \
16267 result; \
16268 })
16269+# else
16270+# define __libc_lock_trylock_recursive(NAME) \
16271+ __libc_lock_trylock_recursive_fn (&(NAME))
16272+# endif /* __OPTION_EGLIBC_BIG_MACROS */
16273 #else
16274 # define __libc_lock_trylock_recursive(NAME) \
16275 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
16276@@ -129,6 +162,14 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
16277
16278 /* Unlock the recursive named lock variable. */
16279 #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
16280+# if __OPTION_EGLIBC_BIG_MACROS != 1
16281+/* EGLIBC: Declare wrapper function for a big macro if either
16282+ !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from
16283+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */
16284+extern void __libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *);
16285+libc_hidden_proto (__libc_lock_unlock_recursive_fn);
16286+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
16287+# if __OPTION_EGLIBC_BIG_MACROS
16288 /* We do no error checking here. */
16289 # define __libc_lock_unlock_recursive(NAME) \
16290 do { \
16291@@ -138,6 +179,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
16292 lll_unlock ((NAME).lock, LLL_PRIVATE); \
16293 } \
16294 } while (0)
16295+# else
16296+# define __libc_lock_unlock_recursive(NAME) \
16297+ __libc_lock_unlock_recursive_fn (&(NAME))
16298+# endif /* __OPTION_EGLIBC_BIG_MACROS */
16299 #else
16300 # define __libc_lock_unlock_recursive(NAME) \
16301 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
16302diff --git a/sysdeps/nptl/bits/libc-lockP.h b/sysdeps/nptl/bits/libc-lockP.h
16303index f55f621..da98869 100644
16304--- a/sysdeps/nptl/bits/libc-lockP.h
16305+++ b/sysdeps/nptl/bits/libc-lockP.h
16306@@ -33,6 +33,8 @@
16307 #include <lowlevellock.h>
16308 #include <tls.h>
16309 #include <pthread-functions.h>
16310+#include <errno.h> /* For EBUSY. */
16311+#include <gnu/option-groups.h> /* For __OPTION_EGLIBC_BIG_MACROS. */
16312
16313 #if IS_IN (libpthread)
16314 /* This gets us the declarations of the __pthread_* internal names,
16315@@ -171,10 +173,22 @@ typedef pthread_key_t __libc_key_t;
16316
16317 /* Lock the named lock variable. */
16318 #if IS_IN (libc) || IS_IN (libpthread)
16319-# ifndef __libc_lock_lock
16320-# define __libc_lock_lock(NAME) \
16321+# if __OPTION_EGLIBC_BIG_MACROS != 1
16322+/* EGLIBC: Declare wrapper function for a big macro if either
16323+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
16324+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */
16325+extern void __libc_lock_lock_fn (__libc_lock_t *);
16326+libc_hidden_proto (__libc_lock_lock_fn);
16327+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
16328+# if __OPTION_EGLIBC_BIG_MACROS
16329+# ifndef __libc_lock_lock
16330+# define __libc_lock_lock(NAME) \
16331 ({ lll_lock (NAME, LLL_PRIVATE); 0; })
16332-# endif
16333+# endif
16334+# else
16335+# define __libc_lock_lock(NAME) \
16336+ __libc_lock_lock_fn (&(NAME))
16337+# endif /* __OPTION_EGLIBC_BIG_MACROS */
16338 #else
16339 # undef __libc_lock_lock
16340 # define __libc_lock_lock(NAME) \
16341@@ -187,10 +201,22 @@ typedef pthread_key_t __libc_key_t;
16342
16343 /* Try to lock the named lock variable. */
16344 #if IS_IN (libc) || IS_IN (libpthread)
16345-# ifndef __libc_lock_trylock
16346-# define __libc_lock_trylock(NAME) \
16347+# if __OPTION_EGLIBC_BIG_MACROS != 1
16348+/* EGLIBC: Declare wrapper function for a big macro if either
16349+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
16350+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */
16351+extern int __libc_lock_trylock_fn (__libc_lock_t *);
16352+libc_hidden_proto (__libc_lock_trylock_fn);
16353+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
16354+# if __OPTION_EGLIBC_BIG_MACROS
16355+# ifndef __libc_lock_trylock
16356+# define __libc_lock_trylock(NAME) \
16357 lll_trylock (NAME)
16358-# endif
16359+# endif
16360+# else
16361+# define __libc_lock_trylock(NAME) \
16362+ __libc_lock_trylock_fn (&(NAME))
16363+# endif /* __OPTION_EGLIBC_BIG_MACROS */
16364 #else
16365 # undef __libc_lock_trylock
16366 # define __libc_lock_trylock(NAME) \
16367@@ -206,8 +232,20 @@ typedef pthread_key_t __libc_key_t;
16368
16369 /* Unlock the named lock variable. */
16370 #if IS_IN (libc) || IS_IN (libpthread)
16371+# if __OPTION_EGLIBC_BIG_MACROS != 1
16372+/* EGLIBC: Declare wrapper function for a big macro if either
16373+ !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from
16374+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */
16375+extern void __libc_lock_unlock_fn (__libc_lock_t *);
16376+libc_hidden_proto (__libc_lock_unlock_fn);
16377+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
16378+# if __OPTION_EGLIBC_BIG_MACROS
16379 # define __libc_lock_unlock(NAME) \
16380 lll_unlock (NAME, LLL_PRIVATE)
16381+# else
16382+# define __libc_lock_unlock(NAME) \
16383+ __libc_lock_unlock_fn (&(NAME))
16384+# endif /* __OPTION_EGLIBC_BIG_MACROS */
16385 #else
16386 # define __libc_lock_unlock(NAME) \
16387 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0)
16388diff --git a/sysdeps/nptl/small-macros-fns.c b/sysdeps/nptl/small-macros-fns.c
16389new file mode 100644
16390index 0000000..f751053
16391--- /dev/null
16392+++ b/sysdeps/nptl/small-macros-fns.c
16393@@ -0,0 +1,72 @@
16394+/* EGLIBC: function wrappers for big macros.
16395+ Copyright (C) 2009 Free Software Foundation, Inc.
16396+ This file is part of the GNU C Library.
16397+
16398+ The GNU C Library is free software; you can redistribute it and/or
16399+ modify it under the terms of the GNU Lesser General Public License as
16400+ published by the Free Software Foundation; either version 2.1 of the
16401+ License, or (at your option) any later version.
16402+
16403+ The GNU C Library is distributed in the hope that it will be useful,
16404+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16405+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16406+ Lesser General Public License for more details.
16407+
16408+ You should have received a copy of the GNU Lesser General Public
16409+ License along with the GNU C Library; see the file COPYING.LIB. If not,
16410+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16411+ Boston, MA 02111-1307, USA. */
16412+
16413+#include <gnu/option-groups.h>
16414+
16415+/* Handle macros from ./bits/libc-lock.h. */
16416+#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
16417+
16418+/* Get the macros for function bodies through a back door. */
16419+# undef __OPTION_EGLIBC_BIG_MACROS
16420+# define __OPTION_EGLIBC_BIG_MACROS 2
16421+# include <bits/libc-lock.h>
16422+
16423+void
16424+__libc_lock_lock_fn (__libc_lock_t *name)
16425+{
16426+ __libc_lock_lock (*name);
16427+}
16428+libc_hidden_def (__libc_lock_lock_fn);
16429+
16430+void
16431+__libc_lock_lock_recursive_fn (__libc_lock_recursive_t *name)
16432+{
16433+ __libc_lock_lock_recursive (*name);
16434+}
16435+libc_hidden_def (__libc_lock_lock_recursive_fn);
16436+
16437+int
16438+__libc_lock_trylock_fn (__libc_lock_t *name)
16439+{
16440+ return __libc_lock_trylock (*name);
16441+}
16442+libc_hidden_def (__libc_lock_trylock_fn);
16443+
16444+int
16445+__libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *name)
16446+{
16447+ return __libc_lock_trylock_recursive (*name);
16448+}
16449+libc_hidden_def (__libc_lock_trylock_recursive_fn);
16450+
16451+void
16452+__libc_lock_unlock_fn (__libc_lock_t *name)
16453+{
16454+ __libc_lock_unlock (*name);
16455+}
16456+libc_hidden_def (__libc_lock_unlock_fn);
16457+
16458+void
16459+__libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *name)
16460+{
16461+ __libc_lock_unlock_recursive (*name);
16462+}
16463+libc_hidden_def (__libc_lock_unlock_recursive_fn);
16464+
16465+#endif /*defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)*/
16466diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c
16467index 26e4692..d0a26c8 100644
16468--- a/sysdeps/unix/sysv/linux/gethostid.c
16469+++ b/sysdeps/unix/sysv/linux/gethostid.c
16470@@ -21,6 +21,7 @@
16471 #include <unistd.h>
16472 #include <netdb.h>
16473 #include <not-cancel.h>
16474+#include <gnu/option-groups.h>
16475
16476 #define HOSTIDFILE "/etc/hostid"
16477
16478@@ -89,6 +90,7 @@ gethostid (void)
16479 return id;
16480 }
16481
16482+#if __OPTION_EGLIBC_INET
16483 /* Getting from the file was not successful. An intelligent guess for
16484 a unique number of a host is its IP address. Return this. */
16485 if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0')
16486@@ -115,5 +117,9 @@ gethostid (void)
16487 /* For the return value to be not exactly the IP address we do some
16488 bit fiddling. */
16489 return (int32_t) (in.s_addr << 16 | in.s_addr >> 16);
16490+#else
16491+ /* Return an arbitrary value. */
16492+ return 0;
16493+#endif
16494 }
16495 #endif
16496diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c
16497index 53a8bbb..cb110d4 100644
16498--- a/sysdeps/unix/sysv/linux/libc_fatal.c
16499+++ b/sysdeps/unix/sysv/linux/libc_fatal.c
16500@@ -23,6 +23,7 @@
16501 #include <string.h>
16502 #include <sys/mman.h>
16503 #include <sys/uio.h>
16504+#include <gnu/option-groups.h>
16505
16506 static bool
16507 writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total)
16508@@ -40,6 +41,7 @@ writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total)
16509 static void
16510 backtrace_and_maps (int do_abort, bool written, int fd)
16511 {
16512+#if __OPTION_EGLIBC_BACKTRACE
16513 if (do_abort > 1 && written)
16514 {
16515 void *addrs[64];
16516@@ -62,6 +64,7 @@ backtrace_and_maps (int do_abort, bool written, int fd)
16517 close_not_cancel_no_status (fd2);
16518 }
16519 }
16520+#endif /* __OPTION_EGLIBC_BACKTRACE */
16521 }
16522 #define BEFORE_ABORT backtrace_and_maps
16523
16524diff --git a/time/Makefile b/time/Makefile
16525index a411f62..2d022ca 100644
16526--- a/time/Makefile
16527+++ b/time/Makefile
16528@@ -18,6 +18,8 @@
16529 #
16530 # Makefile for time routines
16531 #
16532+include ../option-groups.mak
16533+
16534 subdir := time
16535
16536 include ../Makeconfig
16537@@ -30,15 +32,23 @@ routines := offtime asctime clock ctime ctime_r difftime \
16538 tzfile getitimer setitimer \
16539 stime dysize timegm ftime \
16540 getdate strptime strptime_l \
16541- strftime wcsftime strftime_l wcsftime_l \
16542+ strftime strftime_l \
16543 timespec_get
16544-aux := era alt_digit lc-time-cleanup
16545
16546-tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
16547- tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
16548+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
16549+ := wcsftime wcsftime_l
16550+aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup
16551+
16552+tests := test_time clocktest tst-posixtz \
16553+ tst-getdate tst-mktime tst-mktime2 tst-strftime \
16554 tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \
16555 tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime
16556
16557+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
16558+ += tst-strptime tst-ftime_l
16559+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
16560+ += tst_wcsftime
16561+
16562 include ../Rules
16563
16564 tz-cflags = -DTZDIR='"$(zonedir)"' \
16565diff --git a/time/strftime_l.c b/time/strftime_l.c
16566index b48ef34..bfdd618 100644
16567--- a/time/strftime_l.c
16568+++ b/time/strftime_l.c
16569@@ -35,6 +35,10 @@
16570 # include "../locale/localeinfo.h"
16571 #endif
16572
16573+#ifdef _LIBC
16574+# include <gnu/option-groups.h>
16575+#endif
16576+
16577 #if defined emacs && !defined HAVE_BCOPY
16578 # define HAVE_MEMCPY 1
16579 #endif
16580@@ -882,7 +886,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
16581 case L_('C'):
16582 if (modifier == L_('E'))
16583 {
16584-#if HAVE_STRUCT_ERA_ENTRY
16585+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY
16586 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
16587 if (era)
16588 {
16589@@ -955,7 +959,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
16590
16591 if (modifier == L_('O') && 0 <= number_value)
16592 {
16593-#ifdef _NL_CURRENT
16594+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT)
16595 /* Get the locale specific alternate representation of
16596 the number NUMBER_VALUE. If none exist NULL is returned. */
16597 const CHAR_T *cp = nl_get_alt_digit (number_value
16598@@ -1260,7 +1264,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
16599 case L_('Y'):
16600 if (modifier == 'E')
16601 {
16602-#if HAVE_STRUCT_ERA_ENTRY
16603+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY
16604 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
16605 if (era)
16606 {
16607@@ -1285,7 +1289,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
16608 case L_('y'):
16609 if (modifier == L_('E'))
16610 {
16611-#if HAVE_STRUCT_ERA_ENTRY
16612+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY
16613 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
16614 if (era)
16615 {
16616diff --git a/time/strptime_l.c b/time/strptime_l.c
16617index 5640cce..784ccbc 100644
16618--- a/time/strptime_l.c
16619+++ b/time/strptime_l.c
16620@@ -29,6 +29,7 @@
16621
16622 #ifdef _LIBC
16623 # define HAVE_LOCALTIME_R 0
16624+# include <gnu/option-groups.h>
16625 # include "../locale/localeinfo.h"
16626 #endif
16627
16628@@ -84,7 +85,7 @@ localtime_r (t, tp)
16629 if (val < from || val > to) \
16630 return NULL; \
16631 } while (0)
16632-#ifdef _NL_CURRENT
16633+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT)
16634 # define get_alt_number(from, to, n) \
16635 ({ \
16636 __label__ do_normal; \
16637@@ -257,8 +258,10 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16638 int cnt;
16639 int cnt_longest;
16640 size_t val;
16641+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
16642 size_t num_eras;
16643 struct era_entry *era = NULL;
16644+#endif
16645 enum ptime_locale_status { not, loc, raw } decided_longest;
16646 struct __strptime_state
16647 {
16648@@ -820,6 +823,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16649 s.want_xday = 1;
16650 break;
16651 case 'C':
16652+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
16653 if (s.decided != raw)
16654 {
16655 if (s.era_cnt >= 0)
16656@@ -856,10 +860,12 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16657
16658 s.decided = raw;
16659 }
16660+#endif
16661 /* The C locale has no era information, so use the
16662 normal representation. */
16663 goto match_century;
16664 case 'y':
16665+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
16666 if (s.decided != raw)
16667 {
16668 get_number(0, 9999, 4);
16669@@ -918,9 +924,10 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16670
16671 s.decided = raw;
16672 }
16673-
16674+#endif
16675 goto match_year_in_century;
16676 case 'Y':
16677+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
16678 if (s.decided != raw)
16679 {
16680 num_eras = _NL_CURRENT_WORD (LC_TIME,
16681@@ -948,6 +955,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16682
16683 s.decided = raw;
16684 }
16685+#endif
16686 get_number (0, 9999, 4);
16687 tm->tm_year = val - 1900;
16688 s.want_century = 0;
16689@@ -1118,6 +1126,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16690 tm->tm_year = (s.century - 19) * 100;
16691 }
16692
16693+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
16694 if (s.era_cnt != -1)
16695 {
16696 era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG);
16697@@ -1132,6 +1141,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
16698 tm->tm_year = era->start_date[0];
16699 }
16700 else
16701+#endif
16702 if (s.want_era)
16703 {
16704 /* No era found but we have seen an E modifier. Rectify some
16705diff --git a/timezone/Makefile b/timezone/Makefile
16706index 886b06e..f922684 100644
16707--- a/timezone/Makefile
16708+++ b/timezone/Makefile
16709@@ -127,7 +127,7 @@ $(testdata)/XT%: testdata/XT%
16710
16711 $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make
16712 sed -e 's|/bin/bash|/bin/sh|' \
16713- -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \
16714+ -e '/TZDIR=/s|\$$(pwd)|$(zonedir)|' \
16715 -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \
16716 -e '/PKGVERSION=/s|=.*|="$(PKGVERSION)"|' \
16717 -e '/REPORT_BUGS_TO=/s|=.*|="$(REPORT_BUGS_TO)"|' \
16718diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
16719index 44a4494..db9fc24 100644
16720--- a/wcsmbs/Makefile
16721+++ b/wcsmbs/Makefile
16722@@ -18,15 +18,21 @@
16723 #
16724 # Sub-makefile for wcsmbs portion of the library.
16725 #
16726+include ../option-groups.mak
16727+
16728 subdir := wcsmbs
16729
16730 include ../Makeconfig
16731
16732 headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h
16733
16734-routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
16735+# These functions are used by printf_fp.c, even in the plain case; see
16736+# comments there for OPTION_EGLIBC_LOCALE_CODE.
16737+routines := wmemcpy wmemset
16738+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
16739+ := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
16740 wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
16741- wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \
16742+ wmemcmp wmemmove wcpcpy wcpncpy wmempcpy \
16743 btowc wctob mbsinit \
16744 mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
16745 mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
16746@@ -38,14 +44,21 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
16747 wcscoll_l wcsxfrm_l \
16748 wcscasecmp wcsncase wcscasecmp_l wcsncase_l \
16749 wcsmbsload mbsrtowcs_l \
16750- isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \
16751 isoc99_swscanf isoc99_vswscanf \
16752 mbrtoc16 c16rtomb
16753
16754-strop-tests := wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy
16755-tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
16756- tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \
16757- tst-c16c32-1 wcsatcliff $(addprefix test-,$(strop-tests))
16758+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
16759+ += isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf
16760+
16761+strop-tests := wcscmp wmemcmp wmemcmp wcslen wcschr wcsrchr wcscpy
16762+
16763+tests := tst-wchar-h
16764+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
16765+ += tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb tst-c16c32-1
16766+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
16767+ += tst-wcstof wcsmbs-tst1 tst-wcsnlen \
16768+ tst-wcpncpy tst-mbsrtowcs \
16769+ wcsatcliff $(addprefix test-,$(strop-tests))
16770
16771 include ../Rules
16772
16773diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c
16774index 6bb49bc..2ab9d07 100644
16775--- a/wcsmbs/wcsmbsload.c
16776+++ b/wcsmbs/wcsmbsload.c
16777@@ -21,6 +21,7 @@
16778 #include <limits.h>
16779 #include <stdlib.h>
16780 #include <string.h>
16781+#include <gnu/option-groups.h>
16782
16783 #include <locale/localeinfo.h>
16784 #include <wcsmbsload.h>
16785@@ -143,6 +144,7 @@ __wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp)
16786 })
16787
16788
16789+#if __OPTION_EGLIBC_LOCALE_CODE
16790 /* Some of the functions here must not be used while setlocale is called. */
16791 __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
16792
16793@@ -211,6 +213,17 @@ __wcsmbs_load_conv (struct __locale_data *new_category)
16794
16795 __libc_rwlock_unlock (__libc_setlocale_lock);
16796 }
16797+#else
16798+void
16799+internal_function
16800+__wcsmbs_load_conv (struct __locale_data *new_category)
16801+{
16802+ /* When OPTION_EGLIBC_LOCALE_CODE is disabled, we should never reach
16803+ this point: there is no way to change locales, so every locale
16804+ passed to get_gconv_fcts should be _nl_C_LC_CTYPE. */
16805+ abort ();
16806+}
16807+#endif
16808
16809
16810 /* Clone the current conversion function set. */
16811diff --git a/wctype/Makefile b/wctype/Makefile
16812index c56f07c..4e8af43 100644
16813--- a/wctype/Makefile
16814+++ b/wctype/Makefile
16815@@ -18,14 +18,20 @@
16816 #
16817 # Sub-makefile for wctype portion of the library.
16818 #
16819+include ../option-groups.mak
16820+
16821 subdir := wctype
16822
16823 include ../Makeconfig
16824
16825 headers := wctype.h
16826-routines := wcfuncs wctype iswctype wctrans towctrans \
16827- wcfuncs_l wctype_l iswctype_l wctrans_l towctrans_l
16828-
16829-tests := test_wctype test_wcfuncs bug-wctypeh
16830+routines := wctrans towctrans towctrans_l
16831+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
16832+ := wcfuncs wctype iswctype \
16833+ wcfuncs_l wctype_l iswctype_l wctrans_l
16834+
16835+tests :=
16836+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
16837+ += test_wctype test_wcfuncs bug-wctypeh
16838
16839 include ../Rules
16840--
168412.1.4
16842