From cb7368c110553dcb972480abc4a59b975677f7df Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Wed, 18 Mar 2015 02:05:06 +0000 Subject: glibc: Upgrade 2.21 -> 2.22 - git'ify the OE patches - add_resource_h_to_wait_h.patch - dropped, we do not support that old perf anymore - mips-rld-map-check.patch - Dropped because binutils is fixed for it see https://sourceware.org/ml/binutils/2011-12/msg00112.html - initgroups_keys.patch - Folded into 0026-eglibc-Forward-port-eglibc-options-groups-support.patch Change-Id: Ib8e731b212f52b8ff12e2180babbc19970fb1ef1 (From OE-Core rev: 6ea08396dbb628140fd3289fc9fb19df97914326) Signed-off-by: Khem Raj Signed-off-by: Ross Burton Signed-off-by: Richard Purdie --- meta/conf/distro/include/tcmode-default.inc | 2 +- .../glibc/cross-localedef-native_2.21.bb | 56 - .../glibc/cross-localedef-native_2.22.bb | 59 + meta/recipes-core/glibc/glibc-initial_2.21.bb | 11 - meta/recipes-core/glibc/glibc-initial_2.22.bb | 11 + meta/recipes-core/glibc/glibc-locale_2.21.bb | 1 - meta/recipes-core/glibc/glibc-locale_2.22.bb | 1 + meta/recipes-core/glibc/glibc-mtrace_2.21.bb | 1 - meta/recipes-core/glibc/glibc-mtrace_2.22.bb | 1 + meta/recipes-core/glibc/glibc-scripts_2.21.bb | 1 - meta/recipes-core/glibc/glibc-scripts_2.22.bb | 1 + .../glibc/glibc/0001-Add-unused-attribute.patch | 36 - .../glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch | 56 - ...ing-SSE-also-make-sure-that-fpmath-is-not.patch | 32 - ...n-libm-err-tab.pl-with-specific-dirs-in-S.patch | 33 - ...libc-Look-for-host-system-ld.so.cache-as-.patch | 70 + ...thin-the-path-sets-wrong-config-variables.patch | 245 - ...libc-Fix-buffer-overrun-with-a-relocated-.patch | 50 + ...libc-Raise-the-size-of-arrays-containing-.patch | 126 + ...tps-sourceware.org-ml-libc-ports-2007-12-.patch | 34 + ...500-e5500-e6500-603e-fsqrt-implementation.patch | 1584 ++ ...-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch | 33 + ...-Fix-undefined-reference-to-__sqrt_finite.patch | 208 + ...qrt-f-are-now-inline-functions-and-call-o.patch | 387 + ...bug-1443-which-explains-what-the-patch-do.patch | 62 + ...n-libm-err-tab.pl-with-specific-dirs-in-S.patch | 36 + ...qrt-f-are-now-inline-functions-and-call-o.patch | 61 + ...ersion-output-matching-grok-gold-s-output.patch | 44 + ...-configure.ac-handle-correctly-libc_cv_ro.patch | 42 + .../glibc/glibc/0014-Add-unused-attribute.patch | 34 + ...ing-SSE-also-make-sure-that-fpmath-is-not.patch | 32 + ...thin-the-path-sets-wrong-config-variables.patch | 263 + ...-timezone-re-written-tzselect-as-posix-sh.patch | 45 + ...c-Cross-building-and-testing-instructions.patch | 619 + ...g-Eglibc-option-group-infrastructure-to-g.patch | 1436 ++ ...020-eglibc-Help-bootstrap-cross-toolchain.patch | 100 + ...ry-picked-from-http-www.eglibc.org-archiv.patch | 64 + .../0022-eglibc-Clear-cache-lines-on-ppc8xx.patch | 81 + ...0023-eglibc-Resolve-__fpscr_values-on-SH4.patch | 56 + ...orward-port-eglibc-options-groups-support.patch | 16842 +++++++++++++++++++ .../glibc/0025-eglibc-Install-PIC-archives.patch | 123 + ...ebug_mask-is-controlled-by-__OPTION_EGLIB.patch | 556 + ...option-groups-Conditionally-exclude-c-tes.patch | 145 + ...81-resolv-nss_dns-dns-host.c-buffer-overf.patch | 43 - .../glibc/Fix-__memcpy_chk-on-non-SSE2-CPUs.patch | 36 - .../glibc/glibc/GLRO_dl_debug_mask.patch | 529 - .../glibc/glibc/IO-acquire-lock-fix.patch | 17 - .../glibc/glibc/add_resource_h_to_wait_h.patch | 20 - .../glibc/glibc/eglibc-header-bootstrap.patch | 85 - .../glibc/glibc/eglibc-install-pic-archives.patch | 109 - .../eglibc-ppc8xx-cache-line-workaround.patch | 68 - .../glibc/glibc/eglibc-resolv-dynamic.patch | 54 - .../glibc/glibc/eglibc-sh4-fpscr_values.patch | 42 - .../glibc/glibc/eglibc-use-option-groups.patch | 16725 ------------------ meta/recipes-core/glibc/glibc/eglibc.patch | 602 - .../glibc/glibc/elf-Makefile-fix-a-typo.patch | 36 - .../glibc/glibc/fix-tibetian-locales.patch | 38 - .../glibc/glibc/fix_am_rootsbindir.patch | 29 - .../recipes-core/glibc/glibc/glibc.fix_sqrt2.patch | 1516 -- meta/recipes-core/glibc/glibc/grok_gold.patch | 34 - .../recipes-core/glibc/glibc/initgroups_keys.patch | 20 - .../recipes-core/glibc/glibc/ld-search-order.patch | 56 - meta/recipes-core/glibc/glibc/makesyscall.patch | 51 - .../glibc/glibc/mips-rld-map-check.patch | 27 - .../glibc/glibc/multilib_readlib.patch | 19 - meta/recipes-core/glibc/glibc/option-groups.patch | 1397 -- .../recipes-core/glibc/glibc/ppc-sqrt_finite.patch | 184 - .../glibc/glibc/ppc_slow_ieee754_sqrt.patch | 365 - .../glibc/ppce6500-32b_slow_ieee754_sqrt.patch | 47 - .../recipes-core/glibc/glibc/relocatable_sdk.patch | 108 - .../glibc/glibc/relocatable_sdk_fix_openpath.patch | 41 - .../timezone-re-written-tzselect-as-posix-sh.patch | 38 - meta/recipes-core/glibc/glibc_2.21.bb | 146 - meta/recipes-core/glibc/glibc_2.22.bb | 139 + 74 files changed, 23346 insertions(+), 22955 deletions(-) delete mode 100644 meta/recipes-core/glibc/cross-localedef-native_2.21.bb create mode 100644 meta/recipes-core/glibc/cross-localedef-native_2.22.bb delete mode 100644 meta/recipes-core/glibc/glibc-initial_2.21.bb create mode 100644 meta/recipes-core/glibc/glibc-initial_2.22.bb delete mode 100644 meta/recipes-core/glibc/glibc-locale_2.21.bb create mode 100644 meta/recipes-core/glibc/glibc-locale_2.22.bb delete mode 100644 meta/recipes-core/glibc/glibc-mtrace_2.21.bb create mode 100644 meta/recipes-core/glibc/glibc-mtrace_2.22.bb delete mode 100644 meta/recipes-core/glibc/glibc-scripts_2.21.bb create mode 100644 meta/recipes-core/glibc/glibc-scripts_2.22.bb delete mode 100644 meta/recipes-core/glibc/glibc/0001-Add-unused-attribute.patch delete mode 100644 meta/recipes-core/glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch delete mode 100644 meta/recipes-core/glibc/glibc/0001-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch delete mode 100644 meta/recipes-core/glibc/glibc/0001-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch create mode 100644 meta/recipes-core/glibc/glibc/0001-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch delete mode 100644 meta/recipes-core/glibc/glibc/0001-yes-within-the-path-sets-wrong-config-variables.patch create mode 100644 meta/recipes-core/glibc/glibc/0002-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch create mode 100644 meta/recipes-core/glibc/glibc/0003-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch create mode 100644 meta/recipes-core/glibc/glibc/0004-Backport-https-sourceware.org-ml-libc-ports-2007-12-.patch create mode 100644 meta/recipes-core/glibc/glibc/0005-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch create mode 100644 meta/recipes-core/glibc/glibc/0006-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch create mode 100644 meta/recipes-core/glibc/glibc/0007-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch create mode 100644 meta/recipes-core/glibc/glibc/0008-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch create mode 100644 meta/recipes-core/glibc/glibc/0009-Quote-from-bug-1443-which-explains-what-the-patch-do.patch create mode 100644 meta/recipes-core/glibc/glibc/0010-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch create mode 100644 meta/recipes-core/glibc/glibc/0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch create mode 100644 meta/recipes-core/glibc/glibc/0012-Make-ld-version-output-matching-grok-gold-s-output.patch create mode 100644 meta/recipes-core/glibc/glibc/0013-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch create mode 100644 meta/recipes-core/glibc/glibc/0014-Add-unused-attribute.patch create mode 100644 meta/recipes-core/glibc/glibc/0015-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch create mode 100644 meta/recipes-core/glibc/glibc/0016-yes-within-the-path-sets-wrong-config-variables.patch create mode 100644 meta/recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch create mode 100644 meta/recipes-core/glibc/glibc/0018-eglibc-Cross-building-and-testing-instructions.patch create mode 100644 meta/recipes-core/glibc/glibc/0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch create mode 100644 meta/recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch create mode 100644 meta/recipes-core/glibc/glibc/0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch create mode 100644 meta/recipes-core/glibc/glibc/0022-eglibc-Clear-cache-lines-on-ppc8xx.patch create mode 100644 meta/recipes-core/glibc/glibc/0023-eglibc-Resolve-__fpscr_values-on-SH4.patch create mode 100644 meta/recipes-core/glibc/glibc/0024-eglibc-Forward-port-eglibc-options-groups-support.patch create mode 100644 meta/recipes-core/glibc/glibc/0025-eglibc-Install-PIC-archives.patch create mode 100644 meta/recipes-core/glibc/glibc/0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch create mode 100644 meta/recipes-core/glibc/glibc/0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch delete mode 100644 meta/recipes-core/glibc/glibc/CVE-2015-1781-resolv-nss_dns-dns-host.c-buffer-overf.patch delete mode 100644 meta/recipes-core/glibc/glibc/Fix-__memcpy_chk-on-non-SSE2-CPUs.patch delete mode 100644 meta/recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch delete mode 100644 meta/recipes-core/glibc/glibc/IO-acquire-lock-fix.patch delete mode 100644 meta/recipes-core/glibc/glibc/add_resource_h_to_wait_h.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc-header-bootstrap.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc-install-pic-archives.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc-ppc8xx-cache-line-workaround.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc-resolv-dynamic.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc-sh4-fpscr_values.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc-use-option-groups.patch delete mode 100644 meta/recipes-core/glibc/glibc/eglibc.patch delete mode 100644 meta/recipes-core/glibc/glibc/elf-Makefile-fix-a-typo.patch delete mode 100644 meta/recipes-core/glibc/glibc/fix-tibetian-locales.patch delete mode 100644 meta/recipes-core/glibc/glibc/fix_am_rootsbindir.patch delete mode 100644 meta/recipes-core/glibc/glibc/glibc.fix_sqrt2.patch delete mode 100644 meta/recipes-core/glibc/glibc/grok_gold.patch delete mode 100644 meta/recipes-core/glibc/glibc/initgroups_keys.patch delete mode 100644 meta/recipes-core/glibc/glibc/ld-search-order.patch delete mode 100644 meta/recipes-core/glibc/glibc/makesyscall.patch delete mode 100644 meta/recipes-core/glibc/glibc/mips-rld-map-check.patch delete mode 100644 meta/recipes-core/glibc/glibc/multilib_readlib.patch delete mode 100644 meta/recipes-core/glibc/glibc/option-groups.patch delete mode 100644 meta/recipes-core/glibc/glibc/ppc-sqrt_finite.patch delete mode 100644 meta/recipes-core/glibc/glibc/ppc_slow_ieee754_sqrt.patch delete mode 100644 meta/recipes-core/glibc/glibc/ppce6500-32b_slow_ieee754_sqrt.patch delete mode 100644 meta/recipes-core/glibc/glibc/relocatable_sdk.patch delete mode 100644 meta/recipes-core/glibc/glibc/relocatable_sdk_fix_openpath.patch delete mode 100644 meta/recipes-core/glibc/glibc/timezone-re-written-tzselect-as-posix-sh.patch delete mode 100644 meta/recipes-core/glibc/glibc_2.21.bb create mode 100644 meta/recipes-core/glibc/glibc_2.22.bb diff --git a/meta/conf/distro/include/tcmode-default.inc b/meta/conf/distro/include/tcmode-default.inc index c08fe24f9a..fabd347a16 100644 --- a/meta/conf/distro/include/tcmode-default.inc +++ b/meta/conf/distro/include/tcmode-default.inc @@ -26,7 +26,7 @@ GCCVERSION ?= "4.9%" SDKGCCVERSION ?= "${GCCVERSION}" BINUVERSION ?= "2.25%" GDBVERSION ?= "7.9%" -GLIBCVERSION ?= "2.21" +GLIBCVERSION ?= "2.22" UCLIBCVERSION ?= "0.9.33+git%" LINUXLIBCVERSION ?= "4.1" diff --git a/meta/recipes-core/glibc/cross-localedef-native_2.21.bb b/meta/recipes-core/glibc/cross-localedef-native_2.21.bb deleted file mode 100644 index 4e15f02140..0000000000 --- a/meta/recipes-core/glibc/cross-localedef-native_2.21.bb +++ /dev/null @@ -1,56 +0,0 @@ -SUMMARY = "Cross locale generation tool for glibc" -HOMEPAGE = "http://www.gnu.org/software/libc/libc.html" -SECTION = "libs" -LICENSE = "LGPL-2.1" - -LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \ - file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ - file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \ - file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c" - - -inherit native -inherit autotools - -FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:" - -BRANCH = "release/${PV}/master" - -SRC_URI = "git://sourceware.org/git/glibc.git;branch=${BRANCH};name=glibc \ - git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef \ - file://fix_for_centos_5.8.patch \ - ${EGLIBCPATCHES} \ - " -EGLIBCPATCHES = "\ - file://timezone-re-written-tzselect-as-posix-sh.patch \ - file://eglibc.patch \ - file://option-groups.patch \ - file://GLRO_dl_debug_mask.patch \ - file://eglibc-header-bootstrap.patch \ - file://eglibc-resolv-dynamic.patch \ - file://eglibc-ppc8xx-cache-line-workaround.patch \ - file://eglibc-sh4-fpscr_values.patch \ - file://eglibc-use-option-groups.patch \ - " - -SRCREV_glibc = "4e42b5b8f89f0e288e68be7ad70f9525aebc2cff" -SRCREV_localedef = "c833367348d39dad7ba018990bfdaffaec8e9ed3" - -# Makes for a rather long rev (22 characters), but... -# -SRCREV_FORMAT = "glibc_localedef" - -S = "${WORKDIR}/git" - -EXTRA_OECONF = "--with-glibc=${S}" -CFLAGS += "-fgnu89-inline -std=gnu99 -DIS_IN\(x\)='0'" - -do_configure () { - ${S}/localedef/configure ${EXTRA_OECONF} -} - - -do_install() { - install -d ${D}${bindir} - install -m 0755 ${B}/localedef ${D}${bindir}/cross-localedef -} diff --git a/meta/recipes-core/glibc/cross-localedef-native_2.22.bb b/meta/recipes-core/glibc/cross-localedef-native_2.22.bb new file mode 100644 index 0000000000..2153ece0e2 --- /dev/null +++ b/meta/recipes-core/glibc/cross-localedef-native_2.22.bb @@ -0,0 +1,59 @@ +SUMMARY = "Cross locale generation tool for glibc" +HOMEPAGE = "http://www.gnu.org/software/libc/libc.html" +SECTION = "libs" +LICENSE = "LGPL-2.1" + +LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \ + file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ + file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \ + file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c" + + +inherit native +inherit autotools + +FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:" + +BRANCH ?= "release/${PV}/master" +GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" + +SRC_URI = "${GLIBC_GIT_URI};branch=${BRANCH};name=glibc \ + git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef \ + file://fix_for_centos_5.8.patch \ + ${EGLIBCPATCHES} \ +" +EGLIBCPATCHES = "\ + file://0017-timezone-re-written-tzselect-as-posix-sh.patch \ + file://0018-eglibc-Cross-building-and-testing-instructions.patch \ + file://0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch \ + file://0020-eglibc-Help-bootstrap-cross-toolchain.patch \ + file://0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch \ + file://0022-eglibc-Clear-cache-lines-on-ppc8xx.patch \ + file://0023-eglibc-Resolve-__fpscr_values-on-SH4.patch \ + file://0024-eglibc-Forward-port-eglibc-options-groups-support.patch \ + file://0025-eglibc-Install-PIC-archives.patch \ + file://0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch \ + file://0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch \ +" + +SRCREV_glibc ?= "a34d1c6afc86521d6ad17662a3b5362d8481514c" +SRCREV_localedef ?= "c833367348d39dad7ba018990bfdaffaec8e9ed3" + +# Makes for a rather long rev (22 characters), but... +# +SRCREV_FORMAT = "glibc_localedef" + +S = "${WORKDIR}/git" + +EXTRA_OECONF = "--with-glibc=${S}" +CFLAGS += "-fgnu89-inline -std=gnu99 -DIS_IN\(x\)='0'" + +do_configure () { + ${S}/localedef/configure ${EXTRA_OECONF} +} + + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${B}/localedef ${D}${bindir}/cross-localedef +} diff --git a/meta/recipes-core/glibc/glibc-initial_2.21.bb b/meta/recipes-core/glibc/glibc-initial_2.21.bb deleted file mode 100644 index 8ab01dc79d..0000000000 --- a/meta/recipes-core/glibc/glibc-initial_2.21.bb +++ /dev/null @@ -1,11 +0,0 @@ -require glibc_${PV}.bb -require glibc-initial.inc - -DEPENDS += "kconfig-frontends-native" - -# main glibc recipes muck with TARGET_CPPFLAGS to point into -# final target sysroot but we -# are not there when building glibc-initial -# so reset it here - -TARGET_CPPFLAGS = "" diff --git a/meta/recipes-core/glibc/glibc-initial_2.22.bb b/meta/recipes-core/glibc/glibc-initial_2.22.bb new file mode 100644 index 0000000000..8ab01dc79d --- /dev/null +++ b/meta/recipes-core/glibc/glibc-initial_2.22.bb @@ -0,0 +1,11 @@ +require glibc_${PV}.bb +require glibc-initial.inc + +DEPENDS += "kconfig-frontends-native" + +# main glibc recipes muck with TARGET_CPPFLAGS to point into +# final target sysroot but we +# are not there when building glibc-initial +# so reset it here + +TARGET_CPPFLAGS = "" diff --git a/meta/recipes-core/glibc/glibc-locale_2.21.bb b/meta/recipes-core/glibc/glibc-locale_2.21.bb deleted file mode 100644 index f7702e0358..0000000000 --- a/meta/recipes-core/glibc/glibc-locale_2.21.bb +++ /dev/null @@ -1 +0,0 @@ -require glibc-locale.inc diff --git a/meta/recipes-core/glibc/glibc-locale_2.22.bb b/meta/recipes-core/glibc/glibc-locale_2.22.bb new file mode 100644 index 0000000000..f7702e0358 --- /dev/null +++ b/meta/recipes-core/glibc/glibc-locale_2.22.bb @@ -0,0 +1 @@ +require glibc-locale.inc diff --git a/meta/recipes-core/glibc/glibc-mtrace_2.21.bb b/meta/recipes-core/glibc/glibc-mtrace_2.21.bb deleted file mode 100644 index 0b69bad46a..0000000000 --- a/meta/recipes-core/glibc/glibc-mtrace_2.21.bb +++ /dev/null @@ -1 +0,0 @@ -require glibc-mtrace.inc diff --git a/meta/recipes-core/glibc/glibc-mtrace_2.22.bb b/meta/recipes-core/glibc/glibc-mtrace_2.22.bb new file mode 100644 index 0000000000..0b69bad46a --- /dev/null +++ b/meta/recipes-core/glibc/glibc-mtrace_2.22.bb @@ -0,0 +1 @@ +require glibc-mtrace.inc diff --git a/meta/recipes-core/glibc/glibc-scripts_2.21.bb b/meta/recipes-core/glibc/glibc-scripts_2.21.bb deleted file mode 100644 index 5a89bd8022..0000000000 --- a/meta/recipes-core/glibc/glibc-scripts_2.21.bb +++ /dev/null @@ -1 +0,0 @@ -require glibc-scripts.inc diff --git a/meta/recipes-core/glibc/glibc-scripts_2.22.bb b/meta/recipes-core/glibc/glibc-scripts_2.22.bb new file mode 100644 index 0000000000..5a89bd8022 --- /dev/null +++ b/meta/recipes-core/glibc/glibc-scripts_2.22.bb @@ -0,0 +1 @@ +require glibc-scripts.inc diff --git a/meta/recipes-core/glibc/glibc/0001-Add-unused-attribute.patch b/meta/recipes-core/glibc/glibc/0001-Add-unused-attribute.patch deleted file mode 100644 index f51a0ccb22..0000000000 --- a/meta/recipes-core/glibc/glibc/0001-Add-unused-attribute.patch +++ /dev/null @@ -1,36 +0,0 @@ -2015-02-18 Khem Raj > - - * iconv/gconv_charset.h (strip): - Add unused attribute. - -From 9c4a91cb331ff1e8cde2314dadee74559d8cb0dd Mon Sep 17 00:00:00 2001 -From: Khem Raj -Date: Wed, 18 Feb 2015 19:45:31 +0000 -Subject: [PATCH] Add unused attribute - -Helps in avoiding gcc warning when header is is included in -a source file which does not use both functions - -Signed-off-by: Khem Raj - -Upstream-Status: Pending ---- - iconv/gconv_charset.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h -index 80290bc..7890a8e 100644 ---- a/iconv/gconv_charset.h -+++ b/iconv/gconv_charset.h -@@ -21,7 +21,7 @@ - #include - - --static void -+static void __attribute__ ((unused)) - strip (char *wp, const char *s) - { - int slash_count = 0; --- -2.1.4 - diff --git a/meta/recipes-core/glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch b/meta/recipes-core/glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch deleted file mode 100644 index 3922cb818f..0000000000 --- a/meta/recipes-core/glibc/glibc/0001-R_ARM_TLS_DTPOFF32.patch +++ /dev/null @@ -1,56 +0,0 @@ - -Quote from bug 1443 which explains what the patch does : - - We build some random program and link it with -lust. When we run it, - it dies with a SIGSEGV before reaching main(). - - Libust.so depends on liburcu-bp.so from the usermode-rcu package. - Although libust.so is not prelinked, liburcu-bp.so IS prelinked; this - is critical. - - Libust.so uses a TLS / __thread variable that is defined in liburcu- - bp.so. There are special ARM-specific relocation types that allow two - shared libraries to share thread-specific data. This is critical too. - - One more critical issue: although liburcu-bp.so is prelinked, we can't - load it at its prelinked address, because we also link against - librt.so, and librt.so uses that address. - - The dynamic linker is forced to relink liburcu-bp.so at a different - address. In the course of relinking, it processes the special ARM - relocation record mentioned above. The prelinker has already filled - in the information, which is a short offset into a table of thread- - specific data that is allocated per-thread for each library that uses - TLS. Because the normal behavior of a relocation is to add the symbol - value to an addend stored at the address being relocated, we end up - adding the short offset to itself, doubling it. - - Now we have an awkward situation. The libust.so library doesn't know - about the addend, so its TLS data for this element is correct. The - liburcu-bp.so library has a different offset for the element. When we - go to initialize the element for the first time in liburcu-bp.so, we - write the address of the result at the doubled (broken) offset. - Later, when we refer to the address from libust.so, we check the value - at the correct offset, but it's NULL, so we eat hot SIGSEGV. - -Upstream-Status: Pending - -Signed-off-by: Andrei Dinu ---- - .../libc/ports/sysdeps/arm/dl-machine.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -ndex 8d905e8..dcfa71e 100644 -Index: git/sysdeps/arm/dl-machine.h -=================================================================== ---- git.orig/sysdeps/arm/dl-machine.h 2014-08-27 05:30:47.748070587 +0000 -+++ git/sysdeps/arm/dl-machine.h 2014-08-27 05:30:47.740070587 +0000 -@@ -495,7 +495,7 @@ - - case R_ARM_TLS_DTPOFF32: - if (sym != NULL) -- *reloc_addr += sym->st_value; -+ *reloc_addr = sym->st_value; - break; - - case R_ARM_TLS_TPOFF32: diff --git a/meta/recipes-core/glibc/glibc/0001-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch b/meta/recipes-core/glibc/glibc/0001-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch deleted file mode 100644 index a6395b77bc..0000000000 --- a/meta/recipes-core/glibc/glibc/0001-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 6f5639f6405ff9a42e4f71e7b0f18bddb68d992a Mon Sep 17 00:00:00 2001 -From: Khem Raj -Date: Thu, 19 Feb 2015 03:23:45 +0000 -Subject: [PATCH] When disabling SSE also make sure that fpmath is not set to - use SSE as well - -This fixes errors when we inject sse options through CFLAGS and now -that we have -Werror turned on by default this warning turns to become -error on x86 - -Signed-off-by: Khem Raj - -Upstream-Status: Pending ---- - sysdeps/x86/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile -index 19f5eca..827ea71 100644 ---- a/sysdeps/x86/Makefile -+++ b/sysdeps/x86/Makefile -@@ -1,6 +1,6 @@ - ifeq ($(subdir),elf) - CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\ -- -mno-sse -mno-mmx) -+ -mno-sse -mno-mmx -mfpmath=387) - - tests-special += $(objpfx)tst-ld-sse-use.out - $(objpfx)tst-ld-sse-use.out: ../sysdeps/x86/tst-ld-sse-use.sh $(objpfx)ld.so --- -2.1.4 - diff --git a/meta/recipes-core/glibc/glibc/0001-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch b/meta/recipes-core/glibc/glibc/0001-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch deleted file mode 100644 index f341282ffb..0000000000 --- a/meta/recipes-core/glibc/glibc/0001-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 713d822908d1b2ae8403af7f9375c7054ed3dd49 Mon Sep 17 00:00:00 2001 -From: Ting Liu -Date: Wed, 19 Dec 2012 04:39:57 -0600 -Subject: [PATCH] eglibc: run libm-err-tab.pl with specific dirs in ${S} - -libm-err-tab.pl will parse all the files named "libm-test-ulps" -in the given dir recursively. To avoid parsing the one in -${S}/.pc/ (it does exist after eglibc adds aarch64 support, -${S}/.pc/aarch64-0001-glibc-fsf-v1-eaf6f205.patch/ports/sysdeps/ -aarch64/libm-test-ulps), run libm-err-tab.pl with specific dirs -in ${S}. - -Upstream-Status: inappropriate [OE specific] - -Signed-off-by: Ting Liu ---- - manual/Makefile | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -Index: git/manual/Makefile -=================================================================== ---- git.orig/manual/Makefile 2014-08-29 10:35:18.728070587 -0700 -+++ git/manual/Makefile 2014-08-29 10:35:18.720070587 -0700 -@@ -105,7 +105,8 @@ - $(objpfx)stamp-libm-err: libm-err-tab.pl $(wildcard $(foreach dir,$(sysdirs),\ - $(dir)/libm-test-ulps)) - pwd=`pwd`; \ -- $(PERL) $< $$pwd/.. > $(objpfx)libm-err-tmp -+ $(PERL) $< $$pwd/../ports > $(objpfx)libm-err-tmp -+ $(PERL) $< $$pwd/../sysdeps >> $(objpfx)libm-err-tmp - $(move-if-change) $(objpfx)libm-err-tmp $(objpfx)libm-err.texi - touch $@ - diff --git a/meta/recipes-core/glibc/glibc/0001-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch b/meta/recipes-core/glibc/glibc/0001-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch new file mode 100644 index 0000000000..3d66348133 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0001-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch @@ -0,0 +1,70 @@ +From 0876fea1b5b26da84f298714a2e23ba696607dba Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 01:48:24 +0000 +Subject: [PATCH 01/27] nativesdk-glibc: Look for host system ld.so.cache as + well + +Upstream-Status: Inappropriate [embedded specific] + +The default lib search path order is: + + 1) LD_LIBRARY_PATH + 2) RPATH from the binary + 3) ld.so.cache + 4) default search paths embedded in the linker + +For nativesdk binaries which are being used alongside binaries on a host system, we +need the search paths to firstly search the shipped nativesdk libs but then also +cover the host system. For example we want the host system's libGL and this may be +in a non-standard location like /usr/lib/mesa. The only place the location is know +about is in the ld.so.cache of the host system. + +Since nativesdk has a simple structure and doesn't need to use a cache itself, we +repurpose the cache for use as a last resort in finding host system binaries. This +means we need to switch the order of 3 and 4 above to make this work effectively. + +RP 14/10/2010 + +Signed-off-by: Khem Raj +--- + elf/dl-load.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 0c052e4..f45085a 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -2040,7 +2040,14 @@ _dl_map_object (struct link_map *loader, const char *name, + fd = open_path (name, namelen, mode, + &loader->l_runpath_dirs, &realname, &fb, loader, + LA_SER_RUNPATH, &found_other_class); +- ++ /* try the default path. */ ++ if (fd == -1 ++ && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL ++ || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) ++ && rtld_search_dirs.dirs != (void *) -1) ++ fd = open_path (name, namelen, mode & __RTLD_SECURE, &rtld_search_dirs, ++ &realname, &fb, l, LA_SER_DEFAULT, &found_other_class); ++ /* Finally try ld.so.cache */ + #ifdef USE_LDCONFIG + if (fd == -1 + && (__glibc_likely ((mode & __RTLD_SECURE) == 0) +@@ -2099,14 +2106,6 @@ _dl_map_object (struct link_map *loader, const char *name, + } + #endif + +- /* Finally, try the default path. */ +- if (fd == -1 +- && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL +- || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB))) +- && rtld_search_dirs.dirs != (void *) -1) +- fd = open_path (name, namelen, mode, &rtld_search_dirs, +- &realname, &fb, l, LA_SER_DEFAULT, &found_other_class); +- + /* Add another newline when we are tracing the library loading. */ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) + _dl_debug_printf ("\n"); +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0001-yes-within-the-path-sets-wrong-config-variables.patch b/meta/recipes-core/glibc/glibc/0001-yes-within-the-path-sets-wrong-config-variables.patch deleted file mode 100644 index 827e980332..0000000000 --- a/meta/recipes-core/glibc/glibc/0001-yes-within-the-path-sets-wrong-config-variables.patch +++ /dev/null @@ -1,245 +0,0 @@ -'yes' within the path sets wrong config variables - -It seems that the 'AC_EGREP_CPP(yes...' example is quite popular -but being such a short word to grep it is likely to produce -false-positive matches with the path it is configured into. - -The change is to use a more elaborated string to grep for. - -Upstream-Status: Submitted [libc-alpha@sourceware.org] - -Signed-off-by: Benjamin Esquivel ---- -diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure -index 5bd355a..3bc5537 100644 ---- a/sysdeps/aarch64/configure -+++ b/sysdeps/aarch64/configure -@@ -148,12 +148,12 @@ else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - #ifdef __AARCH64EB__ -- yes -+ is_aarch64_be - #endif - - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "is_aarch64_be" >/dev/null 2>&1; then : - libc_cv_aarch64_be=yes - else - libc_cv_aarch64_be=no -diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac -index 7851dd4..6e92381 100644 ---- a/sysdeps/aarch64/configure.ac -+++ b/sysdeps/aarch64/configure.ac -@@ -10,8 +10,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. - # the dynamic linker via %ifdef. - AC_CACHE_CHECK([for big endian], - [libc_cv_aarch64_be], -- [AC_EGREP_CPP(yes,[#ifdef __AARCH64EB__ -- yes -+ [AC_EGREP_CPP(is_aarch64_be,[#ifdef __AARCH64EB__ -+ is_aarch64_be - #endif - ], libc_cv_aarch64_be=yes, libc_cv_aarch64_be=no)]) - if test $libc_cv_aarch64_be = yes; then -diff --git a/sysdeps/arm/configure b/sysdeps/arm/configure -index 45667cc..0b2ef11 100644 ---- a/sysdeps/arm/configure -+++ b/sysdeps/arm/configure -@@ -150,12 +150,12 @@ else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - #ifdef __ARM_PCS_VFP -- yes -+ use_arm_pcs_vfp - #endif - - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "use_arm_pcs_vfp" >/dev/null 2>&1; then : - libc_cv_arm_pcs_vfp=yes - else - libc_cv_arm_pcs_vfp=no -diff --git a/sysdeps/arm/configure.ac b/sysdeps/arm/configure.ac -index 002b8ef..e1746a7 100644 ---- a/sysdeps/arm/configure.ac -+++ b/sysdeps/arm/configure.ac -@@ -16,8 +16,8 @@ dnl it. Until we do, don't define it. - # the dynamic linker via %ifdef. - AC_CACHE_CHECK([whether the compiler is using the ARM hard-float ABI], - [libc_cv_arm_pcs_vfp], -- [AC_EGREP_CPP(yes,[#ifdef __ARM_PCS_VFP -- yes -+ [AC_EGREP_CPP(use_arm_pcs_vfp,[#ifdef __ARM_PCS_VFP -+ use_arm_pcs_vfp - #endif - ], libc_cv_arm_pcs_vfp=yes, libc_cv_arm_pcs_vfp=no)]) - if test $libc_cv_arm_pcs_vfp = yes; then -diff --git a/sysdeps/mips/configure b/sysdeps/mips/configure -index 4e13248..f14af95 100644 ---- a/sysdeps/mips/configure -+++ b/sysdeps/mips/configure -@@ -143,11 +143,11 @@ else - /* end confdefs.h. */ - dnl - #ifdef __mips_nan2008 --yes -+use_mips_nan2008 - #endif - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "use_mips_nan2008" >/dev/null 2>&1; then : - libc_cv_mips_nan2008=yes - else - libc_cv_mips_nan2008=no -diff --git a/sysdeps/mips/configure.ac b/sysdeps/mips/configure.ac -index bcbdaff..ad3057f 100644 ---- a/sysdeps/mips/configure.ac -+++ b/sysdeps/mips/configure.ac -@@ -6,9 +6,9 @@ dnl position independent way. - dnl AC_DEFINE(PI_STATIC_AND_HIDDEN) - - AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding], -- libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl -+ libc_cv_mips_nan2008, [AC_EGREP_CPP(use_mips_nan2008, [dnl - #ifdef __mips_nan2008 --yes -+use_mips_nan2008 - #endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)]) - if test x$libc_cv_mips_nan2008 = xyes; then - AC_DEFINE(HAVE_MIPS_NAN2008) -diff --git a/sysdeps/nios2/configure b/sysdeps/nios2/configure -index 14c8a3a..dde3814 100644 ---- a/sysdeps/nios2/configure -+++ b/sysdeps/nios2/configure -@@ -142,12 +142,12 @@ else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - #ifdef __nios2_big_endian__ -- yes -+ is_nios2_be - #endif - - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "is_nios2_be" >/dev/null 2>&1; then : - libc_cv_nios2_be=yes - else - libc_cv_nios2_be=no -diff --git a/sysdeps/nios2/configure.ac b/sysdeps/nios2/configure.ac -index f05f438..dc86399 100644 ---- a/sysdeps/nios2/configure.ac -+++ b/sysdeps/nios2/configure.ac -@@ -4,8 +4,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. - # Nios II big endian is not yet supported. - AC_CACHE_CHECK([for big endian], - [libc_cv_nios2_be], -- [AC_EGREP_CPP(yes,[#ifdef __nios2_big_endian__ -- yes -+ [AC_EGREP_CPP(is_nios2_be,[#ifdef __nios2_big_endian__ -+ is_nios2_be - #endif - ], libc_cv_nios2_be=yes, libc_cv_nios2_be=no)]) - if test $libc_cv_nios2_be = yes; then -diff --git a/sysdeps/unix/sysv/linux/mips/configure b/sysdeps/unix/sysv/linux/mips/configure -index 83f8b13..2b6cbee 100644 ---- a/sysdeps/unix/sysv/linux/mips/configure -+++ b/sysdeps/unix/sysv/linux/mips/configure -@@ -387,11 +387,11 @@ else - /* end confdefs.h. */ - dnl - #ifdef __mips_nan2008 --yes -+use_mips_nan2008 - #endif - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "use_mips_nan2008" >/dev/null 2>&1; then : - libc_cv_mips_nan2008=yes - else - libc_cv_mips_nan2008=no -diff --git a/sysdeps/unix/sysv/linux/mips/configure.ac b/sysdeps/unix/sysv/linux/mips/configure.ac -index 5039ec9..1035f76 100644 ---- a/sysdeps/unix/sysv/linux/mips/configure.ac -+++ b/sysdeps/unix/sysv/linux/mips/configure.ac -@@ -98,9 +98,9 @@ AC_COMPILE_IFELSE( - LIBC_CONFIG_VAR([mips-mode-switch],[${libc_mips_mode_switch}]) - - AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding], -- libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl -+ libc_cv_mips_nan2008, [AC_EGREP_CPP(use_mips_nan2008, [dnl - #ifdef __mips_nan2008 --yes -+use_mips_nan2008 - #endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)]) - - libc_mips_nan= -diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure -index 70bb18a..ffd9e3e 100644 ---- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure -+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure -@@ -155,12 +155,12 @@ else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - #if _CALL_ELF == 2 -- yes -+ use_ppc_elfv2_abi - #endif - - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "use_ppc_elfv2_abi" >/dev/null 2>&1; then : - libc_cv_ppc64_elfv2_abi=yes - else - libc_cv_ppc64_elfv2_abi=no -@@ -188,12 +188,12 @@ else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - #ifdef _CALL_ELF -- yes -+ is_def_call_elf - #endif - - _ACEOF - if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -- $EGREP "yes" >/dev/null 2>&1; then : -+ $EGREP "is_def_call_elf" >/dev/null 2>&1; then : - libc_cv_ppc64_def_call_elf=yes - else - libc_cv_ppc64_def_call_elf=no -diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac -index 0822915..9a32fdd 100644 ---- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac -+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac -@@ -6,8 +6,8 @@ LIBC_SLIBDIR_RTLDDIR([lib64], [lib64]) - # Define default-abi according to compiler flags. - AC_CACHE_CHECK([whether the compiler is using the PowerPC64 ELFv2 ABI], - [libc_cv_ppc64_elfv2_abi], -- [AC_EGREP_CPP(yes,[#if _CALL_ELF == 2 -- yes -+ [AC_EGREP_CPP(use_ppc_elfv2_abi,[#if _CALL_ELF == 2 -+ use_ppc_elfv2_abi - #endif - ], libc_cv_ppc64_elfv2_abi=yes, libc_cv_ppc64_elfv2_abi=no)]) - if test $libc_cv_ppc64_elfv2_abi = yes; then -@@ -19,8 +19,8 @@ else - # Compiler that do not support ELFv2 ABI does not define _CALL_ELF - AC_CACHE_CHECK([whether the compiler defines _CALL_ELF], - [libc_cv_ppc64_def_call_elf], -- [AC_EGREP_CPP(yes,[#ifdef _CALL_ELF -- yes -+ [AC_EGREP_CPP(is_def_call_elf,[#ifdef _CALL_ELF -+ is_def_call_elf - #endif - ], libc_cv_ppc64_def_call_elf=yes, libc_cv_ppc64_def_call_elf=no)]) - if test $libc_cv_ppc64_def_call_elf = no; then --- -1.8.4.5 - diff --git a/meta/recipes-core/glibc/glibc/0002-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch b/meta/recipes-core/glibc/glibc/0002-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch new file mode 100644 index 0000000000..b568fc6bdc --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0002-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch @@ -0,0 +1,50 @@ +From 086b65d9aacffc47fcd8df68818a476a5ae76fa1 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 01:50:00 +0000 +Subject: [PATCH 02/27] nativesdk-glibc: Fix buffer overrun with a relocated + SDK + +When ld-linux-*.so.2 is relocated to a path that is longer than the +original fixed location, the dynamic loader will crash in open_path +because it implicitly assumes that max_dirnamelen is a fixed size that +never changes. + +The allocated buffer will not be large enough to contain the directory +path string which is larger than the fixed location provided at build +time. + +Upstream-Status: Inappropriate [OE SDK specific] + +Signed-off-by: Jason Wessel +Signed-off-by: Khem Raj +--- + elf/dl-load.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index f45085a..f1eb5ed 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1765,7 +1765,19 @@ open_path (const char *name, size_t namelen, int mode, + given on the command line when rtld is run directly. */ + return -1; + ++ do ++ { ++ struct r_search_path_elem *this_dir = *dirs; ++ if (this_dir->dirnamelen > max_dirnamelen) ++ { ++ max_dirnamelen = this_dir->dirnamelen; ++ } ++ } ++ while (*++dirs != NULL); ++ + buf = alloca (max_dirnamelen + max_capstrlen + namelen); ++ ++ dirs = sps->dirs; + do + { + struct r_search_path_elem *this_dir = *dirs; +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0003-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch b/meta/recipes-core/glibc/glibc/0003-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch new file mode 100644 index 0000000000..a681a64e85 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0003-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch @@ -0,0 +1,126 @@ +From fd595a5ec885bcb4c14417daa21c2e61c5b72e42 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 01:51:38 +0000 +Subject: [PATCH 03/27] nativesdk-glibc: Raise the size of arrays containing dl + paths + +This patch puts the dynamic loader path in the binaries, SYSTEM_DIRS strings +and lengths as well as ld.so.cache path in the dynamic loader to specific +sections in memory. The sections that contain paths have been allocated a 4096 +byte section, which is the maximum path length in linux. This will allow the +relocating script to parse the ELF binary, detect the section and easily replace +the strings in a certain path. + +Upstream-Status: Inappropriate [SDK specific] + +Signed-off-by: Laurentiu Palcu +Signed-off-by: Khem Raj +--- + elf/dl-cache.c | 4 ++++ + elf/dl-load.c | 4 ++-- + elf/interp.c | 2 +- + elf/ldconfig.c | 3 +++ + elf/rtld.c | 5 +++-- + sysdeps/generic/dl-cache.h | 4 ---- + 6 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index dec49bc..862f1d8 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -132,6 +132,10 @@ do \ + while (0) + + ++const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))) = ++ SYSCONFDIR "/ld.so.cache"; ++ ++ + int + internal_function + _dl_cache_libcmp (const char *p1, const char *p2) +diff --git a/elf/dl-load.c b/elf/dl-load.c +index f1eb5ed..f664f50 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -104,8 +104,8 @@ static size_t max_capstrlen attribute_relro; + /* Get the generated information about the trusted directories. */ + #include "trusted-dirs.h" + +-static const char system_dirs[] = SYSTEM_DIRS; +-static const size_t system_dirs_len[] = ++static const char system_dirs[4096] __attribute__ ((section (".sysdirs"))) = SYSTEM_DIRS; ++volatile static const size_t system_dirs_len[] __attribute__ ((section (".sysdirslen"))) = + { + SYSTEM_DIRS_LEN + }; +diff --git a/elf/interp.c b/elf/interp.c +index 422ea95e..6d61a36 100644 +--- a/elf/interp.c ++++ b/elf/interp.c +@@ -18,5 +18,5 @@ + + #include + +-const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp"))) ++const char __invoke_dynamic_linker__[4096] __attribute__ ((section (".interp"))) + = RUNTIME_LINKER; +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index f54ec22..0e78a83 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -167,6 +167,9 @@ static struct argp argp = + options, parse_opt, NULL, doc, NULL, more_help, NULL + }; + ++ ++extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))); ++ + /* Check if string corresponds to an important hardware capability or + a platform. */ + static int +diff --git a/elf/rtld.c b/elf/rtld.c +index 69873c2..6d3add7 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -99,6 +99,7 @@ uintptr_t __pointer_chk_guard_local + strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) + #endif + ++extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))); + + /* List of auditing DSOs. */ + static struct audit_list +@@ -877,12 +878,12 @@ of this helper program; chances are you did not intend to run this program.\n\ + --list list all dependencies and how they are resolved\n\ + --verify verify that given object really is a dynamically linked\n\ + object we can handle\n\ +- --inhibit-cache Do not use " LD_SO_CACHE "\n\ ++ --inhibit-cache Do not use %s\n\ + --library-path PATH use given PATH instead of content of the environment\n\ + variable LD_LIBRARY_PATH\n\ + --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ + in LIST\n\ +- --audit LIST use objects named in LIST as auditors\n"); ++ --audit LIST use objects named in LIST as auditors\n", LD_SO_CACHE); + + ++_dl_skip_args; + --_dl_argc; +diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h +index 4b49869..1800d03 100644 +--- a/sysdeps/generic/dl-cache.h ++++ b/sysdeps/generic/dl-cache.h +@@ -27,10 +27,6 @@ + ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID) + #endif + +-#ifndef LD_SO_CACHE +-# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache" +-#endif +- + #ifndef add_system_dir + # define add_system_dir(dir) add_dir (dir) + #endif +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0004-Backport-https-sourceware.org-ml-libc-ports-2007-12-.patch b/meta/recipes-core/glibc/glibc/0004-Backport-https-sourceware.org-ml-libc-ports-2007-12-.patch new file mode 100644 index 0000000000..748750304f --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0004-Backport-https-sourceware.org-ml-libc-ports-2007-12-.patch @@ -0,0 +1,34 @@ +From 2560b564b5674bf2990e5607f6342c1647a5dc4f Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Sun, 8 Mar 2015 04:01:01 +0000 +Subject: [PATCH 04/27] Backport + https://sourceware.org/ml/libc-ports/2007-12/msg00000.html + +Upstream-Status: Pending + +2007-12-03 Kristian Van Der Vliet + + * bits/stdio-lock.h (_IO_acquire_lock_clear_flags2): Define + +Signed-off-by: Kristian Van Der Vliet +Signed-off-by: Khem Raj +--- + bits/stdio-lock.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/bits/stdio-lock.h b/bits/stdio-lock.h +index 0c5bb65..66304a6 100644 +--- a/bits/stdio-lock.h ++++ b/bits/stdio-lock.h +@@ -49,6 +49,8 @@ __libc_lock_define_recursive (typedef, _IO_lock_t) + _IO_cleanup_region_start ((void (*) (void *)) _IO_funlockfile, (_fp)); \ + _IO_flockfile (_fp) + ++# define _IO_acquire_lock_clear_flags2(_fp) _IO_acquire_lock (_fp) ++ + # define _IO_release_lock(_fp) \ + _IO_funlockfile (_fp); \ + _IO_cleanup_region_end (0) +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0005-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch b/meta/recipes-core/glibc/glibc/0005-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch new file mode 100644 index 0000000000..8d3f859555 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0005-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch @@ -0,0 +1,1584 @@ +From aa0cd82892f32e58602143c697ef0524696a6428 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:01:50 +0000 +Subject: [PATCH 05/27] fsl e500/e5500/e6500/603e fsqrt implementation + +Upstream-Status: Pending +Signed-off-by: Edmar Wienskoski +Signed-off-by: Khem Raj +--- + sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c | 134 +++++++++++++++++++++ + sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c | 101 ++++++++++++++++ + sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c | 134 +++++++++++++++++++++ + sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c | 101 ++++++++++++++++ + sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c | 134 +++++++++++++++++++++ + sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c | 101 ++++++++++++++++ + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c | 134 +++++++++++++++++++++ + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c | 101 ++++++++++++++++ + sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c | 134 +++++++++++++++++++++ + sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c | 101 ++++++++++++++++ + sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c | 134 +++++++++++++++++++++ + sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c | 101 ++++++++++++++++ + .../sysv/linux/powerpc/powerpc32/603e/fpu/Implies | 1 + + .../linux/powerpc/powerpc32/e300c3/fpu/Implies | 2 + + .../linux/powerpc/powerpc32/e500mc/fpu/Implies | 1 + + .../sysv/linux/powerpc/powerpc32/e5500/fpu/Implies | 1 + + .../sysv/linux/powerpc/powerpc32/e6500/fpu/Implies | 1 + + .../sysv/linux/powerpc/powerpc64/e5500/fpu/Implies | 1 + + .../sysv/linux/powerpc/powerpc64/e6500/fpu/Implies | 1 + + 19 files changed, 1418 insertions(+) + create mode 100644 sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c + create mode 100644 sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c + create mode 100644 sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c + create mode 100644 sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c + create mode 100644 sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c + create mode 100644 sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c + create mode 100644 sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c + create mode 100644 sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c + create mode 100644 sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c + create mode 100644 sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c + create mode 100644 sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c + create mode 100644 sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies + create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies + +diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c +new file mode 100644 +index 0000000..71e516d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c +@@ -0,0 +1,134 @@ ++/* Double-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float two108 = 3.245185536584267269e+32; ++static const float twom54 = 5.551115123125782702e-17; ++static const float half = 0.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the actual square root and half of its reciprocal ++ simultaneously. */ ++ ++#ifdef __STDC__ ++double ++__ieee754_sqrt (double b) ++#else ++double ++__ieee754_sqrt (b) ++ double b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++ double y, g, h, d, r; ++ ieee_double_shape_type u; ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ u.value = b; ++ ++ relax_fenv_state (); ++ ++ __asm__ ("frsqrte %[estimate], %[x]\n" ++ : [estimate] "=f" (y) : [x] "f" (b)); ++ ++ /* Following Muller et al, page 168, equation 5.20. ++ ++ h goes to 1/(2*sqrt(b)) ++ g goes to sqrt(b). ++ ++ We need three iterations to get within 1ulp. */ ++ ++ /* Indicate that these can be performed prior to the branch. GCC ++ insists on sinking them below the branch, however; it seems like ++ they'd be better before the branch so that we can cover any latency ++ from storing the argument and loading its high word. Oh well. */ ++ ++ g = b * y; ++ h = 0.5 * y; ++ ++ /* Handle small numbers by scaling. */ ++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) ++ return __ieee754_sqrt (b * two108) * twom54; ++ ++#define FMADD(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ ++ ++ /* Final refinement. */ ++ d = FNMSUB (g, g, b); ++ ++ fesetenv_register (fe); ++ return FMADD (d, h, g); ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_wash (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c +new file mode 100644 +index 0000000..26fa067 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c +@@ -0,0 +1,101 @@ ++/* Single-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float threehalf = 1.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the reciprocal square root and use that to compute the actual ++ square root. */ ++ ++#ifdef __STDC__ ++float ++__ieee754_sqrtf (float b) ++#else ++float ++__ieee754_sqrtf (b) ++ float b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++#define FMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ double y, x; ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ relax_fenv_state (); ++ ++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ ++ y = FMSUB (threehalf, b, b); ++ ++ /* Initial estimate. */ ++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); ++ ++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ ++ /* All done. */ ++ fesetenv_register (fe); ++ return x * b; ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_washf (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c +new file mode 100644 +index 0000000..71e516d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c +@@ -0,0 +1,134 @@ ++/* Double-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float two108 = 3.245185536584267269e+32; ++static const float twom54 = 5.551115123125782702e-17; ++static const float half = 0.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the actual square root and half of its reciprocal ++ simultaneously. */ ++ ++#ifdef __STDC__ ++double ++__ieee754_sqrt (double b) ++#else ++double ++__ieee754_sqrt (b) ++ double b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++ double y, g, h, d, r; ++ ieee_double_shape_type u; ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ u.value = b; ++ ++ relax_fenv_state (); ++ ++ __asm__ ("frsqrte %[estimate], %[x]\n" ++ : [estimate] "=f" (y) : [x] "f" (b)); ++ ++ /* Following Muller et al, page 168, equation 5.20. ++ ++ h goes to 1/(2*sqrt(b)) ++ g goes to sqrt(b). ++ ++ We need three iterations to get within 1ulp. */ ++ ++ /* Indicate that these can be performed prior to the branch. GCC ++ insists on sinking them below the branch, however; it seems like ++ they'd be better before the branch so that we can cover any latency ++ from storing the argument and loading its high word. Oh well. */ ++ ++ g = b * y; ++ h = 0.5 * y; ++ ++ /* Handle small numbers by scaling. */ ++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) ++ return __ieee754_sqrt (b * two108) * twom54; ++ ++#define FMADD(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ ++ ++ /* Final refinement. */ ++ d = FNMSUB (g, g, b); ++ ++ fesetenv_register (fe); ++ return FMADD (d, h, g); ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_wash (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c +new file mode 100644 +index 0000000..26fa067 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c +@@ -0,0 +1,101 @@ ++/* Single-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float threehalf = 1.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the reciprocal square root and use that to compute the actual ++ square root. */ ++ ++#ifdef __STDC__ ++float ++__ieee754_sqrtf (float b) ++#else ++float ++__ieee754_sqrtf (b) ++ float b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++#define FMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ double y, x; ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ relax_fenv_state (); ++ ++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ ++ y = FMSUB (threehalf, b, b); ++ ++ /* Initial estimate. */ ++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); ++ ++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ ++ /* All done. */ ++ fesetenv_register (fe); ++ return x * b; ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_washf (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c +new file mode 100644 +index 0000000..71e516d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c +@@ -0,0 +1,134 @@ ++/* Double-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float two108 = 3.245185536584267269e+32; ++static const float twom54 = 5.551115123125782702e-17; ++static const float half = 0.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the actual square root and half of its reciprocal ++ simultaneously. */ ++ ++#ifdef __STDC__ ++double ++__ieee754_sqrt (double b) ++#else ++double ++__ieee754_sqrt (b) ++ double b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++ double y, g, h, d, r; ++ ieee_double_shape_type u; ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ u.value = b; ++ ++ relax_fenv_state (); ++ ++ __asm__ ("frsqrte %[estimate], %[x]\n" ++ : [estimate] "=f" (y) : [x] "f" (b)); ++ ++ /* Following Muller et al, page 168, equation 5.20. ++ ++ h goes to 1/(2*sqrt(b)) ++ g goes to sqrt(b). ++ ++ We need three iterations to get within 1ulp. */ ++ ++ /* Indicate that these can be performed prior to the branch. GCC ++ insists on sinking them below the branch, however; it seems like ++ they'd be better before the branch so that we can cover any latency ++ from storing the argument and loading its high word. Oh well. */ ++ ++ g = b * y; ++ h = 0.5 * y; ++ ++ /* Handle small numbers by scaling. */ ++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) ++ return __ieee754_sqrt (b * two108) * twom54; ++ ++#define FMADD(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ ++ ++ /* Final refinement. */ ++ d = FNMSUB (g, g, b); ++ ++ fesetenv_register (fe); ++ return FMADD (d, h, g); ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_wash (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c +new file mode 100644 +index 0000000..26fa067 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c +@@ -0,0 +1,101 @@ ++/* Single-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float threehalf = 1.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the reciprocal square root and use that to compute the actual ++ square root. */ ++ ++#ifdef __STDC__ ++float ++__ieee754_sqrtf (float b) ++#else ++float ++__ieee754_sqrtf (b) ++ float b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++#define FMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ double y, x; ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ relax_fenv_state (); ++ ++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ ++ y = FMSUB (threehalf, b, b); ++ ++ /* Initial estimate. */ ++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); ++ ++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ ++ /* All done. */ ++ fesetenv_register (fe); ++ return x * b; ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_washf (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +new file mode 100644 +index 0000000..71e516d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +@@ -0,0 +1,134 @@ ++/* Double-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float two108 = 3.245185536584267269e+32; ++static const float twom54 = 5.551115123125782702e-17; ++static const float half = 0.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the actual square root and half of its reciprocal ++ simultaneously. */ ++ ++#ifdef __STDC__ ++double ++__ieee754_sqrt (double b) ++#else ++double ++__ieee754_sqrt (b) ++ double b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++ double y, g, h, d, r; ++ ieee_double_shape_type u; ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ u.value = b; ++ ++ relax_fenv_state (); ++ ++ __asm__ ("frsqrte %[estimate], %[x]\n" ++ : [estimate] "=f" (y) : [x] "f" (b)); ++ ++ /* Following Muller et al, page 168, equation 5.20. ++ ++ h goes to 1/(2*sqrt(b)) ++ g goes to sqrt(b). ++ ++ We need three iterations to get within 1ulp. */ ++ ++ /* Indicate that these can be performed prior to the branch. GCC ++ insists on sinking them below the branch, however; it seems like ++ they'd be better before the branch so that we can cover any latency ++ from storing the argument and loading its high word. Oh well. */ ++ ++ g = b * y; ++ h = 0.5 * y; ++ ++ /* Handle small numbers by scaling. */ ++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) ++ return __ieee754_sqrt (b * two108) * twom54; ++ ++#define FMADD(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ ++ ++ /* Final refinement. */ ++ d = FNMSUB (g, g, b); ++ ++ fesetenv_register (fe); ++ return FMADD (d, h, g); ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_wash (b); ++} +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +new file mode 100644 +index 0000000..26fa067 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +@@ -0,0 +1,101 @@ ++/* Single-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float threehalf = 1.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the reciprocal square root and use that to compute the actual ++ square root. */ ++ ++#ifdef __STDC__ ++float ++__ieee754_sqrtf (float b) ++#else ++float ++__ieee754_sqrtf (b) ++ float b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++#define FMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ double y, x; ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ relax_fenv_state (); ++ ++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ ++ y = FMSUB (threehalf, b, b); ++ ++ /* Initial estimate. */ ++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); ++ ++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ ++ /* All done. */ ++ fesetenv_register (fe); ++ return x * b; ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_washf (b); ++} +diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c +new file mode 100644 +index 0000000..71e516d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c +@@ -0,0 +1,134 @@ ++/* Double-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float two108 = 3.245185536584267269e+32; ++static const float twom54 = 5.551115123125782702e-17; ++static const float half = 0.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the actual square root and half of its reciprocal ++ simultaneously. */ ++ ++#ifdef __STDC__ ++double ++__ieee754_sqrt (double b) ++#else ++double ++__ieee754_sqrt (b) ++ double b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++ double y, g, h, d, r; ++ ieee_double_shape_type u; ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ u.value = b; ++ ++ relax_fenv_state (); ++ ++ __asm__ ("frsqrte %[estimate], %[x]\n" ++ : [estimate] "=f" (y) : [x] "f" (b)); ++ ++ /* Following Muller et al, page 168, equation 5.20. ++ ++ h goes to 1/(2*sqrt(b)) ++ g goes to sqrt(b). ++ ++ We need three iterations to get within 1ulp. */ ++ ++ /* Indicate that these can be performed prior to the branch. GCC ++ insists on sinking them below the branch, however; it seems like ++ they'd be better before the branch so that we can cover any latency ++ from storing the argument and loading its high word. Oh well. */ ++ ++ g = b * y; ++ h = 0.5 * y; ++ ++ /* Handle small numbers by scaling. */ ++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) ++ return __ieee754_sqrt (b * two108) * twom54; ++ ++#define FMADD(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ ++ ++ /* Final refinement. */ ++ d = FNMSUB (g, g, b); ++ ++ fesetenv_register (fe); ++ return FMADD (d, h, g); ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_wash (b); ++} +diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c +new file mode 100644 +index 0000000..26fa067 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c +@@ -0,0 +1,101 @@ ++/* Single-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float threehalf = 1.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the reciprocal square root and use that to compute the actual ++ square root. */ ++ ++#ifdef __STDC__ ++float ++__ieee754_sqrtf (float b) ++#else ++float ++__ieee754_sqrtf (b) ++ float b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++#define FMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ double y, x; ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ relax_fenv_state (); ++ ++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ ++ y = FMSUB (threehalf, b, b); ++ ++ /* Initial estimate. */ ++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); ++ ++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ ++ /* All done. */ ++ fesetenv_register (fe); ++ return x * b; ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_washf (b); ++} +diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c +new file mode 100644 +index 0000000..71e516d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c +@@ -0,0 +1,134 @@ ++/* Double-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float two108 = 3.245185536584267269e+32; ++static const float twom54 = 5.551115123125782702e-17; ++static const float half = 0.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the actual square root and half of its reciprocal ++ simultaneously. */ ++ ++#ifdef __STDC__ ++double ++__ieee754_sqrt (double b) ++#else ++double ++__ieee754_sqrt (b) ++ double b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++ double y, g, h, d, r; ++ ieee_double_shape_type u; ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ u.value = b; ++ ++ relax_fenv_state (); ++ ++ __asm__ ("frsqrte %[estimate], %[x]\n" ++ : [estimate] "=f" (y) : [x] "f" (b)); ++ ++ /* Following Muller et al, page 168, equation 5.20. ++ ++ h goes to 1/(2*sqrt(b)) ++ g goes to sqrt(b). ++ ++ We need three iterations to get within 1ulp. */ ++ ++ /* Indicate that these can be performed prior to the branch. GCC ++ insists on sinking them below the branch, however; it seems like ++ they'd be better before the branch so that we can cover any latency ++ from storing the argument and loading its high word. Oh well. */ ++ ++ g = b * y; ++ h = 0.5 * y; ++ ++ /* Handle small numbers by scaling. */ ++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) ++ return __ieee754_sqrt (b * two108) * twom54; ++ ++#define FMADD(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ r = FNMSUB (g, h, half); ++ g = FMADD (g, r, g); ++ h = FMADD (h, r, h); ++ ++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ ++ ++ /* Final refinement. */ ++ d = FNMSUB (g, g, b); ++ ++ fesetenv_register (fe); ++ return FMADD (d, h, g); ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_wash (b); ++} +diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c +new file mode 100644 +index 0000000..26fa067 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c +@@ -0,0 +1,101 @@ ++/* Single-precision floating point square root. ++ Copyright (C) 2010 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; ++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; ++static const float threehalf = 1.5; ++ ++/* The method is based on the descriptions in: ++ ++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; ++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 ++ ++ We find the reciprocal square root and use that to compute the actual ++ square root. */ ++ ++#ifdef __STDC__ ++float ++__ieee754_sqrtf (float b) ++#else ++float ++__ieee754_sqrtf (b) ++ float b; ++#endif ++{ ++ if (__builtin_expect (b > 0, 1)) ++ { ++#define FMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++#define FNMSUB(a_, c_, b_) \ ++ ({ double __r; \ ++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ ++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ ++ __r;}) ++ ++ if (__builtin_expect (b != a_inf.value, 1)) ++ { ++ double y, x; ++ fenv_t fe; ++ ++ fe = fegetenv_register (); ++ ++ relax_fenv_state (); ++ ++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ ++ y = FMSUB (threehalf, b, b); ++ ++ /* Initial estimate. */ ++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); ++ ++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ x = x * FNMSUB (y, x * x, threehalf); ++ ++ /* All done. */ ++ fesetenv_register (fe); ++ return x * b; ++ } ++ } ++ else if (b < 0) ++ { ++ /* For some reason, some PowerPC32 processors don't implement ++ FE_INVALID_SQRT. */ ++#ifdef FE_INVALID_SQRT ++ feraiseexcept (FE_INVALID_SQRT); ++ ++ fenv_union_t u = { .fenv = fegetenv_register () }; ++ if ((u.l & FE_INVALID) == 0) ++#endif ++ feraiseexcept (FE_INVALID); ++ b = a_nan.value; ++ } ++ return f_washf (b); ++} +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies +new file mode 100644 +index 0000000..b103b4d +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies +@@ -0,0 +1 @@ ++powerpc/powerpc32/603e/fpu +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies +new file mode 100644 +index 0000000..64db17f +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies +@@ -0,0 +1,2 @@ ++# e300c3 is a variant of 603e so use the same optimizations for sqrt ++powerpc/powerpc32/603e/fpu +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies +new file mode 100644 +index 0000000..7eac5fc +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies +@@ -0,0 +1 @@ ++powerpc/powerpc32/e500mc/fpu +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies +new file mode 100644 +index 0000000..264b2a7 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies +@@ -0,0 +1 @@ ++powerpc/powerpc32/e5500/fpu +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies +new file mode 100644 +index 0000000..a259344 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies +@@ -0,0 +1 @@ ++powerpc/powerpc32/e6500/fpu +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies +new file mode 100644 +index 0000000..a7bc854 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies +@@ -0,0 +1 @@ ++powerpc/powerpc64/e5500/fpu +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies +new file mode 100644 +index 0000000..04ff8cc +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies +@@ -0,0 +1 @@ ++powerpc/powerpc64/e6500/fpu +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0006-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch b/meta/recipes-core/glibc/glibc/0006-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch new file mode 100644 index 0000000000..65c227ff20 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0006-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch @@ -0,0 +1,33 @@ +From 5ec1bc5172851278231ce940b68b35ce9cbf8500 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:11:22 +0000 +Subject: [PATCH 06/27] readlib: Add OECORE_KNOWN_INTERPRETER_NAMES to known + names + +This bolts in a hook for OE to pass its own version of interpreter +names into glibc especially for multilib case, where it differs from any +other distros + +Upstream-Status: Inappropriate [OE specific] + +Signed-off-by: Lianhao Lu +Signed-off-by: Khem Raj +--- + elf/readlib.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/elf/readlib.c b/elf/readlib.c +index 7fd5b8a..2f5da9f 100644 +--- a/elf/readlib.c ++++ b/elf/readlib.c +@@ -51,6 +51,7 @@ static struct known_names interpreters[] = + #ifdef SYSDEP_KNOWN_INTERPRETER_NAMES + SYSDEP_KNOWN_INTERPRETER_NAMES + #endif ++ OECORE_KNOWN_INTERPRETER_NAMES + }; + + static struct known_names known_libs[] = +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0007-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch b/meta/recipes-core/glibc/glibc/0007-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch new file mode 100644 index 0000000000..aec8fbeb9a --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0007-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch @@ -0,0 +1,208 @@ +From ea98b1a12b5f779fd79478ff930a79ef60387851 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:15:07 +0000 +Subject: [PATCH 07/27] ppc/sqrt: Fix undefined reference to `__sqrt_finite' + +on ppc fixes the errors like below +| ./.libs/libpulsecore-1.1.so: undefined reference to `__sqrt_finite' +| collect2: ld returned 1 exit status + +Upstream-Status: Pending + +ChangeLog + +2012-01-06 Khem Raj + + * sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c: Add __*_finite alias. + Remove cruft. + * sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c: Ditto. + * sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c: Ditto. + * sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c: Ditto. + +Signed-off-by: Khem Raj +--- + sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c | 7 +------ + sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c | 7 +------ + sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c | 1 + + sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c | 1 + + sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c | 1 + + sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c | 1 + + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c | 1 + + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c | 1 + + sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c | 7 +------ + sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c | 7 +------ + sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c | 1 + + sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c | 1 + + 12 files changed, 12 insertions(+), 24 deletions(-) + +diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c +index 71e516d..1795fd6 100644 +--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c +@@ -39,14 +39,8 @@ static const float half = 0.5; + We find the actual square root and half of its reciprocal + simultaneously. */ + +-#ifdef __STDC__ + double + __ieee754_sqrt (double b) +-#else +-double +-__ieee754_sqrt (b) +- double b; +-#endif + { + if (__builtin_expect (b > 0, 1)) + { +@@ -132,3 +126,4 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c +index 26fa067..a917f31 100644 +--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c +@@ -37,14 +37,8 @@ static const float threehalf = 1.5; + We find the reciprocal square root and use that to compute the actual + square root. */ + +-#ifdef __STDC__ + float + __ieee754_sqrtf (float b) +-#else +-float +-__ieee754_sqrtf (b) +- float b; +-#endif + { + if (__builtin_expect (b > 0, 1)) + { +@@ -99,3 +93,4 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c +index 71e516d..fc4a749 100644 +--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c +@@ -132,3 +132,4 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c +index 26fa067..9d17512 100644 +--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c +@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c +index 71e516d..fc4a749 100644 +--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c +@@ -132,3 +132,4 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c +index 26fa067..9d17512 100644 +--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c +@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +index 71e516d..fc4a749 100644 +--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +@@ -132,3 +132,4 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +index 26fa067..9d17512 100644 +--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c +index 71e516d..1795fd6 100644 +--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c +@@ -39,14 +39,8 @@ static const float half = 0.5; + We find the actual square root and half of its reciprocal + simultaneously. */ + +-#ifdef __STDC__ + double + __ieee754_sqrt (double b) +-#else +-double +-__ieee754_sqrt (b) +- double b; +-#endif + { + if (__builtin_expect (b > 0, 1)) + { +@@ -132,3 +126,4 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c +index 26fa067..a917f31 100644 +--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c +@@ -37,14 +37,8 @@ static const float threehalf = 1.5; + We find the reciprocal square root and use that to compute the actual + square root. */ + +-#ifdef __STDC__ + float + __ieee754_sqrtf (float b) +-#else +-float +-__ieee754_sqrtf (b) +- float b; +-#endif + { + if (__builtin_expect (b > 0, 1)) + { +@@ -99,3 +93,4 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c +index 71e516d..fc4a749 100644 +--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c +@@ -132,3 +132,4 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c +index 26fa067..9d17512 100644 +--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c +@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++strong_alias (__ieee754_sqrtf, __sqrtf_finite) +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0008-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch b/meta/recipes-core/glibc/glibc/0008-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch new file mode 100644 index 0000000000..b3fa931c6c --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0008-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch @@ -0,0 +1,387 @@ +From 2456ea44aeeedae87edb522f77a7969d636399b0 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:16:38 +0000 +Subject: [PATCH 08/27] __ieee754_sqrt{,f} are now inline functions and call + out __slow versions + +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c | 12 ++++++++++-- + sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c | 8 +++++++- + sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c | 14 +++++++++++--- + sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c | 12 ++++++++++-- + sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c | 14 +++++++++++--- + sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c | 12 ++++++++++-- + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c | 8 ++++++++ + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c | 8 ++++++++ + sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c | 12 ++++++++++-- + sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c | 9 ++++++++- + sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c | 14 +++++++++++--- + sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c | 12 ++++++++++-- + 12 files changed, 114 insertions(+), 21 deletions(-) + +diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c +index 1795fd6..daa83f3 100644 +--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c +@@ -40,7 +40,7 @@ static const float half = 0.5; + simultaneously. */ + + double +-__ieee754_sqrt (double b) ++__slow_ieee754_sqrt (double b) + { + if (__builtin_expect (b > 0, 1)) + { +@@ -77,7 +77,7 @@ __ieee754_sqrt (double b) + + /* Handle small numbers by scaling. */ + if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) +- return __ieee754_sqrt (b * two108) * twom54; ++ return __slow_ieee754_sqrt (b * two108) * twom54; + + #define FMADD(a_, c_, b_) \ + ({ double __r; \ +@@ -126,4 +126,12 @@ __ieee754_sqrt (double b) + } + return f_wash (b); + } ++ ++#undef __ieee754_sqrt ++double ++__ieee754_sqrt (double x) ++{ ++ return __slow_ieee754_sqrt (x); ++} ++ + strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c +index a917f31..b812cf1 100644 +--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c +@@ -38,7 +38,7 @@ static const float threehalf = 1.5; + square root. */ + + float +-__ieee754_sqrtf (float b) ++__slow_ieee754_sqrtf (float b) + { + if (__builtin_expect (b > 0, 1)) + { +@@ -93,4 +93,10 @@ __ieee754_sqrtf (float b) + } + return f_washf (b); + } ++#undef __ieee754_sqrtf ++float ++__ieee754_sqrtf (float x) ++{ ++ return __slow_ieee754_sqrtf (x); ++} + strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c +index fc4a749..7038a70 100644 +--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c +@@ -41,10 +41,10 @@ static const float half = 0.5; + + #ifdef __STDC__ + double +-__ieee754_sqrt (double b) ++__slow_ieee754_sqrt (double b) + #else + double +-__ieee754_sqrt (b) ++__slow_ieee754_sqrt (b) + double b; + #endif + { +@@ -83,7 +83,7 @@ __ieee754_sqrt (b) + + /* Handle small numbers by scaling. */ + if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) +- return __ieee754_sqrt (b * two108) * twom54; ++ return __slow_ieee754_sqrt (b * two108) * twom54; + + #define FMADD(a_, c_, b_) \ + ({ double __r; \ +@@ -132,4 +132,12 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++ ++#undef __ieee754_sqrt ++double ++__ieee754_sqrt (double x) ++{ ++ return __slow_ieee754_sqrt (x); ++} ++ + strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c +index 9d17512..10de1f0 100644 +--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c +@@ -39,10 +39,10 @@ static const float threehalf = 1.5; + + #ifdef __STDC__ + float +-__ieee754_sqrtf (float b) ++__slow_ieee754_sqrtf (float b) + #else + float +-__ieee754_sqrtf (b) ++__slow_ieee754_sqrtf (b) + float b; + #endif + { +@@ -99,4 +99,12 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++ ++#undef __ieee754_sqrtf ++float ++__ieee754_sqrtf (float x) ++{ ++ return __slow_ieee754_sqrtf (x); ++} ++ + strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c +index fc4a749..7038a70 100644 +--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c +@@ -41,10 +41,10 @@ static const float half = 0.5; + + #ifdef __STDC__ + double +-__ieee754_sqrt (double b) ++__slow_ieee754_sqrt (double b) + #else + double +-__ieee754_sqrt (b) ++__slow_ieee754_sqrt (b) + double b; + #endif + { +@@ -83,7 +83,7 @@ __ieee754_sqrt (b) + + /* Handle small numbers by scaling. */ + if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) +- return __ieee754_sqrt (b * two108) * twom54; ++ return __slow_ieee754_sqrt (b * two108) * twom54; + + #define FMADD(a_, c_, b_) \ + ({ double __r; \ +@@ -132,4 +132,12 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++ ++#undef __ieee754_sqrt ++double ++__ieee754_sqrt (double x) ++{ ++ return __slow_ieee754_sqrt (x); ++} ++ + strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c +index 9d17512..10de1f0 100644 +--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c +@@ -39,10 +39,10 @@ static const float threehalf = 1.5; + + #ifdef __STDC__ + float +-__ieee754_sqrtf (float b) ++__slow_ieee754_sqrtf (float b) + #else + float +-__ieee754_sqrtf (b) ++__slow_ieee754_sqrtf (b) + float b; + #endif + { +@@ -99,4 +99,12 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++ ++#undef __ieee754_sqrtf ++float ++__ieee754_sqrtf (float x) ++{ ++ return __slow_ieee754_sqrtf (x); ++} ++ + strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +index fc4a749..1c34244 100644 +--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +@@ -132,4 +132,12 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++ ++#undef __ieee754_sqrt ++double ++__ieee754_sqrt (double x) ++{ ++ return __slow_ieee754_sqrt (x); ++} ++ + strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +index 9d17512..8126535 100644 +--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +@@ -99,4 +99,12 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++ ++#undef __ieee754_sqrtf ++float ++__ieee754_sqrtf (float x) ++{ ++ return __slow_ieee754_sqrtf (x); ++} ++ + strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c +index 1795fd6..13a8197 100644 +--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c +@@ -40,7 +40,7 @@ static const float half = 0.5; + simultaneously. */ + + double +-__ieee754_sqrt (double b) ++__slow_ieee754_sqrt (double b) + { + if (__builtin_expect (b > 0, 1)) + { +@@ -77,7 +77,7 @@ __ieee754_sqrt (double b) + + /* Handle small numbers by scaling. */ + if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) +- return __ieee754_sqrt (b * two108) * twom54; ++ return __slow_ieee754_sqrt (b * two108) * twom54; + + #define FMADD(a_, c_, b_) \ + ({ double __r; \ +@@ -126,4 +126,12 @@ __ieee754_sqrt (double b) + } + return f_wash (b); + } ++ ++#undef __ieee754_sqrt ++double ++__ieee754_sqrt (double x) ++{ ++ return __slow_ieee754_sqrt (x); ++} ++ + strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c +index a917f31..fae2d81 100644 +--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c +@@ -38,7 +38,7 @@ static const float threehalf = 1.5; + square root. */ + + float +-__ieee754_sqrtf (float b) ++__slow_ieee754_sqrtf (float b) + { + if (__builtin_expect (b > 0, 1)) + { +@@ -93,4 +93,11 @@ __ieee754_sqrtf (float b) + } + return f_washf (b); + } ++#undef __ieee754_sqrtf ++float ++__ieee754_sqrtf (float x) ++{ ++ return __slow_ieee754_sqrtf (x); ++} ++ + strong_alias (__ieee754_sqrtf, __sqrtf_finite) +diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c +index fc4a749..7038a70 100644 +--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c +@@ -41,10 +41,10 @@ static const float half = 0.5; + + #ifdef __STDC__ + double +-__ieee754_sqrt (double b) ++__slow_ieee754_sqrt (double b) + #else + double +-__ieee754_sqrt (b) ++__slow_ieee754_sqrt (b) + double b; + #endif + { +@@ -83,7 +83,7 @@ __ieee754_sqrt (b) + + /* Handle small numbers by scaling. */ + if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) +- return __ieee754_sqrt (b * two108) * twom54; ++ return __slow_ieee754_sqrt (b * two108) * twom54; + + #define FMADD(a_, c_, b_) \ + ({ double __r; \ +@@ -132,4 +132,12 @@ __ieee754_sqrt (b) + } + return f_wash (b); + } ++ ++#undef __ieee754_sqrt ++double ++__ieee754_sqrt (double x) ++{ ++ return __slow_ieee754_sqrt (x); ++} ++ + strong_alias (__ieee754_sqrt, __sqrt_finite) +diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c +index 9d17512..10de1f0 100644 +--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c +@@ -39,10 +39,10 @@ static const float threehalf = 1.5; + + #ifdef __STDC__ + float +-__ieee754_sqrtf (float b) ++__slow_ieee754_sqrtf (float b) + #else + float +-__ieee754_sqrtf (b) ++__slow_ieee754_sqrtf (b) + float b; + #endif + { +@@ -99,4 +99,12 @@ __ieee754_sqrtf (b) + } + return f_washf (b); + } ++ ++#undef __ieee754_sqrtf ++float ++__ieee754_sqrtf (float x) ++{ ++ return __slow_ieee754_sqrtf (x); ++} ++ + strong_alias (__ieee754_sqrtf, __sqrtf_finite) +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0009-Quote-from-bug-1443-which-explains-what-the-patch-do.patch b/meta/recipes-core/glibc/glibc/0009-Quote-from-bug-1443-which-explains-what-the-patch-do.patch new file mode 100644 index 0000000000..1f5475912c --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0009-Quote-from-bug-1443-which-explains-what-the-patch-do.patch @@ -0,0 +1,62 @@ +From acf7a028817e71eb99d785037659abd4d120ffe2 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:20:09 +0000 +Subject: [PATCH 09/27] Quote from bug 1443 which explains what the patch does + : + + We build some random program and link it with -lust. When we run it, + it dies with a SIGSEGV before reaching main(). + + Libust.so depends on liburcu-bp.so from the usermode-rcu package. + Although libust.so is not prelinked, liburcu-bp.so IS prelinked; this + is critical. + + Libust.so uses a TLS / __thread variable that is defined in liburcu- + bp.so. There are special ARM-specific relocation types that allow two + shared libraries to share thread-specific data. This is critical too. + + One more critical issue: although liburcu-bp.so is prelinked, we can't + load it at its prelinked address, because we also link against + librt.so, and librt.so uses that address. + + The dynamic linker is forced to relink liburcu-bp.so at a different + address. In the course of relinking, it processes the special ARM + relocation record mentioned above. The prelinker has already filled + in the information, which is a short offset into a table of thread- + specific data that is allocated per-thread for each library that uses + TLS. Because the normal behavior of a relocation is to add the symbol + value to an addend stored at the address being relocated, we end up + adding the short offset to itself, doubling it. + + Now we have an awkward situation. The libust.so library doesn't know + about the addend, so its TLS data for this element is correct. The + liburcu-bp.so library has a different offset for the element. When we + go to initialize the element for the first time in liburcu-bp.so, we + write the address of the result at the doubled (broken) offset. + Later, when we refer to the address from libust.so, we check the value + at the correct offset, but it's NULL, so we eat hot SIGSEGV. + +Upstream-Status: Pending + +Signed-off-by: Andrei Dinu +Signed-off-by: Khem Raj +--- + sysdeps/arm/dl-machine.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h +index 6fb20bd..8805537 100644 +--- a/sysdeps/arm/dl-machine.h ++++ b/sysdeps/arm/dl-machine.h +@@ -499,7 +499,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, + + case R_ARM_TLS_DTPOFF32: + if (sym != NULL) +- *reloc_addr += sym->st_value; ++ *reloc_addr = sym->st_value; + break; + + case R_ARM_TLS_TPOFF32: +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0010-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch b/meta/recipes-core/glibc/glibc/0010-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch new file mode 100644 index 0000000000..d71e576a6f --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0010-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch @@ -0,0 +1,36 @@ +From 017322ee28c1579ce6c81904842aaada9c82403c Mon Sep 17 00:00:00 2001 +From: Ting Liu +Date: Wed, 19 Dec 2012 04:39:57 -0600 +Subject: [PATCH 10/27] eglibc: run libm-err-tab.pl with specific dirs in ${S} + +libm-err-tab.pl will parse all the files named "libm-test-ulps" +in the given dir recursively. To avoid parsing the one in +${S}/.pc/ (it does exist after eglibc adds aarch64 support, +${S}/.pc/aarch64-0001-glibc-fsf-v1-eaf6f205.patch/ports/sysdeps/ +aarch64/libm-test-ulps), run libm-err-tab.pl with specific dirs +in ${S}. + +Upstream-Status: inappropriate [OE specific] + +Signed-off-by: Ting Liu +--- + manual/Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/manual/Makefile b/manual/Makefile +index 5382208..6b701b0 100644 +--- a/manual/Makefile ++++ b/manual/Makefile +@@ -105,7 +105,8 @@ $(objpfx)libm-err.texi: $(objpfx)stamp-libm-err + $(objpfx)stamp-libm-err: libm-err-tab.pl $(wildcard $(foreach dir,$(sysdirs),\ + $(dir)/libm-test-ulps)) + pwd=`pwd`; \ +- $(PERL) $< $$pwd/.. > $(objpfx)libm-err-tmp ++ $(PERL) $< $$pwd/../ports > $(objpfx)libm-err-tmp ++ $(PERL) $< $$pwd/../sysdeps >> $(objpfx)libm-err-tmp + $(move-if-change) $(objpfx)libm-err-tmp $(objpfx)libm-err.texi + touch $@ + +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch b/meta/recipes-core/glibc/glibc/0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch new file mode 100644 index 0000000000..07a112b218 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch @@ -0,0 +1,61 @@ +From 1be45f870ebbb0259bea5250a6d2c2fbcb33409d Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:24:46 +0000 +Subject: [PATCH 11/27] __ieee754_sqrt{,f} are now inline functions and call + out __slow versions + +Upstream-Status: Pending + +Signed-off-by: chunrong guo +Signed-off-by: Khem Raj +--- + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c | 6 +++--- + sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +index 1c34244..7038a70 100644 +--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c +@@ -41,10 +41,10 @@ static const float half = 0.5; + + #ifdef __STDC__ + double +-__ieee754_sqrt (double b) ++__slow_ieee754_sqrt (double b) + #else + double +-__ieee754_sqrt (b) ++__slow_ieee754_sqrt (b) + double b; + #endif + { +@@ -83,7 +83,7 @@ __ieee754_sqrt (b) + + /* Handle small numbers by scaling. */ + if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) +- return __ieee754_sqrt (b * two108) * twom54; ++ return __slow_ieee754_sqrt (b * two108) * twom54; + + #define FMADD(a_, c_, b_) \ + ({ double __r; \ +diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +index 8126535..10de1f0 100644 +--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c ++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c +@@ -39,10 +39,10 @@ static const float threehalf = 1.5; + + #ifdef __STDC__ + float +-__ieee754_sqrtf (float b) ++__slow_ieee754_sqrtf (float b) + #else + float +-__ieee754_sqrtf (b) ++__slow_ieee754_sqrtf (b) + float b; + #endif + { +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0012-Make-ld-version-output-matching-grok-gold-s-output.patch b/meta/recipes-core/glibc/glibc/0012-Make-ld-version-output-matching-grok-gold-s-output.patch new file mode 100644 index 0000000000..267791393e --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0012-Make-ld-version-output-matching-grok-gold-s-output.patch @@ -0,0 +1,44 @@ +From 49471ab1f90e392da9520eea831ce8731be9fc8b Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:25:45 +0000 +Subject: [PATCH 12/27] Make ld --version output matching grok gold's output + +adapted from from upstream branch roland/gold-vs-libc + +Upstream-Status: Backport + +Signed-off-by: Khem Raj +--- + configure | 2 +- + configure.ac | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure b/configure +index 45cc7cb..7d7299a 100755 +--- a/configure ++++ b/configure +@@ -4709,7 +4709,7 @@ else + # Found it, now check the version. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5 + $as_echo_n "checking version of $LD... " >&6; } +- ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*GNU ld.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'` ++ ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*GNU [Bbinutilsd][^.]* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 2.1[0-9][0-9]*|2.2[2-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*) +diff --git a/configure.ac b/configure.ac +index 7e9383a..a467a69 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -941,7 +941,7 @@ AC_CHECK_PROG_VER(AS, $AS, --version, + [2.1[0-9][0-9]*|2.2[2-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*], + AS=: critic_missing="$critic_missing as") + AC_CHECK_PROG_VER(LD, $LD, --version, +- [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)], ++ [GNU [Bbinutilsd][^.]* \([0-9][0-9]*\.[0-9.]*\)], + [2.1[0-9][0-9]*|2.2[2-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*], + LD=: critic_missing="$critic_missing ld") + +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0013-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch b/meta/recipes-core/glibc/glibc/0013-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch new file mode 100644 index 0000000000..c1fda9d433 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0013-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch @@ -0,0 +1,42 @@ +From b55e49b199c46a278ab66b6b1e3eab483b913197 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:27:10 +0000 +Subject: [PATCH 13/27] sysdeps/gnu/configure.ac: handle correctly + $libc_cv_rootsbindir + +Upstream-Status:Pending + +Signed-off-by: Matthieu Crapet +Signed-off-by: Khem Raj +--- + sysdeps/gnu/configure | 2 +- + sysdeps/gnu/configure.ac | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/gnu/configure b/sysdeps/gnu/configure +index 9239297..c5ed3ca 100644 +--- a/sysdeps/gnu/configure ++++ b/sysdeps/gnu/configure +@@ -32,6 +32,6 @@ case "$prefix" in + else + libc_cv_localstatedir=$localstatedir + fi +- libc_cv_rootsbindir=/sbin ++ test -n "$libc_cv_rootsbindir" || libc_cv_rootsbindir=/sbin + ;; + esac +diff --git a/sysdeps/gnu/configure.ac b/sysdeps/gnu/configure.ac +index 634fe4d..3db1697 100644 +--- a/sysdeps/gnu/configure.ac ++++ b/sysdeps/gnu/configure.ac +@@ -21,6 +21,6 @@ case "$prefix" in + else + libc_cv_localstatedir=$localstatedir + fi +- libc_cv_rootsbindir=/sbin ++ test -n "$libc_cv_rootsbindir" || libc_cv_rootsbindir=/sbin + ;; + esac +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0014-Add-unused-attribute.patch b/meta/recipes-core/glibc/glibc/0014-Add-unused-attribute.patch new file mode 100644 index 0000000000..0ba5d2fbad --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0014-Add-unused-attribute.patch @@ -0,0 +1,34 @@ +From 0229d6c9c0e7721773118d5ae1d172c269bc9826 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:28:41 +0000 +Subject: [PATCH 14/27] Add unused attribute + +Helps in avoiding gcc warning when header is is included in +a source file which does not use both functions + + * iconv/gconv_charset.h (strip): + Add unused attribute. + +Signed-off-by: Khem Raj + +Upstream-Status: Pending +--- + iconv/gconv_charset.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h +index 80290bc..7890a8e 100644 +--- a/iconv/gconv_charset.h ++++ b/iconv/gconv_charset.h +@@ -21,7 +21,7 @@ + #include + + +-static void ++static void __attribute__ ((unused)) + strip (char *wp, const char *s) + { + int slash_count = 0; +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0015-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch b/meta/recipes-core/glibc/glibc/0015-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch new file mode 100644 index 0000000000..4b261ca1ef --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0015-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch @@ -0,0 +1,32 @@ +From f058c884dd26d10c94550ca5252ed6576614d659 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Thu, 19 Feb 2015 03:23:45 +0000 +Subject: [PATCH 15/27] When disabling SSE also make sure that fpmath is not + set to use SSE as well + +This fixes errors when we inject sse options through CFLAGS and now +that we have -Werror turned on by default this warning turns to become +error on x86 + +Signed-off-by: Khem Raj + +Upstream-Status: Pending +--- + sysdeps/x86/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 19f5eca..827ea71 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -1,6 +1,6 @@ + ifeq ($(subdir),elf) + CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\ +- -mno-sse -mno-mmx) ++ -mno-sse -mno-mmx -mfpmath=387) + + tests-special += $(objpfx)tst-ld-sse-use.out + $(objpfx)tst-ld-sse-use.out: ../sysdeps/x86/tst-ld-sse-use.sh $(objpfx)ld.so +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0016-yes-within-the-path-sets-wrong-config-variables.patch b/meta/recipes-core/glibc/glibc/0016-yes-within-the-path-sets-wrong-config-variables.patch new file mode 100644 index 0000000000..089e8b1b0b --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0016-yes-within-the-path-sets-wrong-config-variables.patch @@ -0,0 +1,263 @@ +From 70199fe59c38b621ab4121d7a55719b2b29b36de Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:31:06 +0000 +Subject: [PATCH 16/27] 'yes' within the path sets wrong config variables + +It seems that the 'AC_EGREP_CPP(yes...' example is quite popular +but being such a short word to grep it is likely to produce +false-positive matches with the path it is configured into. + +The change is to use a more elaborated string to grep for. + +Upstream-Status: Submitted [libc-alpha@sourceware.org] + +Signed-off-by: Benjamin Esquivel +Signed-off-by: Khem Raj +--- + sysdeps/aarch64/configure | 4 ++-- + sysdeps/aarch64/configure.ac | 4 ++-- + sysdeps/arm/configure | 4 ++-- + sysdeps/arm/configure.ac | 4 ++-- + sysdeps/mips/configure | 4 ++-- + sysdeps/mips/configure.ac | 4 ++-- + sysdeps/nios2/configure | 4 ++-- + sysdeps/nios2/configure.ac | 4 ++-- + sysdeps/unix/sysv/linux/mips/configure | 4 ++-- + sysdeps/unix/sysv/linux/mips/configure.ac | 4 ++-- + sysdeps/unix/sysv/linux/powerpc/powerpc64/configure | 8 ++++---- + sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac | 8 ++++---- + 12 files changed, 28 insertions(+), 28 deletions(-) + +diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure +index 5bd355a..3bc5537 100644 +--- a/sysdeps/aarch64/configure ++++ b/sysdeps/aarch64/configure +@@ -148,12 +148,12 @@ else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + #ifdef __AARCH64EB__ +- yes ++ is_aarch64_be + #endif + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "is_aarch64_be" >/dev/null 2>&1; then : + libc_cv_aarch64_be=yes + else + libc_cv_aarch64_be=no +diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac +index 7851dd4..6e92381 100644 +--- a/sysdeps/aarch64/configure.ac ++++ b/sysdeps/aarch64/configure.ac +@@ -10,8 +10,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + # the dynamic linker via %ifdef. + AC_CACHE_CHECK([for big endian], + [libc_cv_aarch64_be], +- [AC_EGREP_CPP(yes,[#ifdef __AARCH64EB__ +- yes ++ [AC_EGREP_CPP(is_aarch64_be,[#ifdef __AARCH64EB__ ++ is_aarch64_be + #endif + ], libc_cv_aarch64_be=yes, libc_cv_aarch64_be=no)]) + if test $libc_cv_aarch64_be = yes; then +diff --git a/sysdeps/arm/configure b/sysdeps/arm/configure +index 158116b..5eaf54e 100644 +--- a/sysdeps/arm/configure ++++ b/sysdeps/arm/configure +@@ -151,12 +151,12 @@ else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + #ifdef __ARM_PCS_VFP +- yes ++ use_arm_pcs_vfp + #endif + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "use_arm_pcs_vfp" >/dev/null 2>&1; then : + libc_cv_arm_pcs_vfp=yes + else + libc_cv_arm_pcs_vfp=no +diff --git a/sysdeps/arm/configure.ac b/sysdeps/arm/configure.ac +index 859c92a..2f4a6e2 100644 +--- a/sysdeps/arm/configure.ac ++++ b/sysdeps/arm/configure.ac +@@ -15,8 +15,8 @@ AC_DEFINE(PI_STATIC_AND_HIDDEN) + # the dynamic linker via %ifdef. + AC_CACHE_CHECK([whether the compiler is using the ARM hard-float ABI], + [libc_cv_arm_pcs_vfp], +- [AC_EGREP_CPP(yes,[#ifdef __ARM_PCS_VFP +- yes ++ [AC_EGREP_CPP(use_arm_pcs_vfp,[#ifdef __ARM_PCS_VFP ++ use_arm_pcs_vfp + #endif + ], libc_cv_arm_pcs_vfp=yes, libc_cv_arm_pcs_vfp=no)]) + if test $libc_cv_arm_pcs_vfp = yes; then +diff --git a/sysdeps/mips/configure b/sysdeps/mips/configure +index 4e13248..f14af95 100644 +--- a/sysdeps/mips/configure ++++ b/sysdeps/mips/configure +@@ -143,11 +143,11 @@ else + /* end confdefs.h. */ + dnl + #ifdef __mips_nan2008 +-yes ++use_mips_nan2008 + #endif + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "use_mips_nan2008" >/dev/null 2>&1; then : + libc_cv_mips_nan2008=yes + else + libc_cv_mips_nan2008=no +diff --git a/sysdeps/mips/configure.ac b/sysdeps/mips/configure.ac +index bcbdaff..ad3057f 100644 +--- a/sysdeps/mips/configure.ac ++++ b/sysdeps/mips/configure.ac +@@ -6,9 +6,9 @@ dnl position independent way. + dnl AC_DEFINE(PI_STATIC_AND_HIDDEN) + + AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding], +- libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl ++ libc_cv_mips_nan2008, [AC_EGREP_CPP(use_mips_nan2008, [dnl + #ifdef __mips_nan2008 +-yes ++use_mips_nan2008 + #endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)]) + if test x$libc_cv_mips_nan2008 = xyes; then + AC_DEFINE(HAVE_MIPS_NAN2008) +diff --git a/sysdeps/nios2/configure b/sysdeps/nios2/configure +index 14c8a3a..dde3814 100644 +--- a/sysdeps/nios2/configure ++++ b/sysdeps/nios2/configure +@@ -142,12 +142,12 @@ else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + #ifdef __nios2_big_endian__ +- yes ++ is_nios2_be + #endif + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "is_nios2_be" >/dev/null 2>&1; then : + libc_cv_nios2_be=yes + else + libc_cv_nios2_be=no +diff --git a/sysdeps/nios2/configure.ac b/sysdeps/nios2/configure.ac +index f05f438..dc86399 100644 +--- a/sysdeps/nios2/configure.ac ++++ b/sysdeps/nios2/configure.ac +@@ -4,8 +4,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + # Nios II big endian is not yet supported. + AC_CACHE_CHECK([for big endian], + [libc_cv_nios2_be], +- [AC_EGREP_CPP(yes,[#ifdef __nios2_big_endian__ +- yes ++ [AC_EGREP_CPP(is_nios2_be,[#ifdef __nios2_big_endian__ ++ is_nios2_be + #endif + ], libc_cv_nios2_be=yes, libc_cv_nios2_be=no)]) + if test $libc_cv_nios2_be = yes; then +diff --git a/sysdeps/unix/sysv/linux/mips/configure b/sysdeps/unix/sysv/linux/mips/configure +index 83f8b13..2b6cbee 100644 +--- a/sysdeps/unix/sysv/linux/mips/configure ++++ b/sysdeps/unix/sysv/linux/mips/configure +@@ -387,11 +387,11 @@ else + /* end confdefs.h. */ + dnl + #ifdef __mips_nan2008 +-yes ++use_mips_nan2008 + #endif + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "use_mips_nan2008" >/dev/null 2>&1; then : + libc_cv_mips_nan2008=yes + else + libc_cv_mips_nan2008=no +diff --git a/sysdeps/unix/sysv/linux/mips/configure.ac b/sysdeps/unix/sysv/linux/mips/configure.ac +index 5039ec9..1035f76 100644 +--- a/sysdeps/unix/sysv/linux/mips/configure.ac ++++ b/sysdeps/unix/sysv/linux/mips/configure.ac +@@ -98,9 +98,9 @@ AC_COMPILE_IFELSE( + LIBC_CONFIG_VAR([mips-mode-switch],[${libc_mips_mode_switch}]) + + AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding], +- libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl ++ libc_cv_mips_nan2008, [AC_EGREP_CPP(use_mips_nan2008, [dnl + #ifdef __mips_nan2008 +-yes ++use_mips_nan2008 + #endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)]) + + libc_mips_nan= +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure +index 70bb18a..ffd9e3e 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure +@@ -155,12 +155,12 @@ else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + #if _CALL_ELF == 2 +- yes ++ use_ppc_elfv2_abi + #endif + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "use_ppc_elfv2_abi" >/dev/null 2>&1; then : + libc_cv_ppc64_elfv2_abi=yes + else + libc_cv_ppc64_elfv2_abi=no +@@ -188,12 +188,12 @@ else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + #ifdef _CALL_ELF +- yes ++ is_def_call_elf + #endif + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "yes" >/dev/null 2>&1; then : ++ $EGREP "is_def_call_elf" >/dev/null 2>&1; then : + libc_cv_ppc64_def_call_elf=yes + else + libc_cv_ppc64_def_call_elf=no +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac +index 0822915..9a32fdd 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac +@@ -6,8 +6,8 @@ LIBC_SLIBDIR_RTLDDIR([lib64], [lib64]) + # Define default-abi according to compiler flags. + AC_CACHE_CHECK([whether the compiler is using the PowerPC64 ELFv2 ABI], + [libc_cv_ppc64_elfv2_abi], +- [AC_EGREP_CPP(yes,[#if _CALL_ELF == 2 +- yes ++ [AC_EGREP_CPP(use_ppc_elfv2_abi,[#if _CALL_ELF == 2 ++ use_ppc_elfv2_abi + #endif + ], libc_cv_ppc64_elfv2_abi=yes, libc_cv_ppc64_elfv2_abi=no)]) + if test $libc_cv_ppc64_elfv2_abi = yes; then +@@ -19,8 +19,8 @@ else + # Compiler that do not support ELFv2 ABI does not define _CALL_ELF + AC_CACHE_CHECK([whether the compiler defines _CALL_ELF], + [libc_cv_ppc64_def_call_elf], +- [AC_EGREP_CPP(yes,[#ifdef _CALL_ELF +- yes ++ [AC_EGREP_CPP(is_def_call_elf,[#ifdef _CALL_ELF ++ is_def_call_elf + #endif + ], libc_cv_ppc64_def_call_elf=yes, libc_cv_ppc64_def_call_elf=no)]) + if test $libc_cv_ppc64_def_call_elf = no; then +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch b/meta/recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch new file mode 100644 index 0000000000..0ce823087d --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch @@ -0,0 +1,45 @@ +From c90306107fbbe2979012917e87747ce78c82ab88 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:33:03 +0000 +Subject: [PATCH 17/27] timezone: re-written tzselect as posix sh + +To avoid the bash dependency. + +Upstream-Status: Pending + +Signed-off-by: Hongxu Jia +Signed-off-by: Khem Raj +--- + timezone/Makefile | 2 +- + timezone/tzselect.ksh | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/timezone/Makefile b/timezone/Makefile +index 24c93c6..886b06e 100644 +--- a/timezone/Makefile ++++ b/timezone/Makefile +@@ -126,7 +126,7 @@ $(testdata)/XT%: testdata/XT% + cp $< $@ + + $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make +- sed -e 's|/bin/bash|$(BASH)|' \ ++ sed -e 's|/bin/bash|/bin/sh|' \ + -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ + -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \ + -e '/PKGVERSION=/s|=.*|="$(PKGVERSION)"|' \ +diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh +index 9d70691..25f45a8 100755 +--- a/timezone/tzselect.ksh ++++ b/timezone/tzselect.ksh +@@ -35,7 +35,7 @@ REPORT_BUGS_TO=tz@iana.org + + # Specify default values for environment variables if they are unset. + : ${AWK=awk} +-: ${TZDIR=`pwd`} ++: ${TZDIR=$(pwd)} + + # Check for awk Posix compliance. + ($AWK -v x=y 'BEGIN { exit 123 }') /dev/null 2>&1 +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0018-eglibc-Cross-building-and-testing-instructions.patch b/meta/recipes-core/glibc/glibc/0018-eglibc-Cross-building-and-testing-instructions.patch new file mode 100644 index 0000000000..8eacbc059f --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0018-eglibc-Cross-building-and-testing-instructions.patch @@ -0,0 +1,619 @@ +From eff048074ac7b5258bb615e5a5b221daa19b18ae Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:42:58 +0000 +Subject: [PATCH 18/27] eglibc: Cross building and testing instructions + +Ported from eglibc +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + GLIBC.cross-building | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++ + GLIBC.cross-testing | 205 +++++++++++++++++++++++++++ + 2 files changed, 588 insertions(+) + create mode 100644 GLIBC.cross-building + create mode 100644 GLIBC.cross-testing + +diff --git a/GLIBC.cross-building b/GLIBC.cross-building +new file mode 100644 +index 0000000..e6e0da1 +--- /dev/null ++++ b/GLIBC.cross-building +@@ -0,0 +1,383 @@ ++ -*- mode: text -*- ++ ++ Cross-Compiling GLIBC ++ Jim Blandy ++ ++ ++Introduction ++ ++Most GNU tools have a simple build procedure: you run their ++'configure' script, and then you run 'make'. Unfortunately, the ++process of cross-compiling the GNU C library is quite a bit more ++involved: ++ ++1) Build a cross-compiler, with certain facilities disabled. ++ ++2) Configure the C library using the compiler you built in step 1). ++ Build a few of the C run-time object files, but not the rest of the ++ library. Install the library's header files and the run-time ++ object files, and create a dummy libc.so. ++ ++3) Build a second cross-compiler, using the header files and object ++ files you installed in step 2. ++ ++4) Configure, build, and install a fresh C library, using the compiler ++ built in step 3. ++ ++5) Build a third cross-compiler, based on the C library built in step 4. ++ ++The reason for this complexity is that, although GCC and the GNU C ++library are distributed separately, they are not actually independent ++of each other: GCC requires the C library's headers and some object ++files to compile its own libraries, while the C library depends on ++GCC's libraries. GLIBC includes features and bug fixes to the stock ++GNU C library that simplify this process, but the fundamental ++interdependency stands. ++ ++In this document, we explain how to cross-compile an GLIBC/GCC pair ++from source. Our intended audience is developers who are already ++familiar with the GNU toolchain and comfortable working with ++cross-development tools. While we do present a worked example to ++accompany the explanation, for clarity's sake we do not cover many of ++the options available to cross-toolchain users. ++ ++ ++Preparation ++ ++GLIBC requires recent versions of the GNU binutils, GCC, and the ++Linux kernel. The web page ++documents the current requirements, and lists patches needed for ++certain target architectures. As of this writing, these build ++instructions have been tested with binutils 2.22.51, GCC 4.6.2, ++and Linux 3.1. ++ ++First, let's set some variables, to simplify later commands. We'll ++build GLIBC and GCC for an ARM target, known to the Linux kernel ++as 'arm', and we'll do the build on an Intel x86_64 Linux box: ++ ++ $ build=x86_64-pc-linux-gnu ++ $ host=$build ++ $ target=arm-none-linux-gnueabi ++ $ linux_arch=arm ++ ++We're using the aforementioned versions of Binutils, GCC, and Linux: ++ ++ $ binutilsv=binutils-2.22.51 ++ $ gccv=gcc-4.6.2 ++ $ linuxv=linux-3.1 ++ ++We're carrying out the entire process under '~/cross-build', which ++contains unpacked source trees for binutils, gcc, and linux kernel, ++along with GLIBC svn trunk (which can be checked-out with ++'svn co http://www.eglibc.org/svn/trunk eglibc'): ++ ++ $ top=$HOME/cross-build/$target ++ $ src=$HOME/cross-build/src ++ $ ls $src ++ binutils-2.22.51 glibc gcc-4.6.2 linux-3.1 ++ ++We're going to place our build directories in a subdirectory 'obj', ++we'll install the cross-development toolchain in 'tools', and we'll ++place our sysroot (containing files to be installed on the target ++system) in 'sysroot': ++ ++ $ obj=$top/obj ++ $ tools=$top/tools ++ $ sysroot=$top/sysroot ++ ++ ++Binutils ++ ++Configuring and building binutils for the target is straightforward: ++ ++ $ mkdir -p $obj/binutils ++ $ cd $obj/binutils ++ $ $src/$binutilsv/configure \ ++ > --target=$target \ ++ > --prefix=$tools \ ++ > --with-sysroot=$sysroot ++ $ make ++ $ make install ++ ++ ++The First GCC ++ ++For our work, we need a cross-compiler targeting an ARM Linux ++system. However, that configuration includes the shared library ++'libgcc_s.so', which is compiled against the GLIBC headers (which we ++haven't installed yet) and linked against 'libc.so' (which we haven't ++built yet). ++ ++Fortunately, there are configuration options for GCC which tell it not ++to build 'libgcc_s.so'. The '--without-headers' option is supposed to ++take care of this, but its implementation is incomplete, so you must ++also configure with the '--with-newlib' option. While '--with-newlib' ++appears to mean "Use the Newlib C library", its effect is to tell the ++GCC build machinery, "Don't assume there is a C library available." ++ ++We also need to disable some of the libraries that would normally be ++built along with GCC, and specify that only the compiler for the C ++language is needed. ++ ++So, we create a build directory, configure, make, and install. ++ ++ $ mkdir -p $obj/gcc1 ++ $ cd $obj/gcc1 ++ $ $src/$gccv/configure \ ++ > --target=$target \ ++ > --prefix=$tools \ ++ > --without-headers --with-newlib \ ++ > --disable-shared --disable-threads --disable-libssp \ ++ > --disable-libgomp --disable-libmudflap --disable-libquadmath \ ++ > --disable-decimal-float --disable-libffi \ ++ > --enable-languages=c ++ $ PATH=$tools/bin:$PATH make ++ $ PATH=$tools/bin:$PATH make install ++ ++ ++Linux Kernel Headers ++ ++To configure GLIBC, we also need Linux kernel headers in place. ++Fortunately, the Linux makefiles have a target that installs them for ++us. Since the process does modify the source tree a bit, we make a ++copy first: ++ ++ $ cp -r $src/$linuxv $obj/linux ++ $ cd $obj/linux ++ ++Now we're ready to install the headers into the sysroot: ++ ++ $ PATH=$tools/bin:$PATH \ ++ > make headers_install \ ++ > ARCH=$linux_arch CROSS_COMPILE=$target- \ ++ > INSTALL_HDR_PATH=$sysroot/usr ++ ++ ++GLIBC Headers and Preliminary Objects ++ ++Using the cross-compiler we've just built, we can now configure GLIBC ++well enough to install the headers and build the object files that the ++full cross-compiler will need: ++ ++ $ mkdir -p $obj/glibc-headers ++ $ cd $obj/glibc-headers ++ $ BUILD_CC=gcc \ ++ > CC=$tools/bin/$target-gcc \ ++ > CXX=$tools/bin/$target-g++ \ ++ > AR=$tools/bin/$target-ar \ ++ > RANLIB=$tools/bin/$target-ranlib \ ++ > $src/glibc/libc/configure \ ++ > --prefix=/usr \ ++ > --with-headers=$sysroot/usr/include \ ++ > --build=$build \ ++ > --host=$target \ ++ > --disable-profile --without-gd --without-cvs \ ++ > --enable-add-ons=nptl,libidn,../ports ++ ++The option '--prefix=/usr' may look strange, but you should never ++configure GLIBC with a prefix other than '/usr': in various places, ++GLIBC's build system checks whether the prefix is '/usr', and does ++special handling only if that is the case. Unless you use this ++prefix, you will get a sysroot that does not use the standard Linux ++directory layouts and cannot be used as a basis for the root ++filesystem on your target system compatibly with normal GLIBC ++installations. ++ ++The '--with-headers' option tells GLIBC where the Linux headers have ++been installed. ++ ++The '--enable-add-ons=nptl,libidn,../ports' option tells GLIBC to look ++for the listed glibc add-ons. Most notably the ports add-on (located ++just above the libc sources in the GLIBC svn tree) is required to ++support ARM targets. ++ ++We can now use the 'install-headers' makefile target to install the ++headers: ++ ++ $ make install-headers install_root=$sysroot \ ++ > install-bootstrap-headers=yes ++ ++The 'install_root' variable indicates where the files should actually ++be installed; its value is treated as the parent of the '--prefix' ++directory we passed to the configure script, so the headers will go in ++'$sysroot/usr/include'. The 'install-bootstrap-headers' variable ++requests special handling for certain tricky header files. ++ ++Next, there are a few object files needed to link shared libraries, ++which we build and install by hand: ++ ++ $ mkdir -p $sysroot/usr/lib ++ $ make csu/subdir_lib ++ $ cp csu/crt1.o csu/crti.o csu/crtn.o $sysroot/usr/lib ++ ++Finally, 'libgcc_s.so' requires a 'libc.so' to link against. However, ++since we will never actually execute its code, it doesn't matter what ++it contains. So, treating '/dev/null' as a C source file, we produce ++a dummy 'libc.so' in one step: ++ ++ $ $tools/bin/$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null \ ++ > -o $sysroot/usr/lib/libc.so ++ ++ ++The Second GCC ++ ++With the GLIBC headers and selected object files installed, we can ++now build a GCC that is capable of compiling GLIBC. We configure, ++build, and install the second GCC, again building only the C compiler, ++and avoiding libraries we won't use: ++ ++ $ mkdir -p $obj/gcc2 ++ $ cd $obj/gcc2 ++ $ $src/$gccv/configure \ ++ > --target=$target \ ++ > --prefix=$tools \ ++ > --with-sysroot=$sysroot \ ++ > --disable-libssp --disable-libgomp --disable-libmudflap \ ++ > --disable-libffi --disable-libquadmath \ ++ > --enable-languages=c ++ $ PATH=$tools/bin:$PATH make ++ $ PATH=$tools/bin:$PATH make install ++ ++ ++GLIBC, Complete ++ ++With the second compiler built and installed, we're now ready for the ++full GLIBC build: ++ ++ $ mkdir -p $obj/glibc ++ $ cd $obj/glibc ++ $ BUILD_CC=gcc \ ++ > CC=$tools/bin/$target-gcc \ ++ > CXX=$tools/bin/$target-g++ \ ++ > AR=$tools/bin/$target-ar \ ++ > RANLIB=$tools/bin/$target-ranlib \ ++ > $src/glibc/libc/configure \ ++ > --prefix=/usr \ ++ > --with-headers=$sysroot/usr/include \ ++ > --with-kconfig=$obj/linux/scripts/kconfig \ ++ > --build=$build \ ++ > --host=$target \ ++ > --disable-profile --without-gd --without-cvs \ ++ > --enable-add-ons=nptl,libidn,../ports ++ ++Note the additional '--with-kconfig' option. This tells GLIBC where to ++find the host config tools used by the kernel 'make config' and 'make ++menuconfig'. These tools can be re-used by GLIBC for its own 'make ++*config' support, which will create 'option-groups.config' for you. ++But first make sure those tools have been built by running some ++dummy 'make *config' calls in the kernel directory: ++ ++ $ cd $obj/linux ++ $ PATH=$tools/bin:$PATH make config \ ++ > ARCH=$linux_arch CROSS_COMPILE=$target- \ ++ $ PATH=$tools/bin:$PATH make menuconfig \ ++ > ARCH=$linux_arch CROSS_COMPILE=$target- \ ++ ++Now we can configure and build the full GLIBC: ++ ++ $ cd $obj/glibc ++ $ PATH=$tools/bin:$PATH make defconfig ++ $ PATH=$tools/bin:$PATH make menuconfig ++ $ PATH=$tools/bin:$PATH make ++ $ PATH=$tools/bin:$PATH make install install_root=$sysroot ++ ++At this point, we have a complete GLIBC installation in '$sysroot', ++with header files, library files, and most of the C runtime startup ++files in place. ++ ++ ++The Third GCC ++ ++Finally, we recompile GCC against this full installation, enabling ++whatever languages and libraries we would like to use: ++ ++ $ mkdir -p $obj/gcc3 ++ $ cd $obj/gcc3 ++ $ $src/$gccv/configure \ ++ > --target=$target \ ++ > --prefix=$tools \ ++ > --with-sysroot=$sysroot \ ++ > --enable-__cxa_atexit \ ++ > --disable-libssp --disable-libgomp --disable-libmudflap \ ++ > --enable-languages=c,c++ ++ $ PATH=$tools/bin:$PATH make ++ $ PATH=$tools/bin:$PATH make install ++ ++The '--enable-__cxa_atexit' option tells GCC what sort of C++ ++destructor support to expect from the C library; it's required with ++GLIBC. ++ ++And since GCC's installation process isn't designed to help construct ++sysroot trees, we must manually copy certain libraries into place in ++the sysroot. ++ ++ $ cp -d $tools/$target/lib/libgcc_s.so* $sysroot/lib ++ $ cp -d $tools/$target/lib/libstdc++.so* $sysroot/usr/lib ++ ++ ++Trying Things Out ++ ++At this point, '$tools' contains a cross toolchain ready to use ++the GLIBC installation in '$sysroot': ++ ++ $ cat > hello.c < #include ++ > int ++ > main (int argc, char **argv) ++ > { ++ > puts ("Hello, world!"); ++ > return 0; ++ > } ++ > EOF ++ $ $tools/bin/$target-gcc -Wall hello.c -o hello ++ $ cat > c++-hello.cc < #include ++ > int ++ > main (int argc, char **argv) ++ > { ++ > std::cout << "Hello, C++ world!" << std::endl; ++ > return 0; ++ > } ++ > EOF ++ $ $tools/bin/$target-g++ -Wall c++-hello.cc -o c++-hello ++ ++ ++We can use 'readelf' to verify that these are indeed executables for ++our target, using our dynamic linker: ++ ++ $ $tools/bin/$target-readelf -hl hello ++ ELF Header: ++ ... ++ Type: EXEC (Executable file) ++ Machine: ARM ++ ++ ... ++ Program Headers: ++ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align ++ PHDR 0x000034 0x10000034 0x10000034 0x00100 0x00100 R E 0x4 ++ INTERP 0x000134 0x00008134 0x00008134 0x00013 0x00013 R 0x1 ++ [Requesting program interpreter: /lib/ld-linux.so.3] ++ LOAD 0x000000 0x00008000 0x00008000 0x0042c 0x0042c R E 0x8000 ++ ... ++ ++Looking at the dynamic section of the installed 'libgcc_s.so', we see ++that the 'NEEDED' entry for the C library does include the '.6' ++suffix, indicating that was linked against our fully build GLIBC, and ++not our dummy 'libc.so': ++ ++ $ $tools/bin/$target-readelf -d $sysroot/lib/libgcc_s.so.1 ++ Dynamic section at offset 0x1083c contains 24 entries: ++ Tag Type Name/Value ++ 0x00000001 (NEEDED) Shared library: [libc.so.6] ++ 0x0000000e (SONAME) Library soname: [libgcc_s.so.1] ++ ... ++ ++ ++And on the target machine, we can run our programs: ++ ++ $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \ ++ > ./hello ++ Hello, world! ++ $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \ ++ > ./c++-hello ++ Hello, C++ world! +diff --git a/GLIBC.cross-testing b/GLIBC.cross-testing +new file mode 100644 +index 0000000..b67b468 +--- /dev/null ++++ b/GLIBC.cross-testing +@@ -0,0 +1,205 @@ ++ -*- mode: text -*- ++ ++ Cross-Testing With GLIBC ++ Jim Blandy ++ ++ ++Introduction ++ ++Developers writing software for embedded systems often use a desktop ++or other similarly capable computer for development, but need to run ++tests on the embedded system, or perhaps on a simulator. When ++configured for cross-compilation, the stock GNU C library simply ++disables running tests altogether: the command 'make tests' builds ++test programs, but does not run them. GLIBC, however, provides ++facilities for compiling tests and generating data files on the build ++system, but running the test programs themselves on a remote system or ++simulator. ++ ++ ++Test environment requirements ++ ++The test environment must meet certain conditions for GLIBC's ++cross-testing facilities to work: ++ ++- Shared filesystems. The 'build' system, on which you configure and ++ compile GLIBC, and the 'host' system, on which you intend to run ++ GLIBC, must share a filesystem containing the GLIBC build and ++ source trees. Files must appear at the same paths on both systems. ++ ++- Remote-shell like invocation. There must be a way to run a program ++ on the host system from the build system, passing it properly quoted ++ command-line arguments, setting environment variables, and ++ inheriting the caller's standard input and output. ++ ++ ++Usage ++ ++To use GLIBC's cross-testing support, provide values for the ++following Make variables when you invoke 'make': ++ ++- cross-test-wrapper ++ ++ This should be the name of the cross-testing wrapper command, along ++ with any arguments. ++ ++- cross-localedef ++ ++ This should be the name of a cross-capable localedef program, like ++ that included in the GLIBC 'localedef' module, along with any ++ arguments needed. ++ ++These are each explained in detail below. ++ ++ ++The Cross-Testing Wrapper ++ ++To run test programs reliably, the stock GNU C library takes care to ++ensure that test programs use the newly compiled dynamic linker and ++shared libraries, and never the host system's installed libraries. To ++accomplish this, it runs the tests by explicitly invoking the dynamic ++linker from the build tree, passing it a list of build tree ++directories to search for shared libraries, followed by the name of ++the executable to run and its arguments. ++ ++For example, where one might normally run a test program like this: ++ ++ $ ./tst-foo arg1 arg2 ++ ++the GNU C library might run that program like this: ++ ++ $ $objdir/elf/ld-linux.so.3 --library-path $objdir \ ++ ./tst-foo arg1 arg2 ++ ++(where $objdir is the path to the top of the build tree, and the ++trailing backslash indicates a continuation of the command). In other ++words, each test program invocation is 'wrapped up' inside an explicit ++invocation of the dynamic linker, which must itself execute the test ++program, having loaded shared libraries from the appropriate ++directories. ++ ++To support cross-testing, GLIBC allows the developer to optionally ++set the 'cross-test-wrapper' Make variable to another wrapper command, ++to which it passes the entire dynamic linker invocation shown above as ++arguments. For example, if the developer supplies a wrapper of ++'my-wrapper hostname', then GLIBC would run the test above as ++follows: ++ ++ $ my-wrapper hostname \ ++ $objdir/elf/ld-linux.so.3 --library-path $objdir \ ++ ./tst-foo arg1 arg2 ++ ++The 'my-wrapper' command is responsible for executing the command ++given on the host system. ++ ++Since tests are run in varying directories, the wrapper should either ++be in your command search path, or 'cross-test-wrapper' should give an ++absolute path for the wrapper. ++ ++The wrapper must meet several requirements: ++ ++- It must preserve the current directory. As explained above, the ++ build directory tree must be visible on both the build and host ++ systems, at the same path. The test wrapper must ensure that the ++ current directory it inherits is also inherited by the dynamic ++ linker (and thus the test program itself). ++ ++- It must preserve environment variables' values. Many GLIBC tests ++ set environment variables for test runs; in native testing, it ++ invokes programs like this: ++ ++ $ GCONV_PATH=$objdir/iconvdata \ ++ $objdir/elf/ld-linux.so.3 --library-path $objdir \ ++ ./tst-foo arg1 arg2 ++ ++ With the cross-testing wrapper, that invocation becomes: ++ ++ $ GCONV_PATH=$objdir/iconvdata \ ++ my-wrapper hostname \ ++ $objdir/elf/ld-linux.so.3 --library-path $objdir \ ++ ./tst-foo arg1 arg2 ++ ++ Here, 'my-wrapper' must ensure that the value it sees for ++ 'GCONV_PATH' will be seen by the dynamic linker, and thus 'tst-foo' ++ itself. (The wrapper supplied with GLIBC simply preserves the ++ values of *all* enviroment variables, with a fixed set of ++ exceptions.) ++ ++ If your wrapper is a shell script, take care to correctly propagate ++ environment variables whose values contain spaces and shell ++ metacharacters. ++ ++- It must pass the command's arguments, unmodified. The arguments ++ seen by the test program should be exactly those seen by the wrapper ++ (after whatever arguments are given to the wrapper itself). The ++ GLIBC test framework performs all needed shell word splitting and ++ expansion (wildcard expansion, parameter substitution, and so on) ++ before invoking the wrapper; further expansion may break the tests. ++ ++ ++The 'cross-test-ssh.sh' script ++ ++If you want to use 'ssh' (or something sufficiently similar) to run ++test programs on your host system, GLIBC includes a shell script, ++'scripts/cross-test-ssh.sh', which you can use as your wrapper ++command. This script takes care of setting the test command's current ++directory, propagating environment variable values, and carrying ++command-line arguments, all across an 'ssh' connection. You may even ++supply an alternative to 'ssh' on the command line, if needed. ++ ++For more details, pass 'cross-test-ssh.sh' the '--help' option. ++ ++ ++The Cross-Compiling Locale Definition Command ++ ++Some GLIBC tests rely on locales generated especially for the test ++process. In a native configuration, these tests simply run the ++'localedef' command built by the normal GLIBC build process, ++'locale/localedef', to process and install their locales. However, in ++a cross-compiling configuration, this 'localedef' is built for the ++host system, not the build system, and since it requires quite a bit ++of memory to run (we have seen it fail on systems with 64MiB of ++memory), it may not be practical to run it on the host system. ++ ++If set, GLIBC uses the 'cross-localedef' Make variable as the command ++to run on the build system to process and install locales. The ++localedef program built from the GLIBC 'localedef' module is ++suitable. ++ ++The value of 'cross-localedef' may also include command-line arguments ++to be passed to the program; if you are using GLIBC's 'localedef', ++you may include endianness and 'uint32_t' alignment arguments here. ++ ++ ++Example ++ ++In developing GLIBC's cross-testing facility, we invoked 'make' with ++the following script: ++ ++ #!/bin/sh ++ ++ srcdir=... ++ test_hostname=... ++ localedefdir=... ++ cross_gxx=...-g++ ++ ++ wrapper="$srcdir/scripts/cross-test-ssh.sh $test_hostname" ++ localedef="$localedefdir/localedef --little-endian --uint32-align=4" ++ ++ make cross-test-wrapper="$wrapper" \ ++ cross-localedef="$localedef" \ ++ CXX="$cross_gxx" \ ++ "$@" ++ ++ ++Other Cross-Testing Concerns ++ ++Here are notes on some other issues which you may encounter in running ++the GLIBC tests in a cross-compiling environment: ++ ++- Some tests require a C++ cross-compiler; you should set the 'CXX' ++ Make variable to the name of an appropriate cross-compiler. ++ ++- Some tests require access to libstdc++.so.6 and libgcc_s.so.1; we ++ simply place copies of these libraries in the top GLIBC build ++ directory. +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch b/meta/recipes-core/glibc/glibc/0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch new file mode 100644 index 0000000000..dcb80f9c80 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch @@ -0,0 +1,1436 @@ +From aa7c5fe86d04584a9aed4dc40ba856c65a1ef9c4 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:45:18 +0000 +Subject: [PATCH 19/27] eglibc: Bring Eglibc option group infrastructure to + glibc + +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + EGLIBC.option-groups | 122 ++++++ + Makefile | 1 + + config.make.in | 2 + + configure | 13 + + configure.ac | 10 + + option-groups.def | 868 ++++++++++++++++++++++++++++++++++++++ + option-groups.defaults | 47 +++ + option-groups.mak | 41 ++ + options-config/Makefile | 55 +++ + options-config/config-postproc.pl | 58 +++ + options-config/config-preproc.pl | 8 + + scripts/option-groups.awk | 63 +++ + 12 files changed, 1288 insertions(+) + create mode 100644 EGLIBC.option-groups + create mode 100644 option-groups.def + create mode 100644 option-groups.defaults + create mode 100644 option-groups.mak + create mode 100644 options-config/Makefile + create mode 100644 options-config/config-postproc.pl + create mode 100644 options-config/config-preproc.pl + create mode 100644 scripts/option-groups.awk + +diff --git a/EGLIBC.option-groups b/EGLIBC.option-groups +new file mode 100644 +index 0000000..6a50b8d +--- /dev/null ++++ b/EGLIBC.option-groups +@@ -0,0 +1,122 @@ ++ -*- mode: text -*- ++ ++ The EGLIBC Component Configuration System ++ Jim Blandy ++ ++Introduction ++ ++The GNU C library (GLIBC) provides a broad range of functionality, ++ranging from internationalization support to transcendental ++mathematical functions. Its website boasts that "nearly all known and ++useful functions from any other C library are available." This ++exhaustive approach has been one of GLIBC's strengths on desktop and ++server systems, but it has also given GLIBC a large footprint, both in ++memory and on disk, making it a challenge to use in embedded systems ++with limited resources. ++ ++The Embedded GNU C library (EGLIBC) is a variant of the GNU C library ++designed to work well on embedded systems. In particular, EGLIBC's ++component configuration system allows embedded developers to build ++customized versions of the library that include only the features ++their application uses, reducing its space requirements. ++ ++EGLIBC's component configuration system categorizes the library's ++functions into "option groups", and allows you to include or exclude ++option groups individually. Some option groups depend on others; ++EGLIBC tracks these relationships, and ensures that the selected ++configuration yields a functioning library. ++ ++ ++Consistent and Predictable Behavior ++ ++A flexible configuration system is a mixed blessing: if the options ++offered are poorly designed, it can be hard to see which choices will ++have the desired effects, and choices with obscure consequences can ++make debugging difficult. EGLIBC's configuration follows some general ++principles to reduce these risks: ++ ++- EGLIBC has a single default configuration for each target ++ architecture. ++ ++- In the default configuration, all option groups are enabled, and ++ EGLIBC is upwardly API- and ABI-compatible with GLIBC. ++ ++- As much as possible, configurations only affect what functions are ++ present, not how they behave. If the system works with an option ++ group disabled, it will still work with it enabled. ++ ++- As much as possible, configurations only select option groups --- ++ they do not describe characteristics of the target architecture. ++ ++These rules mean that you have a simple debugging strategy available ++if you suspect that your EGLIBC configuration might be the source of a ++problem: fall back to the default configuration, re-test, and then ++disable option groups one by one, until the problem reappears. ++ ++ ++The Option Groups ++ ++To see the current full list of implemented option groups, refer to the ++file 'option-groups.def' at the top of the source tree, or run ++'make menuconfig' from the top-level build directory. ++ ++The POSIX.1-2001 specification includes a suggested partition of all ++the functions in the POSIX C API into option groups: math functions ++like 'sin' and 'cos'; networking functions like 'socket' and ++'connect'; and so on. EGLIBC could use this partitioning as the basis ++for future option groups. ++ ++ ++Implementation ++ ++The EGLIBC component configuration system resembles the approach used ++by the Linux kernel to select device drivers, network protocols, and ++other features. A file named 'option-groups.config' in the top-level ++build directory contains assignments to Make variables, each of which ++enables or disables a particular option group. If the variable's ++value is set to 'y', then the option group is enabled; if it set to ++anything else, the option group is omitted. The file ++'option-groups.defaults', at the top of the source tree, establishes ++default values for all variables; all option groups are enabled by ++default. ++ ++For example, the following 'option-groups.config' would omit locale ++data, but include mathematical functions, and everything else: ++ ++ OPTION_EGLIBC_LOCALES = n ++ OPTION_EGLIBC_LIBM = y ++ ++Like the Linux kernel, EGLIBC supports a similar set of '*config' make ++targets to make it easier to create 'option-groups.config', with all ++dependencies between option groups automatically satisfied. Run ++'make help' to see the list of supported make config targets. For ++example, 'make menuconfig' will update the current config utilising a ++menu based program. ++ ++The option group names and their type (boolean, int, hex, string), help ++description, and dependencies with other option groups, are described by ++'option-groups.def' at the top of the source tree, analogous to the ++'Kconfig' files in the Linux kernel. ++ ++In general, each option group variable controls whether a given set of ++object files in EGLIBC is compiled and included in the final ++libraries, or omitted from the build. ++ ++Each subdirectory's Makefile categorizes its routines, libraries, and ++executables by option group. For example, EGLIBC's 'math/Makefile' ++places the 'libm' library in the OPTION_EGLIBC_LIBM group as follows: ++ ++ extra-libs-$(OPTION_EGLIBC_LIBM) := libm ++ ++Finally, common code in 'Makerules' cites the value of the variable ++'extra-libs-y', selecting only those libraries that belong to enabled ++option groups to be built. ++ ++ ++Current Status and Future Directions ++ ++The EGLIBC component configuration system described here is still ++under development. ++ ++We have used the system to subset some portions of EGLIBC's ++Index: libc/configure.ac +diff --git a/Makefile b/Makefile +index 658ccfa..f906391 100644 +--- a/Makefile ++++ b/Makefile +@@ -24,6 +24,7 @@ endif + + include Makeconfig + ++include options-config/Makefile + + # This is the default target; it makes everything except the tests. + .PHONY: all +diff --git a/config.make.in b/config.make.in +index a9f5696..294f8d1 100644 +--- a/config.make.in ++++ b/config.make.in +@@ -47,6 +47,8 @@ c++-sysincludes = @CXX_SYSINCLUDES@ + all-warnings = @all_warnings@ + enable-werror = @enable_werror@ + ++kconfig_tools = @KCONFIG_TOOLS@ ++ + have-z-combreloc = @libc_cv_z_combreloc@ + have-z-execstack = @libc_cv_z_execstack@ + have-Bgroup = @libc_cv_Bgroup@ +diff --git a/configure b/configure +index 7d7299a..4116404 100755 +--- a/configure ++++ b/configure +@@ -641,6 +641,7 @@ INSTALL_INFO + PERL + BASH_SHELL + libc_cv_gcc_static_libgcc ++KCONFIG_TOOLS + CXX_SYSINCLUDES + SYSINCLUDES + AUTOCONF +@@ -755,6 +756,7 @@ with_fp + with_binutils + with_selinux + with_headers ++with_kconfig + with_default_link + enable_sanity_checks + enable_shared +@@ -1459,6 +1461,9 @@ Optional Packages: + --with-selinux if building with SELinux support + --with-headers=PATH location of system headers to use (for example + /usr/src/linux/include) [default=compiler default] ++ --with-kconfig=PATH location of kconfig tools to use (from Linux kernel ++ builds) to re-use for configuring EGLIBC option ++ groups + --with-default-link do not use explicit linker scripts + --with-cpu=CPU select code for CPU variant + +@@ -3517,6 +3522,14 @@ fi + + + ++# Check whether --with-kconfig was given. ++if test "${with_kconfig+set}" = set; then ++ withval=$with_kconfig; KCONFIG_TOOLS=$withval ++else ++ KCONFIG_TOOLS='' ++fi ++ ++ + + # Check whether --with-default-link was given. + if test "${with_default_link+set}" = set; then : +diff --git a/configure.ac b/configure.ac +index a467a69..fc0ed4d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -136,6 +136,16 @@ AC_ARG_WITH([headers], + [sysheaders='']) + AC_SUBST(sysheaders) + ++AC_ARG_WITH([kconfig], ++ AC_HELP_STRING([--with-kconfig=PATH], ++ [location of kconfig tools to use (from Linux ++ kernel builds) to re-use for configuring EGLIBC ++ option groups]), ++ [KCONFIG_TOOLS=$withval], ++ [KCONFIG_TOOLS='']) ++AC_SUBST(KCONFIG_TOOLS) ++ ++ + AC_SUBST(use_default_link) + AC_ARG_WITH([default-link], + AC_HELP_STRING([--with-default-link], +diff --git a/option-groups.def b/option-groups.def +new file mode 100644 +index 0000000..6aebd94 +--- /dev/null ++++ b/option-groups.def +@@ -0,0 +1,868 @@ ++# This file documents the option groups EGLIBC currently supports, in ++# a format akin to the Linux Kconfig system's. The syntax may change ++# over time. ++# ++# An entry of the form: ++# ++# config GROUP_NAME ++# bool "one-line explanation of what this option group controls" ++# help ++# Multi-line help explaining the option group's meaning in ++# some detail, terminated by indentation level. ++# ++# defines an option group whose variable is GROUP_NAME, with ++# meaningful values 'y' (enabled) and 'n' (disabled). The ++# documentation is formatted to be consumed by some sort of ++# interactive configuration interface, but EGLIBC doesn't have such an ++# interface yet. ++# ++# An option may have a 'depends on' line, indicating which other options ++# must also be enabled if this option is. At present, EGLIBC doesn't ++# check that these dependencies are satisfied. ++# ++# Option group variables get their default values from the file ++# 'option-groups.defaults', in the top directory of the EGLIBC source ++# tree. By default, all EGLIBC option groups are enabled --- their ++# variables are set to 'y'. ++# ++# After including 'option-groups.defaults', the EGLIBC make machinery ++# includes the file 'option-groups.config' from the top of the build ++# tree, if it is present. Developers can place assignments to option ++# group variables in that file to override the defaults. For example, ++# to disable an option group, place a line of the form: ++# ++# OPTION_GROUP_NAME = n ++# ++# in 'option-groups.config' at the top of your build tree. To ++# explicitly enable an option group, you may also write: ++# ++# OPTION_GROUP_NAME = y ++# ++# although this simply reestablishes the value already set by ++# 'option-groups.defaults'. ++ ++config EGLIBC_ADVANCED_INET6 ++ bool "IPv6 Advanced Sockets API support (RFC3542)" ++ depends on EGLIBC_INET ++ help ++ This option group includes the functions specified by RFC 3542, ++ "Advanced Sockets Application Program Interface (API) for ++ IPv6". ++ ++ This option group includes the following functions: ++ ++ inet6_opt_append ++ inet6_opt_find ++ inet6_opt_finish ++ inet6_opt_get_val ++ inet6_opt_init ++ inet6_option_alloc ++ inet6_option_append ++ inet6_option_find ++ inet6_option_init ++ inet6_option_next ++ inet6_option_space ++ inet6_opt_next ++ inet6_opt_set_val ++ inet6_rth_add ++ inet6_rth_getaddr ++ inet6_rth_init ++ inet6_rth_reverse ++ inet6_rth_segments ++ inet6_rth_space ++ ++config EGLIBC_BACKTRACE ++ bool "Functions for producing backtraces" ++ help ++ This option group includes functions for producing a list of ++ the function calls that are currently active in a thread, from ++ within the thread itself. These functions are often used ++ within signal handlers, to produce diagnostic output. ++ ++ This option group includes the following functions: ++ ++ backtrace ++ backtrace_symbols ++ backtrace_symbols_fd ++ ++config EGLIBC_BIG_MACROS ++ bool "Use extensive inline code" ++ help ++ This option group specifies whether certain pieces of code ++ should be inlined to achieve maximum speed. If this option ++ group is not selected, function calls will be used instead, ++ hence reducing the library footprint. ++ ++config EGLIBC_BSD ++ bool "BSD-specific functions, and their compatibility stubs" ++ help ++ This option group includes functions specific to BSD kernels. ++ A number of these functions have stub versions that are also ++ included in libraries built for non-BSD systems for ++ compatibility. ++ ++ This option group includes the following functions: ++ ++ chflags ++ fchflags ++ lchmod ++ revoke ++ setlogin ++ ++config EGLIBC_CXX_TESTS ++ bool "Tests that link against the standard C++ library." ++ depends on POSIX_WIDE_CHAR_DEVICE_IO && EGLIBC_LIBM ++ help ++ This option group does not include any C library functions; ++ instead, it controls which EGLIBC tests an ordinary 'make ++ tests' runs. With this group disabled, tests that would ++ normally link against the standard C++ library are not ++ run. ++ ++ The standard C++ library depends on the math library 'libm' and ++ the wide character I/O functions included in EGLIBC. So those ++ option groups must be enabled if this test is enabled. ++ ++config EGLIBC_CATGETS ++ bool "Functions for accessing message catalogs" ++ depends on EGLIBC_LOCALE_CODE ++ help ++ This option group includes functions for accessing message ++ catalogs: catopen, catclose, and catgets. ++ ++ This option group depends on the EGLIBC_LOCALE_CODE ++ option group. ++ ++config EGLIBC_CHARSETS ++ bool "iconv/gconv character set conversion libraries" ++ help ++ This option group includes support for character sets other ++ than ASCII (ANSI_X3.4-1968) and Unicode and ISO-10646 in their ++ various encodings. This affects both the character sets ++ supported by the wide and multibyte character functions, and ++ those supported by the 'iconv' functions. ++ ++ With this option group disabled, EGLIBC supports only the ++ following character sets: ++ ++ ANSI_X3.4 - ASCII ++ ANSI_X3.4-1968 ++ ANSI_X3.4-1986 ++ ASCII ++ CP367 ++ CSASCII ++ IBM367 ++ ISO-IR-6 ++ ISO646-US ++ ISO_646.IRV:1991 ++ OSF00010020 ++ US ++ US-ASCII ++ ++ 10646-1:1993 - ISO 10646, in big-endian UCS4 form ++ 10646-1:1993/UCS4 ++ CSUCS4 ++ ISO-10646 ++ ISO-10646/UCS4 ++ OSF00010104 ++ OSF00010105 ++ OSF00010106 ++ UCS-4 ++ UCS-4BE ++ UCS4 ++ ++ UCS-4LE - ISO 10646, in little-endian UCS4 form ++ ++ ISO-10646/UTF-8 - ISO 10646, in UTF-8 form ++ ISO-10646/UTF8 ++ ISO-IR-193 ++ OSF05010001 ++ UTF-8 ++ UTF8 ++ ++ ISO-10646/UCS2 - ISO 10646, in target-endian UCS2 form ++ OSF00010100 ++ OSF00010101 ++ OSF00010102 ++ UCS-2 ++ UCS2 ++ ++ UCS-2BE - ISO 10646, in big-endian UCS2 form ++ UNICODEBIG ++ ++ UCS-2LE - ISO 10646, in little-endian UCS2 form ++ UNICODELITTLE ++ ++ WCHAR_T - EGLIBC's internal form (target-endian, ++ 32-bit ISO 10646) ++ ++config EGLIBC_CRYPT ++ bool "Encryption library" ++ help ++ This option group includes the `libcrypt' library which ++ provides functions for one-way encryption. Supported ++ encryption algorithms include MD5, SHA-256, SHA-512 and DES. ++ ++config EGLIBC_CRYPT_UFC ++ bool "Ultra fast `crypt' implementation" ++ depends on EGLIBC_CRYPT ++ help ++ This option group provides ultra fast DES-based implementation of ++ the `crypt' function. When this option group is disabled, ++ (a) the library will not provide the setkey[_r] and encrypt[_r] ++ functions and (b) the crypt[_r] function will return NULL and set the ++ errno to ENOSYS if /salt/ passed does not correspond to either MD5, ++ SHA-256 or SHA-512 algorithm. ++ ++config EGLIBC_DB_ALIASES ++ bool "Functions for accessing the mail aliases database" ++ help ++ This option group includues functions for looking up mail ++ aliases in '/etc/aliases' or using nsswitch. It includes the ++ following functions: ++ ++ endaliasent ++ getaliasbyname ++ getaliasbyname_r ++ getaliasent ++ getaliasent_r ++ setaliasent ++ ++ When this option group is disabled, the NSS service libraries ++ also lack support for querying their mail alias tables. ++ ++config EGLIBC_ENVZ ++ bool "Functions for handling envz-style environment vectors." ++ help ++ This option group contains functions for creating and operating ++ on envz vectors. An "envz vector" is a vector of strings in a ++ contiguous block of memory, where each element is a name-value ++ pair, and elements are separated from their neighbors by null ++ characters. ++ ++ This option group includes the following functions: ++ ++ envz_add envz_merge ++ envz_entry envz_remove ++ envz_get envz_strip ++ ++config EGLIBC_FCVT ++ bool "Functions for converting floating-point numbers to strings" ++ help ++ This option group includes functions for converting ++ floating-point numbers to strings. ++ ++ This option group includes the following functions: ++ ++ ecvt qecvt ++ ecvt_r qecvt_r ++ fcvt qfcvt ++ fcvt_r qfcvt_r ++ gcvt qgcvt ++ ++config EGLIBC_FMTMSG ++ bool "Functions for formatting messages" ++ help ++ This option group includes the following functions: ++ ++ addseverity fmtmsg ++ ++config EGLIBC_FSTAB ++ bool "Access functions for 'fstab'" ++ help ++ This option group includes functions for reading the mount ++ point specification table, '/etc/fstab'. These functions are ++ not included in the POSIX standard, which provides the ++ 'getmntent' family of functions instead. ++ ++ This option group includes the following functions: ++ ++ endfsent getfsspec ++ getfsent setfsent ++ getfsfile ++ ++config EGLIBC_FTRAVERSE ++ bool "Functions for traversing file hierarchies" ++ help ++ This option group includes functions for traversing file ++ UNIX file hierachies. ++ ++ This option group includes the following functions: ++ ++ fts_open ftw ++ fts_read nftw ++ fts_children ftw64 ++ fts_set nftw64 ++ fts_close ++ ++config EGLIBC_GETLOGIN ++ bool "The getlogin function" ++ depends on EGLIBC_UTMP ++ help ++ This function group includes the 'getlogin' and 'getlogin_r' ++ functions, which return the user name associated by the login ++ activity with the current process's controlling terminal. ++ ++ With this option group disabled, the 'glob' function will not ++ fall back on 'getlogin' to find the user's login name for tilde ++ expansion when the 'HOME' environment variable is not set. ++ ++config EGLIBC_IDN ++ bool "International domain names support" ++ help ++ This option group includes the `libcidn' library which ++ provides support for international domain names. ++ ++config EGLIBC_INET ++ bool "Networking support" ++ help ++ This option group includes networking-specific functions and ++ data. With EGLIBC_INET disabled, the EGLIBC ++ installation and API changes as follows: ++ ++ - The following libraries are not installed: ++ ++ libnsl ++ libnss_compat ++ libnss_dns ++ libnss_hesiod ++ libnss_nis ++ libnss_nisplus ++ libresolv ++ ++ - The following functions and variables are omitted from libc: ++ ++ authdes_create hstrerror svc_fdset ++ authdes_getucred htonl svc_getreq ++ authdes_pk_create htons svc_getreq_common ++ authnone_create if_freenameindex svc_getreq_poll ++ authunix_create if_indextoname svc_getreqset ++ authunix_create_default if_nameindex svc_max_pollfd ++ bindresvport if_nametoindex svc_pollfd ++ callrpc in6addr_any svcraw_create ++ cbc_crypt in6addr_loopback svc_register ++ clnt_broadcast inet6_opt_append svc_run ++ clnt_create inet6_opt_find svc_sendreply ++ clnt_pcreateerror inet6_opt_finish svctcp_create ++ clnt_perrno inet6_opt_get_val svcudp_bufcreate ++ clnt_perror inet6_opt_init svcudp_create ++ clntraw_create inet6_option_alloc svcudp_enablecache ++ clnt_spcreateerror inet6_option_append svcunix_create ++ clnt_sperrno inet6_option_find svcunixfd_create ++ clnt_sperror inet6_option_init svc_unregister ++ clnttcp_create inet6_option_next user2netname ++ clntudp_bufcreate inet6_option_space xdecrypt ++ clntudp_create inet6_opt_next xdr_accepted_reply ++ clntunix_create inet6_opt_set_val xdr_array ++ des_setparity inet6_rth_add xdr_authdes_cred ++ ecb_crypt inet6_rth_getaddr xdr_authdes_verf ++ endaliasent inet6_rth_init xdr_authunix_parms ++ endhostent inet6_rth_reverse xdr_bool ++ endnetent inet6_rth_segments xdr_bytes ++ endnetgrent inet6_rth_space xdr_callhdr ++ endprotoent inet_addr xdr_callmsg ++ endrpcent inet_aton xdr_char ++ endservent inet_lnaof xdr_cryptkeyarg ++ ether_aton inet_makeaddr xdr_cryptkeyarg2 ++ ether_aton_r inet_netof xdr_cryptkeyres ++ ether_hostton inet_network xdr_des_block ++ ether_line inet_nsap_addr xdr_double ++ ether_ntoa inet_nsap_ntoa xdr_enum ++ ether_ntoa_r inet_ntoa xdr_float ++ ether_ntohost inet_ntop xdr_free ++ freeaddrinfo inet_pton xdr_getcredres ++ freeifaddrs innetgr xdr_hyper ++ gai_strerror iruserok xdr_int ++ getaddrinfo iruserok_af xdr_int16_t ++ getaliasbyname key_decryptsession xdr_int32_t ++ getaliasbyname_r key_decryptsession_pk xdr_int64_t ++ getaliasent key_encryptsession xdr_int8_t ++ getaliasent_r key_encryptsession_pk xdr_keybuf ++ gethostbyaddr key_gendes xdr_key_netstarg ++ gethostbyaddr_r key_get_conv xdr_key_netstres ++ gethostbyname key_secretkey_is_set xdr_keystatus ++ gethostbyname2 key_setnet xdr_long ++ gethostbyname2_r key_setsecret xdr_longlong_t ++ gethostbyname_r netname2host xdrmem_create ++ gethostent netname2user xdr_netnamestr ++ gethostent_r ntohl xdr_netobj ++ getifaddrs ntohs xdr_opaque ++ getipv4sourcefilter passwd2des xdr_opaque_auth ++ get_myaddress pmap_getmaps xdr_pmap ++ getnameinfo pmap_getport xdr_pmaplist ++ getnetbyaddr pmap_rmtcall xdr_pointer ++ getnetbyaddr_r pmap_set xdr_quad_t ++ getnetbyname pmap_unset xdrrec_create ++ getnetbyname_r rcmd xdrrec_endofrecord ++ getnetent rcmd_af xdrrec_eof ++ getnetent_r registerrpc xdrrec_skiprecord ++ getnetgrent res_init xdr_reference ++ getnetgrent_r rexec xdr_rejected_reply ++ getnetname rexec_af xdr_replymsg ++ getprotobyname rexecoptions xdr_rmtcall_args ++ getprotobyname_r rpc_createerr xdr_rmtcallres ++ getprotobynumber rresvport xdr_short ++ getprotobynumber_r rresvport_af xdr_sizeof ++ getprotoent rtime xdrstdio_create ++ getprotoent_r ruserok xdr_string ++ getpublickey ruserok_af xdr_u_char ++ getrpcbyname ruserpass xdr_u_hyper ++ getrpcbyname_r setaliasent xdr_u_int ++ getrpcbynumber sethostent xdr_uint16_t ++ getrpcbynumber_r setipv4sourcefilter xdr_uint32_t ++ getrpcent setnetent xdr_uint64_t ++ getrpcent_r setnetgrent xdr_uint8_t ++ getrpcport setprotoent xdr_u_long ++ getsecretkey setrpcent xdr_u_longlong_t ++ getservbyname setservent xdr_union ++ getservbyname_r setsourcefilter xdr_unixcred ++ getservbyport svcauthdes_stats xdr_u_quad_t ++ getservbyport_r svcerr_auth xdr_u_short ++ getservent svcerr_decode xdr_vector ++ getservent_r svcerr_noproc xdr_void ++ getsourcefilter svcerr_noprog xdr_wrapstring ++ h_errlist svcerr_progvers xencrypt ++ h_errno svcerr_systemerr xprt_register ++ herror svcerr_weakauth xprt_unregister ++ h_nerr svc_exit ++ host2netname svcfd_create ++ ++ - The rpcgen, nscd, and rpcinfo commands are not installed. ++ ++ - The 'rpc' file (a text file listing RPC services) is not installed. ++ ++ Socket-related system calls do not fall in this option group, ++ because many are also used for other inter-process ++ communication mechanisms. For example, the 'syslog' routines ++ use Unix-domain sockets to communicate with the syslog daemon; ++ syslog is valuable in non-networked contexts. ++ ++config EGLIBC_INET_ANL ++ bool "Asynchronous name lookup" ++ depends on EGLIBC_INET ++ help ++ This option group includes the `libanl' library which ++ provides support for asynchronous name lookup. ++ ++config EGLIBC_LIBM ++ bool "libm (math library)" ++ help ++ This option group includes the 'libm' library, containing ++ mathematical functions. If this option group is omitted, then ++ an EGLIBC installation does not include shared or unshared versions ++ of the math library. ++ ++ Note that this does not remove all floating-point related ++ functionality from EGLIBC; for example, 'printf' and 'scanf' ++ can still print and read floating-point values with this option ++ group disabled. ++ ++ Note that the ISO Standard C++ library 'libstdc++' depends on ++ EGLIBC's math library 'libm'. If you disable this option ++ group, you will not be able to build 'libstdc++' against the ++ resulting EGLIBC installation. ++ ++config EGLIBC_LOCALES ++ bool "Locale definitions" ++ help ++ This option group includes all locale definitions other than ++ that for the "C" locale. If this option group is omitted, then ++ only the "C" locale is supported. ++ ++ ++config EGLIBC_LOCALE_CODE ++ bool "Locale functions" ++ depends on POSIX_C_LANG_WIDE_CHAR ++ help ++ This option group includes locale support functions, programs, ++ and libraries. With EGLIBC_LOCALE_CODE disabled, ++ EGLIBC supports only the 'C' locale (also known as 'POSIX'), ++ and ignores the settings of the 'LANG' and 'LC_*' environment ++ variables. ++ ++ With EGLIBC_LOCALE_CODE disabled, the following ++ functions are omitted from libc: ++ ++ duplocale localeconv nl_langinfo rpmatch strfmon_l ++ freelocale newlocale nl_langinfo_l strfmon uselocale ++ ++ Furthermore, only the LC_CTYPE and LC_TIME categories of the ++ standard "C" locale are available. ++ ++ The EGLIBC_CATGETS option group depends on this option group. ++ ++ ++config EGLIBC_MEMUSAGE ++ bool "Memory profiling library" ++ help ++ This option group includes the `libmemusage' library and ++ the `memusage' and `memusagestat' utilities. ++ These components provide memory profiling functions. ++ ++config EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE ++ int "Memory profiling library buffer size" ++ depends on EGLIBC_MEMUSAGE ++ default "32768" ++ help ++ Libmemusage library buffers the profiling data in memory ++ before writing it out to disk. By default, the library ++ allocates 1.5M buffer, which can be substantial for some ++ systems. EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE option ++ allows to change the default buffer size. It specifies ++ the number of entries the buffer should have. ++ On most architectures one buffer entry amounts to 48 bytes, ++ so setting this option to the value of 512 will reduce the size of ++ the memory buffer to 24K. ++ ++config EGLIBC_NIS ++ bool "Support for NIS, NIS+, and the special 'compat' services." ++ depends on EGLIBC_INET && EGLIBC_SUNRPC ++ help ++ This option group includes the NIS, NIS+, and 'compat' Name ++ Service Switch service libraries. When it is disabled, those ++ services libraries are not installed; you should remove any ++ references to them from your 'nsswitch.conf' file. ++ ++ This option group depends on the EGLIBC_INET option ++ group; you must enable that to enable this option group. ++ ++config EGLIBC_NSSWITCH ++ bool "Name service switch (nsswitch) support" ++ help ++ This option group includes support for the 'nsswitch' facility. ++ With this option group enabled, all EGLIBC functions for ++ accessing various system databases (passwords and groups; ++ networking; aliases; public keys; and so on) consult the ++ '/etc/nsswitch.conf' configuration file to decide how to handle ++ queries. ++ ++ With this option group disabled, EGLIBC uses a fixed list of ++ services to satisfy queries on each database, as requested by ++ configuration files specified when EGLIBC is built. Your ++ 'option-groups.config' file must set the following two ++ variables: ++ ++config EGLIBC_NSSWITCH_FIXED_CONFIG ++ string "Nsswitch fixed config filename" ++ depends on !EGLIBC_NSSWITCH ++ default "" ++ help ++ Set this to the name of a file whose contents observe the ++ same syntax as an ordinary '/etc/nsswitch.conf' file. The ++ EGLIBC build process parses this file just as EGLIBC would ++ at run time if EGLIBC_NSSWITCH were enabled, and ++ produces a C library that uses the nsswitch service ++ libraries to search for database entries as this file ++ specifies, instead of consulting '/etc/nsswitch.conf' at run ++ time. ++ ++ This should be an absolute filename. The EGLIBC build ++ process may use it from several different working ++ directories. It may include references to Makefile ++ variables like 'common-objpfx' (the top of the build tree, ++ with a trailing slash), or '..' (the top of the source tree, ++ with a trailing slash). ++ ++ The EGLIBC source tree includes a sample configuration file ++ named 'nss/fixed-nsswitch.conf'; for simple configurations, ++ you will probably want to delete references to databases not ++ needed on your system. ++ ++config EGLIBC_NSSWITCH_FIXED_FUNCTIONS ++ string "Nsswitch fixed functions filename" ++ depends on !EGLIBC_NSSWITCH ++ default "" ++ help ++ The EGLIBC build process uses this file to decide which ++ functions to make available from which service libraries. ++ The file 'nss/fixed-nsswitch.functions' serves as a sample ++ configuration file for this setting, and explains its syntax ++ and meaning in more detail. ++ ++ This should be an absolute file name. The EGLIBC build ++ process may use it from several different working ++ directories. It may include references to Makefile ++ variables like 'common-objpfx' (the top of the build tree, ++ with a trailing slash), or '..' (the top of the source tree, ++ with a trailing slash). ++ ++ Be sure to mention each function in each service you wish to ++ use. If you do not mention a service's function here, the ++ EGLIBC database access functions will not find it, even if ++ it is listed in the EGLIBC_NSSWITCH_FIXED_CONFIG ++ file. ++ ++ In this arrangement, EGLIBC will not use the 'dlopen' and ++ 'dlsym' functions to find database access functions. Instead, ++ libc hard-codes references to the service libraries' database ++ access functions. You must explicitly link your program ++ against the name service libraries (those whose names start ++ with 'libnss_', in the sysroot's '/lib' directory) whose ++ functions you intend to use. This arrangement helps ++ system-wide static analysis tools decide which functions a ++ system actually uses. ++ ++ Note that some nsswitch service libraries require other option ++ groups to be enabled; for example, the EGLIBC_INET ++ option group must be enabled to use the 'libnss_dns.so.2' ++ service library, which uses the Domain Name System network ++ protocol to answer queries. ++ ++config EGLIBC_RCMD ++ bool "Support for 'rcmd' and related library functions" ++ depends on EGLIBC_INET ++ help ++ This option group includes functions for running commands on ++ remote machines via the 'rsh' protocol, and doing authentication ++ related to those functions. This also includes functions that ++ use the 'rexec' protocol. ++ ++ This option group includes the following functions: ++ ++ rcmd ruserok ++ rcmd_af ruserok_af ++ rexec iruserok ++ rexec_af iruserok_af ++ rresvport ruserpass ++ rresvport_af ++ ++config EGLIBC_RTLD_DEBUG ++ bool "Runtime linker debug print outs" ++ help ++ This option group enables debug output of the runtime linker ++ which is activated via LD_DEBUG and LD_TRACE_PRELINKING ++ environment variables. Disabling this option group yields ++ a smaller runtime linker binary. ++ BEWARE: Disabling this option group is likely to break ++ the `ldd' utility which may also be used by the prelinker. ++ In particular, the `--unused' ldd option will not work correctly. ++ ++config EGLIBC_SPAWN ++ bool "Support for POSIX posix_spawn functions" ++ help ++ This option group includes the POSIX functions for executing ++ programs in child processes without using 'fork' or 'vfork'. ++ ++ This option group includes the following functions: ++ ++ posix_spawn ++ posix_spawnattr_destroy ++ posix_spawnattr_getflags ++ posix_spawnattr_getpgroup ++ posix_spawnattr_getschedparam ++ posix_spawnattr_getschedpolicy ++ posix_spawnattr_getsigdefault ++ posix_spawnattr_getsigmask ++ posix_spawnattr_init ++ posix_spawnattr_setflags ++ posix_spawnattr_setpgroup ++ posix_spawnattr_setschedparam ++ posix_spawnattr_setschedpolicy ++ posix_spawnattr_setsigdefault ++ posix_spawnattr_setsigmask ++ posix_spawn_file_actions_addclose ++ posix_spawn_file_actions_adddup2 ++ posix_spawn_file_actions_addopen ++ posix_spawn_file_actions_destroy ++ posix_spawn_file_actions_init ++ posix_spawnp ++ ++ This option group also provides the ability for the iconv, ++ localedef, and locale programs to operate transparently on ++ compressed charset definitions. When this option group is ++ disabled, those programs will only operate on uncompressed ++ charmap files. ++ ++config EGLIBC_STREAMS ++ bool "Support for accessing STREAMS." ++ help ++ This option group includes functions for reading and writing ++ messages to and from STREAMS. The STREAMS interface provides a ++ uniform mechanism for implementing networking services and other ++ character-based I/O. (STREAMS are not to be confused with ++ FILE objects, also called 'streams'.) ++ ++ This option group includes the following functions: ++ ++ getmsg putpmsg ++ getpmsg fattach ++ isastream fdetach ++ putmsg ++ ++config EGLIBC_SUNRPC ++ bool "Support for the Sun 'RPC' protocol." ++ depends on EGLIBC_INET ++ help ++ This option group includes support for the Sun RPC protocols, ++ including the 'rpcgen' and 'rpcinfo' programs. ++ ++config EGLIBC_UTMP ++ bool "Older access functions for 'utmp' login records" ++ help ++ This option group includes the older 'utent' family of ++ functions for accessing user login records in the 'utmp' file. ++ POSIX omits these functions in favor of the 'utxent' family, ++ and they are obsolete on systems other than Linux. ++ ++ This option group includes the following functions: ++ ++ endutent ++ getutent ++ getutent_r ++ getutid ++ getutid_r ++ getutline ++ getutline_r ++ logwtmp ++ pututline ++ setutent ++ updwtmp ++ utmpname ++ ++ This option group includes the following libraries: ++ ++ libutil.so (and libutil.a) ++ ++config EGLIBC_UTMPX ++ bool "POSIX access functions for 'utmp' login records" ++ depends on EGLIBC_UTMP ++ help ++ This option group includes the POSIX functions for reading and ++ writing user login records in the 'utmp' file (usually ++ '/var/run/utmp'). The POSIX functions operate on 'struct ++ utmpx' structures, as opposed to the family of older 'utent' ++ functions, which operate on 'struct utmp' structures. ++ ++ This option group includes the following functions: ++ ++ endutxent ++ getutmp ++ getutmpx ++ getutxent ++ getutxid ++ getutxline ++ pututxline ++ setutxent ++ updwtmpx ++ utmpxname ++ ++config EGLIBC_WORDEXP ++ bool "Shell-style word expansion" ++ help ++ This option group includes the 'wordexp' function for ++ performing word expansion in the manner of the shell, and the ++ accompanying 'wordfree' function. ++ ++config POSIX_C_LANG_WIDE_CHAR ++ bool "ISO C library wide character functions, excluding I/O" ++ help ++ This option group includes the functions defined by the ISO C ++ standard for working with wide and multibyte characters in ++ memory. Functions for reading and writing wide and multibyte ++ characters from and to files call in the ++ POSIX_WIDE_CHAR_DEVICE_IO option group. ++ ++ This option group includes the following functions: ++ ++ btowc mbsinit wcscspn wcstoll ++ iswalnum mbsrtowcs wcsftime wcstombs ++ iswalpha mbstowcs wcslen wcstoul ++ iswblank mbtowc wcsncat wcstoull ++ iswcntrl swprintf wcsncmp wcstoumax ++ iswctype swscanf wcsncpy wcsxfrm ++ iswdigit towctrans wcspbrk wctob ++ iswgraph towlower wcsrchr wctomb ++ iswlower towupper wcsrtombs wctrans ++ iswprint vswprintf wcsspn wctype ++ iswpunct vswscanf wcsstr wmemchr ++ iswspace wcrtomb wcstod wmemcmp ++ iswupper wcscat wcstof wmemcpy ++ iswxdigit wcschr wcstoimax wmemmove ++ mblen wcscmp wcstok wmemset ++ mbrlen wcscoll wcstol ++ mbrtowc wcscpy wcstold ++ ++config POSIX_REGEXP ++ bool "Regular expressions" ++ help ++ This option group includes the POSIX regular expression ++ functions, and the associated non-POSIX extensions and ++ compatibility functions. ++ ++ With POSIX_REGEXP disabled, the following functions are ++ omitted from libc: ++ ++ re_comp re_max_failures regcomp ++ re_compile_fastmap re_search regerror ++ re_compile_pattern re_search_2 regexec ++ re_exec re_set_registers regfree ++ re_match re_set_syntax rpmatch ++ re_match_2 re_syntax_options ++ ++ Furthermore, the compatibility regexp interface defined in the ++ header file, 'compile', 'step', and 'advance', is ++ omitted. ++ ++config POSIX_REGEXP_GLIBC ++ bool "Regular expressions from GLIBC" ++ depends on POSIX_REGEXP ++ help ++ This option group specifies which regular expression ++ library to use. The choice is between regex ++ implementation from GLIBC and regex implementation from ++ libiberty. The GLIBC variant is fully POSIX conformant and ++ optimized for speed; regex from libiberty is more than twice ++ as small while still is enough for most practical purposes. ++ ++config POSIX_WIDE_CHAR_DEVICE_IO ++ bool "Input and output functions for wide characters" ++ depends on POSIX_C_LANG_WIDE_CHAR ++ help ++ This option group includes functions for reading and writing ++ wide characters to and from streams. ++ ++ This option group includes the following functions: ++ ++ fgetwc fwprintf putwchar vwscanf ++ fgetws fwscanf ungetwc wprintf ++ fputwc getwc vfwprintf wscanf ++ fputws getwchar vfwscanf ++ fwide putwc vwprintf ++ ++ This option group further includes the following unlocked ++ variants of the above functions: ++ ++ fgetwc_unlocked getwc_unlocked ++ fgetws_unlocked getwchar_unlocked ++ fputwc_unlocked putwc_unlocked ++ fputws_unlocked putwchar_unlocked ++ ++ Note that the GNU standard C++ library, 'libstdc++.so', uses ++ some of these functions; you will not be able to link or run ++ C++ programs if you disable this option group. ++ ++ This option group also affects the behavior of the following ++ functions: ++ ++ fdopen ++ fopen ++ fopen64 ++ freopen ++ freopen64 ++ ++ These functions all take an OPENTYPE parameter which may ++ contain a string of the form ",ccs=CHARSET", indicating that ++ the underlying file uses the character set named CHARSET. ++ This produces a wide-oriented stream, which is only useful ++ when the functions included in this option group are present. ++ If the user attempts to open a file specifying a character set ++ in the OPENTYPE parameter, and EGLIBC was built with this ++ option group disabled, the function returns NULL, and sets ++ errno to EINVAL. ++ ++ ++# This helps Emacs users browse this file using the page motion commands ++# and commands like 'pages-directory'. ++# Local Variables: ++# page-delimiter: "^config\\s-" ++# End: +diff --git a/option-groups.defaults b/option-groups.defaults +new file mode 100644 +index 0000000..8141201 +--- /dev/null ++++ b/option-groups.defaults +@@ -0,0 +1,47 @@ ++# This file sets default values for all option group variables ++# mentioned in option-groups.def; see that file for a description of ++# each option group. ++# ++# Subdirectory makefiles include this file before including the user's ++# settings from option-groups.config at the top of the build tree; ++# that file need only refer to those options whose default settings ++# are to be changed. ++# ++# By default, all option groups are enabled. ++OPTION_EGLIBC_ADVANCED_INET6 = y ++OPTION_EGLIBC_BACKTRACE = y ++OPTION_EGLIBC_BIG_MACROS = y ++OPTION_EGLIBC_BSD = y ++OPTION_EGLIBC_CXX_TESTS = y ++OPTION_EGLIBC_CATGETS = y ++OPTION_EGLIBC_CHARSETS = y ++OPTION_EGLIBC_CRYPT = y ++OPTION_EGLIBC_CRYPT_UFC = y ++OPTION_EGLIBC_DB_ALIASES = y ++OPTION_EGLIBC_ENVZ = y ++OPTION_EGLIBC_FCVT = y ++OPTION_EGLIBC_FMTMSG = y ++OPTION_EGLIBC_FSTAB = y ++OPTION_EGLIBC_FTRAVERSE = y ++OPTION_EGLIBC_GETLOGIN = y ++OPTION_EGLIBC_IDN = y ++OPTION_EGLIBC_INET = y ++OPTION_EGLIBC_INET_ANL = y ++OPTION_EGLIBC_LIBM = y ++OPTION_EGLIBC_LOCALES = y ++OPTION_EGLIBC_LOCALE_CODE = y ++OPTION_EGLIBC_MEMUSAGE = y ++OPTION_EGLIBC_NIS = y ++OPTION_EGLIBC_NSSWITCH = y ++OPTION_EGLIBC_RCMD = y ++OPTION_EGLIBC_RTLD_DEBUG = y ++OPTION_EGLIBC_SPAWN = y ++OPTION_EGLIBC_STREAMS = y ++OPTION_EGLIBC_SUNRPC = y ++OPTION_EGLIBC_UTMP = y ++OPTION_EGLIBC_UTMPX = y ++OPTION_EGLIBC_WORDEXP = y ++OPTION_POSIX_C_LANG_WIDE_CHAR = y ++OPTION_POSIX_REGEXP = y ++OPTION_POSIX_REGEXP_GLIBC = y ++OPTION_POSIX_WIDE_CHAR_DEVICE_IO = y +diff --git a/option-groups.mak b/option-groups.mak +new file mode 100644 +index 0000000..f83e0c1 +--- /dev/null ++++ b/option-groups.mak +@@ -0,0 +1,41 @@ ++# Setup file for subdirectory Makefiles that define EGLIBC option groups. ++ ++# EGLIBC shouldn't need to override this. However, the ++# cross-build-friendly localedef includes this makefile to get option ++# group variable definitions; it uses a single build tree for all the ++# multilibs, and needs to be able to specify a different option group ++# configuration file for each multilib. ++option_group_config_file ?= $(objdir)/option-groups.config ++ ++# Read the default settings for all options. ++# We're included before ../Rules, so we can't assume $(..) is set. ++include $(firstword $(..) ../)option-groups.defaults ++ ++# Read the developer's option group selections, overriding the ++# defaults from option-groups.defaults. ++-include $(option_group_config_file) ++ ++# $(call option-disabled, VAR) is 'y' if VAR is not 'y', or 'n' otherwise. ++# VAR should be a variable name, not a variable reference; this is ++# less general, but more terse for the intended use. ++# You can use it to add a file to a list if an option group is ++# disabled, like this: ++# routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += ... ++define option-disabled ++$(firstword $(subst y,n,$(filter y,$($(strip $(1))))) y) ++endef ++ ++# Establish 'routines-y', etc. as simply-expanded variables. ++aux-y := ++extra-libs-others-y := ++extra-libs-y := ++extra-objs-y := ++install-bin-y := ++install-others-y := ++install-sbin-y := ++others-y := ++others-pie-y := ++routines-y := ++test-srcs-y := ++tests-y := ++xtests-y := +diff --git a/options-config/Makefile b/options-config/Makefile +new file mode 100644 +index 0000000..db00708 +--- /dev/null ++++ b/options-config/Makefile +@@ -0,0 +1,55 @@ ++# =========================================================================== ++# EGLIBC option-groups configuration targets ++# These targets are included from top-level makefile ++ ++ifneq ($(kconfig_tools),) ++ifneq (no,$(PERL)) ++ ++ocdir := options-config ++ ++OconfigDefaults := option-groups.defaults ++OconfigDefaults_tmp := $(common-objpfx).tmp.defconfig ++OconfigDef := option-groups.def ++Oconfig := $(common-objpfx)option-groups.config ++Oconfig_tmp := $(common-objpfx).tmp.config ++ ++conf := $(kconfig_tools)/conf ++mconf := $(kconfig_tools)/mconf ++ ++preproc := $(PERL) $(ocdir)/config-preproc.pl ++postproc := $(PERL) $(ocdir)/config-postproc.pl ++ ++PHONY += defconfig config menuconfig ++ ++defconfig: $(conf) $(OconfigDefaults) $(OconfigDef) ++ rm -f $(OconfigDefaults_tmp) ++ rm -f $(Oconfig_tmp) ++ $(preproc) $(OconfigDefaults) > $(OconfigDefaults_tmp) ++ KCONFIG_CONFIG=$(Oconfig_tmp) $< --defconfig=$(OconfigDefaults_tmp) \ ++ $(OconfigDef) ++ $(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig) ++ rm $(Oconfig_tmp) ++ rm $(OconfigDefaults_tmp) ++ ++config: $(conf) $(OconfigDefaults) $(OconfigDef) ++ rm -f $(Oconfig_tmp) ++ $(preproc) $(wildcard $(Oconfig)) > $(Oconfig_tmp) ++ KCONFIG_CONFIG=$(Oconfig_tmp) $< --oldaskconfig $(OconfigDef) ++ $(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig) ++ rm $(Oconfig_tmp) ++ ++menuconfig: $(mconf) $(OconfigDefaults) $(OconfigDef) ++ rm -f $(Oconfig_tmp) ++ $(preproc) $(wildcard $(Oconfig)) > $(Oconfig_tmp) ++ KCONFIG_CONFIG=$(Oconfig_tmp) $< $(OconfigDef) ++ $(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig) ++ rm $(Oconfig_tmp) ++ ++# Help text used by make help ++help: ++ @echo ' defconfig - New config with default from default config' ++ @echo ' config - Update current config utilising a line-oriented program' ++ @echo ' menuconfig - Update current config utilising a menu based program' ++ ++endif ++endif +diff --git a/options-config/config-postproc.pl b/options-config/config-postproc.pl +new file mode 100644 +index 0000000..4dd1c63 +--- /dev/null ++++ b/options-config/config-postproc.pl +@@ -0,0 +1,58 @@ ++#!/usr/bin/perl ++ ++$usage = "usage: $0 \n"; ++ ++die "$usage" unless @ARGV; ++$defaults = shift @ARGV; ++die "$usage" unless @ARGV; ++die "Could not open $ARGV[0]" unless -T $ARGV[0]; ++ ++sub yank { ++ @option = grep(!($_ =~ /$_[0]\s*=/), @option); ++} ++ ++open(DEFAULTS, $defaults) || die "Could not open $defaults\n"; ++ ++# get the full list of available options using the default config file ++$i = 0; ++while () { ++ if (/^\s*OPTION_(\w+\s*=.*$)/) { ++ $option[$i++] = $1; ++ } ++} ++ ++# now go through the config file, making the necessary changes ++while (<>) { ++ if (/Linux Kernel Configuration/) { ++ # change title ++ s/Linux Kernel/Option Groups/; ++ print; ++ } elsif (/^\s*CONFIG_(\w+)\s*=/) { ++ # this is an explicit option set line, change CONFIG_ to OPTION_ ++ # before printing and remove this option from option list ++ $opt = $1; ++ yank($opt); ++ s/CONFIG_/OPTION_/g; ++ print; ++ } elsif (/^\s*#\s+CONFIG_(\w+) is not set/) { ++ # this is a comment line for an unset boolean option, change CONFIG_ ++ # to OPTION_, remove this option from option list, and convert to ++ # explicit OPTION_FOO=n ++ $opt = $1; ++ yank($opt); ++ s/CONFIG_/OPTION_/g; ++ print "OPTION_$opt=n\n"; ++ } else { ++ print; ++ } ++} ++ ++# any boolean options left in @options, are options that were not mentioned in ++# the config file, and implicitly that means the option must be set =n, ++# so do that here. ++foreach $opt (@option) { ++ if ($opt =~ /=\s*[yn]/) { ++ $opt =~ s/=\s*[yn]/=n/; ++ print "OPTION_$opt\n"; ++ } ++} +diff --git a/options-config/config-preproc.pl b/options-config/config-preproc.pl +new file mode 100644 +index 0000000..b83bb85 +--- /dev/null ++++ b/options-config/config-preproc.pl +@@ -0,0 +1,8 @@ ++#!/usr/bin/perl ++ ++if (@ARGV) { ++ while (<>) { ++ s/OPTION_/CONFIG_/g; ++ print; ++ } ++} +diff --git a/scripts/option-groups.awk b/scripts/option-groups.awk +new file mode 100644 +index 0000000..533af0c +--- /dev/null ++++ b/scripts/option-groups.awk +@@ -0,0 +1,63 @@ ++# option-groups.awk --- generate option group header file ++# Given input files containing makefile-style assignments to variables, ++# print out a header file that #defines an appropriate preprocessor ++# symbol for each variable left set to 'y'. ++ ++BEGIN { FS="=" } ++ ++# Trim spaces. ++{ gsub (/[[:blank:]]/, "") } ++ ++# Skip comments. ++/^#/ { next } ++ ++# Process assignments. ++NF == 2 { ++ vars[$1] = $2 ++} ++ ++# Print final values. ++END { ++ print "/* This file is automatically generated by scripts/option-groups.awk" ++ print " in the EGLIBC source tree." ++ print "" ++ print " It defines macros that indicate which EGLIBC option groups were" ++ print " configured in 'option-groups.config' when this C library was" ++ print " built. For each option group named OPTION_foo, it #defines" ++ print " __OPTION_foo to be 1 if the group is enabled, or #defines that" ++ print " symbol to be 0 if the group is disabled. */" ++ print "" ++ print "#ifndef __GNU_OPTION_GROUPS_H" ++ print "#define __GNU_OPTION_GROUPS_H" ++ print "" ++ ++ # Produce a sorted list of variable names. ++ i=0 ++ for (var in vars) ++ names[i++] = var ++ n = asort (names) ++ ++ for (i = 1; i <= n; i++) ++ { ++ var = names[i] ++ if (var ~ /^OPTION_/) ++ { ++ if (vars[var] == "y") ++ print "#define __" var " 1" ++ else if (vars[var] == "n") ++ print "#define __" var " 0" ++ else if (vars[var] ~ /^[0-9]+/ || ++ vars[var] ~ /^0x[0-9aAbBcCdDeEfF]+/ || ++ vars[var] ~ /^\"/) ++ print "#define __" var " " vars[var] ++ else ++ print "/* #undef __" var " */" ++ # Ignore variables that don't have boolean, int, hex, or ++ # string values. Ideally, this would be driven by the types ++ # given in option-groups.def. ++ } ++ } ++ ++ print "" ++ print "#endif /* __GNU_OPTION_GROUPS_H */" ++} +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch b/meta/recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch new file mode 100644 index 0000000000..df93094543 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch @@ -0,0 +1,100 @@ +From 8fe0d29488b376011cdaaa462d557ffc0b31fb63 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:49:28 +0000 +Subject: [PATCH 20/27] eglibc: Help bootstrap cross toolchain + +Taken from EGLIBC, r1484 + r1525 + + 2007-02-20 Jim Blandy + + * Makefile (install-headers): Preserve old behavior: depend on + $(inst_includedir)/gnu/stubs.h only if install-bootstrap-headers + is set; otherwise, place gnu/stubs.h on the 'install-others' list. + + 2007-02-16 Jim Blandy + + * Makefile: Amend make install-headers to install everything + necessary for building a cross-compiler. Install gnu/stubs.h as + part of 'install-headers', not 'install-others'. + If install-bootstrap-headers is 'yes', install a dummy copy of + gnu/stubs.h, instead of computing the real thing. + * include/stubs-bootstrap.h: New file. + +Upstream-Status: Pending +Signed-off-by: Khem Raj +--- + Makefile | 22 +++++++++++++++++++++- + include/stubs-bootstrap.h | 12 ++++++++++++ + 2 files changed, 33 insertions(+), 1 deletion(-) + create mode 100644 include/stubs-bootstrap.h + +diff --git a/Makefile b/Makefile +index f906391..e4e149e 100644 +--- a/Makefile ++++ b/Makefile +@@ -69,9 +69,18 @@ subdir-dirs = include + vpath %.h $(subdir-dirs) + + # What to install. +-install-others = $(inst_includedir)/gnu/stubs.h + install-bin-script = + ++# If we're bootstrapping, install a dummy gnu/stubs.h along with the ++# other headers, so 'make install-headers' produces a useable include ++# tree. Otherwise, install gnu/stubs.h later, after the rest of the ++# build is done. ++ifeq ($(install-bootstrap-headers),yes) ++install-headers: $(inst_includedir)/gnu/stubs.h ++else ++install-others = $(inst_includedir)/gnu/stubs.h ++endif ++ + ifeq (yes,$(build-shared)) + headers += gnu/lib-names.h + endif +@@ -151,6 +160,16 @@ others: $(common-objpfx)testrun.sh + + subdir-stubs := $(foreach dir,$(subdirs),$(common-objpfx)$(dir)/stubs) + ++# gnu/stubs.h depends (via the subdir 'stubs' targets) on all the .o ++# files in EGLIBC. For bootstrapping a GCC/EGLIBC pair, an empty ++# gnu/stubs.h is good enough. ++ifeq ($(install-bootstrap-headers),yes) ++$(inst_includedir)/gnu/stubs.h: include/stubs-bootstrap.h $(+force) ++ $(make-target-directory) ++ $(INSTALL_DATA) $< $@ ++ ++installed-stubs = ++else + ifndef abi-variants + installed-stubs = $(inst_includedir)/gnu/stubs.h + else +@@ -177,6 +196,7 @@ $(inst_includedir)/gnu/stubs.h: $(+force) + + install-others-nosubdir: $(installed-stubs) + endif ++endif + + + # Since stubs.h is never needed when building the library, we simplify the +diff --git a/include/stubs-bootstrap.h b/include/stubs-bootstrap.h +new file mode 100644 +index 0000000..1d2b669 +--- /dev/null ++++ b/include/stubs-bootstrap.h +@@ -0,0 +1,12 @@ ++/* Placeholder stubs.h file for bootstrapping. ++ ++ When bootstrapping a GCC/EGLIBC pair, GCC requires that the EGLIBC ++ headers be installed, but we can't fully build EGLIBC without that ++ GCC. So we run the command: ++ ++ make install-headers install-bootstrap-headers=yes ++ ++ to install the headers GCC needs, but avoid building certain ++ difficult headers. The header depends, via the ++ EGLIBC subdir 'stubs' make targets, on every .o file in EGLIBC, but ++ an empty stubs.h like this will do fine for GCC. */ +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch b/meta/recipes-core/glibc/glibc/0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch new file mode 100644 index 0000000000..38bb8a15e3 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch @@ -0,0 +1,64 @@ +From fe2ae4f877928dd6bff5bac3f15bce4b50d2bd12 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:51:16 +0000 +Subject: [PATCH 21/27] eglibc: cherry-picked from + http://www.eglibc.org/archives/patches/msg00772.html + +It hasn't yet been merged into glibc + +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + resolv/res_libc.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/resolv/res_libc.c b/resolv/res_libc.c +index ee3fa21..29e2340 100644 +--- a/resolv/res_libc.c ++++ b/resolv/res_libc.c +@@ -22,12 +22,13 @@ + #include + #include + #include +- ++#include + + /* The following bit is copied from res_data.c (where it is #ifdef'ed + out) since res_init() should go into libc.so but the rest of that + file should not. */ + ++__libc_lock_define_initialized (static, lock); + extern unsigned long long int __res_initstamp attribute_hidden; + /* We have atomic increment operations on 64-bit platforms. */ + #if __WORDSIZE == 64 +@@ -35,7 +36,6 @@ extern unsigned long long int __res_initstamp attribute_hidden; + # define atomicincunlock(lock) (void) 0 + # define atomicinc(var) catomic_increment (&(var)) + #else +-__libc_lock_define_initialized (static, lock); + # define atomicinclock(lock) __libc_lock_lock (lock) + # define atomicincunlock(lock) __libc_lock_unlock (lock) + # define atomicinc(var) ++var +@@ -94,7 +94,18 @@ res_init(void) { + int + __res_maybe_init (res_state resp, int preinit) + { ++ static time_t last_mtime; ++ struct stat statbuf; ++ int ret; ++ + if (resp->options & RES_INIT) { ++ ret = stat (_PATH_RESCONF, &statbuf); ++ __libc_lock_lock (lock); ++ if ((ret == 0) && (last_mtime != statbuf.st_mtime)) { ++ last_mtime = statbuf.st_mtime; ++ atomicinc (__res_initstamp); ++ } ++ __libc_lock_unlock (lock); + if (__res_initstamp != resp->_u._ext.initstamp) { + if (resp->nscount > 0) + __res_iclose (resp, true); +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0022-eglibc-Clear-cache-lines-on-ppc8xx.patch b/meta/recipes-core/glibc/glibc/0022-eglibc-Clear-cache-lines-on-ppc8xx.patch new file mode 100644 index 0000000000..8a4c9c3e89 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0022-eglibc-Clear-cache-lines-on-ppc8xx.patch @@ -0,0 +1,81 @@ +From be7273225698074347a71de58006977bb304d7f7 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:53:47 +0000 +Subject: [PATCH 22/27] eglibc: Clear cache lines on ppc8xx + +2007-06-13 Nathan Sidwell + Mark Shinwell + + * sysdeps/unix/sysv/linux/powerpc/libc-start.c + (__libc_start_main): Detect 8xx parts and clear + __cache_line_size if detected. + * sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c + (DL_PLATFORM_AUXV): Likewise. + +Upstream-Status: Pending +Signed-off-by: Khem Raj +--- + sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c | 14 +++++++++++++- + sysdeps/unix/sysv/linux/powerpc/libc-start.c | 15 ++++++++++++++- + 2 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c +index c2504ff..d50f1cb 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c ++++ b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c +@@ -24,9 +24,21 @@ int __cache_line_size attribute_hidden; + /* Scan the Aux Vector for the "Data Cache Block Size" entry. If found + verify that the static extern __cache_line_size is defined by checking + for not NULL. If it is defined then assign the cache block size +- value to __cache_line_size. */ ++ value to __cache_line_size. This is used by memset to ++ optimize setting to zero. We have to detect 8xx processors, which ++ have buggy dcbz implementations that cannot report page faults ++ correctly. That requires reading SPR, which is a privileged ++ operation. Fortunately 2.2.18 and later emulates PowerPC mfspr ++ reads from the PVR register. */ + #define DL_PLATFORM_AUXV \ + case AT_DCACHEBSIZE: \ ++ if (__LINUX_KERNEL_VERSION >= 0x020218) \ ++ { \ ++ unsigned pvr = 0; \ ++ asm ("mfspr %0, 287" : "=r" (pvr)); \ ++ if ((pvr & 0xffff0000) == 0x00500000) \ ++ break; \ ++ } \ + __cache_line_size = av->a_un.a_val; \ + break; + +diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.c b/sysdeps/unix/sysv/linux/powerpc/libc-start.c +index a9364c7..a3ed1d4 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/libc-start.c ++++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.c +@@ -68,11 +68,24 @@ __libc_start_main (int argc, char **argv, + rtld_fini = NULL; + } + +- /* Initialize the __cache_line_size variable from the aux vector. */ ++ /* Initialize the __cache_line_size variable from the aux vector. ++ This is used by memset to optimize setting to zero. We have to ++ detect 8xx processors, which have buggy dcbz implementations that ++ cannot report page faults correctly. That requires reading SPR, ++ which is a privileged operation. Fortunately 2.2.18 and later ++ emulates PowerPC mfspr reads from the PVR register. */ + for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av) + switch (av->a_type) + { + case AT_DCACHEBSIZE: ++ if (__LINUX_KERNEL_VERSION >= 0x020218) ++ { ++ unsigned pvr = 0; ++ ++ asm ("mfspr %0, 287" : "=r" (pvr) :); ++ if ((pvr & 0xffff0000) == 0x00500000) ++ break; ++ } + __cache_line_size = av->a_un.a_val; + break; + } +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0023-eglibc-Resolve-__fpscr_values-on-SH4.patch b/meta/recipes-core/glibc/glibc/0023-eglibc-Resolve-__fpscr_values-on-SH4.patch new file mode 100644 index 0000000000..9f3d753d70 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0023-eglibc-Resolve-__fpscr_values-on-SH4.patch @@ -0,0 +1,56 @@ +From 718e7e5db1c8b073adb9a79ec6f167238c2d8bda Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:55:53 +0000 +Subject: [PATCH 23/27] eglibc: Resolve __fpscr_values on SH4 + +2010-09-29 Nobuhiro Iwamatsu + Andrew Stubbs + + Resolve SH's __fpscr_values to symbol in libc.so. + + * sysdeps/sh/sh4/fpu/fpu_control.h: Add C++ __set_fpscr prototype. + * sysdeps/unix/sysv/linux/sh/Versions (GLIBC_2.2): Add __fpscr_values. + * sysdeps/unix/sysv/linux/sh/sysdep.S (___fpscr_values): New constant. + +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + sysdeps/unix/sysv/linux/sh/Versions | 1 + + sysdeps/unix/sysv/linux/sh/sysdep.S | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/sysdeps/unix/sysv/linux/sh/Versions b/sysdeps/unix/sysv/linux/sh/Versions +index e0938c4..ca1d7da 100644 +--- a/sysdeps/unix/sysv/linux/sh/Versions ++++ b/sysdeps/unix/sysv/linux/sh/Versions +@@ -2,6 +2,7 @@ libc { + GLIBC_2.2 { + # functions used in other libraries + __xstat64; __fxstat64; __lxstat64; ++ __fpscr_values; + + # a* + alphasort64; +diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.S b/sysdeps/unix/sysv/linux/sh/sysdep.S +index a02b7e2..b9be326 100644 +--- a/sysdeps/unix/sysv/linux/sh/sysdep.S ++++ b/sysdeps/unix/sysv/linux/sh/sysdep.S +@@ -30,3 +30,14 @@ ENTRY (__syscall_error) + + #define __syscall_error __syscall_error_1 + #include ++ ++ .data ++ .align 3 ++ .globl ___fpscr_values ++ .type ___fpscr_values, @object ++ .size ___fpscr_values, 8 ++___fpscr_values: ++ .long 0 ++ .long 0x80000 ++weak_alias (___fpscr_values, __fpscr_values) ++ +-- +2.1.4 + 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 @@ +From 2a5d7bcf0ff791c95ee1388772408a1bf4454694 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 01:33:49 +0000 +Subject: [PATCH 24/27] eglibc: Forward port eglibc options groups support + +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + Makeconfig | 20 +- + Makerules | 19 + + argp/Makefile | 2 + + argp/argp-fmtstream.c | 25 +- + argp/argp-help.c | 13 +- + argp/argp-namefrob.h | 2 + + catgets/Makefile | 17 +- + crypt/Makefile | 20 +- + crypt/crypt-entry.c | 13 + + crypt/crypt_common.c | 42 + + crypt/crypt_util.c | 18 - + csu/Makefile | 2 + + debug/Makefile | 41 +- + debug/segfault.c | 11 +- + debug/tst-chk1.c | 7 + + dlfcn/Makefile | 7 +- + elf/dl-support.c | 3 + + elf/rtld.c | 17 +- + extra-lib.mk | 6 +- + grp/Makefile | 5 + + hesiod/Makefile | 6 +- + iconv/Makefile | 7 + + iconv/gconv_db.c | 3 + + iconv/gconv_trans.c | 7 + + iconv/iconv_prog.c | 8 + + iconvdata/Makefile | 27 +- + include/netdb.h | 4 + + inet/Makefile | 22 +- + intl/Makefile | 3 +- + intl/dcigettext.c | 39 +- + io/Makefile | 18 +- + libidn/Makefile | 5 +- + libidn/toutf8.c | 11 +- + libio/Makefile | 66 +- + libio/__fpurge.c | 2 +- + libio/fileops.c | 10 +- + libio/iofwide.c | 26 + + libio/ioseekoff.c | 2 +- + libio/ioseekpos.c | 2 +- + libio/iosetbuffer.c | 4 + + libio/libioP.h | 18 +- + libio/wdummyfileops.c | 161 + + locale/C-ctype.c | 20 + + locale/Makefile | 41 +- + locale/catnames.c | 48 + + locale/dummy-setlocale.c | 33 + + locale/localeinfo.h | 2 +- + locale/programs/charmap-dir.c | 6 + + locale/programs/ld-collate.c | 17 +- + locale/programs/ld-ctype.c | 27 +- + locale/programs/ld-messages.c | 5 + + locale/programs/ld-time.c | 31 +- + locale/programs/linereader.c | 2 +- + locale/programs/localedef.c | 8 + + locale/programs/locfile.c | 5 +- + locale/programs/locfile.h | 59 +- + locale/setlocale.c | 30 - + locale/xlocale.c | 37 + + localedata/Makefile | 35 +- + login/Makefile | 17 +- + malloc/Makefile | 10 +- + malloc/memusage.c | 7 +- + malloc/memusage.sh | 2 +- + math/Makefile | 6 +- + misc/Makefile | 25 +- + misc/err.c | 11 + + misc/error.c | 5 + + misc/tst-efgcvt.c | 2 +- + nis/Makefile | 31 +- + nptl/Makefile | 28 +- + nptl/pthread_create.c | 5 + + nscd/Makefile | 33 +- + nscd/nis_hash.c | 3 + + nss/Makefile | 67 +- + nss/fixed-nsswitch.conf | 22 + + nss/fixed-nsswitch.functions | 121 + + nss/gen-fixed-nsswitch.c | 803 +++ + nss/getent.c | 46 +- + nss/getnssent_r.c | 9 +- + nss/nsswitch.c | 109 +- + nss/nsswitch.h | 18 +- + posix/Makefile | 94 +- + posix/bug-regex1.c | 3 + + posix/bug-regex6.c | 8 +- + posix/fnmatch.c | 6 +- + posix/fnmatch_loop.c | 23 +- + posix/glob.c | 15 +- + posix/regcomp.c | 98 +- + posix/regex.h | 11 + + posix/regex_internal.c | 45 +- + posix/regex_internal.h | 23 +- + posix/regexec-compat.c | 39 + + posix/regexec.c | 71 +- + posix/xregex.c | 8215 +++++++++++++++++++++++++++++++ + pwd/Makefile | 2 + + resolv/Makefile | 21 +- + stdio-common/Makefile | 35 +- + stdio-common/_i18n_number.h | 13 + + stdio-common/fxprintf.c | 5 + + stdio-common/printf_fp.c | 22 + + stdio-common/printf_fphex.c | 13 + + stdio-common/printf_size.c | 8 + + stdio-common/scanf14.c | 3 + + stdio-common/tst-popen.c | 3 + + stdio-common/tst-sprintf.c | 4 +- + stdio-common/tstdiomisc.c | 5 + + stdio-common/vfprintf.c | 31 +- + stdio-common/vfscanf.c | 53 +- + stdlib/Makefile | 34 +- + stdlib/strtod_l.c | 13 + + stdlib/tst-strtod.c | 5 + + streams/Makefile | 5 +- + string/Makefile | 14 +- + string/strcoll_l.c | 5 + + string/strerror_l.c | 5 + + string/strxfrm_l.c | 5 + + string/test-strcmp.c | 28 - + string/tst-strxfrm.c | 3 + + string/tst-strxfrm2.c | 3 + + sunrpc/Makefile | 44 +- + sysdeps/arm/Makefile | 5 +- + sysdeps/generic/ldsodefs.h | 8 + + sysdeps/gnu/Makefile | 3 +- + sysdeps/ieee754/ldbl-opt/Makefile | 27 +- + sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 40 +- + sysdeps/ieee754/ldbl-opt/nldbl-compat.h | 24 +- + sysdeps/nptl/Makefile | 3 + + sysdeps/nptl/bits/libc-lock.h | 45 + + sysdeps/nptl/bits/libc-lockP.h | 50 +- + sysdeps/nptl/small-macros-fns.c | 72 + + sysdeps/unix/sysv/linux/gethostid.c | 6 + + sysdeps/unix/sysv/linux/libc_fatal.c | 3 + + time/Makefile | 18 +- + time/strftime_l.c | 12 +- + time/strptime_l.c | 14 +- + timezone/Makefile | 2 +- + wcsmbs/Makefile | 27 +- + wcsmbs/wcsmbsload.c | 13 + + wctype/Makefile | 14 +- + 139 files changed, 11363 insertions(+), 583 deletions(-) + create mode 100644 crypt/crypt_common.c + create mode 100644 libio/wdummyfileops.c + create mode 100644 locale/catnames.c + create mode 100644 locale/dummy-setlocale.c + create mode 100644 nscd/nis_hash.c + create mode 100644 nss/fixed-nsswitch.conf + create mode 100644 nss/fixed-nsswitch.functions + create mode 100644 nss/gen-fixed-nsswitch.c + create mode 100644 posix/regexec-compat.c + create mode 100644 posix/xregex.c + create mode 100644 sysdeps/nptl/small-macros-fns.c + +diff --git a/Makeconfig b/Makeconfig +index f136b88..52dae8f 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -609,7 +609,7 @@ elf-objpfx = $(common-objpfx)elf/ + # and run on the build system, causes that program with those + # arguments to be run on the host for which the library is built. + ifndef test-wrapper +-test-wrapper = ++test-wrapper = $(cross-test-wrapper) + endif + # Likewise, but the name of the program is preceded by + # = assignments for environment variables. +@@ -1089,6 +1089,24 @@ libm = $(common-objpfx)math/libm.a + libmvec = $(common-objpfx)mathvec/libmvec.a + endif + ++# Generate a header file that #defines preprocessor symbols indicating ++# which option groups are enabled. Note that the option-groups.config file ++# may not exist at all. ++before-compile += $(common-objpfx)gnu/option-groups.h ++common-generated += gnu/option-groups.h gnu/option-groups.stmp ++headers += gnu/option-groups.h ++$(common-objpfx)gnu/option-groups.h: $(common-objpfx)gnu/option-groups.stmp; @: ++$(common-objpfx)gnu/option-groups.stmp: \ ++ $(..)scripts/option-groups.awk \ ++ $(..)option-groups.defaults \ ++ $(wildcard $(common-objpfx)option-groups.config) ++ $(make-target-directory) ++ @rm -f ${@:stmp=T} $@ ++ LC_ALL=C $(AWK) -f $^ > ${@:stmp=T} ++ $(move-if-change) ${@:stmp=T} ${@:stmp=h} ++ touch $@ ++ ++ + # These are the subdirectories containing the library source. The order + # is more or less arbitrary. The sorting step will take care of the + # dependencies. +diff --git a/Makerules b/Makerules +index f9ca3f5..1dd41aa 100644 +--- a/Makerules ++++ b/Makerules +@@ -456,6 +456,25 @@ define sed-remove-objpfx + endef + endif + ++# Include targets in the selected option groups. ++aux += $(aux-y) ++extra-libs += $(extra-libs-y) ++extra-libs-others += $(extra-libs-others-y) ++extra-objs += $(extra-objs-y) ++install-bin += $(install-bin-y) ++install-others += $(install-others-y) ++install-sbin += $(install-sbin-y) ++modules += $(modules-y) ++others += $(others-y) ++others-pie += $(others-pie-y) ++routines += $(routines-y) ++static-only-routines += $(static-only-routines-y) ++sysdep_routines += $(sysdep_routines-y) ++test-srcs += $(test-srcs-y) ++tests += $(tests-y) ++xtests += $(xtests-y) ++ ++ + # Modify the list of routines we build for different targets + + ifeq (yes,$(build-shared)) +diff --git a/argp/Makefile b/argp/Makefile +index 1a87629..f7c1e40 100644 +--- a/argp/Makefile ++++ b/argp/Makefile +@@ -18,6 +18,8 @@ + # + # Makefile for argp. + # ++include ../option-groups.mak ++ + subdir := argp + + include ../Makeconfig +diff --git a/argp/argp-fmtstream.c b/argp/argp-fmtstream.c +index 2b845e0..c344e7b 100644 +--- a/argp/argp-fmtstream.c ++++ b/argp/argp-fmtstream.c +@@ -42,6 +42,7 @@ + #ifdef _LIBC + # include + # include ++# include + # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) + #endif + +@@ -100,7 +101,11 @@ __argp_fmtstream_free (argp_fmtstream_t fs) + __argp_fmtstream_update (fs); + if (fs->p > fs->buf) + { ++#ifdef _LIBC + __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); ++#else ++ fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); ++#endif + } + free (fs->buf); + free (fs); +@@ -145,9 +150,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + size_t i; + for (i = 0; i < pad; i++) + { ++#ifdef _LIBC + if (_IO_fwide (fs->stream, 0) > 0) +- putwc_unlocked (L' ', fs->stream); ++ { ++#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO ++ putwc_unlocked (L' ', fs->stream); ++#else ++ abort (); ++#endif ++ } + else ++#endif + putc_unlocked (' ', fs->stream); + } + } +@@ -308,9 +321,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + *nl++ = ' '; + else + for (i = 0; i < fs->wmargin; ++i) ++#ifdef _LIBC + if (_IO_fwide (fs->stream, 0) > 0) +- putwc_unlocked (L' ', fs->stream); ++ { ++#ifdef OPTION_POSIX_WIDE_CHAR_DEVICE_IO ++ putwc_unlocked (L' ', fs->stream); ++#else ++ abort (); ++#endif ++ } + else ++#endif + putc_unlocked (' ', fs->stream); + + /* Copy the tail of the original buffer into the current buffer +diff --git a/argp/argp-help.c b/argp/argp-help.c +index b055e45..6b3c4c1 100644 +--- a/argp/argp-help.c ++++ b/argp/argp-help.c +@@ -51,6 +51,7 @@ char *alloca (); + #ifdef _LIBC + # include <../libio/libioP.h> + # include ++# include + #endif + + #ifndef _ +@@ -1702,7 +1703,7 @@ char *__argp_basename (char *name) + } + + char * +-__argp_short_program_name (void) ++(__argp_short_program_name) (void) + { + # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + return program_invocation_short_name; +@@ -1873,9 +1874,17 @@ __argp_failure (const struct argp_state *state, int status, int errnum, + #endif + } + ++#ifdef _LIBC + if (_IO_fwide (stream, 0) > 0) +- putwc_unlocked (L'\n', stream); ++ { ++#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO ++ putwc_unlocked (L'\n', stream); ++#else ++ abort (); ++#endif ++ } + else ++#endif + putc_unlocked ('\n', stream); + + #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) +diff --git a/argp/argp-namefrob.h b/argp/argp-namefrob.h +index f67c58f..e2002dc 100644 +--- a/argp/argp-namefrob.h ++++ b/argp/argp-namefrob.h +@@ -76,10 +76,12 @@ + #undef __argp_fmtstream_wmargin + #define __argp_fmtstream_wmargin argp_fmtstream_wmargin + ++#if 0 + #include "mempcpy.h" + #include "strcase.h" + #include "strchrnul.h" + #include "strndup.h" ++#endif + + /* normal libc functions we call */ + #undef __flockfile +diff --git a/catgets/Makefile b/catgets/Makefile +index 4624a88..05714fd 100644 +--- a/catgets/Makefile ++++ b/catgets/Makefile +@@ -22,20 +22,23 @@ subdir := catgets + + include ../Makeconfig + ++include ../option-groups.mak ++ + headers = nl_types.h +-routines = catgets open_catalog +-others = gencat +-install-bin = gencat +-extra-objs = $(gencat-modules:=.o) ++routines-$(OPTION_EGLIBC_CATGETS) := catgets open_catalog ++others-$(OPTION_EGLIBC_CATGETS) := gencat ++install-bin-$(OPTION_EGLIBC_CATGETS) := gencat ++extra-objs-$(OPTION_EGLIBC_CATGETS) := $(gencat-modules:=.o) + +-tests = tst-catgets +-test-srcs = test-gencat ++tests-$(OPTION_EGLIBC_CATGETS) := tst-catgets ++test-srcs-$(OPTION_EGLIBC_CATGETS) := test-gencat + ++ifeq (y,$(OPTION_EGLIBC_CATGETS)) + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \ + $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out + endif +- ++endif + gencat-modules = xmalloc + + # To find xmalloc.c +diff --git a/crypt/Makefile b/crypt/Makefile +index 34c4dd7..7c18c88 100644 +--- a/crypt/Makefile ++++ b/crypt/Makefile +@@ -18,21 +18,25 @@ + # + # Sub-makefile for crypt() portion of the library. + # ++include ../option-groups.mak ++ + subdir := crypt + + include ../Makeconfig + + headers := crypt.h + +-extra-libs := libcrypt +-extra-libs-others := $(extra-libs) ++extra-libs-$(OPTION_EGLIBC_CRYPT) := libcrypt ++extra-libs-others-y := $(extra-libs-y) + +-libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \ +- crypt_util ++libcrypt-routines :=crypt-entry md5-crypt sha256-crypt sha512-crypt crypt_common ++libcrypt-routines-$(OPTION_EGLIBC_CRYPT_UFC) := crypt crypt_util ++libcrypt-routines += $(libcrypt-routines-y) + +-tests := cert md5c-test sha256c-test sha512c-test badsalttest ++tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test badsalttest ++tests-$(OPTION_EGLIBC_CRYPT_UFC) += cert + +-ifeq ($(crypt-in-libc),yes) ++ifeq ($(crypt-in-libc)$(OPTION_EGLIBC_CRYPT),yesy) + routines += $(libcrypt-routines) + endif + +@@ -44,7 +48,7 @@ LDLIBS-crypt.so = -lfreebl3 + else + libcrypt-routines += md5 sha256 sha512 + +-tests += md5test sha256test sha512test ++tests-$(OPTION_EGLIBC_CRYPT) += md5test sha256test sha512test + + # The test md5test-giant uses up to 400 MB of RSS and runs on a fast + # machine over a minute. +@@ -64,8 +68,10 @@ $(objpfx)sha256test: $(patsubst %, $(objpfx)%.o,$(sha256-routines)) + $(objpfx)sha512test: $(patsubst %, $(objpfx)%.o,$(sha512-routines)) + endif + ++ifeq ($(OPTION_EGLIBC_CRYPT),y) + ifeq (yes,$(build-shared)) + $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.so + else + $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.a + endif ++endif # eglibc: OPTION_EGLIBC_CRYPT +diff --git a/crypt/crypt-entry.c b/crypt/crypt-entry.c +index 7e655ba..6ae5c2b 100644 +--- a/crypt/crypt-entry.c ++++ b/crypt/crypt-entry.c +@@ -27,6 +27,7 @@ + #include + #endif + #include ++#include + #include + #include + +@@ -76,9 +77,11 @@ __crypt_r (key, salt, data) + const char *salt; + struct crypt_data * __restrict data; + { ++#if __OPTION_EGLIBC_CRYPT_UFC + ufc_long res[4]; + char ktab[9]; + ufc_long xx = 25; /* to cope with GCC long long compiler bugs */ ++#endif /*__OPTION_EGLIBC_CRYPT_UFC*/ + + #ifdef _LIBC + /* Try to find out whether we have to use MD5 encryption replacement. */ +@@ -105,6 +108,7 @@ __crypt_r (key, salt, data) + sizeof (struct crypt_data)); + #endif + ++#if __OPTION_EGLIBC_CRYPT_UFC + /* + * Hack DES tables according to salt + */ +@@ -144,6 +148,10 @@ __crypt_r (key, salt, data) + */ + _ufc_output_conversion_r (res[0], res[1], salt, data); + return data->crypt_3_buf; ++#else /* __OPTION_EGLIBC_CRYPT_UFC */ ++ __set_errno (ENOSYS); ++ return NULL; ++#endif /* __OPTION_EGLIBC_CRYPT_UFC */ + } + weak_alias (__crypt_r, crypt_r) + +@@ -168,7 +176,12 @@ crypt (key, salt) + return __sha512_crypt (key, salt); + #endif + ++#if __OPTION_EGLIBC_CRYPT_UFC + return __crypt_r (key, salt, &_ufc_foobar); ++#else /* __OPTION_EGLIBC_CRYPT_UFC */ ++ __set_errno (ENOSYS); ++ return NULL; ++#endif /* __OPTION_EGLIBC_CRYPT_UFC */ + } + + +diff --git a/crypt/crypt_common.c b/crypt/crypt_common.c +new file mode 100644 +index 0000000..cce6a31 +--- /dev/null ++++ b/crypt/crypt_common.c +@@ -0,0 +1,42 @@ ++/* ++ * crypt: crypt(3) implementation ++ * ++ * Copyright (C) 1991-2014 Free Software Foundation, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; see the file COPYING.LIB. If not, ++ * see . ++ * ++ * General Support routines ++ * ++ */ ++ ++#include "crypt-private.h" ++ ++/* Table with characters for base64 transformation. */ ++static const char b64t[64] = ++"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; ++ ++void ++__b64_from_24bit (char **cp, int *buflen, ++ unsigned int b2, unsigned int b1, unsigned int b0, ++ int n) ++{ ++ unsigned int w = (b2 << 16) | (b1 << 8) | b0; ++ while (n-- > 0 && (*buflen) > 0) ++ { ++ *(*cp)++ = b64t[w & 0x3f]; ++ --(*buflen); ++ w >>= 6; ++ } ++} +diff --git a/crypt/crypt_util.c b/crypt/crypt_util.c +index 1597885..9297974 100644 +--- a/crypt/crypt_util.c ++++ b/crypt/crypt_util.c +@@ -242,10 +242,6 @@ static ufc_long eperm32tab[4][256][2]; + */ + static ufc_long efp[16][64][2]; + +-/* Table with characters for base64 transformation. */ +-static const char b64t[64] = +-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +- + /* + * For use by the old, non-reentrant routines + * (crypt/encrypt/setkey) +@@ -949,17 +945,3 @@ setkey(__key) + { + __setkey_r(__key, &_ufc_foobar); + } +- +-void +-__b64_from_24bit (char **cp, int *buflen, +- unsigned int b2, unsigned int b1, unsigned int b0, +- int n) +-{ +- unsigned int w = (b2 << 16) | (b1 << 8) | b0; +- while (n-- > 0 && (*buflen) > 0) +- { +- *(*cp)++ = b64t[w & 0x3f]; +- --(*buflen); +- w >>= 6; +- } +-} +diff --git a/csu/Makefile b/csu/Makefile +index 9f0855a..b1c3363 100644 +--- a/csu/Makefile ++++ b/csu/Makefile +@@ -22,6 +22,8 @@ + # crtn.o, special "initializer" and "finalizer" files used in the link + # to make the .init and .fini sections work right. + ++include ../option-groups.mak ++ + subdir := csu + + include ../Makeconfig +diff --git a/debug/Makefile b/debug/Makefile +index 9ff357b..d23d97d 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for debug portion of the library. + # ++include ../option-groups.mak ++ + subdir := debug + + include ../Makeconfig +@@ -27,7 +29,7 @@ headers := execinfo.h + # Note that ptsname_r_chk and getlogin_r are not here, but in + # login/Makefile instead. If that subdir is omitted from the + # build, its _FORTIFY_SOURCE support will be too. +-routines = backtrace backtracesyms backtracesymsfd noophooks \ ++routines = noophooks \ + memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ + strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ + sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ +@@ -36,20 +38,27 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \ + read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ + readlink_chk readlinkat_chk getwd_chk getcwd_chk \ + realpath_chk fread_chk fread_u_chk \ +- wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ +- wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ +- wcpncpy_chk \ +- swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \ +- vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \ + confstr_chk getgroups_chk ttyname_r_chk \ +- gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \ +- wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ +- wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \ ++ gethostname_chk getdomainname_chk \ ++ asprintf_chk vasprintf_chk dprintf_chk \ + vdprintf_chk obprintf_chk \ + longjmp_chk ____longjmp_chk \ + fdelt_chk poll_chk ppoll_chk \ + stack_chk_fail fortify_fail \ + $(static-only-routines) ++routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd ++routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ ++ += wprintf_chk fwprintf_chk \ ++ vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ ++ wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ ++ wcpncpy_chk \ ++ swprintf_chk vswprintf_chk \ ++ wcrtomb_chk mbsnrtowcs_chk \ ++ wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ ++ wcstombs_chk ++ + static-only-routines := warning-nop stack_chk_fail_local + + CFLAGS-backtrace.c = -fno-omit-frame-pointer +@@ -131,11 +140,15 @@ LDFLAGS-tst-backtrace4 = -rdynamic + LDFLAGS-tst-backtrace5 = -rdynamic + LDFLAGS-tst-backtrace6 = -rdynamic + +-tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ +- tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ +- tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \ +- tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \ +- tst-backtrace5 tst-backtrace6 ++tests = tst-longjmp_chk test-strcpy_chk test-stpcpy_chk tst-longjmp_chk2 ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-chk1 tst-chk2 tst-chk3 tst-lfschk1 tst-lfschk2 tst-lfschk3 ++tests-$(OPTION_EGLIBC_BACKTRACE) \ ++ += backtrace-tst tst-backtrace2 tst-backtrace3 tst-backtrace4 \ ++ tst-backtrace5 tst-backtrace6 ++ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_EGLIBC_CXX_TESTS)) ++tests += tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 ++endif + + ifeq (,$(CXX)) + tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \ +diff --git a/debug/segfault.c b/debug/segfault.c +index 3459a2a..ee9a146 100644 +--- a/debug/segfault.c ++++ b/debug/segfault.c +@@ -30,6 +30,7 @@ + #include + #include <_itoa.h> + #include ++#include + + /* This file defines macros to access the content of the sigcontext element + passed up by the signal handler. */ +@@ -68,11 +69,13 @@ write_strsignal (int fd, int signal) + static void + catch_segfault (int signal, SIGCONTEXT ctx) + { +- int fd, cnt, i; +- void **arr; ++ int fd; + struct sigaction sa; ++#if __OPTION_EGLIBC_BACKTRACE ++ int cnt, i; ++ void **arr; + uintptr_t pc; +- ++#endif + /* This is the name of the file we are writing to. If none is given + or we cannot write to this file write to stderr. */ + fd = 2; +@@ -91,6 +94,7 @@ catch_segfault (int signal, SIGCONTEXT ctx) + REGISTER_DUMP; + #endif + ++#if __OPTION_EGLIBC_BACKTRACE + WRITE_STRING ("\nBacktrace:\n"); + + /* Get the backtrace. */ +@@ -113,6 +117,7 @@ catch_segfault (int signal, SIGCONTEXT ctx) + + /* Now generate nicely formatted output. */ + __backtrace_symbols_fd (arr + i, cnt - i, fd); ++#endif + + #ifdef HAVE_PROC_SELF + /* Now the link map. */ +diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c +index 53559e6..362d92a 100644 +--- a/debug/tst-chk1.c ++++ b/debug/tst-chk1.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + + #define obstack_chunk_alloc malloc +@@ -307,6 +308,7 @@ do_test (void) + snprintf (buf + 8, l0 + 3, "%d", num2); + CHK_FAIL_END + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + CHK_FAIL_START + swprintf (wbuf + 8, 3, L"%d", num1); + CHK_FAIL_END +@@ -314,6 +316,7 @@ do_test (void) + CHK_FAIL_START + swprintf (wbuf + 8, l0 + 3, L"%d", num1); + CHK_FAIL_END ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + # endif + + memcpy (buf, str1 + 2, l0 + 9); +@@ -381,6 +384,7 @@ do_test (void) + CHK_FAIL_END + #endif + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + + /* These ops can be done without runtime checking of object size. */ + wmemcpy (wbuf, L"abcdefghij", 10); +@@ -605,6 +609,7 @@ do_test (void) + CHK_FAIL_END + #endif + ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + + /* Now checks for %n protection. */ + +@@ -1192,6 +1197,7 @@ do_test (void) + # endif + #endif + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL) + { + assert (MB_CUR_MAX <= 10); +@@ -1348,6 +1354,7 @@ do_test (void) + puts ("cannot set locale"); + ret = 1; + } ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + + int fd = posix_openpt (O_RDWR); + if (fd != -1) +diff --git a/dlfcn/Makefile b/dlfcn/Makefile +index 759780d..3827607 100644 +--- a/dlfcn/Makefile ++++ b/dlfcn/Makefile +@@ -15,6 +15,8 @@ + # License along with the GNU C Library; if not, see + # . + ++include ../option-groups.mak ++ + subdir := dlfcn + + include ../Makeconfig +@@ -36,8 +38,11 @@ endif + ifeq (yes,$(build-shared)) + tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \ + bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ +- bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen ++ tstatexit bug-dl-leaf tst-rec-dlopen + endif ++ ++tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3 ++ + modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \ + defaultmod2 errmsg1mod modatexit modcxaatexit \ + bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 4d036f1..c15f405 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -19,6 +19,7 @@ + /* This file defines some things that for the dynamic linker are defined in + rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ + ++#include + #include + #include + #include +@@ -42,7 +43,9 @@ char **_dl_argv = &__progname; /* This is checked for some error messages. */ + const char *_dl_platform; + size_t _dl_platformlen; + ++#if __OPTION_EGLIBC_RTLD_DEBUG + int _dl_debug_mask; ++#endif + int _dl_lazy; + ElfW(Addr) _dl_use_load_bias = -2; + int _dl_dynamic_weak; +diff --git a/elf/rtld.c b/elf/rtld.c +index 6d3add7..fc3a2db 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + #include + #include +@@ -2201,6 +2202,7 @@ print_missing_version (int errcode __attribute__ ((unused)), + objname, errstring); + } + ++#if __OPTION_EGLIBC_RTLD_DEBUG + /* Nonzero if any of the debugging options is enabled. */ + static int any_debug attribute_relro; + +@@ -2310,6 +2312,7 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); + _exit (0); + } + } ++#endif /* __OPTION_EGLIBC_RTLD_DEBUG */ + + static void + process_dl_audit (char *str) +@@ -2349,8 +2352,9 @@ process_envvars (enum mode *modep) + char **runp = _environ; + char *envline; + enum mode mode = normal; ++#if __OPTION_EGLIBC_RTLD_DEBUG + char *debug_output = NULL; +- ++#endif + /* This is the default place for profiling data file. */ + GLRO(dl_profile_output) + = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0]; +@@ -2377,12 +2381,14 @@ process_envvars (enum mode *modep) + break; + + case 5: ++#if __OPTION_EGLIBC_RTLD_DEBUG + /* Debugging of the dynamic linker? */ + if (memcmp (envline, "DEBUG", 5) == 0) + { + process_dl_debug (&envline[6]); + break; + } ++#endif + if (memcmp (envline, "AUDIT", 5) == 0) + process_dl_audit (&envline[6]); + break; +@@ -2448,13 +2454,14 @@ process_envvars (enum mode *modep) + break; + } + ++#if __OPTION_EGLIBC_RTLD_DEBUG + /* Where to place the profiling data file. */ + if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0) + { + debug_output = &envline[13]; + break; + } +- ++#endif + if (!__libc_enable_secure + && memcmp (envline, "DYNAMIC_WEAK", 12) == 0) + GLRO(dl_dynamic_weak) = 1; +@@ -2491,7 +2498,9 @@ process_envvars (enum mode *modep) + { + mode = trace; + GLRO(dl_verbose) = 1; ++#if __OPTION_EGLIBC_RTLD_DEBUG + GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK; ++#endif + GLRO(dl_trace_prelink) = &envline[17]; + } + break; +@@ -2538,12 +2547,15 @@ process_envvars (enum mode *modep) + if (__access ("/etc/suid-debug", F_OK) != 0) + { + unsetenv ("MALLOC_CHECK_"); ++#if __OPTION_EGLIBC_RTLD_DEBUG + GLRO(dl_debug_mask) = 0; ++#endif + } + + if (mode != normal) + _exit (5); + } ++#if __OPTION_EGLIBC_RTLD_DEBUG + /* If we have to run the dynamic linker in debugging mode and the + LD_DEBUG_OUTPUT environment variable is given, we write the debug + messages to this file. */ +@@ -2568,6 +2580,7 @@ process_envvars (enum mode *modep) + /* We use standard output if opening the file failed. */ + GLRO(dl_debug_fd) = STDOUT_FILENO; + } ++#endif /* __OPTION_EGLIBC_RTLD_DEBUG */ + } + + +diff --git a/extra-lib.mk b/extra-lib.mk +index b10748d..d71a06f 100644 +--- a/extra-lib.mk ++++ b/extra-lib.mk +@@ -25,7 +25,9 @@ install-lib := $(install-lib) + extra-objs := $(extra-objs) + + # The modules that go in $(lib). +-all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines) ++all-$(lib)-routines := $($(lib)-routines) \ ++ $($(lib)-routines-y) \ ++ $($(lib)-sysdep_routines) + + # Add each flavor of library to the lists of things to build and install. + install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o))) +@@ -101,7 +103,7 @@ endif + endif + + # This will define `libof-ROUTINE := LIB' for each of the routines. +-cpp-srcs-left := $($(lib)-routines) $($(lib)-sysdep_routines) ++cpp-srcs-left := $(all-$(lib)-routines) + ifneq (,$(cpp-srcs-left)) + include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left)) + endif +diff --git a/grp/Makefile b/grp/Makefile +index c63b552..7486f32 100644 +--- a/grp/Makefile ++++ b/grp/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for grp portion of the library. + # ++include ../option-groups.mak ++ + subdir := grp + + include ../Makeconfig +@@ -29,6 +31,9 @@ routines := fgetgrent initgroups setgroups \ + getgrent_r getgrgid_r getgrnam_r fgetgrent_r + + tests := testgrp ++ifneq (y,$(OPTION_EGLIBC_NSSWITCH)) ++LDLIBS-testgrp += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs) ++endif + + ifeq (yes,$(build-shared)) + test-srcs := tst_fgetgrent +diff --git a/hesiod/Makefile b/hesiod/Makefile +index ac0bc01..38263b4 100644 +--- a/hesiod/Makefile ++++ b/hesiod/Makefile +@@ -18,12 +18,14 @@ + # + # Sub-makefile for hesiod portion of the library. + # ++include ../option-groups.mak ++ + subdir := hesiod + + include ../Makeconfig + +-extra-libs := libnss_hesiod +-extra-libs-others = $(extra-libs) ++extra-libs-$(OPTION_EGLIBC_INET) += libnss_hesiod ++extra-libs-others-y += $(extra-libs-y) + + subdir-dirs = nss_hesiod + vpath %.c nss_hesiod +diff --git a/iconv/Makefile b/iconv/Makefile +index 0d55eda..a1847c6 100644 +--- a/iconv/Makefile ++++ b/iconv/Makefile +@@ -18,6 +18,8 @@ + # + # Makefile for iconv. + # ++include ../option-groups.mak ++ + subdir := iconv + + include ../Makeconfig +@@ -39,6 +41,11 @@ CFLAGS-iconv_charmap.c = -I../locale/programs + CFLAGS-dummy-repertoire.c = -I../locale/programs + CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \ + -DDEFAULT_CHARMAP=null_pointer -DNEED_NULL_POINTER ++ ++ifneq (y,$(OPTION_EGLIBC_SPAWN)) ++CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS ++endif ++ + CFLAGS-linereader.c = -DNO_TRANSLITERATION + CFLAGS-simple-hash.c = -I../locale + +diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c +index ce46216..ea18964 100644 +--- a/iconv/gconv_db.c ++++ b/iconv/gconv_db.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -828,9 +829,11 @@ free_modules_db (struct gconv_module *node) + /* Free all resources if necessary. */ + libc_freeres_fn (free_mem) + { ++#if __OPTION_EGLIBC_LOCALE_CODE + /* First free locale memory. This needs to be done before freeing derivations, + as ctype cleanup functions dereference steps arrays which we free below. */ + _nl_locale_subfreeres (); ++#endif + + /* finddomain.c has similar problem. */ + extern void _nl_finddomain_subfreeres (void) attribute_hidden; +diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c +index 5d5d4d7..a7d3072 100644 +--- a/iconv/gconv_trans.c ++++ b/iconv/gconv_trans.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + #include "gconv_int.h" +@@ -38,15 +39,19 @@ __gconv_transliterate (struct __gconv_step *step, + unsigned char **outbufstart, size_t *irreversible) + { + /* Find out about the locale's transliteration. */ ++#if __OPTION_EGLIBC_LOCALE_CODE + uint_fast32_t size; + const uint32_t *from_idx; + const uint32_t *from_tbl; + const uint32_t *to_idx; + const uint32_t *to_tbl; ++#endif + const uint32_t *winbuf; + const uint32_t *winbufend; ++#if __OPTION_EGLIBC_LOCALE_CODE + uint_fast32_t low; + uint_fast32_t high; ++#endif + + /* The input buffer. There are actually 4-byte values. */ + winbuf = (const uint32_t *) *inbufp; +@@ -58,6 +63,7 @@ __gconv_transliterate (struct __gconv_step *step, + PTR_DEMANGLE (fct); + #endif + ++#if __OPTION_EGLIBC_LOCALE_CODE + /* If there is no transliteration information in the locale don't do + anything and return the error. */ + size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_TAB_SIZE); +@@ -193,6 +199,7 @@ __gconv_transliterate (struct __gconv_step *step, + sorted. */ + break; + } ++#endif + + /* One last chance: use the default replacement. */ + if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN) != 0) +diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c +index e249bce..403ece5 100644 +--- a/iconv/iconv_prog.c ++++ b/iconv/iconv_prog.c +@@ -35,6 +35,7 @@ + #ifdef _POSIX_MAPPED_FILES + # include + #endif ++#include + #include + #include + #include "iconv_prog.h" +@@ -221,10 +222,17 @@ main (int argc, char *argv[]) + bool to_wrong = + (iconv_open (to_code, "UTF-8") == (iconv_t) -1 + && errno == EINVAL); ++#if __OPTION_EGLIBC_LOCALE_CODE + const char *from_pretty = + (from_code[0] ? from_code : nl_langinfo (CODESET)); + const char *to_pretty = + (orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET)); ++#else ++ const char *from_pretty = ++ (from_code[0] ? from_code : "ANSI_X3.4-1968"); ++ const char *to_pretty = ++ (orig_to_code[0] ? orig_to_code : "ANSI_X3.4-1968"); ++#endif + + if (from_wrong) + { +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index a3d1d09..0832708 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -18,12 +18,15 @@ + # + # Makefile for iconv data and code. + # ++include ../option-groups.mak ++ + subdir := iconvdata + + include ../Makeconfig + + # Names of all the shared objects which implement the transformations. +-modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ ++modules-$(OPTION_EGLIBC_CHARSETS) \ ++ := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ + ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10 \ + ISO8859-11 ISO8859-13 ISO8859-14 ISO8859-15 ISO8859-16 \ + T.61 ISO_6937 SJIS KOI-8 HP-ROMAN8 HP-ROMAN9 EBCDIC-AT-DE \ +@@ -63,11 +66,13 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ + MAC-CENTRALEUROPE KOI8-RU ISO8859-9E \ + CP770 CP771 CP772 CP773 CP774 + +-modules.so := $(addsuffix .so, $(modules)) ++modules.so := $(addsuffix .so, $(modules-y)) + + ifeq (yes,$(build-shared)) + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ +- tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 ++ tst-iconv6 bug-iconv5 bug-iconv8 bug-iconv9 ++tests-$(OPTION_EGLIBC_LOCALE_CODE) += bug-iconv6 tst-iconv7 ++ + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +@@ -127,13 +132,13 @@ ifeq (yes,$(build-shared)) + # Rule to generate the shared objects. + charmaps = ../localedata/charmaps + -include $(objpfx)iconv-rules +-extra-modules-left := $(modules) ++extra-modules-left := $(modules-y) + include extra-module.mk + + + extra-objs += $(modules.so) +-install-others = $(addprefix $(inst_gconvdir)/, $(modules.so)) \ +- $(inst_gconvdir)/gconv-modules ++install-others-y += $(addprefix $(inst_gconvdir)/, $(modules.so)) ++install-others-$(OPTION_EGLIBC_CHARSETS) += $(inst_gconvdir)/gconv-modules + + # We can build the conversion tables for numerous charsets automatically. + +@@ -201,7 +206,7 @@ before-compile += $(addprefix $(objpfx),$(generated-modules:=.h)) + ifndef avoid-generated + $(objpfx)iconv-rules: Makefile + $(make-target-directory) +- { echo $(filter-out lib%, $(modules)); \ ++ { echo $(filter-out lib%, $(modules-y)); \ + echo 8bit $(gen-8bit-modules); \ + echo 8bit-gap $(gen-8bit-gap-modules); } | \ + LC_ALL=C \ +@@ -245,7 +250,7 @@ $(addprefix $(inst_gconvdir)/, $(modules.so)): \ + $(do-install-program) + $(inst_gconvdir)/gconv-modules: gconv-modules $(+force) + $(do-install) +-ifeq (no,$(cross-compiling)) ++# eglibc: ifeq (no,$(cross-compiling)) + # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary + # if this libc has more gconv modules than the previously installed one. + if test -f "$(inst_gconvdir)/gconv-modules.cache"; then \ +@@ -254,9 +259,9 @@ ifeq (no,$(cross-compiling)) + $(common-objpfx)iconv/iconvconfig \ + $(addprefix --prefix=,$(install_root)); \ + fi +-else +- @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache' +-endif ++# eglibc: else ++# eglibc: @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache' ++# eglibc: endif + + endif # build-shared = yes + +diff --git a/include/netdb.h b/include/netdb.h +index e1f051d..f6d15aa 100644 +--- a/include/netdb.h ++++ b/include/netdb.h +@@ -232,6 +232,10 @@ extern enum nss_status _nss_ ## service ## _gethostbyname2_r \ + (const char *name, int af, struct hostent *host, \ + char *buffer, size_t buflen, int *errnop, \ + int *h_errnop); \ ++extern enum nss_status _nss_ ## service ## _gethostbyname3_r \ ++ (const char *name, int af, struct hostent *result, \ ++ char *buffer, size_t buflen, int *errnop, \ ++ int *h_errnop, int32_t *ttlp, char **canonp); \ + extern enum nss_status _nss_ ## service ## _gethostbyname_r \ + (const char *name, struct hostent *host, char *buffer, \ + size_t buflen, int *errnop, int *h_errnop); \ +diff --git a/inet/Makefile b/inet/Makefile +index f1d871f..7cb1709 100644 +--- a/inet/Makefile ++++ b/inet/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for inet portion of the library. + # ++include ../option-groups.mak ++ + subdir := inet + + include ../Makeconfig +@@ -27,7 +29,8 @@ headers := netinet/ether.h netinet/in.h netinet/in_systm.h \ + netinet/tcp.h netinet/ip.h $(wildcard arpa/*.h protocols/*.h) \ + aliases.h ifaddrs.h netinet/ip6.h netinet/icmp6.h bits/in.h + +-routines := htonl htons \ ++routines-$(OPTION_EGLIBC_INET) \ ++ += htonl htons \ + inet_lnaof inet_mkadr \ + inet_netof inet_ntoa inet_net herrno herrno-loc \ + gethstbyad gethstbyad_r gethstbynm gethstbynm2 gethstbynm2_r \ +@@ -39,18 +42,23 @@ routines := htonl htons \ + getservent_r \ + ether_aton ether_aton_r ether_hton ether_line \ + ether_ntoa ether_ntoa_r ether_ntoh \ +- rcmd rexec ruserpass \ + getnetgrent_r getnetgrent \ +- getaliasent_r getaliasent getaliasname getaliasname_r \ +- in6_addr getnameinfo if_index ifaddrs inet6_option \ ++ in6_addr getnameinfo if_index ifaddrs \ + getipv4sourcefilter setipv4sourcefilter \ +- getsourcefilter setsourcefilter inet6_opt inet6_rth ++ getsourcefilter setsourcefilter ++routines-$(OPTION_EGLIBC_RCMD) \ ++ += rcmd rexec ruserpass ++routines-$(OPTION_EGLIBC_DB_ALIASES) \ ++ += getaliasent_r getaliasent getaliasname getaliasname_r ++routines-$(OPTION_EGLIBC_ADVANCED_INET6) \ ++ += inet6_option inet6_opt inet6_rth + +-aux := check_pf check_native ifreq ++aux-$(OPTION_EGLIBC_INET) += check_pf check_native ifreq + + tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ +- tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ ++ tst-gethnm test-ifaddrs bug-if1 tst-ether_line \ + tst-getni1 tst-getni2 tst-inet6_rth tst-checks ++tests-$(OPTION_EGLIBC_ADVANCED_INET6) += test-inet6_opt + + include ../Rules + +diff --git a/intl/Makefile b/intl/Makefile +index 9ecf8fe..587bc0d 100644 +--- a/intl/Makefile ++++ b/intl/Makefile +@@ -16,6 +16,7 @@ + # . + + # Makefile for intl subdirectory: message handling code from GNU gettext. ++include ../option-groups.mak + + subdir = intl + +@@ -48,7 +49,7 @@ endif + $(objpfx)plural.o: plural.c + + ifeq ($(run-built-tests),yes) +-ifeq (yes,$(build-shared)) ++ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared)) + ifneq ($(strip $(MSGFMT)),:) + tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \ + $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \ +diff --git a/intl/dcigettext.c b/intl/dcigettext.c +index 8a3f091..e271648 100644 +--- a/intl/dcigettext.c ++++ b/intl/dcigettext.c +@@ -100,11 +100,15 @@ extern int errno; + # include "libgnuintl.h" + #endif + #include "hash-string.h" ++#ifdef _LIBC ++# include ++#endif + + /* Handle multi-threaded applications. */ + #ifdef _LIBC + # include + # define gl_rwlock_define_initialized __libc_rwlock_define_initialized ++# define gl_rwlock_define __libc_rwlock_define + # define gl_rwlock_rdlock __libc_rwlock_rdlock + # define gl_rwlock_wrlock __libc_rwlock_wrlock + # define gl_rwlock_unlock __libc_rwlock_unlock +@@ -523,8 +527,10 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + saved_errno = errno; + + #ifdef _LIBC +- __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) +- __libc_rwlock_rdlock (__libc_setlocale_lock); ++# if __OPTION_EGLIBC_LOCALE_CODE ++ gl_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) ++ gl_rwlock_rdlock (__libc_setlocale_lock); ++# endif + #endif + + gl_rwlock_rdlock (_nl_state_lock); +@@ -550,7 +556,11 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + #ifdef HAVE_PER_THREAD_LOCALE + # ifndef IN_LIBGLOCALE + # ifdef _LIBC +- localename = strdupa (__current_locale_name (category)); ++# if __OPTION_EGLIBC_LOCALE_CODE ++ localename = strdupa (__current_locale_name (category)); ++# else ++ localename = "C"; ++# endif + # else + categoryname = category_to_name (category); + # define CATEGORYNAME_INITIALIZED +@@ -581,10 +591,12 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + else + retval = (char *) (*foundp)->translation; + +- gl_rwlock_unlock (_nl_state_lock); + # ifdef _LIBC +- __libc_rwlock_unlock (__libc_setlocale_lock); ++# if __OPTION_EGLIBC_LOCALE_CODE ++ gl_rwlock_unlock (__libc_setlocale_lock); ++# endif + # endif ++ gl_rwlock_unlock (_nl_state_lock); + __set_errno (saved_errno); + return retval; + } +@@ -838,10 +850,13 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + if (plural) + retval = plural_lookup (domain, n, retval, retlen); + +- gl_rwlock_unlock (_nl_state_lock); + #ifdef _LIBC +- __libc_rwlock_unlock (__libc_setlocale_lock); ++# if __OPTION_EGLIBC_LOCALE_CODE ++ ++ gl_rwlock_unlock (__libc_setlocale_lock); ++# endif + #endif ++ gl_rwlock_unlock (_nl_state_lock); + return retval; + } + } +@@ -850,10 +865,12 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + return_untranslated: + /* Return the untranslated MSGID. */ + FREE_BLOCKS (block_list); +- gl_rwlock_unlock (_nl_state_lock); + #ifdef _LIBC +- __libc_rwlock_unlock (__libc_setlocale_lock); ++# if __OPTION_EGLIBC_LOCALE_CODE ++ gl_rwlock_unlock (__libc_setlocale_lock); ++# endif + #endif ++ gl_rwlock_unlock (_nl_state_lock); + #ifndef _LIBC + if (!ENABLE_SECURE) + { +@@ -1550,7 +1567,11 @@ guess_category_value (int category, const char *categoryname) + `LC_xxx', and `LANG'. On some systems this can be done by the + `setlocale' function itself. */ + # ifdef _LIBC ++# if __OPTION_EGLIBC_LOCALE_CODE + locale = __current_locale_name (category); ++# else ++ locale = "C"; ++# endif + # else + locale_defaulted = 0; + # if HAVE_USELOCALE +diff --git a/io/Makefile b/io/Makefile +index 613dce0..697439e 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for I/O portion of the library. + # ++include ../option-groups.mak ++ + subdir := io + + include ../Makeconfig +@@ -36,7 +38,7 @@ routines := \ + fxstatat fxstatat64 \ + statfs fstatfs statfs64 fstatfs64 \ + statvfs fstatvfs statvfs64 fstatvfs64 \ +- umask chmod fchmod lchmod fchmodat \ ++ umask chmod fchmod fchmodat \ + mkdir mkdirat \ + open open_2 open64 open64_2 openat openat_2 openat64 openat64_2 \ + read write lseek lseek64 access euidaccess faccessat \ +@@ -49,11 +51,13 @@ routines := \ + ttyname ttyname_r isatty \ + link linkat symlink symlinkat readlink readlinkat \ + unlink unlinkat rmdir \ +- ftw ftw64 fts poll ppoll \ ++ poll ppoll \ + posix_fadvise posix_fadvise64 \ + posix_fallocate posix_fallocate64 \ + sendfile sendfile64 \ + utimensat futimens ++routines-$(OPTION_EGLIBC_BSD) += lchmod ++routines-$(OPTION_EGLIBC_FTRAVERSE) += ftw ftw64 fts + + aux := have_o_cloexec + +@@ -64,18 +68,22 @@ static-only-routines = stat fstat lstat stat64 fstat64 lstat64 \ + fstatat fstatat64 mknod mknodat + + others := pwd +-test-srcs := ftwtest ++test-srcs-$(OPTION_EGLIBC_FTRAVERSE) := ftwtest + tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ +- tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \ ++ tst-fcntl tst-statvfs \ + tst-openat tst-unlinkat tst-fstatat tst-futimesat \ + tst-renameat tst-fchownat tst-fchmodat tst-faccessat \ + tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \ +- tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \ ++ tst-mknodat tst-mkfifoat tst-ttyname_r \ + tst-posix_fallocate ++tests-$(OPTION_EGLIBC_FTRAVERSE) += bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 \ ++ bug-ftw5 + + ifeq ($(run-built-tests),yes) ++ifeq (y,$(OPTION_EGLIBC_FTRAVERSE)) + tests-special += $(objpfx)ftwtest.out + endif ++endif + + include ../Rules + +diff --git a/libidn/Makefile b/libidn/Makefile +index 940fa52..43aad0c 100644 +--- a/libidn/Makefile ++++ b/libidn/Makefile +@@ -16,6 +16,7 @@ + # . + + # Makefile for libidn subdirectory of GNU C Library. ++include ../option-groups.mak + + subdir := libidn + +@@ -23,8 +24,8 @@ include ../Makeconfig + + routines = idn-stub + +-extra-libs = libcidn +-extra-libs-others = $(extra-libs) ++extra-libs-$(OPTION_EGLIBC_IDN) = libcidn ++extra-libs-others-y = $(extra-libs-y) + + libcidn-routines := punycode toutf8 nfkc stringprep rfc3454 profiles idna \ + iconvme +diff --git a/libidn/toutf8.c b/libidn/toutf8.c +index c7e67ca..62df478 100644 +--- a/libidn/toutf8.c ++++ b/libidn/toutf8.c +@@ -33,6 +33,11 @@ + /* Get strlen. */ + #include + ++/* Get __OPTION_EGLIBC_LOCALE_CODE. */ ++#ifdef _LIBC ++# include ++#endif ++ + /* Get iconv_string. */ + #include "iconvme.h" + +@@ -47,7 +52,11 @@ + #endif + + #ifdef _LIBC +-# define stringprep_locale_charset() nl_langinfo (CODESET) ++# if __OPTION_EGLIBC_LOCALE_CODE ++# define stringprep_locale_charset() nl_langinfo (CODESET) ++# else ++# define stringprep_locale_charset() "ANSI_X3.4-1968" ++# endif + #else + /** + * stringprep_locale_charset - return charset used in current locale +diff --git a/libio/Makefile b/libio/Makefile +index 7b3bcf9..27c9186 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -18,6 +18,8 @@ + # + # Specific makefile for libio. + # ++include ../option-groups.mak ++ + subdir := libio + + include ../Makeconfig +@@ -27,16 +29,13 @@ headers := stdio.h libio.h _G_config.h bits/stdio.h bits/stdio-lock.h \ + + routines := \ + filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ +- iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc \ ++ iofopncook iofputs iofread iofsetpos ioftell \ + iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs \ + ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc \ + iovsprintf iovsscanf \ + iofgetpos64 iofopen64 iofsetpos64 \ +- fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ +- iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u \ +- putwchar putwchar_u putchar putchar_u fwprintf swprintf vwprintf \ +- wprintf wscanf fwscanf vwscanf vswprintf iovswscanf swscanf wgenops \ +- wstrops wfileops iofwide fwide wmemstream \ ++ putchar putchar_u \ ++ iofwide \ + \ + clearerr feof ferror fileno fputc freopen fseek getc getchar \ + memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \ +@@ -48,24 +47,49 @@ routines := \ + \ + libc_fatal fmemopen oldfmemopen + +-tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ +- tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \ +- tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf \ +- tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof \ +- tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \ ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \ ++ wfiledoalloc \ ++ iowpadn \ ++ swprintf \ ++ vswprintf iovswscanf swscanf wgenops \ ++ wstrops wfileops wmemstream ++routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += \ ++ wdummyfileops ++routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += \ ++ fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ ++ iofputws iofputws_u iogetwline ioungetwc putwc putwc_u \ ++ putwchar putwchar_u fwprintf vwprintf \ ++ wprintf wscanf fwscanf vwscanf \ ++ fwide ++ ++tests = test-fmemopen tst-ext tst-ext2 \ ++ tst-mmap-setvbuf tst-atime tst-eof \ ++ tst-freopen bug-ungetc bug-fseek \ + tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \ +- tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \ +- bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \ ++ tst-mmap2-eofsync tst-mmap-offend bug-fopena+ \ ++ bug-ungetc2 bug-ungetc3 bug-ungetc4 \ + tst-memstream1 tst-memstream2 \ +- tst-wmemstream1 tst-wmemstream2 \ +- bug-memstream1 bug-wmemstream1 \ +- tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ +- tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ +- tst-ftell-append tst-fputws ++ bug-memstream1 tst-popen1 tst-fwrite-error \ ++ tst-ftell-active-handler tst-ftell-append ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-swscanf tst-fgetws tst-setvbuf1 \ ++ tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2 \ ++ tst-widetext tst-fputws ++tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ ++ += bug-rewind bug-rewind2 bug-ungetwc1 \ ++ bug-wfflush bug-wmemstream1 tst-fopenloc2 \ ++ tst_getwc \ ++ tst_putwc tst_wprintf tst_wprintf2 tst_wscanf \ ++ tst-fgetwc bug-wsetpos tst-fseek tst-ftell-partial-wide ++tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += tst_swprintf tst_swscanf \ ++ tst-sscanf \ ++ tst-wmemstream1 tst-wmemstream2 ++ + ifeq (yes,$(build-shared)) + # Add test-fopenloc only if shared library is enabled since it depends on + # shared localedata objects. +-tests += tst-fopenloc ++tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-fopenloc + endif + test-srcs = test-freopen + +@@ -164,13 +188,17 @@ shared-only-routines = oldiofopen oldiofdopen oldiofclose oldfileops \ + oldiofsetpos64 + + ifeq ($(run-built-tests),yes) ++ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)) + tests-special += $(objpfx)test-freopen.out ++endif ++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) + ifeq (yes,$(build-shared)) + # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared + # library is enabled since they depend on tst-fopenloc.out. + tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out + endif + endif ++endif + + include ../Rules + +diff --git a/libio/__fpurge.c b/libio/__fpurge.c +index 065cf61..e32a3e9 100644 +--- a/libio/__fpurge.c ++++ b/libio/__fpurge.c +@@ -21,7 +21,7 @@ + void + __fpurge (FILE *fp) + { +- if (fp->_mode > 0) ++ if (_IO_is_wide (fp)) + { + /* Wide-char stream. */ + if (_IO_in_backup (fp)) +diff --git a/libio/fileops.c b/libio/fileops.c +index cbcd6f5..19e43c2 100644 +--- a/libio/fileops.c ++++ b/libio/fileops.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + #if _LIBC + # include "../wcsmbs/wcsmbsload.h" +@@ -173,7 +174,7 @@ _IO_new_file_close_it (_IO_FILE *fp) + + /* Free buffer. */ + #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T +- if (fp->_mode > 0) ++ if (_IO_is_wide (fp)) + { + if (_IO_have_wbackup (fp)) + _IO_free_wbackup_area (fp); +@@ -348,6 +349,7 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode, + cs = strstr (last_recognized + 1, ",ccs="); + if (cs != NULL) + { ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + /* Yep. Load the appropriate conversions and set the orientation + to wide. */ + struct gconv_fcts fcts; +@@ -418,6 +420,12 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode, + + /* Set the mode now. */ + result->_mode = 1; ++#else ++ /* Treat this as if we couldn't find the given character set. */ ++ (void) _IO_file_close_it (fp); ++ __set_errno (EINVAL); ++ return NULL; ++#endif + } + } + +diff --git a/libio/iofwide.c b/libio/iofwide.c +index 0c175d1..3e9f52b 100644 +--- a/libio/iofwide.c ++++ b/libio/iofwide.c +@@ -26,6 +26,7 @@ + + #include + #ifdef _LIBC ++# include + # include + # include + #endif +@@ -43,6 +44,8 @@ + #endif + + ++#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR ++ + /* Prototypes of libio's codecvt functions. */ + static enum __codecvt_result do_out (struct _IO_codecvt *codecvt, + __mbstate_t *statep, +@@ -499,3 +502,26 @@ do_max_length (struct _IO_codecvt *codecvt) + return MB_CUR_MAX; + #endif + } ++ ++#else ++/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled. */ ++ ++#undef _IO_fwide ++int ++_IO_fwide (fp, mode) ++ _IO_FILE *fp; ++ int mode; ++{ ++ /* Die helpfully if the user tries to create a wide stream; I ++ disbelieve that most users check the return value from ++ 'fwide (fp, 1)'. */ ++ assert (mode <= 0); ++ ++ /* We can only make streams byte-oriented, which is trivial. */ ++ if (mode < 0) ++ fp->_mode = -1; ++ ++ return fp->_mode; ++} ++ ++#endif +diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c +index 11765cf..15d6230 100644 +--- a/libio/ioseekoff.c ++++ b/libio/ioseekoff.c +@@ -60,7 +60,7 @@ _IO_seekoff_unlocked (fp, offset, dir, mode) + else + abort (); + } +- if (_IO_fwide (fp, 0) < 0) ++ if (! _IO_is_wide (fp)) + _IO_free_backup_area (fp); + else + _IO_free_wbackup_area (fp); +diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c +index a7652a1..6938b68 100644 +--- a/libio/ioseekpos.c ++++ b/libio/ioseekpos.c +@@ -35,7 +35,7 @@ _IO_seekpos_unlocked (fp, pos, mode) + /* If we have a backup buffer, get rid of it, since the __seekoff + callback may not know to do the right thing about it. + This may be over-kill, but it'll do for now. TODO */ +- if (_IO_fwide (fp, 0) <= 0) ++ if (! _IO_is_wide (fp)) + { + if (_IO_have_backup (fp)) + _IO_free_backup_area (fp); +diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c +index 0a41c10..3d99fa0 100644 +--- a/libio/iosetbuffer.c ++++ b/libio/iosetbuffer.c +@@ -24,6 +24,8 @@ + This exception applies to code released by its copyright holders + in files containing the exception. */ + ++#include ++ + #include "libioP.h" + + void +@@ -38,9 +40,11 @@ _IO_setbuffer (fp, buf, size) + if (!buf) + size = 0; + (void) _IO_SETBUF (fp, buf, size); ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp)) + /* We also have to set the buffer using the wide char function. */ + (void) _IO_WSETBUF (fp, buf, size); ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + _IO_release_lock (fp); + } + libc_hidden_def (_IO_setbuffer) +diff --git a/libio/libioP.h b/libio/libioP.h +index 0f16e2d..d2626d6 100644 +--- a/libio/libioP.h ++++ b/libio/libioP.h +@@ -44,6 +44,10 @@ + /*# include */ + #endif + ++#if defined _LIBC ++# include ++#endif ++ + #include + + #include "iolibio.h" +@@ -523,8 +527,20 @@ extern void _IO_old_init (_IO_FILE *fp, int flags) __THROW; + + + #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T ++ ++/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0', ++ except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it ++ expands to a constant, allowing the compiler to realize that it can ++ eliminate code that references wide stream handling functions. ++ This, in turn, allows us to omit them. */ ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR ++# define _IO_is_wide(_f) ((_f)->_mode > 0) ++#else ++# define _IO_is_wide(_f) (0) ++#endif ++ + # define _IO_do_flush(_f) \ +- ((_f)->_mode <= 0 \ ++ (! _IO_is_wide (_f) \ + ? _IO_do_write(_f, (_f)->_IO_write_base, \ + (_f)->_IO_write_ptr-(_f)->_IO_write_base) \ + : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base, \ +diff --git a/libio/wdummyfileops.c b/libio/wdummyfileops.c +new file mode 100644 +index 0000000..c0150b8 +--- /dev/null ++++ b/libio/wdummyfileops.c +@@ -0,0 +1,161 @@ ++/* Copyright (C) 2007 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. ++ ++ As a special exception, if you link the code in this file with ++ files compiled with a GNU compiler to produce an executable, ++ that does not cause the resulting executable to be covered by ++ the GNU Lesser General Public License. This exception does not ++ however invalidate any other reasons why the executable file ++ might be covered by the GNU Lesser General Public License. ++ This exception applies to code released by its copyright holders ++ in files containing the exception. */ ++ ++#include ++#include ++#include ++#include ++ ++static void __THROW __attribute__ ((__noreturn__)) ++_IO_wfile_wide_char_support_disabled (void) ++{ ++ static const char errstr[] ++ = ("The application tried to use wide character I/O, but libc.so" ++ " was compiled\n" ++ "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n"); ++ __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); ++ abort (); ++} ++ ++static void ++_IO_wfile_disabled_void_int (_IO_FILE *fp, int x) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static int ++_IO_wfile_disabled_int_int (_IO_FILE *fp, int x) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static int ++_IO_wfile_disabled_int_none (_IO_FILE *fp) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_size_t ++_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_size_t ++_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_off64_t ++_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_off64_t ++_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_FILE * ++_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_ssize_t ++_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_ssize_t ++_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static _IO_off64_t ++_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static int ++_IO_wfile_disabled_close (_IO_FILE *fp) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static int ++_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static int ++_IO_wfile_disabled_showmanyc (_IO_FILE *fp) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static void ++_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale) ++{ ++ _IO_wfile_wide_char_support_disabled (); ++} ++ ++static const struct _IO_jump_t _IO_wfile_jumps_disabled = ++{ ++ JUMP_INIT_DUMMY, ++ JUMP_INIT(finish, _IO_wfile_disabled_void_int), ++ JUMP_INIT(overflow, _IO_wfile_disabled_int_int), ++ JUMP_INIT(underflow, _IO_wfile_disabled_int_none), ++ JUMP_INIT(uflow, _IO_wfile_disabled_int_none), ++ JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int), ++ JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn), ++ JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn), ++ JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff), ++ JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos), ++ JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf), ++ JUMP_INIT(sync, _IO_wfile_disabled_int_none), ++ JUMP_INIT(doallocate, _IO_wfile_disabled_int_none), ++ JUMP_INIT(read, _IO_wfile_disabled_read), ++ JUMP_INIT(write, _IO_wfile_disabled_write), ++ JUMP_INIT(seek, _IO_wfile_disabled_seek), ++ JUMP_INIT(close, _IO_wfile_disabled_close), ++ JUMP_INIT(stat, _IO_wfile_disabled_stat), ++ JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc), ++ JUMP_INIT(imbue, _IO_wfile_disabled_imbue) ++}; ++ ++strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps) ++libc_hidden_data_def (_IO_wfile_jumps) ++strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap) ++strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap) +diff --git a/locale/C-ctype.c b/locale/C-ctype.c +index aa5f19f..06be081 100644 +--- a/locale/C-ctype.c ++++ b/locale/C-ctype.c +@@ -19,8 +19,11 @@ + #include "localeinfo.h" + #include + #include ++#include + ++#if __OPTION_EGLIBC_LOCALE_CODE + #include "C-translit.h" ++#endif + + /* This table's entries are taken from POSIX.2 Table 2-6 + ``LC_CTYPE Category Definition in the POSIX Locale''. +@@ -634,6 +637,7 @@ const struct __locale_data _nl_C_LC_CTYPE attribute_hidden = + { .word = L'7' }, + { .word = L'8' }, + { .word = L'9' }, ++#if __OPTION_EGLIBC_LOCALE_CODE + /* _NL_CTYPE_TRANSLIT_TAB_SIZE */ + { .word = NTRANSLIT }, + /* _NL_CTYPE_TRANSLIT_FROM_IDX */ +@@ -644,6 +648,22 @@ const struct __locale_data _nl_C_LC_CTYPE attribute_hidden = + { .wstr = translit_to_idx }, + /* _NL_CTYPE_TRANSLIT_TO_TBL */ + { .wstr = (uint32_t *) translit_to_tbl }, ++#else ++ /* If the locale code isn't enabled, we don't have the ++ transliteration code in iconv/gconv_trans.c anyway, so there's ++ no need for the transliteration tables here. We'll fall back ++ on the default missing replacement, '?'. */ ++ /* _NL_CTYPE_TRANSLIT_TAB_SIZE */ ++ { .word = 0 }, ++ /* _NL_CTYPE_TRANSLIT_FROM_IDX */ ++ { .wstr = NULL }, ++ /* _NL_CTYPE_TRANSLIT_FROM_TBL */ ++ { .wstr = NULL }, ++ /* _NL_CTYPE_TRANSLIT_TO_IDX */ ++ { .wstr = NULL }, ++ /* _NL_CTYPE_TRANSLIT_TO_TBL */ ++ { .wstr = NULL }, ++#endif + /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN */ + { .word = 1 }, + /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING */ +diff --git a/locale/Makefile b/locale/Makefile +index f1b4343..599a1a9 100644 +--- a/locale/Makefile ++++ b/locale/Makefile +@@ -18,27 +18,43 @@ + # + # Makefile for locales. + # ++include ../option-groups.mak ++ + subdir := locale + + include ../Makeconfig + + headers = locale.h bits/locale.h langinfo.h xlocale.h +-routines = setlocale findlocale loadlocale loadarchive \ +- localeconv nl_langinfo nl_langinfo_l mb_cur_max \ +- newlocale duplocale freelocale uselocale +-tests = tst-C-locale tst-locname tst-duplocale ++# catnames is needed by OPTION_EGLIBC_LOCALE_CODE and by the 'intl' code. ++# If we put the latter in an option group, too, we can omit catnames ++# when both option groups are disabled. libstdc++-v3 needs mb_cur_max. ++routines-y := catnames mb_cur_max ++routines-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += setlocale findlocale loadlocale loadarchive \ ++ localeconv nl_langinfo nl_langinfo_l \ ++ newlocale duplocale freelocale uselocale ++ifneq (y,$(OPTION_EGLIBC_LOCALE_CODE)) ++routines-y += dummy-setlocale ++endif ++tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-C-locale tst-locname tst-duplocale + categories = ctype messages monetary numeric time paper name \ + address telephone measurement identification collate +-aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ +- xlocale localename global-locale coll-lookup +-others = localedef locale ++# C-messages belongs in an intl option group. ++aux-y := C-ctype C-time \ ++ SYS_libc C_name xlocale global-locale coll-lookup ++aux-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += $(filter-out $(aux-y), \ ++ $(categories:%=lc-%) $(categories:%=C-%)) \ ++ localename ++others-$(OPTION_EGLIBC_LOCALE_CODE) = localedef locale + #others-static = localedef locale +-install-bin = localedef locale +-extra-objs = $(localedef-modules:=.o) $(localedef-aux:=.o) \ ++install-bin = $(others-y) ++extra-objs-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ = $(localedef-modules:=.o) $(localedef-aux:=.o) \ + $(locale-modules:=.o) $(lib-modules:=.o) + +-extra-libs = libBrokenLocale +-extra-libs-others = $(extra-libs) ++extra-libs-$(OPTION_EGLIBC_LOCALE_CODE) = libBrokenLocale ++extra-libs-others = $(extra-libs-y) + + libBrokenLocale-routines = broken_cur_max + +@@ -93,6 +109,9 @@ CPPFLAGS-locale-programs = -DLOCALE_PATH='$(localepath)' \ + CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts + CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts + CFLAGS-charmap-dir.c = -Wno-write-strings ++ifneq (y,$(OPTION_EGLIBC_SPAWN)) ++CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS ++endif + + # Set libof-* for each routine. + cpp-srcs-left := $(localedef-modules) $(localedef-aux) $(locale-modules) \ +diff --git a/locale/catnames.c b/locale/catnames.c +new file mode 100644 +index 0000000..9fad357 +--- /dev/null ++++ b/locale/catnames.c +@@ -0,0 +1,48 @@ ++/* Copyright (C) 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include "localeinfo.h" ++ ++/* Define an array of category names (also the environment variable names). */ ++const union catnamestr_t _nl_category_names attribute_hidden = ++ { ++ { ++#define DEFINE_CATEGORY(category, category_name, items, a) \ ++ category_name, ++#include "categories.def" ++#undef DEFINE_CATEGORY ++ } ++ }; ++ ++const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = ++ { ++#define DEFINE_CATEGORY(category, category_name, items, a) \ ++ [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), ++#include "categories.def" ++#undef DEFINE_CATEGORY ++ }; ++ ++/* An array of their lengths, for convenience. */ ++const uint8_t _nl_category_name_sizes[] attribute_hidden = ++ { ++#define DEFINE_CATEGORY(category, category_name, items, a) \ ++ [category] = sizeof (category_name) - 1, ++#include "categories.def" ++#undef DEFINE_CATEGORY ++ [LC_ALL] = sizeof ("LC_ALL") - 1 ++ }; +diff --git a/locale/dummy-setlocale.c b/locale/dummy-setlocale.c +new file mode 100644 +index 0000000..219964a +--- /dev/null ++++ b/locale/dummy-setlocale.c +@@ -0,0 +1,33 @@ ++/* Copyright (C) 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++ ++char * ++setlocale (int category, const char *locale) ++{ ++ if (! locale ++ || locale[0] == '\0' ++ || strcmp (locale, "C") == 0 ++ || strcmp (locale, "POSIX") == 0) ++ return (char *) "C"; ++ else ++ return NULL; ++} ++libc_hidden_def (setlocale) +diff --git a/locale/localeinfo.h b/locale/localeinfo.h +index bdab9fe..a7516c0 100644 +--- a/locale/localeinfo.h ++++ b/locale/localeinfo.h +@@ -232,7 +232,7 @@ __libc_tsd_define (extern, __locale_t, LOCALE) + unused. We can manage this playing some tricks with weak references. + But with thread-local locale settings, it becomes quite ungainly unless + we can use __thread variables. So only in that case do we attempt this. */ +-#ifndef SHARED ++#if !defined SHARED && !defined IN_GLIBC_LOCALEDEF + # include + # define NL_CURRENT_INDIRECT 1 + #endif +diff --git a/locale/programs/charmap-dir.c b/locale/programs/charmap-dir.c +index cf7adea..ef3b811 100644 +--- a/locale/programs/charmap-dir.c ++++ b/locale/programs/charmap-dir.c +@@ -19,7 +19,9 @@ + #include + #include + #include ++#ifndef NO_UNCOMPRESS + #include ++#endif + #include + #include + #include +@@ -156,6 +158,7 @@ charmap_closedir (CHARMAP_DIR *cdir) + return closedir (dir); + } + ++#ifndef NO_UNCOMPRESS + /* Creates a subprocess decompressing the given pathname, and returns + a stream reading its output (the decompressed data). */ + static +@@ -204,6 +207,7 @@ fopen_uncompressed (const char *pathname, const char *compressor) + } + return NULL; + } ++#endif + + /* Opens a charmap for reading, given its name (not an alias name). */ + FILE * +@@ -226,6 +230,7 @@ charmap_open (const char *directory, const char *name) + if (stream != NULL) + return stream; + ++#ifndef NO_UNCOMPRESS + memcpy (p, ".gz", 4); + stream = fopen_uncompressed (pathname, "gzip"); + if (stream != NULL) +@@ -235,6 +240,7 @@ charmap_open (const char *directory, const char *name) + stream = fopen_uncompressed (pathname, "bzip2"); + if (stream != NULL) + return stream; ++#endif + + return NULL; + } +diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c +index a39a94f..16e9039 100644 +--- a/locale/programs/ld-collate.c ++++ b/locale/programs/ld-collate.c +@@ -351,7 +351,7 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen, + } + if (wcs != NULL) + { +- size_t nwcs = wcslen ((wchar_t *) wcs); ++ size_t nwcs = wcslen_uint32 (wcs); + uint32_t zero = 0; + /* Handle as a single character. */ + if (nwcs == 0) +@@ -1777,8 +1777,7 @@ symbol `%s' has the same encoding as"), (*eptr)->name); + + if ((*eptr)->nwcs == runp->nwcs) + { +- int c = wmemcmp ((wchar_t *) (*eptr)->wcs, +- (wchar_t *) runp->wcs, runp->nwcs); ++ int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs); + + if (c == 0) + { +@@ -2011,9 +2010,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp) + one consecutive entry. */ + if (runp->wcnext != NULL + && runp->nwcs == runp->wcnext->nwcs +- && wmemcmp ((wchar_t *) runp->wcs, +- (wchar_t *)runp->wcnext->wcs, +- runp->nwcs - 1) == 0 ++ && wmemcmp_uint32 (runp->wcs, ++ runp->wcnext->wcs, ++ runp->nwcs - 1) == 0 + && (runp->wcs[runp->nwcs - 1] + == runp->wcnext->wcs[runp->nwcs - 1] + 1)) + { +@@ -2037,9 +2036,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp) + runp = runp->wcnext; + while (runp->wcnext != NULL + && runp->nwcs == runp->wcnext->nwcs +- && wmemcmp ((wchar_t *) runp->wcs, +- (wchar_t *)runp->wcnext->wcs, +- runp->nwcs - 1) == 0 ++ && wmemcmp_uint32 (runp->wcs, ++ runp->wcnext->wcs, ++ runp->nwcs - 1) == 0 + && (runp->wcs[runp->nwcs - 1] + == runp->wcnext->wcs[runp->nwcs - 1] + 1)); + +diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c +index 3f464ef..b7b6b51 100644 +--- a/locale/programs/ld-ctype.c ++++ b/locale/programs/ld-ctype.c +@@ -926,7 +926,7 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap, + allocate_arrays (ctype, charmap, ctype->repertoire); + + default_missing_len = (ctype->default_missing +- ? wcslen ((wchar_t *) ctype->default_missing) ++ ? wcslen_uint32 (ctype->default_missing) + : 0); + + init_locale_data (&file, nelems); +@@ -1937,7 +1937,7 @@ read_translit_entry (struct linereader *ldfile, struct locale_ctype_t *ctype, + ignore = 1; + else + /* This value is usable. */ +- obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4); ++ obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4); + + first = 0; + } +@@ -2471,8 +2471,8 @@ with character code range values one must use the absolute ellipsis `...'")); + } + + handle_tok_digit: +- class_bit = _ISwdigit; +- class256_bit = _ISdigit; ++ class_bit = BITw (tok_digit); ++ class256_bit = BIT (tok_digit); + handle_digits = 1; + goto read_charclass; + +@@ -3929,8 +3929,7 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap, + + while (idx < number) + { +- int res = wcscmp ((const wchar_t *) sorted[idx]->from, +- (const wchar_t *) runp->from); ++ int res = wcscmp_uint32 (sorted[idx]->from, runp->from); + if (res == 0) + { + replace = 1; +@@ -3967,11 +3966,11 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap, + for (size_t cnt = 0; cnt < number; ++cnt) + { + struct translit_to_t *srunp; +- from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1; ++ from_len += wcslen_uint32 (sorted[cnt]->from) + 1; + srunp = sorted[cnt]->to; + while (srunp != NULL) + { +- to_len += wcslen ((const wchar_t *) srunp->str) + 1; ++ to_len += wcslen_uint32 (srunp->str) + 1; + srunp = srunp->next; + } + /* Plus one for the extra NUL character marking the end of +@@ -3995,18 +3994,18 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap, + ctype->translit_from_idx[cnt] = from_len; + ctype->translit_to_idx[cnt] = to_len; + +- len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1; +- wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len], +- (const wchar_t *) sorted[cnt]->from, len); ++ len = wcslen_uint32 (sorted[cnt]->from) + 1; ++ wmemcpy_uint32 (&ctype->translit_from_tbl[from_len], ++ sorted[cnt]->from, len); + from_len += len; + + ctype->translit_to_idx[cnt] = to_len; + srunp = sorted[cnt]->to; + while (srunp != NULL) + { +- len = wcslen ((const wchar_t *) srunp->str) + 1; +- wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len], +- (const wchar_t *) srunp->str, len); ++ len = wcslen_uint32 (srunp->str) + 1; ++ wmemcpy_uint32 (&ctype->translit_to_tbl[to_len], ++ srunp->str, len); + to_len += len; + srunp = srunp->next; + } +diff --git a/locale/programs/ld-messages.c b/locale/programs/ld-messages.c +index ec1a80b..736eed8 100644 +--- a/locale/programs/ld-messages.c ++++ b/locale/programs/ld-messages.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + +@@ -124,6 +125,7 @@ No definition for %s category found"), "LC_MESSAGES")); + } + else + { ++#if __OPTION_POSIX_REGEXP + int result; + regex_t re; + +@@ -140,6 +142,7 @@ No definition for %s category found"), "LC_MESSAGES")); + } + else if (result != 0) + regfree (&re); ++#endif + } + + if (messages->noexpr == NULL) +@@ -158,6 +161,7 @@ No definition for %s category found"), "LC_MESSAGES")); + } + else + { ++#if __OPTION_POSIX_REGEXP + int result; + regex_t re; + +@@ -174,6 +178,7 @@ No definition for %s category found"), "LC_MESSAGES")); + } + else if (result != 0) + regfree (&re); ++#endif + } + } + +diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c +index db490c6..75dc505 100644 +--- a/locale/programs/ld-time.c ++++ b/locale/programs/ld-time.c +@@ -215,8 +215,10 @@ No definition for %s category found"), "LC_TIME")); + } + else + { ++ static const uint32_t wt_fmt_ampm[] ++ = { '%','I',':','%','M',':','%','S',' ','%','p',0 }; + time->t_fmt_ampm = "%I:%M:%S %p"; +- time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p"; ++ time->wt_fmt_ampm = wt_fmt_ampm; + } + } + +@@ -226,7 +228,7 @@ No definition for %s category found"), "LC_TIME")); + const int days_per_month[12] = { 31, 29, 31, 30, 31, 30, + 31, 31, 30, 31 ,30, 31 }; + size_t idx; +- wchar_t *wstr; ++ uint32_t *wstr; + + time->era_entries = + (struct era_data *) xmalloc (time->num_era +@@ -464,18 +466,18 @@ No definition for %s category found"), "LC_TIME")); + } + + /* Now generate the wide character name and format. */ +- wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */ +- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end offset */ +- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end start */ +- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end end */ ++ wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */ ++ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */ ++ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */ ++ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */ + if (wstr != NULL) + { +- time->era_entries[idx].wname = (uint32_t *) wstr + 1; +- wstr = wcschr (wstr + 1, L':'); /* end name */ ++ time->era_entries[idx].wname = wstr + 1; ++ wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */ + if (wstr != NULL) + { + *wstr = L'\0'; +- time->era_entries[idx].wformat = (uint32_t *) wstr + 1; ++ time->era_entries[idx].wformat = wstr + 1; + } + else + time->era_entries[idx].wname = +@@ -530,7 +532,16 @@ No definition for %s category found"), "LC_TIME")); + if (time->date_fmt == NULL) + time->date_fmt = "%a %b %e %H:%M:%S %Z %Y"; + if (time->wdate_fmt == NULL) +- time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y"; ++ { ++ static const uint32_t wdate_fmt[] = ++ { '%','a',' ', ++ '%','b',' ', ++ '%','e',' ', ++ '%','H',':','%','M',':','%','S',' ', ++ '%','Z',' ', ++ '%','Y',0 }; ++ time->wdate_fmt = wdate_fmt; ++ } + } + + +diff --git a/locale/programs/linereader.c b/locale/programs/linereader.c +index 2e05130..653b68c 100644 +--- a/locale/programs/linereader.c ++++ b/locale/programs/linereader.c +@@ -595,7 +595,7 @@ get_string (struct linereader *lr, const struct charmap_t *charmap, + { + int return_widestr = lr->return_widestr; + char *buf; +- wchar_t *buf2 = NULL; ++ uint32_t *buf2 = NULL; + size_t bufact; + size_t bufmax = 56; + +diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c +index 2a0f2aa..583d233 100644 +--- a/locale/programs/localedef.c ++++ b/locale/programs/localedef.c +@@ -114,6 +114,7 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + #define OPT_LIST_ARCHIVE 309 + #define OPT_LITTLE_ENDIAN 400 + #define OPT_BIG_ENDIAN 401 ++#define OPT_UINT32_ALIGN 402 + + /* Definitions of arguments for argp functions. */ + static const struct argp_option options[] = +@@ -150,6 +151,8 @@ static const struct argp_option options[] = + N_("Generate little-endian output") }, + { "big-endian", OPT_BIG_ENDIAN, NULL, 0, + N_("Generate big-endian output") }, ++ { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0, ++ N_("Set the target's uint32_t alignment in bytes (default 4)") }, + { NULL, 0, NULL, 0, NULL } + }; + +@@ -239,12 +242,14 @@ main (int argc, char *argv[]) + ctype locale. (P1003.2 4.35.5.2) */ + setlocale (LC_CTYPE, "POSIX"); + ++#ifndef NO_SYSCONF + /* Look whether the system really allows locale definitions. POSIX + defines error code 3 for this situation so I think it must be + a fatal error (see P1003.2 4.35.8). */ + if (sysconf (_SC_2_LOCALEDEF) < 0) + WITH_CUR_LOCALE (error (3, 0, _("\ + FATAL: system does not define `_POSIX2_LOCALEDEF'"))); ++#endif + + /* Process charmap file. */ + charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1); +@@ -338,6 +343,9 @@ parse_opt (int key, char *arg, struct argp_state *state) + case OPT_BIG_ENDIAN: + set_big_endian (true); + break; ++ case OPT_UINT32_ALIGN: ++ uint32_align_mask = strtol (arg, NULL, 0) - 1; ++ break; + case 'c': + force_output = 1; + break; +diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c +index 33da52e..f790c4c 100644 +--- a/locale/programs/locfile.c ++++ b/locale/programs/locfile.c +@@ -544,6 +544,9 @@ compare_files (const char *filename1, const char *filename2, size_t size, + machine running localedef. */ + bool swap_endianness_p; + ++/* The target's value of __align__(uint32_t) - 1. */ ++unsigned int uint32_align_mask = 3; ++ + /* When called outside a start_locale_structure/end_locale_structure + or start_locale_prelude/end_locale_prelude block, record that the + next byte in FILE's obstack will be the first byte of a new element. +@@ -621,7 +624,7 @@ add_locale_string (struct locale_file *file, const char *string) + void + add_locale_wstring (struct locale_file *file, const uint32_t *string) + { +- add_locale_uint32_array (file, string, wcslen ((const wchar_t *) string) + 1); ++ add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1); + } + + /* Record that FILE's next element is the 32-bit integer VALUE. */ +diff --git a/locale/programs/locfile.h b/locale/programs/locfile.h +index 6fc441b..118b171 100644 +--- a/locale/programs/locfile.h ++++ b/locale/programs/locfile.h +@@ -71,6 +71,8 @@ extern void write_all_categories (struct localedef_t *definitions, + + extern bool swap_endianness_p; + ++extern unsigned int uint32_align_mask; ++ + /* Change the output to be big-endian if BIG_ENDIAN is true and + little-endian otherwise. */ + static inline void +@@ -89,7 +91,8 @@ maybe_swap_uint32 (uint32_t value) + } + + /* Likewise, but munge an array of N uint32_ts starting at ARRAY. */ +-static inline void ++static void ++__attribute__ ((unused)) + maybe_swap_uint32_array (uint32_t *array, size_t n) + { + if (swap_endianness_p) +@@ -99,7 +102,8 @@ maybe_swap_uint32_array (uint32_t *array, size_t n) + + /* Like maybe_swap_uint32_array, but the array of N elements is at + the end of OBSTACK's current object. */ +-static inline void ++static void ++__attribute__ ((unused)) + maybe_swap_uint32_obstack (struct obstack *obstack, size_t n) + { + maybe_swap_uint32_array ((uint32_t *) obstack_next_free (obstack) - n, n); +@@ -276,4 +280,55 @@ extern void identification_output (struct localedef_t *locale, + const struct charmap_t *charmap, + const char *output_path); + ++static size_t wcslen_uint32 (const uint32_t *str) __attribute__ ((unused)); ++static uint32_t * wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused)); ++static uint32_t * wcschr_uint32 (const uint32_t *s, uint32_t ch) __attribute__ ((unused)); ++static int wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) __attribute__ ((unused)); ++static int wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused)); ++ ++static size_t ++wcslen_uint32 (const uint32_t *str) ++{ ++ size_t len = 0; ++ while (str[len] != 0) ++ len++; ++ return len; ++} ++ ++static int ++wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) ++{ ++ while (n-- != 0) ++ { ++ int diff = *s1++ - *s2++; ++ if (diff != 0) ++ return diff; ++ } ++ return 0; ++} ++ ++static int ++wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) ++{ ++ while (*s1 != 0 && *s1 == *s2) ++ s1++, s2++; ++ return *s1 - *s2; ++} ++ ++static uint32_t * ++wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) ++{ ++ return memcpy (s1, s2, n * sizeof (uint32_t)); ++} ++ ++static uint32_t * ++wcschr_uint32 (const uint32_t *s, uint32_t ch) ++{ ++ do ++ if (*s == ch) ++ return (uint32_t *) s; ++ while (*s++ != 0); ++ return 0; ++} ++ + #endif /* locfile.h */ +diff --git a/locale/setlocale.c b/locale/setlocale.c +index fa9cb3a..8eee284 100644 +--- a/locale/setlocale.c ++++ b/locale/setlocale.c +@@ -64,36 +64,6 @@ static char *const _nl_current_used[] = + #endif + + +-/* Define an array of category names (also the environment variable names). */ +-const union catnamestr_t _nl_category_names attribute_hidden = +- { +- { +-#define DEFINE_CATEGORY(category, category_name, items, a) \ +- category_name, +-#include "categories.def" +-#undef DEFINE_CATEGORY +- } +- }; +- +-const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = +- { +-#define DEFINE_CATEGORY(category, category_name, items, a) \ +- [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), +-#include "categories.def" +-#undef DEFINE_CATEGORY +- }; +- +-/* An array of their lengths, for convenience. */ +-const uint8_t _nl_category_name_sizes[] attribute_hidden = +- { +-#define DEFINE_CATEGORY(category, category_name, items, a) \ +- [category] = sizeof (category_name) - 1, +-#include "categories.def" +-#undef DEFINE_CATEGORY +- [LC_ALL] = sizeof ("LC_ALL") - 1 +- }; +- +- + #ifdef NL_CURRENT_INDIRECT + # define WEAK_POSTLOAD(postload) weak_extern (postload) + #else +diff --git a/locale/xlocale.c b/locale/xlocale.c +index fec4564..f00269c 100644 +--- a/locale/xlocale.c ++++ b/locale/xlocale.c +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + #include "localeinfo.h" + + #define DEFINE_CATEGORY(category, category_name, items, a) \ +@@ -25,6 +26,19 @@ extern struct __locale_data _nl_C_##category; + #include "categories.def" + #undef DEFINE_CATEGORY + ++/* If the locale support code isn't enabled, don't generate strong ++ reference to the C locale_data structures here; let the Makefile ++ decide which ones to include. (In the static linking case, the ++ strong reference to the 'class', 'toupper', and 'tolower' tables ++ will cause C-ctype.o to be brought in, as it should be, even when ++ the reference to _nl_C_LC_CTYPE will be weak.) */ ++#if ! __OPTION_EGLIBC_LOCALE_CODE ++# define DEFINE_CATEGORY(category, category_name, items, a) \ ++ weak_extern (_nl_C_##category) ++# include "categories.def" ++# undef DEFINE_CATEGORY ++#endif ++ + /* Defined in locale/C-ctype.c. */ + extern const char _nl_C_LC_CTYPE_class[] attribute_hidden; + extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden; +@@ -52,3 +66,26 @@ const struct __locale_struct _nl_C_locobj attribute_hidden = + .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128, + .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128 + }; ++ ++ ++#if ! __OPTION_EGLIBC_LOCALE_CODE ++/* When locale code is enabled, these are each defined in the ++ appropriate lc-CATEGORY.c file, so that static links (when __thread ++ is supported) bring in only those lc-CATEGORY.o files for ++ categories the program actually uses; look for NL_CURRENT_INDIRECT ++ in localeinfo.h. ++ ++ When locale code is disabled, the _nl_C_CATEGORY objects are the ++ only possible referents. At the moment, there isn't a way to get ++ __OPTION_EGLIBC_LOCALE_CODE defined in every compilation unit that ++ #includes localeinfo.h, so we can't just turn off ++ NL_CURRENT_INDIRECT. So we'll define the _nl_current_CATEGORY ++ pointers here. */ ++#if defined (NL_CURRENT_INDIRECT) ++#define DEFINE_CATEGORY(category, category_name, items, a) \ ++ __thread struct __locale_data * const *_nl_current_##category \ ++ attribute_hidden = &_nl_C_locobj.__locales[category]; ++#include "categories.def" ++#undef DEFINE_CATEGORY ++#endif ++#endif /* __OPTION_EGLIBC_LOCALE_CODE */ +diff --git a/localedata/Makefile b/localedata/Makefile +index ebf6ac9..1870753 100644 +--- a/localedata/Makefile ++++ b/localedata/Makefile +@@ -21,12 +21,22 @@ subdir := localedata + + include ../Makeconfig + +-# List with all available character set descriptions. +-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*) ++include ../option-groups.mak + + # List with all available character set descriptions. +-locales := $(wildcard locales/*) +- ++all-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*) ++ ++all-locales := $(wildcard locales/*) ++ ++# If the EGLIBC_LOCALES option group is not enabled, trim the ++# list of charmap and locale source files. ++ifeq ($(OPTION_EGLIBC_LOCALES),y) ++charmaps := $(all-charmaps) ++locales := $(all-locales) ++else ++charmaps := ++locales := locales/POSIX ++endif + + subdir-dirs = tests-mbwc + vpath %.c tests-mbwc +@@ -71,14 +81,20 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \ + tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \ + tst_wctype tst_wcwidth + +-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \ ++# Since these tests build their own locale files, they're not ++# dependent on the OPTION_EGLIBC_LOCALES option group. But they do ++# need the locale functions to be present. ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \ + tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \ + tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \ + tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \ + tst-wctype ++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) + tests-static = bug-setlocale1-static + tests += $(tests-static) +-ifeq (yes,$(build-shared)) ++endif ++ifeq (yesy,$(build-shared)$(OPTION_EGLIBC_LOCALE_CODE)) + ifneq (no,$(PERL)) + tests-special += $(objpfx)mtrace-tst-leaks.out + endif +@@ -95,6 +111,7 @@ tests: $(objdir)/iconvdata/gconv-modules + tests-static += tst-langinfo-static + + ifeq ($(run-built-tests),yes) ++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) + tests-special += $(objpfx)sort-test.out $(objpfx)tst-fmon.out \ + $(objpfx)tst-locale.out $(objpfx)tst-rpmatch.out \ + $(objpfx)tst-trans.out $(objpfx)tst-ctype.out \ +@@ -109,6 +126,7 @@ LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 \ + tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8 + include ../gen-locales.mk + endif ++endif + + include ../Rules + +@@ -191,6 +209,11 @@ endif + + include SUPPORTED + ++# Only install locale data if OPTION_EGLIBC_LOCALES is selected. ++ifneq ($(OPTION_EGLIBC_LOCALES),y) ++SUPPORTED-LOCALES := ++endif ++ + INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES)) + + # Sometimes the whole collection of locale files should be installed. +diff --git a/login/Makefile b/login/Makefile +index 0f4bb22..4036ddb 100644 +--- a/login/Makefile ++++ b/login/Makefile +@@ -18,6 +18,7 @@ + # + # Sub-makefile for login portion of the library. + # ++include ../option-groups.mak + + subdir := login + +@@ -25,14 +26,16 @@ include ../Makeconfig + + headers := utmp.h bits/utmp.h lastlog.h pty.h + +-routines := getlogin getlogin_r setlogin getlogin_r_chk \ +- getutent getutent_r getutid getutline getutid_r getutline_r \ +- utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \ +- ptsname_r_chk ++routines := getpt grantpt unlockpt ptsname ptsname_r_chk ++routines-$(OPTION_EGLIBC_UTMP) \ ++ += getutent getutent_r getutid getutline getutid_r getutline_r \ ++ utmp_file utmpname updwtmp ++routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin getlogin_r getlogin_r_chk ++routines-$(OPTION_EGLIBC_BSD) += setlogin + + CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"' + +-others = utmpdump ++others-$(OPTION_EGLIBC_UTMP) += utmpdump + + ifeq (yes,$(build-pt-chown)) + others += pt_chown +@@ -46,8 +49,8 @@ vpath %.c programs + tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin + + # Build the -lutil library with these extra functions. +-extra-libs := libutil +-extra-libs-others := $(extra-libs) ++extra-libs-$(OPTION_EGLIBC_UTMP) := libutil ++extra-libs-others := $(extra-libs-y) + + libutil-routines:= login login_tty logout logwtmp openpty forkpty + +diff --git a/malloc/Makefile b/malloc/Makefile +index 67ed293..272ca4d 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -18,6 +18,8 @@ + # + # Makefile for malloc routines + # ++include ../option-groups.mak ++ + subdir := malloc + + include ../Makeconfig +@@ -39,9 +41,15 @@ install-lib := libmcheck.a + non-lib.a := libmcheck.a + + # Additional library. ++ifeq ($(OPTION_EGLIBC_MEMUSAGE),y) + extra-libs = libmemusage + extra-libs-others = $(extra-libs) + ++ifdef OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE ++CPPFLAGS-memusage += -D__OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE=$(OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE) ++endif ++endif ++ + libmemusage-routines = memusage + libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) + +@@ -71,7 +79,7 @@ endif + # Unless we get a test for the availability of libgd which also works + # for cross-compiling we disable the memusagestat generation in this + # situation. +-ifneq ($(cross-compiling),yes) ++ifeq ($(cross-compiling)$(OPTION_EGLIBC_MEMUSAGE),noy) + # If the gd library is available we build the `memusagestat' program. + ifneq ($(LIBGD),no) + others: $(objpfx)memusage +diff --git a/malloc/memusage.c b/malloc/memusage.c +index a57ba8e..732ba9d 100644 +--- a/malloc/memusage.c ++++ b/malloc/memusage.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #include + +@@ -93,7 +94,11 @@ static __thread uintptr_t start_sp; + #define peak_stack peak_use[1] + #define peak_total peak_use[2] + +-#define DEFAULT_BUFFER_SIZE 32768 ++#ifndef __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE ++# define DEFAULT_BUFFER_SIZE 32768 ++#else ++# define DEFAULT_BUFFER_SIZE __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE ++#endif + static size_t buffer_size; + + static int fd = -1; +diff --git a/malloc/memusage.sh b/malloc/memusage.sh +index 8ab8cc2..d18f446 100755 +--- a/malloc/memusage.sh ++++ b/malloc/memusage.sh +@@ -35,7 +35,7 @@ do_missing_arg() { + + # Print help message + do_help() { +- echo $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]... ++ printf $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]... + Profile memory usage of PROGRAM. + + -n,--progname=NAME Name of the program file to profile +diff --git a/math/Makefile b/math/Makefile +index 6388bae..ed1c511 100644 +--- a/math/Makefile ++++ b/math/Makefile +@@ -21,6 +21,8 @@ subdir := math + + include ../Makeconfig + ++include ../option-groups.mak ++ + # Installed header files. + headers := math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \ + bits/huge_valf.h bits/huge_vall.h bits/inf.h bits/nan.h \ +@@ -34,8 +36,8 @@ aux := setfpucw fpu_control + + # Build the -lm library. + +-extra-libs := libm +-extra-libs-others = $(extra-libs) ++extra-libs-$(OPTION_EGLIBC_LIBM) := libm ++extra-libs-others-$(OPTION_EGLIBC_LIBM) = $(extra-libs-$(OPTION_EGLIBC_LIBM)) + + libm-support = s_lib_version s_matherr s_signgam \ + fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg \ +diff --git a/misc/Makefile b/misc/Makefile +index aecb0da..e6b7c23 100644 +--- a/misc/Makefile ++++ b/misc/Makefile +@@ -19,6 +19,10 @@ + # Sub-makefile for misc portion of the library. + # + ++# Some system-dependent implementations of these functions use option ++# groups (see sysdeps/unix/sysv/linux/Makefile, for example). ++include ../option-groups.mak ++ + subdir := misc + + include ../Makeconfig +@@ -46,40 +50,47 @@ routines := brk sbrk sstk ioctl \ + select pselect \ + acct chroot fsync sync fdatasync syncfs reboot \ + gethostid sethostid \ +- revoke vhangup \ ++ vhangup \ + swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \ + mkostemp mkostemp64 mkstemps mkstemps64 mkostemps mkostemps64 \ + ualarm usleep \ + gtty stty \ + ptrace \ +- fstab mntent mntent_r \ ++ mntent mntent_r \ + utimes lutimes futimes futimesat \ + truncate ftruncate truncate64 ftruncate64 \ +- chflags fchflags \ + insremque getttyent getusershell getpass ttyslot \ + syslog syscall daemon \ + mmap mmap64 munmap mprotect msync madvise mincore remap_file_pages\ + mlock munlock mlockall munlockall \ +- efgcvt efgcvt_r qefgcvt qefgcvt_r \ + hsearch hsearch_r tsearch lsearch \ + err error ustat \ +- getsysstats dirname regexp \ ++ getsysstats dirname \ + getloadavg getclktck \ + fgetxattr flistxattr fremovexattr fsetxattr getxattr \ + listxattr lgetxattr llistxattr lremovexattr lsetxattr \ + removexattr setxattr getauxval ifunc-impl-list + ++routines-$(OPTION_POSIX_REGEXP) += regexp ++routines-$(OPTION_EGLIBC_FSTAB) += fstab ++routines-$(OPTION_EGLIBC_BSD) += chflags fchflags revoke ++routines-$(OPTION_EGLIBC_FCVT) += efgcvt efgcvt_r qefgcvt qefgcvt_r ++ + generated += tst-error1.mtrace tst-error1-mem.out + + aux := init-misc + install-lib := libg.a + gpl2lgpl := error.c error.h + +-tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ +- tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 ++tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \ ++ tst-pselect tst-insremque tst-mntent2 bug-hsearch1 ++tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += tst-error1 ++tests-$(OPTION_EGLIBC_FCVT) += tst-efgcvt + ifeq ($(run-built-tests),yes) ++ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)) + tests-special += $(objpfx)tst-error1-mem.out + endif ++endif + + CFLAGS-select.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-tsearch.c = $(uses-callbacks) +diff --git a/misc/err.c b/misc/err.c +index 7b98157..efce8d5 100644 +--- a/misc/err.c ++++ b/misc/err.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include + #define flockfile(s) _IO_flockfile (s) +@@ -37,6 +38,7 @@ extern char *__progname; + va_end (ap); \ + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + static void + convert_and_print (const char *format, __gnuc_va_list ap) + { +@@ -81,6 +83,7 @@ convert_and_print (const char *format, __gnuc_va_list ap) + + __vfwprintf (stderr, wformat, ap); + } ++#endif + + void + vwarnx (const char *format, __gnuc_va_list ap) +@@ -88,9 +91,13 @@ vwarnx (const char *format, __gnuc_va_list ap) + flockfile (stderr); + if (_IO_fwide (stderr, 0) > 0) + { ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + __fwprintf (stderr, L"%s: ", __progname); + convert_and_print (format, ap); + putwc_unlocked (L'\n', stderr); ++#else ++ abort (); ++#endif + } + else + { +@@ -111,6 +118,7 @@ vwarn (const char *format, __gnuc_va_list ap) + flockfile (stderr); + if (_IO_fwide (stderr, 0) > 0) + { ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + __fwprintf (stderr, L"%s: ", __progname); + if (format) + { +@@ -119,6 +127,9 @@ vwarn (const char *format, __gnuc_va_list ap) + } + __set_errno (error); + __fwprintf (stderr, L"%m\n"); ++#else ++ abort (); ++#endif + } + else + { +diff --git a/misc/error.c b/misc/error.c +index aaa120d..d6cbc82 100644 +--- a/misc/error.c ++++ b/misc/error.c +@@ -35,6 +35,7 @@ + #endif + + #ifdef _LIBC ++# include + # include + # include + # include +@@ -205,6 +206,7 @@ error_tail (int status, int errnum, const char *message, va_list args) + #if _LIBC + if (_IO_fwide (stderr, 0) > 0) + { ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + size_t len = strlen (message) + 1; + wchar_t *wmessage = NULL; + mbstate_t st; +@@ -265,6 +267,9 @@ error_tail (int status, int errnum, const char *message, va_list args) + + if (use_malloc) + free (wmessage); ++#else ++ abort (); ++#endif + } + else + #endif +diff --git a/misc/tst-efgcvt.c b/misc/tst-efgcvt.c +index 5083fec..79ed36c 100644 +--- a/misc/tst-efgcvt.c ++++ b/misc/tst-efgcvt.c +@@ -59,7 +59,7 @@ static testcase ecvt_tests[] = + { 123.01, -4, 3, "" }, + { 126.71, -4, 3, "" }, + { 0.0, 4, 1, "0000" }, +-#if DBL_MANT_DIG == 53 ++#if DBL_MANT_DIG == 53 && !(defined __powerpc__ && defined __NO_FPRS__ && !defined _SOFT_FLOAT && !defined _SOFT_DOUBLE) + { 0x1p-1074, 3, -323, "494" }, + { -0x1p-1074, 3, -323, "494" }, + #endif +diff --git a/nis/Makefile b/nis/Makefile +index 037e674..c967850 100644 +--- a/nis/Makefile ++++ b/nis/Makefile +@@ -18,6 +18,8 @@ + # + # Makefile for NIS/NIS+ part. + # ++include ../option-groups.mak ++ + subdir := nis + + include ../Makeconfig +@@ -30,19 +32,26 @@ endif + + # These are the databases available for the nis (and perhaps later nisplus) + # service. This must be a superset of the services in nss. +-databases = proto service hosts network grp pwd rpc ethers \ +- spwd netgrp alias publickey ++databases-y := proto service hosts network grp pwd rpc ethers \ ++ spwd netgrp publickey ++databases-$(OPTION_EGLIBC_DB_ALIASES) += alias + + # Specify rules for the nss_* modules. +-services := nis nisplus compat ++# The 'compat' module includes nis support, and the 'nss' directory ++# includes a bare-bones "files" library, so we'll include 'compat' in ++# OPTION_EGLIBC_NIS. ++services-y := ++services-$(OPTION_EGLIBC_NIS) += nis nisplus compat ++ ++extra-libs-$(OPTION_EGLIBC_NIS) += libnsl ++extra-libs-y += $(services-y:%=libnss_%) + +-extra-libs = libnsl $(services:%=libnss_%) + # These libraries will be built in the `others' pass rather than + # the `lib' pass, because they depend on libc.so being built already. +-extra-libs-others = $(extra-libs) ++extra-libs-others-y += $(extra-libs-y) + + # The sources are found in the appropriate subdir. +-subdir-dirs = $(services:%=nss_%) ++subdir-dirs = $(services-y:%=nss_%) + vpath %.c $(subdir-dirs) + + libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ +@@ -60,11 +69,11 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ + libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) + libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) + +-libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \ ++libnss_nis-routines := $(addprefix nis-,$(databases-y)) nis-initgroups \ + nss-nis + libnss_nis-inhibit-o = $(filter-out .os,$(object-suffixes)) + +-libnss_nisplus-routines := $(addprefix nisplus-,$(databases)) nisplus-parser \ ++libnss_nisplus-routines := $(addprefix nisplus-,$(databases-y)) nisplus-parser \ + nss-nisplus nisplus-initgroups + libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes)) + +@@ -80,12 +89,12 @@ libnsl-libc = $(common-objpfx)linkobj/libc.so + # Target-specific variable setting to link objects using deprecated + # RPC interfaces with the version of libc.so that makes them available + # for new links: +-$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \ ++$(services-y:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \ + libc-for-link = $(libnsl-libc) + + + ifeq ($(build-shared),yes) +-$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) ++$(others-y:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) + else +-$(others:%=$(objpfx)%): $(objpfx)libnsl.a ++$(others-y:%=$(objpfx)%): $(objpfx)libnsl.a + endif +diff --git a/nptl/Makefile b/nptl/Makefile +index aaca0a4..596ca3c 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for NPTL portion of the library. + # ++include ../option-groups.mak ++ + subdir := nptl + + include ../Makeconfig +@@ -118,7 +120,7 @@ libpthread-routines = nptl-init vars events version pt-interp \ + pt-raise pt-system \ + flockfile ftrylockfile funlockfile \ + sigaction \ +- herrno res pt-allocrtsig \ ++ pt-allocrtsig \ + pthread_kill_other_threads \ + pthread_getaffinity pthread_setaffinity \ + pthread_attr_getaffinity pthread_attr_setaffinity \ +@@ -138,8 +140,10 @@ libpthread-routines = nptl-init vars events version pt-interp \ + # pthread_setgid pthread_setegid pthread_setregid \ + # pthread_setresgid + ++libpthread-routines-$(OPTION_EGLIBC_INET) := herrno res + libpthread-shared-only-routines = version pt-interp pt-allocrtsig \ + unwind-forcedunwind ++ + libpthread-static-only-routines = pthread_atfork + + # Since cancellation handling is in large parts handled using exceptions +@@ -220,7 +224,7 @@ tests = tst-typesizes \ + tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ + tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \ + tst-mutexpi9 \ +- tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ ++ tst-spin1 tst-spin2 tst-spin3 \ + tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ + tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ + tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ +@@ -256,14 +260,14 @@ tests = tst-typesizes \ + tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \ + tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \ + tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \ +- tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \ ++ tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \ + tst-cancel-self tst-cancel-self-cancelstate \ + tst-cancel-self-canceltype tst-cancel-self-testcancel \ + tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ + tst-flock1 tst-flock2 \ + tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ + tst-signal6 tst-signal7 \ +- tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ ++ tst-exec2 tst-exec3 tst-exec4 \ + tst-exit1 tst-exit2 tst-exit3 \ + tst-stdio1 tst-stdio2 \ + tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \ +@@ -271,13 +275,12 @@ tests = tst-typesizes \ + tst-unload \ + tst-dlsym1 \ + tst-sysconf \ +- tst-locale1 tst-locale2 \ ++ tst-locale2 \ + tst-umask1 \ + tst-popen1 \ + tst-clock1 \ + tst-context1 \ + tst-sched1 \ +- tst-backtrace1 \ + tst-abstime \ + tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ + tst-getpid3 \ +@@ -288,9 +291,16 @@ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ + tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 + test-srcs = tst-oddstacklimit + +-# Test expected to fail on most targets (except x86_64) due to bug +-# 18435 - pthread_once hangs when init routine throws an exception. +-test-xfail-tst-once5 = yes ++# This test uses the posix_spawn functions. ++tests-$(OPTION_EGLIBC_SPAWN) += tst-exec1 ++ ++# This test uses the 'backtrace' functions. ++tests-$(OPTION_EGLIBC_BACKTRACE) += tst-backtrace1 ++ ++# This test is written in C++. ++tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24 ++ ++tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1 + + # Files which must not be linked with libpthread. + tests-nolibpthread = tst-unload +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index d10f4ea..14257ce 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -33,6 +33,7 @@ + #include + #include + ++#include + #include + + #include +@@ -262,8 +263,10 @@ START_THREAD_DEFN + THREAD_SETMEM (pd, cpuclock_offset, now); + #endif + ++#if __OPTION_EGLIBC_INET + /* Initialize resolver state pointer. */ + __resp = &pd->res; ++#endif + + /* Initialize pointers to locale data. */ + __ctype_init (); +@@ -346,8 +349,10 @@ START_THREAD_DEFN + /* Run the destructor for the thread-local data. */ + __nptl_deallocate_tsd (); + ++#if __OPTION_EGLIBC_INET + /* Clean up any state libc stored in thread-local variables. */ + __libc_thread_freeres (); ++#endif + + /* If this is the last thread we terminate the process now. We + do not notify the debugger, it might just irritate it if there +diff --git a/nscd/Makefile b/nscd/Makefile +index ede941d..f4f3f8d 100644 +--- a/nscd/Makefile ++++ b/nscd/Makefile +@@ -18,14 +18,17 @@ + # + # Sub-makefile for nscd portion of the library. + # ++include ../option-groups.mak ++ + subdir := nscd + + include ../Makeconfig + + ifneq ($(use-nscd),no) +-routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ ++routines-$(OPTION_EGLIBC_INET) += \ ++ nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ + nscd_initgroups nscd_getserv_r nscd_netgroup +-aux := nscd_helper ++aux-$(OPTION_EGLIBC_INET) += nscd_helper + endif + + # To find xmalloc.c +@@ -37,14 +40,18 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \ + dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ + xmalloc xstrdup aicache initgrcache gai res_hconf \ + netgroupcache +- ++ifneq (y,$(OPTION_EGLIBC_NIS)) ++# If we haven't build libnsl.so, then we'll need to include our ++# own copy of nis_hash. ++nscd-modules += nis_hash ++endif + ifeq ($(build-nscd)$(have-thread-library),yesyes) + +-others += nscd +-others-pie += nscd +-install-sbin := nscd ++others-$(OPTION_EGLIBC_INET) += nscd ++others-pie-$(OPTION_EGLIBC_INET) += nscd ++install-sbin-$(OPTION_EGLIBC_INET) += nscd + +-extra-objs = $(nscd-modules:=.o) ++extra-objs-$(OPTION_EGLIBC_INET) += $(nscd-modules:=.o) + + endif + +@@ -100,7 +107,15 @@ include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left)) + $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o) + + ifeq ($(build-shared),yes) +-$(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so ++$(objpfx)nscd: $(shared-thread-library) ++else ++$(objpfx)nscd: $(static-thread-library) ++endif ++ ++ifeq (y,$(OPTION_EGLIBC_NIS)) ++ifeq ($(build-shared),yes) ++$(objpfx)nscd: $(common-objpfx)nis/libnsl.so + else +-$(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a ++$(objpfx)nscd: $(common-objpfx)nis/libnsl.a ++endif + endif +diff --git a/nscd/nis_hash.c b/nscd/nis_hash.c +new file mode 100644 +index 0000000..d244c41 +--- /dev/null ++++ b/nscd/nis_hash.c +@@ -0,0 +1,3 @@ ++/* If OPTION_EGLIBC_NIS is disabled, nscd can't get this from libnsl.so; ++ we need our own copy. */ ++#include "../nis/nis_hash.c" +diff --git a/nss/Makefile b/nss/Makefile +index 65ab7b5..19f0aef 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -18,28 +18,35 @@ + # + # Makefile for name service switch. + # ++include ../option-groups.mak ++ + subdir := nss + + include ../Makeconfig + + headers := nss.h + +-# This is the trivial part which goes into libc itself. +-routines = nsswitch getnssent getnssent_r digits_dots \ +- $(addsuffix -lookup,$(databases)) +- + # These are the databases that go through nss dispatch. + # Caution: if you add a database here, you must add its real name + # in databases.def, too. +-databases = proto service hosts network grp pwd ethers \ +- spwd netgrp alias sgrp ++databases-y = grp pwd spwd sgrp ++databases-$(OPTION_EGLIBC_INET) \ ++ += proto service hosts network ethers \ ++ netgrp ++databases-$(OPTION_EGLIBC_DB_ALIASES) += alias ++ ++routines-$(OPTION_EGLIBC_INET) += digits_dots + + ifneq (,$(filter sunrpc,$(subdirs))) +-databases += key rpc ++databases-$(OPTION_EGLIBC_INET) += key rpc + have-sunrpc := 1 + else + have-sunrpc := 0 + endif ++# This is the trivial part which goes into libc itself. ++routines-y += nsswitch getnssent getnssent_r \ ++ $(addsuffix -lookup,$(databases-y)) ++ + CPPFLAGS-getent.c = -DHAVE_SUNRPC=$(have-sunrpc) + + others := getent makedb +@@ -47,8 +54,9 @@ install-bin := getent makedb + makedb-modules = xmalloc hash-string + extra-objs += $(makedb-modules:=.o) + +-tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent +-xtests = bug-erange ++tests = tst-nss-test1 tst-nss-getpwent ++tests-$(OPTION_EGLIBC_INET) += test-netdb test-digits-dots ++xtests-$(OPTION_EGLIBC_INET) += bug-erange + + # Specify rules for the nss_* modules. We have some services. + services := files db +@@ -63,7 +71,7 @@ subdir-dirs = $(services:%=nss_%) + vpath %.c $(subdir-dirs) ../locale/programs ../intl + + +-libnss_files-routines := $(addprefix files-,$(databases)) \ ++libnss_files-routines := $(addprefix files-,$(databases-y)) \ + files-initgroups files-have_o_cloexec files-init + + libnss_db-dbs := $(addprefix db-,\ +@@ -86,6 +94,45 @@ tests-static = tst-nss-static + tests += $(tests-static) + endif + ++ifneq ($(OPTION_EGLIBC_NSSWITCH),y) ++ ++ifndef OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG ++$(error OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG variable left unset) ++endif ++ ++ifndef OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS ++$(error OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS variable left unset) ++endif ++ ++ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG))) ++$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed config file) ++$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)) ++endif ++ ++ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS))) ++$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed functions file) ++$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)) ++endif ++ ++before-compile := $(objpfx)fixed-nsswitch.h ++generated := fixed-nsswitch.h ++$(objpfx)fixed-nsswitch.h $(objfpx)fixed-nsswitch-libs: \ ++ $(objpfx)gen-fixed-nsswitch \ ++ $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG) ++ $< $(objpfx)fixed-nsswitch.h \ ++ $(objpfx)fixed-nsswitch-libs \ ++ $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG) ++ ++$(objpfx)gen-fixed-nsswitch: gen-fixed-nsswitch.c \ ++ $(common-objpfx)option-groups.config \ ++ $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS) ++ $(native-compile) ++gen-fixed-nsswitch-CFLAGS = \ ++ -g3 -O -Wall \ ++ -I $(objpfx) \ ++ -DFIXED_FUNCTIONS='"$(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)"' ++endif ++ + include ../Rules + + ifeq (yes,$(have-selinux)) +diff --git a/nss/fixed-nsswitch.conf b/nss/fixed-nsswitch.conf +new file mode 100644 +index 0000000..91bb675 +--- /dev/null ++++ b/nss/fixed-nsswitch.conf +@@ -0,0 +1,22 @@ ++# /etc/nsswitch.conf ++# ++# Example configuration for fixed name service. ++# See the description of OPTION_EGLIBC_NSSWITCH in option-groups.def ++# for details. ++# ++ ++aliases: files ++ ++passwd: files ++group: files ++shadow: files ++ ++hosts: files dns ++networks: files dns ++ ++protocols: files ++services: files ++ethers: files ++rpc: files ++ ++netgroup: files +diff --git a/nss/fixed-nsswitch.functions b/nss/fixed-nsswitch.functions +new file mode 100644 +index 0000000..2f3fa83 +--- /dev/null ++++ b/nss/fixed-nsswitch.functions +@@ -0,0 +1,121 @@ ++/* List of functions defined for fixed NSS in GNU C Library. ++ Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++/* When OPTION_EGLIBC_NSSWITCH is disabled (see option-groups.def), ++ EGLIBC does not use the 'dlopen' and 'dlsym' functions to look for ++ database query functions in the individual name service libraries. ++ Instead, it uses a set of functions chosen at compile time, as ++ directed by the OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS file. This ++ file is a sample of what you might use there. ++ ++ This file is C source code; it should only contain invocations of ++ the following macros: ++ ++ - DEFINE_ENT (DATABASE, SERVICE, X) ++ ++ Declare the 'setXent', 'getXent_r', and 'endXent' functions that ++ query DATABASE using the service library 'libnss_SERVICE.so.2'. ++ DATABASE should be the full name of the database as it appears in ++ 'nsswitch.conf', like 'passwd' or 'aliases'. ++ ++ (The non-reentrant 'getXent' functions are implemented in terms ++ of the reentrant 'getXent_r' functions, so there is no need to ++ refer to them explicitly here.) ++ ++ - DEFINE_GETBY (DATABASE, SERVICE, X, KEY) ++ ++ Declare the 'getXbyKEY_r' functions that query DATABASE using ++ SERVICE. DATABASE and SERVICE are as described above. ++ ++ (The non-reentrant 'getXbyKEY' functions are implemented in terms ++ of the reentrant 'getXbyKEY_r' functions, so there is no need to ++ refer to them explicitly here.) ++ ++ Use the special key 'name3' for the service library function that ++ implements the 'getaddrinfo' function. ++ ++ - DEFINE_GET (DATABASE, SERVICE, QUERY) ++ ++ Declare the 'getQUERY_r' functions that query DATABASE using ++ SERVICE. This is used for functions like 'getpwnam'. ++ ++ (The non-reentrant 'getQUERY' functions are implemented in terms ++ of the reentrant 'getQUERY_r' functions, so there is no need to ++ refer to them explicitly here.) ++ ++ This sample file only includes functions that consult the files in ++ '/etc', and the Domain Name System (DNS). */ ++ ++/* aliases */ ++DEFINE_ENT (aliases, files, alias) ++DEFINE_GETBY (aliases, files, alias, name) ++ ++/* ethers */ ++DEFINE_ENT (ethers, files, ether) ++ ++/* group */ ++DEFINE_ENT (group, files, gr) ++DEFINE_GET (group, files, grgid) ++DEFINE_GET (group, files, grnam) ++ ++/* hosts */ ++DEFINE_ENT (hosts, files, host) ++DEFINE_GETBY (hosts, files, host, addr) ++DEFINE_GETBY (hosts, files, host, name) ++DEFINE_GETBY (hosts, files, host, name2) ++DEFINE_GET (hosts, files, hostton) ++DEFINE_GET (hosts, files, ntohost) ++DEFINE_GETBY (hosts, dns, host, addr) ++DEFINE_GETBY (hosts, dns, host, name) ++DEFINE_GETBY (hosts, dns, host, name2) ++DEFINE_GETBY (hosts, dns, host, name3) ++ ++/* netgroup */ ++DEFINE_ENT (netgroup, files, netgr) ++ ++/* networks */ ++DEFINE_ENT (networks, files, net) ++DEFINE_GETBY (networks, files, net, name) ++DEFINE_GETBY (networks, files, net, addr) ++DEFINE_GETBY (networks, dns, net, name) ++DEFINE_GETBY (networks, dns, net, addr) ++ ++/* protocols */ ++DEFINE_ENT (protocols, files, proto) ++DEFINE_GETBY (protocols, files, proto, name) ++DEFINE_GETBY (protocols, files, proto, number) ++ ++/* passwd */ ++DEFINE_ENT (passwd, files, pw) ++DEFINE_GET (passwd, files, pwnam) ++DEFINE_GET (passwd, files, pwuid) ++ ++/* rpc */ ++DEFINE_ENT (rpc, files, rpc) ++DEFINE_GETBY (rpc, files, rpc, name) ++DEFINE_GETBY (rpc, files, rpc, number) ++ ++/* services */ ++DEFINE_ENT (services, files, serv) ++DEFINE_GETBY (services, files, serv, name) ++DEFINE_GETBY (services, files, serv, port) ++ ++/* shadow */ ++DEFINE_ENT (shadow, files, sp) ++DEFINE_GET (shadow, files, spnam) +diff --git a/nss/gen-fixed-nsswitch.c b/nss/gen-fixed-nsswitch.c +new file mode 100644 +index 0000000..6e1c98c +--- /dev/null ++++ b/nss/gen-fixed-nsswitch.c +@@ -0,0 +1,803 @@ ++/* gen-fixed-nsswitch.c --- generate fixed name service data structures ++ Copyright (C) 1996-1999, 2001-2006, 2007 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#define _GNU_SOURCE ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "gnu/lib-names.h" ++#include "nss.h" ++ ++/* Provide a fallback definition to allow this file to be compiled outside ++ libc. */ ++#ifndef internal_function ++# define internal_function ++#endif ++ ++ ++/* Simple utilities. */ ++ ++void __attribute__ ((noreturn)) ++error (const char *message) ++{ ++ fprintf (stderr, "%s\n", message); ++ exit (1); ++} ++ ++ ++void * ++check_alloc (void *p) ++{ ++ if (p) ++ return p; ++ else ++ error ("out of memory"); ++} ++ ++void * ++xmalloc (size_t size) ++{ ++ return check_alloc (malloc (size)); ++} ++ ++ ++/* Format ARGS according to FORMAT, and return the result as a ++ malloc'ed string. */ ++char * ++saprintf (const char *format, ...) ++{ ++ va_list args; ++ size_t len; ++ char *buf; ++ ++ va_start (args, format); ++ len = vsnprintf (NULL, 0, format, args); ++ va_end (args); ++ ++ buf = xmalloc (len + 1); ++ va_start (args, format); ++ assert (len == vsnprintf (buf, len + 1, format, args)); ++ va_end (args); ++ ++ return buf; ++} ++ ++ ++ ++/* Data structures representing the configuration file in memory. */ ++ ++/* These are copied from nsswitch.h. ++ ++ We could simply #include that file, but this program runs on the ++ build machine and links against the build machine's libraries, ++ whereas that header is meant for use by target code; it uses ++ 'libc_hidden_proto', 'internal_function', and related hair. Since ++ we've copied the parsing code, we might as well copy the data ++ structure definitions as well. */ ++ ++/* Actions performed after lookup finished. */ ++typedef enum ++{ ++ NSS_ACTION_CONTINUE, ++ NSS_ACTION_RETURN ++} lookup_actions; ++ ++ ++typedef struct service_library ++{ ++ /* Name of service (`files', `dns', `nis', ...). */ ++ const char *name; ++ /* Pointer to the loaded shared library. */ ++ void *lib_handle; ++ /* And the link to the next entry. */ ++ struct service_library *next; ++} service_library; ++ ++ ++/* For mapping a function name to a function pointer. It is known in ++ nsswitch.c:nss_lookup_function that a string pointer for the lookup key ++ is the first member. */ ++typedef struct ++{ ++ const char *fct_name; ++ void *fct_ptr; ++} known_function; ++ ++ ++typedef struct service_user ++{ ++ /* And the link to the next entry. */ ++ struct service_user *next; ++ /* Action according to result. */ ++ lookup_actions actions[5]; ++ /* Link to the underlying library object. */ ++ service_library *library; ++ /* Collection of known functions. ++ ++ With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a ++ 'tsearch'-style tree. ++ ++ With OPTION_EGLIBC_NSSWITCH disabled, this is an array of ++ pointers to known_function structures, NULL-terminated. */ ++ union ++ { ++ void *tree; ++ const known_function **array; ++ } known; ++ /* Name of the service (`files', `dns', `nis', ...). */ ++ const char *name; ++} service_user; ++ ++/* To access the action based on the status value use this macro. */ ++#define nss_next_action(ni, status) ((ni)->actions[2 + status]) ++ ++ ++typedef struct name_database_entry ++{ ++ /* And the link to the next entry. */ ++ struct name_database_entry *next; ++ /* List of service to be used. */ ++ service_user *service; ++ /* Name of the database. */ ++ const char *name; ++} name_database_entry; ++ ++ ++typedef struct name_database ++{ ++ /* List of all known databases. */ ++ name_database_entry *entry; ++ /* List of libraries with service implementation. */ ++ service_library *library; ++} name_database; ++ ++ ++ ++/* Gathering the contents of the FIXED_FUNCTIONS file. */ ++ ++/* It should be possible to generate this list automatically by ++ looking at the services and databases used in the nsswitch.conf ++ file, and having a hard-coded set of queries supported on each ++ database. */ ++ ++/* We #include the FIXED_FUNCTIONS file several times to build an ++ array of function structures holding its data. */ ++enum function_kind { ++ fk_end = 0, /* Last entry. */ ++ fk_setent, /* Like setpwent. */ ++ fk_getent, /* Like getpwent. */ ++ fk_endent, /* Like endpwent. */ ++ fk_getby, /* Like gethostbyname. */ ++ fk_get /* Like getpwnam. */ ++}; ++ ++ ++struct function { ++ /* What kind of function this is. */ ++ enum function_kind kind; ++ ++ /* The database and service of the function being hardwired in. */ ++ char *database, *service; ++ ++ /* The kind of entry being queried, for 'fk_setent', 'fk_getent', ++ 'fk_endent', and 'fk_getby' functions. */ ++ char *entry; ++ ++ /* The key, for 'fk_getby' entries. */ ++ char *key; ++ ++ /* The value and key, for 'fk_get' entries. */ ++ char *value_and_key; ++}; ++ ++ ++const struct function functions[] = ++ { ++ ++#define DEFINE_ENT(database, service, entry) \ ++ { fk_setent, #database, #service, #entry }, \ ++ { fk_getent, #database, #service, #entry }, \ ++ { fk_endent, #database, #service, #entry }, ++#define DEFINE_GETBY(database, service, entry, key) \ ++ { fk_getby, #database, #service, #entry, #key }, ++#define DEFINE_GET(database, service, value_and_key) \ ++ { fk_get, #database, #service, NULL, NULL, #value_and_key }, ++ ++#include FIXED_FUNCTIONS ++ ++#undef DEFINE_ENT ++#undef DEFINE_GETBY ++#undef DEFINE_GET ++ ++ { fk_end } ++ }; ++ ++ ++/* Parsing the config file. Functions copied from nsswitch.c. */ ++ ++#define __strchrnul strchrnul ++#define __getline getline ++#define __strncasecmp strncasecmp ++ ++/* Prototypes for the local functions. */ ++static name_database *nss_parse_file (const char *fname) internal_function; ++static name_database_entry *nss_getline (char *line) internal_function; ++static service_user *nss_parse_service_list (const char *line) ++ internal_function; ++ ++static name_database * ++internal_function ++nss_parse_file (const char *fname) ++{ ++ FILE *fp; ++ name_database *result; ++ name_database_entry *last; ++ char *line; ++ size_t len; ++ ++ /* Open the configuration file. */ ++ fp = fopen (fname, "rc"); ++ if (fp == NULL) ++ return NULL; ++ ++ // /* No threads use this stream. */ ++ // __fsetlocking (fp, FSETLOCKING_BYCALLER); ++ ++ result = (name_database *) xmalloc (sizeof (name_database)); ++ ++ result->entry = NULL; ++ result->library = NULL; ++ last = NULL; ++ line = NULL; ++ len = 0; ++ do ++ { ++ name_database_entry *this; ++ ssize_t n; ++ ++ n = __getline (&line, &len, fp); ++ if (n < 0) ++ break; ++ if (line[n - 1] == '\n') ++ line[n - 1] = '\0'; ++ ++ /* Because the file format does not know any form of quoting we ++ can search forward for the next '#' character and if found ++ make it terminating the line. */ ++ *__strchrnul (line, '#') = '\0'; ++ ++ /* If the line is blank it is ignored. */ ++ if (line[0] == '\0') ++ continue; ++ ++ /* Each line completely specifies the actions for a database. */ ++ this = nss_getline (line); ++ if (this != NULL) ++ { ++ if (last != NULL) ++ last->next = this; ++ else ++ result->entry = this; ++ ++ last = this; ++ } ++ } ++ while (!feof_unlocked (fp)); ++ ++ /* Free the buffer. */ ++ free (line); ++ /* Close configuration file. */ ++ fclose (fp); ++ ++ return result; ++} ++ ++ ++/* Read the source names: ++ `( ( "[" "!"? ( "=" )+ "]" )? )*' ++ */ ++static service_user * ++internal_function ++nss_parse_service_list (const char *line) ++{ ++ service_user *result = NULL, **nextp = &result; ++ ++ while (1) ++ { ++ service_user *new_service; ++ const char *name; ++ ++ while (isspace (line[0])) ++ ++line; ++ if (line[0] == '\0') ++ /* No source specified. */ ++ return result; ++ ++ /* Read identifier. */ ++ name = line; ++ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') ++ ++line; ++ if (name == line) ++ return result; ++ ++ ++ new_service = (service_user *) xmalloc (sizeof (*new_service)); ++ new_service->name = (char *) xmalloc (line - name + 1); ++ ++ *((char *) __mempcpy ((char *) new_service->name, name, line - name)) ++ = '\0'; ++ ++ /* Set default actions. */ ++ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; ++ new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; ++ new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; ++ new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; ++ new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; ++ new_service->library = NULL; ++ new_service->known.tree = NULL; ++ new_service->next = NULL; ++ ++ while (isspace (line[0])) ++ ++line; ++ ++ if (line[0] == '[') ++ { ++ /* Read criterions. */ ++ do ++ ++line; ++ while (line[0] != '\0' && isspace (line[0])); ++ ++ do ++ { ++ int not; ++ enum nss_status status; ++ lookup_actions action; ++ ++ /* Grok ! before name to mean all statii but that one. */ ++ not = line[0] == '!'; ++ if (not) ++ ++line; ++ ++ /* Read status name. */ ++ name = line; ++ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' ++ && line[0] != ']') ++ ++line; ++ ++ /* Compare with known statii. */ ++ if (line - name == 7) ++ { ++ if (__strncasecmp (name, "SUCCESS", 7) == 0) ++ status = NSS_STATUS_SUCCESS; ++ else if (__strncasecmp (name, "UNAVAIL", 7) == 0) ++ status = NSS_STATUS_UNAVAIL; ++ else ++ return result; ++ } ++ else if (line - name == 8) ++ { ++ if (__strncasecmp (name, "NOTFOUND", 8) == 0) ++ status = NSS_STATUS_NOTFOUND; ++ else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) ++ status = NSS_STATUS_TRYAGAIN; ++ else ++ return result; ++ } ++ else ++ return result; ++ ++ while (isspace (line[0])) ++ ++line; ++ if (line[0] != '=') ++ return result; ++ do ++ ++line; ++ while (isspace (line[0])); ++ ++ name = line; ++ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' ++ && line[0] != ']') ++ ++line; ++ ++ if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) ++ action = NSS_ACTION_RETURN; ++ else if (line - name == 8 ++ && __strncasecmp (name, "CONTINUE", 8) == 0) ++ action = NSS_ACTION_CONTINUE; ++ else ++ return result; ++ ++ if (not) ++ { ++ /* Save the current action setting for this status, ++ set them all to the given action, and reset this one. */ ++ const lookup_actions save = new_service->actions[2 + status]; ++ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; ++ new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; ++ new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; ++ new_service->actions[2 + NSS_STATUS_SUCCESS] = action; ++ new_service->actions[2 + status] = save; ++ } ++ else ++ new_service->actions[2 + status] = action; ++ ++ /* Skip white spaces. */ ++ while (isspace (line[0])) ++ ++line; ++ } ++ while (line[0] != ']'); ++ ++ /* Skip the ']'. */ ++ ++line; ++ } ++ ++ *nextp = new_service; ++ nextp = &new_service->next; ++ } ++} ++ ++static name_database_entry * ++internal_function ++nss_getline (char *line) ++{ ++ const char *name; ++ name_database_entry *result; ++ size_t len; ++ ++ /* Ignore leading white spaces. ATTENTION: this is different from ++ what is implemented in Solaris. The Solaris man page says a line ++ beginning with a white space character is ignored. We regard ++ this as just another misfeature in Solaris. */ ++ while (isspace (line[0])) ++ ++line; ++ ++ /* Recognize ` ":"'. */ ++ name = line; ++ while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') ++ ++line; ++ if (line[0] == '\0' || name == line) ++ /* Syntax error. */ ++ return NULL; ++ *line++ = '\0'; ++ ++ len = strlen (name) + 1; ++ ++ result = (name_database_entry *) xmalloc (sizeof (*result)); ++ result->name = (char *) xmalloc (len); ++ ++ /* Save the database name. */ ++ memcpy ((char *) result->name, name, len); ++ ++ /* Parse the list of services. */ ++ result->service = nss_parse_service_list (line); ++ ++ result->next = NULL; ++ return result; ++} ++ ++ ++ ++/* Generating code for statically initialized nsswitch structures. */ ++ ++ ++/* Return the service-neutral suffix of the name of the service ++ library function referred to by the function F. The result is ++ allocated with malloc. */ ++char * ++known_function_suffix (const struct function *f) ++{ ++ switch (f->kind) ++ { ++ case fk_setent: ++ return saprintf ("set%sent", f->entry); ++ ++ case fk_getent: ++ return saprintf ("get%sent_r", f->entry); ++ ++ case fk_endent: ++ return saprintf ("end%sent", f->entry); ++ ++ case fk_getby: ++ return saprintf ("get%sby%s_r", f->entry, f->key); ++ ++ case fk_get: ++ return saprintf ("get%s_r", f->value_and_key); ++ ++ default: ++ abort (); ++ } ++} ++ ++ ++/* Return the name of the service library function referred to by the ++ function F. The result is allocated with malloc. */ ++char * ++known_function_name (const struct function *f) ++{ ++ return saprintf ("_nss_%s_%s", f->service, known_function_suffix (f)); ++} ++ ++ ++/* Write initialized known_function structures to OUT for ++ all the functions we'll use. */ ++void ++generate_known_functions (FILE *out) ++{ ++ int i; ++ ++ /* First, generate weak references to the functions. The service ++ libraries depend on libc, and if these references weren't weak, ++ we'd be making libc depend circularly on the service ++ libraries. */ ++ for (i = 0; functions[i].kind; i++) ++ { ++ char *name = known_function_name (&functions[i]); ++ fprintf (out, "typeof (%s) %s __attribute__ ((weak));\n", ++ name, name); ++ } ++ fputs ("\n", out); ++ ++ /* Then, a table mapping names to functions. */ ++ fputs ("static const known_function fixed_known_functions[] = {\n", ++ out); ++ for (i = 0; functions[i].kind; i++) ++ { ++ const struct function *f = &functions[i]; ++ char *suffix = known_function_suffix (f); ++ ++ fprintf (out, " /* %2d */ { \"%s\", _nss_%s_%s },\n", ++ i, suffix, f->service, suffix); ++ } ++ fputs ("};\n", out); ++ fputs ("\n", out); ++} ++ ++ ++/* Print code to OUT for an initialized array of pointers to the ++ 'known_function' structures needed for USER, which is for ++ DATABASE. Return its name, allocated with malloc. */ ++char * ++generate_known_function_list (FILE *out, ++ const name_database_entry *database, ++ const service_user *user) ++{ ++ char *list_name = saprintf ("fixed_%s_%s_known_funcs", ++ database->name, user->name); ++ fprintf (out, "static const known_function *%s[] = {\n", ++ list_name); ++ int i; ++ for (i = 0; functions[i].kind; i++) ++ if (strcmp (functions[i].database, database->name) == 0 ++ && strcmp (functions[i].service, user->name) == 0) ++ fprintf (out, " &fixed_known_functions[%d], /* %s */\n", ++ i, known_function_name (&functions[i])); ++ fputs (" NULL\n", out); ++ fputs ("};\n", out); ++ fputs ("\n", out); ++ ++ return list_name; ++} ++ ++ ++/* Return the name of the status value STATUS, as a statically ++ allocated string. */ ++const char * ++lookup_status_name (enum nss_status status) ++{ ++ switch (status) ++ { ++ case NSS_STATUS_TRYAGAIN: return "NSS_STATUS_TRYAGAIN"; ++ case NSS_STATUS_UNAVAIL: return "NSS_STATUS_UNAVAIL"; ++ case NSS_STATUS_NOTFOUND: return "NSS_STATUS_NOTFOUND"; ++ case NSS_STATUS_SUCCESS: return "NSS_STATUS_SUCCESS"; ++ case NSS_STATUS_RETURN: return "NSS_STATUS_RETURN"; ++ default: abort (); ++ }; ++} ++ ++ ++/* Return the name of ACTION as a statically allocated string. */ ++const char * ++lookup_action_name (lookup_actions action) ++{ ++ switch (action) ++ { ++ case NSS_ACTION_CONTINUE: return "NSS_ACTION_CONTINUE"; ++ case NSS_ACTION_RETURN: return "NSS_ACTION_RETURN"; ++ default: abort (); ++ } ++} ++ ++ ++/* Print code to OUT for the list of service_user structures starting ++ with USER, which are all for DATABASE. Return the name of the ++ first structure in that list, or zero if USER is NULL. */ ++char * ++generate_service_user_list (FILE *out, ++ name_database_entry *database, ++ service_user *user) ++{ ++ if (user) ++ { ++ /* Generate the tail of the list. */ ++ char *next_name = generate_service_user_list (out, database, user->next); ++ /* Generate our known function list. */ ++ char *known_function_list_name = ++ generate_known_function_list (out, database, user); ++ ++ char *name = saprintf ("fixed_%s_%s_user", database->name, user->name); ++ ++ fprintf (out, "static const service_user %s = {\n", name); ++ if (next_name) ++ fprintf (out, " (service_user *) &%s,\n", next_name); ++ else ++ fprintf (out, " NULL, /* no next entry */\n"); ++ fputs (" {\n", out); ++ int i; ++ for (i = 0; i < sizeof (user->actions) / sizeof (user->actions[0]); i++) ++ fprintf (out, " %s, /* %s */\n", ++ lookup_action_name (user->actions[i]), ++ lookup_status_name (i - 2)); ++ fputs (" },\n", out); ++ fprintf (out, " NULL, /* we never need the service library */\n"); ++ fprintf (out, " { .array = %s },\n", known_function_list_name); ++ fprintf (out, " \"%s\"\n", user->name); ++ fputs ("};\n", out); ++ fputs ("\n", out); ++ ++ return name; ++ } ++ else ++ return NULL; ++} ++ ++ ++/* Print code to OUT for the list of name_database_entry structures ++ starting with DATABASE. Return the name of the first structure ++ in that list, or zero if DATABASE is NULL. */ ++char * ++generate_name_database_entries (FILE *out, name_database_entry *database) ++{ ++ if (database) ++ { ++ char *next_name = generate_name_database_entries (out, database->next); ++ char *service_user_name ++ = generate_service_user_list (out, database, database->service); ++ char *name = saprintf ("fixed_%s_name_database", database->name); ++ ++ fprintf (out, "static const name_database_entry %s = {\n", name); ++ ++ if (next_name) ++ fprintf (out, " (name_database_entry *) &%s,\n", next_name); ++ else ++ fprintf (out, " NULL,\n"); ++ ++ if (service_user_name) ++ fprintf (out, " (service_user *) &%s,\n", service_user_name); ++ else ++ fprintf (out, " NULL,\n"); ++ ++ fprintf (out, " \"%s\"\n", database->name); ++ fprintf (out, "};\n"); ++ fputs ("\n", out); ++ ++ return name; ++ } ++ else ++ return NULL; ++} ++ ++ ++void ++generate_name_database (FILE *out, name_database *service_table) ++{ ++ /* Produce a linked list of the known name_database_entry ++ structures. */ ++ char *entries = generate_name_database_entries (out, service_table->entry); ++ ++ /* Now produce the main structure that points to them all. */ ++ fprintf (out, "static const name_database fixed_name_database = {\n"); ++ if (entries) ++ fprintf (out, " (name_database_entry *) &%s,\n", entries); ++ else ++ fprintf (out, " NULL,\n"); ++ fputs (" NULL /* we don't need the libraries */\n" ++ "};\n", ++ out); ++} ++ ++ ++ ++/* Generating the list of service libraries we generate references to. */ ++ ++/* String with revision number of the shared object files. */ ++static const char *const nss_shlib_revision = LIBNSS_FILES_SO + 15; ++ ++void ++generate_service_lib_list (FILE *out, name_database *service_table) ++{ ++ int i, j; ++ int printed_any = 0; ++ ++ for (i = 0; functions[i].kind; i++) ++ { ++ /* Mention each service library only once. */ ++ for (j = 0; j < i; j++) ++ if (strcmp (functions[i].service, functions[j].service) == 0) ++ break; ++ ++ if (j >= i) ++ { ++ if (printed_any) ++ putc (' ', out); ++ fprintf (out, "-lnss_%s", ++ functions[i].service, ++ nss_shlib_revision); ++ printed_any = 1; ++ } ++ } ++} ++ ++ ++/* Main. */ ++ ++int ++main (int argc, char **argv) ++{ ++ if (argc != 4) ++ { ++ fprintf (stderr, "usage: gen-fixed-nsswitch HEADER SERVLIBS CONFIG\n"); ++ exit (1); ++ } ++ ++ name_database *service_table = nss_parse_file (argv[3]); ++ ++ FILE *header = fopen (argv[1], "w"); ++ if (! header) ++ { ++ fprintf (stderr, ++ "gen-fixed-nsswitch: couldn't open output file %s: %s\n", ++ argv[1], strerror (errno)); ++ exit (1); ++ } ++ fputs ("/* Generated by nss/gen-fixed-nsswitch.c. */\n", header); ++ fputs ("\n", header); ++ generate_known_functions (header); ++ generate_name_database (header, service_table); ++ fclose (header); ++ ++ FILE *service_lib_list = fopen (argv[2], "w"); ++ if (! service_lib_list) ++ { ++ fprintf (stderr, ++ "gen-fixed-nsswitch: couldn't open output file %s: %s\n", ++ argv[2], strerror (errno)); ++ exit (1); ++ } ++ generate_service_lib_list (service_lib_list, service_table); ++ fclose (service_lib_list); ++ ++ return 0; ++} +diff --git a/nss/getent.c b/nss/getent.c +index 34df848..674c8ee 100644 +--- a/nss/getent.c ++++ b/nss/getent.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + /* Get libc version number. */ + #include +@@ -91,6 +92,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ + fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk"); + } + ++#if __OPTION_EGLIBC_DB_ALIASES + /* This is for aliases */ + static void + print_aliases (struct aliasent *alias) +@@ -135,7 +137,9 @@ aliases_keys (int number, char *key[]) + + return result; + } ++#endif /* __OPTION_EGLIBC_DB_ALIASES */ + ++#if __OPTION_EGLIBC_INET + /* This is for ethers */ + static int + ethers_keys (int number, char *key[]) +@@ -179,6 +183,7 @@ ethers_keys (int number, char *key[]) + + return result; + } ++#endif /* __OPTION_EGLIBC_INET */ + + /* This is for group */ + static void +@@ -301,6 +306,7 @@ gshadow_keys (int number, char *key[]) + return result; + } + ++#if __OPTION_EGLIBC_INET + /* This is for hosts */ + static void + print_hosts (struct hostent *host) +@@ -598,6 +604,7 @@ networks_keys (int number, char *key[]) + + return result; + } ++#endif /* __OPTION_EGLIBC_INET */ + + /* Now is all for passwd */ + static void +@@ -650,6 +657,7 @@ passwd_keys (int number, char *key[]) + return result; + } + ++#if __OPTION_EGLIBC_INET + /* This is for protocols */ + static void + print_protocols (struct protoent *proto) +@@ -807,6 +815,7 @@ services_keys (int number, char *key[]) + + return result; + } ++#endif /* __OPTION_EGLIBC_INET */ + + /* This is for shadow */ + static void +@@ -873,23 +882,36 @@ struct + } databases[] = + { + #define D(name) { #name, name ## _keys }, +-D(ahosts) +-D(ahostsv4) +-D(ahostsv6) +-D(aliases) +-D(ethers) ++ ++#if __OPTION_EGLIBC_INET ++# define DN(name) D(name) ++#else ++# define DN(name) ++#endif ++ ++#if __OPTION_EGLIBC_DB_ALIASES ++# define DA(name) D(name) ++#else ++# define DA(name) ++#endif ++ ++DN(ahosts) ++DN(ahostsv4) ++DN(ahostsv6) ++DA(aliases) ++DN(ethers) + D(group) + D(gshadow) +-D(hosts) +-D(initgroups) +-D(netgroup) +-D(networks) ++DN(hosts) ++DN(initgroups) ++DN(netgroup) ++DN(networks) + D(passwd) +-D(protocols) ++DN(protocols) + #if HAVE_SUNRPC +-D(rpc) ++DN(rpc) + #endif +-D(services) ++DN(services) + D(shadow) + #undef D + { NULL, NULL } +diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c +index f5b9036..f09f7fe 100644 +--- a/nss/getnssent_r.c ++++ b/nss/getnssent_r.c +@@ -16,6 +16,7 @@ + . */ + + #include ++#include + #include + #include "nsswitch.h" + +@@ -59,11 +60,13 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct, + } fct; + int no_more; + ++#if __OPTION_EGLIBC_INET + if (res && __res_maybe_init (&_res, 0) == -1) + { + __set_h_errno (NETDB_INTERNAL); + return; + } ++#endif /* __OPTION_EGLIBC_INET */ + + /* Cycle through the services and run their `setXXent' functions until + we find an available service. */ +@@ -101,11 +104,13 @@ __nss_endent (const char *func_name, db_lookup_function lookup_fct, + } fct; + int no_more; + ++#if __OPTION_EGLIBC_INET + if (res && __res_maybe_init (&_res, 0) == -1) + { + __set_h_errno (NETDB_INTERNAL); + return; + } ++#endif /* __OPTION_EGLIBC_INET */ + + /* Cycle through all the services and run their endXXent functions. */ + no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1); +@@ -141,12 +146,14 @@ __nss_getent_r (const char *getent_func_name, + int no_more; + enum nss_status status; + ++#if __OPTION_EGLIBC_INET + if (res && __res_maybe_init (&_res, 0) == -1) + { + *h_errnop = NETDB_INTERNAL; + *result = NULL; + return errno; + } ++#endif /* __OPTION_EGLIBC_INET */ + + /* Initialize status to return if no more functions are found. */ + status = NSS_STATUS_NOTFOUND; +@@ -161,7 +168,7 @@ __nss_getent_r (const char *getent_func_name, + int is_last_nip = *nip == *last_nip; + + status = DL_CALL_FCT (fct.f, +- (resbuf, buffer, buflen, &errno, &h_errno)); ++ (resbuf, buffer, buflen, &errno, h_errnop)); + + /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the + provided buffer is too small. In this case we should give +diff --git a/nss/nsswitch.c b/nss/nsswitch.c +index 9712623..c81e207 100644 +--- a/nss/nsswitch.c ++++ b/nss/nsswitch.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -41,6 +42,15 @@ + #include "../nscd/nscd_proto.h" + #include + ++/* When OPTION_EGLIBC_NSSWITCH is disabled, we use fixed tables of ++ databases and services, generated at library build time. Thus: ++ - We can't reconfigure individual databases, so we don't need a ++ name-to-database map. ++ - We never add databases or service libraries, or look up functions ++ at runtime, so there's no need for a lock to protect our tables. ++ See ../option-groups.def for the details. */ ++#if __OPTION_EGLIBC_NSSWITCH ++ + /* Prototypes for the local functions. */ + static name_database *nss_parse_file (const char *fname) internal_function; + static name_database_entry *nss_getline (char *line) internal_function; +@@ -79,6 +89,9 @@ bool __nss_database_custom[NSS_DBSIDX_max]; + + __libc_lock_define_initialized (static, lock) + ++#define lock_nsswitch __libc_lock_lock (lock) ++#define unlock_nsswitch __libc_lock_unlock (lock) ++ + #if !defined DO_STATIC_NSS || defined SHARED + /* String with revision number of the shared object files. */ + static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15; +@@ -93,6 +106,20 @@ static name_database *service_table; + __libc_freeres. */ + static name_database_entry *defconfig_entries; + ++#else /* __OPTION_EGLIBC_NSSWITCH */ ++ ++/* Bring in the statically initialized service table we generated at ++ build time. */ ++#include "fixed-nsswitch.h" ++ ++const static name_database *service_table = &fixed_name_database; ++ ++/* Nothing ever changes, so there's no need to lock anything. */ ++#define lock_nsswitch (0) ++#define unlock_nsswitch (0) ++ ++#endif /* __OPTION_EGLIBC_NSSWITCH */ ++ + + #ifdef USE_NSCD + /* Nonzero if this is the nscd process. */ +@@ -109,20 +136,22 @@ __nss_database_lookup (const char *database, const char *alternate_name, + const char *defconfig, service_user **ni) + { + /* Prevent multiple threads to change the service table. */ +- __libc_lock_lock (lock); ++ lock_nsswitch; + + /* Reconsider database variable in case some other thread called + `__nss_configure_lookup' while we waited for the lock. */ + if (*ni != NULL) + { +- __libc_lock_unlock (lock); ++ unlock_nsswitch; + return 0; + } + ++#if __OPTION_EGLIBC_NSSWITCH + /* Are we initialized yet? */ + if (service_table == NULL) + /* Read config file. */ + service_table = nss_parse_file (_PATH_NSSWITCH_CONF); ++#endif + + /* Test whether configuration data is available. */ + if (service_table != NULL) +@@ -144,6 +173,7 @@ __nss_database_lookup (const char *database, const char *alternate_name, + *ni = entry->service; + } + ++#if __OPTION_EGLIBC_NSSWITCH + /* No configuration data is available, either because nsswitch.conf + doesn't exist or because it doesn't have a line for this database. + +@@ -166,13 +196,23 @@ __nss_database_lookup (const char *database, const char *alternate_name, + { + entry->next = defconfig_entries; + entry->service = *ni; +- entry->name[0] = '\0'; ++ entry->name = ""; + defconfig_entries = entry; + } + } + } ++#else ++ /* Without the dynamic behavior, we can't process defconfig. The ++ databases the user specified at library build time are all you ++ get. */ ++ if (*ni == NULL) ++ { ++ unlock_nsswitch; ++ return -1; ++ } ++#endif + +- __libc_lock_unlock (lock); ++ unlock_nsswitch; + + return *ni != NULL ? 0 : -1; + } +@@ -252,6 +292,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, + libc_hidden_def (__nss_next2) + + ++#if __OPTION_EGLIBC_NSSWITCH + int + attribute_compat_text_section + __nss_next (service_user **ni, const char *fct_name, void **fctp, int status, +@@ -300,13 +341,13 @@ __nss_configure_lookup (const char *dbname, const char *service_line) + } + + /* Prevent multiple threads to change the service table. */ +- __libc_lock_lock (lock); ++ lock_nsswitch; + + /* Install new rules. */ + *databases[cnt].dbp = new_db; + __nss_database_custom[cnt] = true; + +- __libc_lock_unlock (lock); ++ unlock_nsswitch; + + return 0; + } +@@ -402,7 +443,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name) + void **found, *result; + + /* We now modify global data. Protect it. */ +- __libc_lock_lock (lock); ++ lock_nsswitch; + + /* Search the tree of functions previously requested. Data in the + tree are `known_function' structures, whose first member is a +@@ -413,7 +454,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name) + enough to a pointer to our structure to use as a lookup key that + will be passed to `known_compare' (above). */ + +- found = __tsearch (&fct_name, &ni->known, &known_compare); ++ found = __tsearch (&fct_name, &ni->known.tree, &known_compare); + if (found == NULL) + /* This means out-of-memory. */ + result = NULL; +@@ -440,7 +481,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name) + #endif + /* Oops. We can't instantiate this node properly. + Remove it from the tree. */ +- __tdelete (&fct_name, &ni->known, &known_compare); ++ __tdelete (&fct_name, &ni->known.tree, &known_compare); + free (known); + result = NULL; + } +@@ -520,13 +561,43 @@ __nss_lookup_function (service_user *ni, const char *fct_name) + } + + /* Remove the lock. */ +- __libc_lock_unlock (lock); ++ unlock_nsswitch; + + return result; + } + libc_hidden_def (__nss_lookup_function) + + ++#else /* below if ! __OPTION_EGLIBC_NSSWITCH */ ++ ++ ++int ++__nss_configure_lookup (const char *dbname, const char *service_line) ++{ ++ /* We can't dynamically configure lookup without ++ OPTION_EGLIBC_NSSWITCH. */ ++ __set_errno (EINVAL); ++ return -1; ++} ++ ++ ++void * ++__nss_lookup_function (service_user *ni, const char *fct_name) ++{ ++ int i; ++ const known_function **known = ni->known.array; ++ ++ for (i = 0; known[i]; i++) ++ if (strcmp (fct_name, known[i]->fct_name) == 0) ++ return known[i]->fct_ptr; ++ ++ return NULL; ++} ++libc_hidden_def (__nss_lookup_function) ++#endif ++ ++ ++#if __OPTION_EGLIBC_NSSWITCH + static name_database * + internal_function + nss_parse_file (const char *fname) +@@ -632,8 +703,10 @@ nss_parse_service_list (const char *line) + + (line - name + 1)); + if (new_service == NULL) + return result; ++ new_service->name = (char *) (new_service + 1); + +- *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; ++ *((char *) __mempcpy ((char *) new_service->name, name, line - name)) ++ = '\0'; + + /* Set default actions. */ + new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; +@@ -642,7 +715,7 @@ nss_parse_service_list (const char *line) + new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; + new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; + new_service->library = NULL; +- new_service->known = NULL; ++ new_service->known.tree = NULL; + new_service->next = NULL; + + while (isspace (line[0])) +@@ -778,9 +851,10 @@ nss_getline (char *line) + result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); + if (result == NULL) + return NULL; ++ result->name = (char *) (result + 1); + + /* Save the database name. */ +- memcpy (result->name, name, len); ++ memcpy ((char *) result->name, name, len); + + /* Parse the list of services. */ + result->service = nss_parse_service_list (line); +@@ -816,6 +890,7 @@ nss_new_service (name_database *database, const char *name) + return *currentp; + } + #endif ++#endif /* __OPTION_EGLIBC_NSSWITCH */ + + + #if defined SHARED && defined USE_NSCD +@@ -834,6 +909,7 @@ nss_load_all_libraries (const char *service, const char *def) + } + + ++#if __OPTION_EGLIBC_INET + /* Called by nscd and nscd alone. */ + void + __nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) +@@ -857,8 +933,10 @@ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) + __nss_not_use_nscd_services = -1; + __nss_not_use_nscd_netgroup = -1; + } ++#endif /* __OPTION_EGLIBC_INET */ + #endif + ++#if __OPTION_EGLIBC_NSSWITCH + static void + free_database_entries (name_database_entry *entry) + { +@@ -871,8 +949,8 @@ free_database_entries (name_database_entry *entry) + { + service_user *olds = service; + +- if (service->known != NULL) +- __tdestroy (service->known, free); ++ if (service->known.tree != NULL) ++ __tdestroy (service->known.tree, free); + + service = service->next; + free (olds); +@@ -926,3 +1004,4 @@ libc_freeres_fn (free_mem) + + free (top); + } ++#endif /* __OPTION_EGLIBC_NSSWITCH */ +diff --git a/nss/nsswitch.h b/nss/nsswitch.h +index a5318fa..1730977 100644 +--- a/nss/nsswitch.h ++++ b/nss/nsswitch.h +@@ -65,10 +65,20 @@ typedef struct service_user + lookup_actions actions[5]; + /* Link to the underlying library object. */ + service_library *library; +- /* Collection of known functions. */ +- void *known; ++ /* Collection of known functions. ++ ++ With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a ++ 'tsearch'-style tree. ++ ++ With OPTION_EGLIBC_NSSWITCH disabled, this is an array of ++ pointers to known_function structures, NULL-terminated. */ ++ union ++ { ++ void *tree; ++ const known_function **array; ++ } known; + /* Name of the service (`files', `dns', `nis', ...). */ +- char name[0]; ++ const char *name; + } service_user; + + /* To access the action based on the status value use this macro. */ +@@ -82,7 +92,7 @@ typedef struct name_database_entry + /* List of service to be used. */ + service_user *service; + /* Name of the database. */ +- char name[0]; ++ const char *name; + } name_database_entry; + + +diff --git a/posix/Makefile b/posix/Makefile +index 15e8818..609ed03 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for POSIX portion of the library. + # ++include ../option-groups.mak ++ + subdir := posix + + include ../Makeconfig +@@ -43,13 +45,24 @@ routines := \ + getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \ + getresuid getresgid setresuid setresgid \ + pathconf sysconf fpathconf \ +- glob glob64 fnmatch regex \ ++ glob glob64 fnmatch \ + confstr \ + getopt getopt1 getopt_init \ + sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \ + sched_primin sched_rr_gi sched_getaffinity sched_setaffinity \ +- getaddrinfo gai_strerror wordexp \ + pread pwrite pread64 pwrite64 \ ++ posix_madvise \ ++ get_child_max sched_cpucount sched_cpualloc sched_cpufree ++ ++routines-$(OPTION_EGLIBC_INET) += getaddrinfo gai_strerror ++ ++ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC)) ++routines-$(OPTION_POSIX_REGEXP) += regex ++else ++routines-$(OPTION_POSIX_REGEXP) += xregex ++endif ++ ++routines-$(OPTION_EGLIBC_SPAWN) += \ + spawn_faction_init spawn_faction_destroy spawn_faction_addclose \ + spawn_faction_addopen spawn_faction_adddup2 \ + spawnattr_init spawnattr_destroy \ +@@ -61,37 +74,54 @@ routines := \ + posix_madvise \ + get_child_max sched_cpucount sched_cpualloc sched_cpufree + ++routines-$(OPTION_EGLIBC_WORDEXP) += wordexp ++ + aux := init-posix environ +-tests := tstgetopt testfnm runtests runptests \ ++tests := tstgetopt testfnm runtests \ + tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \ +- tst-mmap tst-getaddrinfo tst-truncate \ +- tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \ +- tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \ +- tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \ +- bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \ +- bug-regex13 bug-regex14 bug-regex15 bug-regex16 \ +- bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ +- bug-regex21 bug-regex22 bug-regex23 bug-regex24 \ +- bug-regex25 bug-regex26 bug-regex27 bug-regex28 \ ++ tst-mmap tst-truncate \ ++ tst-truncate64 tst-fork tst-dir \ ++ tst-chmod bug-regex2 bug-regex3 bug-regex4 \ ++ tst-gnuglob bug-regex6 bug-regex7 \ ++ bug-regex8 bug-regex9 bug-regex10 bug-regex12 \ ++ bug-regex14 bug-regex15 \ ++ bug-regex21 bug-regex24 \ ++ bug-regex27 bug-regex28 \ + bug-regex29 bug-regex30 bug-regex31 bug-regex32 \ +- bug-regex33 tst-nice tst-nanosleep tst-regex2 \ +- transbug tst-rxspencer tst-pcre tst-boost \ +- bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \ +- tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \ ++ tst-nice tst-nanosleep \ ++ transbug \ ++ tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \ ++ bug-glob1 bug-glob2 bug-glob3 tst-sysconf \ + tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \ + tst-execv1 tst-execv2 tst-execl1 tst-execl2 \ + tst-execve1 tst-execve2 tst-execle1 tst-execle2 \ +- tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \ +- tst-rfc3484-3 \ +- tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \ ++ tst-execvp3 tst-execvp4 \ ++ tst-fnmatch2 tst-cpucount tst-cpuset \ + bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ + bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ + tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ + tst-fnmatch3 bug-regex36 tst-getaddrinfo5 +-xtests := bug-ga2 ++ ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \ ++ bug-regex23 bug-regex25 bug-regex32 bug-regex33 ++tests-$(OPTION_EGLIBC_INET) \ ++ += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \ ++ tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 tst-getaddrinfo3 ++tests-$(OPTION_POSIX_REGEXP_GLIBC) \ ++ += runptests bug-regex11 bug-regex13 bug-regex16 \ ++ tst-regex2 tst-rxspencer tst-pcre tst-boost ++ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP_GLIBC)) ++tests += tst-regex bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ ++ bug-regex22 bug-regex26 ++endif ++xtests-$(OPTION_EGLIBC_INET) += bug-ga2 ++ + ifeq (yes,$(build-shared)) + test-srcs := globtest +-tests += wordexp-test tst-exec tst-spawn ++tests += tst-exec ++tests-$(OPTION_EGLIBC_SPAWN) += tst-spawn ++tests-$(OPTION_EGLIBC_WORDEXP) += wordexp-test + endif + tests-static = tst-exec-static tst-spawn-static + tests += $(tests-static) +@@ -117,7 +147,10 @@ generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \ + + ifeq ($(run-built-tests),yes) + ifeq (yes,$(build-shared)) +-tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out ++tests-special += $(objpfx)globtest.out ++ifeq (y,$(OPTION_EGLIBC_WORDEXP)) ++tests-special += $(objpfx)wordexp-tst.out ++endif + endif + endif + +@@ -125,12 +158,16 @@ endif + # XXX Please note that for now we ignore the result of this test. + tests-special += $(objpfx)annexc.out + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \ ++tests-special += $(objpfx)bug-regex2-mem.out \ + $(objpfx)bug-regex21-mem.out $(objpfx)bug-regex31-mem.out \ +- $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \ +- $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \ ++ $(objpfx)tst-getconf.out \ + $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \ + $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out ++ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC)) ++tests-special += $(objpfx)bug-regex14-mem.out $(objpfx)tst-rxspencer-no-utf8-mem.out \ ++ $(objpfx)tst-pcre-mem.out $(objpfx)tst-boost-mem.out ++endif ++ + xtests-special += $(objpfx)bug-ga2-mem.out + endif + +@@ -143,6 +180,8 @@ $(objpfx)globtest.out: globtest.sh $(objpfx)globtest + $(SHELL) $< $(common-objpfx) '$(test-via-rtld-prefix)' \ + '$(test-program-prefix)' '$(test-wrapper-env)'; \ + $(evaluate-test) ++LDLIBS-globtest += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs) ++ + $(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test + $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \ + '$(run-program-env)' '$(test-program-prefix-after-env)'; \ +@@ -205,7 +244,10 @@ tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); + tst-chmod-ARGS = $(objdir) + tst-vfork3-ARGS = --test-dir=$(objpfx) + +-tst-rxspencer-ARGS = --utf8 rxspencer/tests ++tst-rxspencer-ARGS = rxspencer/tests ++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) ++tst-rxspencer-ARGS += --utf8 ++endif + tst-rxspencer-no-utf8-ARGS = rxspencer/tests + tst-pcre-ARGS = PCRE.tests + tst-boost-ARGS = BOOST.tests +diff --git a/posix/bug-regex1.c b/posix/bug-regex1.c +index 38eb543..17cd1a0 100644 +--- a/posix/bug-regex1.c ++++ b/posix/bug-regex1.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + int + main (void) +@@ -17,7 +18,9 @@ main (void) + memset (®ex, '\0', sizeof (regex)); + + setlocale (LC_ALL, "de_DE.ISO-8859-1"); ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + fwide (stdout, -1); ++#endif + + re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_DEBUG); + +diff --git a/posix/bug-regex6.c b/posix/bug-regex6.c +index efcc890..3b270c7 100644 +--- a/posix/bug-regex6.c ++++ b/posix/bug-regex6.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + + int +@@ -30,7 +31,12 @@ main (int argc, char *argv[]) + regex_t re; + regmatch_t mat[10]; + int i, j, ret = 0; +- const char *locales[] = { "C", "de_DE.UTF-8" }; ++ const char *locales[] = { ++ "C", ++#if __OPTION_EGLIBC_LOCALE_CODE ++ "de_DE.UTF-8" ++#endif ++ }; + const char *string = "http://www.regex.com/pattern/matching.html#intro"; + regmatch_t expect[10] = { + { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 }, +diff --git a/posix/fnmatch.c b/posix/fnmatch.c +index fd85efa..01cc9fe 100644 +--- a/posix/fnmatch.c ++++ b/posix/fnmatch.c +@@ -30,6 +30,10 @@ + #include + #include + ++#if defined _LIBC ++# include ++#endif ++ + #if defined STDC_HEADERS || defined _LIBC + # include + #endif +@@ -131,7 +135,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); + # define ISWCTYPE(WC, WT) iswctype (WC, WT) + # endif + +-# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC ++# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS && _LIBC && __OPTION_EGLIBC_LOCALE_CODE) + /* In this case we are implementing the multibyte character handling. */ + # define HANDLE_MULTIBYTE 1 + # endif +diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c +index f46c9df..74e1754 100644 +--- a/posix/fnmatch_loop.c ++++ b/posix/fnmatch_loop.c +@@ -15,6 +15,8 @@ + License along with the GNU C Library; if not, see + . */ + ++#include ++ + #include + + struct STRUCT +@@ -54,10 +56,15 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); + # else ++# if __OPTION_EGLIBC_LOCALE_CODE + const UCHAR *collseq = (const UCHAR *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +-# endif +-#endif ++# define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)]) ++# else ++# define COLLSEQ_BYTE_LOOKUP(ix) (ix) ++# endif /* __OPTION_EGLIBC_LOCALE_CODE */ ++# endif /* WIDE_CHAR_VERSION */ ++#endif /* _LIBC */ + + while ((c = *p++) != L('\0')) + { +@@ -277,7 +284,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + /* Leave room for the null. */ + CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) ++#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; + #endif + const CHAR *startp = p; +@@ -307,7 +314,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + } + str[c1] = L('\0'); + +-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) ++#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ +@@ -680,8 +687,10 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + else + lcollseq = __collseq_table_lookup (collseq, cold); + # else +- fcollseq = collseq[fn]; +- lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; ++ fcollseq = COLLSEQ_BYTE_LOOKUP (fn); ++ lcollseq = (is_seqval ++ ? cold ++ : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold)); + # endif + + is_seqval = 0; +@@ -857,7 +866,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + goto matched; + } + # else +- hcollseq = collseq[cend]; ++ hcollseq = COLLSEQ_BYTE_LOOKUP (cend); + # endif + } + +diff --git a/posix/glob.c b/posix/glob.c +index d65e55d..1ac00a1 100644 +--- a/posix/glob.c ++++ b/posix/glob.c +@@ -25,6 +25,9 @@ + #include + #include + #include ++#ifdef _LIBC ++# include ++#endif + + /* Outcomment the following line for production quality code. */ + /* #define NDEBUG 1 */ +@@ -607,6 +610,7 @@ glob (pattern, flags, errfunc, pglob) + if (home_dir == NULL || home_dir[0] == '\0') + home_dir = "c:/users/default"; /* poor default */ + # else ++# if ! _LIBC || __OPTION_EGLIBC_GETLOGIN + if (home_dir == NULL || home_dir[0] == '\0') + { + int success; +@@ -623,19 +627,19 @@ glob (pattern, flags, errfunc, pglob) + if (success) + { + struct passwd *p; +-# if defined HAVE_GETPWNAM_R || defined _LIBC ++# if defined HAVE_GETPWNAM_R || defined _LIBC + long int pwbuflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int malloc_pwtmpbuf = 0; + int save = errno; + +-# ifndef _LIBC ++# ifndef _LIBC + if (pwbuflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. + Try a moderate value. */ + pwbuflen = 1024; +-# endif ++# endif + if (__libc_use_alloca (alloca_used + pwbuflen)) + pwtmpbuf = alloca_account (pwbuflen, alloca_used); + else +@@ -682,9 +686,9 @@ glob (pattern, flags, errfunc, pglob) + } + __set_errno (save); + } +-# else ++# else + p = getpwnam (name); +-# endif ++# endif + if (p != NULL) + { + if (!malloc_pwtmpbuf) +@@ -713,6 +717,7 @@ glob (pattern, flags, errfunc, pglob) + } + } + } ++# endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */ + if (home_dir == NULL || home_dir[0] == '\0') + { + if (flags & GLOB_TILDE_CHECK) +diff --git a/posix/regcomp.c b/posix/regcomp.c +index bf8aa16..6a41251 100644 +--- a/posix/regcomp.c ++++ b/posix/regcomp.c +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + + #ifdef _LIBC + # include +@@ -309,7 +310,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + { + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + int node_cnt; +- int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); ++ int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE)); + for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) + { + int node = init_state->nodes.elems[node_cnt]; +@@ -319,9 +320,9 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + { + re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); + #ifdef RE_ENABLE_I18N +- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) ++ if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1) + { +- unsigned char *buf = alloca (dfa->mb_cur_max), *p; ++ unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p; + wchar_t wc; + mbstate_t state; + +@@ -352,7 +353,11 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + re_set_fastmap (fastmap, icase, ch); + } + } +-#ifdef RE_ENABLE_I18N ++ ++ /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current ++ locale is always C, which has no rules and no multi-byte ++ characters. */ ++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE + else if (type == COMPLEX_BRACKET) + { + re_charset_t *cset = dfa->nodes[node].opr.mbcset; +@@ -380,7 +385,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + i.e. where we would not find an invalid sequence. This only + applies to multibyte character sets; for single byte character + sets, the SIMPLE_BRACKET again suffices. */ +- if (dfa->mb_cur_max > 1 ++ if (dfa_mb_cur_max (dfa) > 1 + && (cset->nchar_classes || cset->non_match || cset->nranges + # ifdef _LIBC + || cset->nequiv_classes +@@ -408,7 +413,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + memset (&state, '\0', sizeof (state)); + if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) + re_set_fastmap (fastmap, icase, *(unsigned char *) buf); +- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) ++ if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1) + { + if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state) + != (size_t) -1) +@@ -417,7 +422,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + } + } + } +-#endif /* RE_ENABLE_I18N */ ++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ + else if (type == OP_PERIOD + #ifdef RE_ENABLE_I18N + || type == OP_UTF8_PERIOD +@@ -860,11 +865,15 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) + + dfa->mb_cur_max = MB_CUR_MAX; + #ifdef _LIBC +- if (dfa->mb_cur_max == 6 ++ if (dfa_mb_cur_max (dfa) == 6 + && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) + dfa->is_utf8 = 1; ++# if __OPTION_EGLIBC_LOCALE_CODE + dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) + != 0); ++# else ++ dfa->map_notascii = 0; ++# endif + #else + # ifdef HAVE_LANGINFO_CODESET + codeset_name = nl_langinfo (CODESET); +@@ -890,7 +899,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) + #endif + + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + { + if (dfa->is_utf8) + dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; +@@ -1788,7 +1797,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) + token->word_char = 0; + #ifdef RE_ENABLE_I18N + token->mb_partial = 0; +- if (input->mb_cur_max > 1 && ++ if (string_mb_cur_max (input) > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; +@@ -1809,7 +1818,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) + token->opr.c = c2; + token->type = CHARACTER; + #ifdef RE_ENABLE_I18N +- if (input->mb_cur_max > 1) ++ if (string_mb_cur_max (input) > 1) + { + wint_t wc = re_string_wchar_at (input, + re_string_cur_idx (input) + 1); +@@ -1923,7 +1932,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) + + token->type = CHARACTER; + #ifdef RE_ENABLE_I18N +- if (input->mb_cur_max > 1) ++ if (string_mb_cur_max (input) > 1) + { + wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; +@@ -2023,7 +2032,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) + token->opr.c = c; + + #ifdef RE_ENABLE_I18N +- if (input->mb_cur_max > 1 && ++ if (string_mb_cur_max (input) > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; +@@ -2246,7 +2255,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, + return NULL; + } + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + { + while (!re_string_eoi (regexp) + && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) +@@ -2384,7 +2393,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, + *err = REG_ESPACE; + return NULL; + } +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + dfa->has_mb_node = 1; + break; + case OP_WORD: +@@ -2690,7 +2699,7 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, + However, for !_LIBC we have no collation elements: if the + character set is single byte, the single byte character set + that we build below suffices. parse_bracket_exp passes +- no MBCSET if dfa->mb_cur_max == 1. */ ++ no MBCSET if dfa_mb_cur_max (dfa) == 1. */ + if (mbcset) + { + /* Check the space of the arrays. */ +@@ -2786,7 +2795,13 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err) + { + #ifdef _LIBC ++#if __OPTION_EGLIBC_LOCALE_CODE + const unsigned char *collseqmb; ++# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)]) ++#else ++# define COLLSEQMB_LOOKUP(ix) (ix) ++#endif ++ + const char *collseqwc; + uint32_t nrules; + int32_t table_size; +@@ -2834,18 +2849,20 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) +- return collseqmb[br_elem->opr.ch]; ++ return COLLSEQMB_LOOKUP (br_elem->opr.ch); + else + { + wint_t wc = __btowc (br_elem->opr.ch); + return __collseq_table_lookup (collseqwc, wc); + } + } ++#if __OPTION_EGLIBC_LOCALE_CODE + else if (br_elem->type == MB_CHAR) + { + if (nrules != 0) + return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + } ++#endif + else if (br_elem->type == COLL_SYM) + { + size_t sym_name_len = strlen ((char *) br_elem->opr.name); +@@ -2876,11 +2893,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + { + /* No valid character. Match it as a single byte + character. */ +- return collseqmb[br_elem->opr.name[0]]; ++ return COLLSEQMB_LOOKUP (br_elem->opr.name[0]); + } + } + else if (sym_name_len == 1) +- return collseqmb[br_elem->opr.name[0]]; ++ return COLLSEQMB_LOOKUP (br_elem->opr.name[0]); + } + return UINT_MAX; + } +@@ -2920,7 +2937,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + However, if we have no collation elements, and the character set + is single byte, the single byte character set that we + build below suffices. */ +- if (nrules > 0 || dfa->mb_cur_max > 1) ++ if (nrules > 0 || dfa_mb_cur_max (dfa) > 1) + { + /* Check the space of the arrays. */ + if (BE (*range_alloc == mbcset->nranges, 0)) +@@ -2957,7 +2974,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) +- ch_collseq = collseqmb[ch]; ++ ch_collseq = COLLSEQMB_LOOKUP (ch); + else + ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); + if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) +@@ -3035,7 +3052,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + re_bitset_ptr_t sbcset; + #ifdef RE_ENABLE_I18N + re_charset_t *mbcset; +- int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; ++ int coll_sym_alloc = 0, range_alloc = 0; ++#if __OPTION_EGLIBC_LOCALE_CODE ++ int mbchar_alloc = 0; ++#endif + int equiv_class_alloc = 0, char_class_alloc = 0; + #endif /* not RE_ENABLE_I18N */ + int non_match = 0; +@@ -3043,9 +3063,15 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + int token_len; + int first_round = 1; + #ifdef _LIBC ++#if __OPTION_EGLIBC_LOCALE_CODE + collseqmb = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); ++#else ++ /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the ++ compiler can't figure that out. */ ++ nrules = 0; ++#endif + if (nrules) + { + /* +@@ -3175,7 +3201,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + #else + # ifdef RE_ENABLE_I18N + *err = build_range_exp (sbcset, +- dfa->mb_cur_max > 1 ? mbcset : NULL, ++ dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL, + &range_alloc, &start_elem, &end_elem); + # else + *err = build_range_exp (sbcset, &start_elem, &end_elem); +@@ -3191,7 +3217,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + case SB_CHAR: + bitset_set (sbcset, start_elem.opr.ch); + break; +-#ifdef RE_ENABLE_I18N ++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE + case MB_CHAR: + /* Check whether the array has enough space. */ + if (BE (mbchar_alloc == mbcset->nmbchars, 0)) +@@ -3209,7 +3235,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + } + mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; + break; +-#endif /* RE_ENABLE_I18N */ ++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ + case EQUIV_CLASS: + *err = build_equiv_class (sbcset, + #ifdef RE_ENABLE_I18N +@@ -3259,11 +3285,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + + #ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + bitset_mask (sbcset, dfa->sb_char); + + if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes +- || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes ++ || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes + || mbcset->non_match))) + { + bin_tree_t *mbc_tree; +@@ -3332,7 +3358,7 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token, int token_len, re_dfa_t *dfa, + reg_syntax_t syntax, int accept_hyphen) + { +-#ifdef RE_ENABLE_I18N ++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE + int cur_char_size; + cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); + if (cur_char_size > 1) +@@ -3342,7 +3368,7 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, + re_string_skip_bytes (regexp, cur_char_size); + return REG_NOERROR; + } +-#endif /* RE_ENABLE_I18N */ ++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS + || token->type == OP_OPEN_EQUIV_CLASS) +@@ -3422,7 +3448,9 @@ build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, + build_equiv_class (bitset_t sbcset, const unsigned char *name) + #endif /* not RE_ENABLE_I18N */ + { +-#ifdef _LIBC ++ /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale ++ is supported; it has no collation rules. */ ++#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { +@@ -3492,7 +3520,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) + mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; + } + else +-#endif /* _LIBC */ ++#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ + { + if (BE (strlen ((const char *) name) != 1, 0)) + return REG_ECOLLATE; +@@ -3526,7 +3554,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) + name = "alpha"; + +-#ifdef RE_ENABLE_I18N ++#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE + /* Check the space of the arrays. */ + if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) + { +@@ -3542,7 +3570,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + *char_class_alloc = new_char_class_alloc; + } + mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); +-#endif /* RE_ENABLE_I18N */ ++#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ + + #define BUILD_CHARCLASS_LOOP(ctype_func) \ + do { \ +@@ -3653,7 +3681,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, + + #ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + bitset_mask (sbcset, dfa->sb_char); + #endif + +@@ -3665,7 +3693,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, + goto build_word_op_espace; + + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + { + bin_tree_t *mbc_tree; + /* Build a tree for complex bracket. */ +diff --git a/posix/regex.h b/posix/regex.h +index 5b1981e..2941f94 100644 +--- a/posix/regex.h ++++ b/posix/regex.h +@@ -21,6 +21,7 @@ + #define _REGEX_H 1 + + #include ++#include + + /* Allow the use in C++ code. */ + #ifdef __cplusplus +@@ -156,6 +157,8 @@ typedef unsigned long int reg_syntax_t; + treated as 'a\{1'. */ + # define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) + ++/* EGLIBC: Old regex implementation does not support these. */ ++# if __OPTION_POSIX_REGEXP_GLIBC + /* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ + # define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) +@@ -172,6 +175,7 @@ typedef unsigned long int reg_syntax_t; + /* If this bit is set, then no_sub will be set to 1 during + re_compile_pattern. */ + # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) ++# endif /* __OPTION_POSIX_REGEXP_GLIBC */ + #endif + + /* This global variable defines the particular regexp syntax to use (for +@@ -231,8 +235,13 @@ extern reg_syntax_t re_syntax_options; + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + ++#if __OPTION_POSIX_REGEXP_GLIBC + #define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) ++#else ++#define RE_SYNTAX_POSIX_BASIC \ ++ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) ++#endif + + /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this +@@ -298,9 +307,11 @@ extern reg_syntax_t re_syntax_options; + /* Like REG_NOTBOL, except for the end-of-line. */ + #define REG_NOTEOL (1 << 1) + ++#if __OPTION_POSIX_REGEXP_GLIBC + /* Use PMATCH[0] to delimit the start and end of the search in the + buffer. */ + #define REG_STARTEND (1 << 2) ++#endif + + + /* If any error codes are removed, changed, or added, update the +diff --git a/posix/regex_internal.c b/posix/regex_internal.c +index 8597d7e..d53b2a8 100644 +--- a/posix/regex_internal.c ++++ b/posix/regex_internal.c +@@ -43,8 +43,8 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, + int init_buf_len; + + /* Ensure at least one character fits into the buffers. */ +- if (init_len < dfa->mb_cur_max) +- init_len = dfa->mb_cur_max; ++ if (init_len < dfa_mb_cur_max (dfa)) ++ init_len = dfa_mb_cur_max (dfa); + init_buf_len = (len + 1 < init_len) ? len + 1: init_len; + re_string_construct_common (str, len, pstr, trans, icase, dfa); + +@@ -55,7 +55,7 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, + pstr->word_char = dfa->word_char; + pstr->word_ops_used = dfa->word_ops_used; + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; +- pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; ++ pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len; + pstr->valid_raw_len = pstr->valid_len; + return REG_NOERROR; + } +@@ -82,7 +82,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len, + if (icase) + { + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + { + while (1) + { +@@ -91,7 +91,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len, + return ret; + if (pstr->valid_raw_len >= len) + break; +- if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) ++ if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa)) + break; + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (BE (ret != REG_NOERROR, 0)) +@@ -105,7 +105,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len, + else + { + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + build_wcs_buffer (pstr); + else + #endif /* RE_ENABLE_I18N */ +@@ -130,7 +130,7 @@ internal_function __attribute_warn_unused_result__ + re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) + { + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + { + wint_t *new_wcs; + +@@ -177,7 +177,7 @@ re_string_construct_common (const char *str, int len, re_string_t *pstr, + pstr->trans = trans; + pstr->icase = icase ? 1 : 0; + pstr->mbs_allocated = (trans != NULL || icase); +- pstr->mb_cur_max = dfa->mb_cur_max; ++ pstr->mb_cur_max = dfa_mb_cur_max (dfa); + pstr->is_utf8 = dfa->is_utf8; + pstr->map_notascii = dfa->map_notascii; + pstr->stop = pstr->len; +@@ -203,7 +203,7 @@ build_wcs_buffer (re_string_t *pstr) + { + #ifdef _LIBC + unsigned char buf[MB_LEN_MAX]; +- assert (MB_LEN_MAX >= pstr->mb_cur_max); ++ assert (MB_LEN_MAX >= string_mb_cur_max (pstr)); + #else + unsigned char buf[64]; + #endif +@@ -226,7 +226,7 @@ build_wcs_buffer (re_string_t *pstr) + { + int i, ch; + +- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) ++ for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; + buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; +@@ -275,7 +275,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + size_t mbclen; + #ifdef _LIBC + char buf[MB_LEN_MAX]; +- assert (MB_LEN_MAX >= pstr->mb_cur_max); ++ assert (MB_LEN_MAX >= string_mb_cur_max (pstr)); + #else + char buf[64]; + #endif +@@ -369,7 +369,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + { + int i, ch; + +- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) ++ for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; + buf[i] = pstr->trans[ch]; +@@ -567,8 +567,9 @@ re_string_translate_buffer (re_string_t *pstr) + } + + /* This function re-construct the buffers. +- Concretely, convert to wide character in case of pstr->mb_cur_max > 1, +- convert to upper case in case of REG_ICASE, apply translation. */ ++ Concretely, convert to wide character in case of ++ string_mb_cur_max (pstr) > 1, convert to upper case in case of ++ REG_ICASE, apply translation. */ + + static reg_errcode_t + internal_function __attribute_warn_unused_result__ +@@ -579,7 +580,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) + { + /* Reset buffer. */ + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); + #endif /* RE_ENABLE_I18N */ + pstr->len = pstr->raw_len; +@@ -670,7 +671,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) + pstr->tip_context = re_string_context_at (pstr, offset - 1, + eflags); + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); + #endif /* RE_ENABLE_I18N */ +@@ -699,7 +700,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) + #endif + pstr->valid_len = 0; + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + { + int wcs_idx; + wint_t wc = WEOF; +@@ -711,7 +712,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) + /* Special case UTF-8. Multi-byte chars start with any + byte other than 0x80 - 0xbf. */ + raw = pstr->raw_mbs + pstr->raw_mbs_idx; +- end = raw + (offset - pstr->mb_cur_max); ++ end = raw + (offset - string_mb_cur_max (pstr)); + if (end < pstr->raw_mbs) + end = pstr->raw_mbs; + p = raw + offset - 1; +@@ -803,7 +804,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) + + /* Then build the buffers. */ + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + { + if (pstr->icase) + { +@@ -841,7 +842,7 @@ re_string_peek_byte_case (const re_string_t *pstr, int idx) + return re_string_peek_byte (pstr, idx); + + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1 ++ if (string_mb_cur_max (pstr) > 1 + && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) + return re_string_peek_byte (pstr, idx); + #endif +@@ -930,7 +931,7 @@ re_string_context_at (const re_string_t *input, int idx, int eflags) + return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF + : CONTEXT_NEWLINE | CONTEXT_ENDBUF); + #ifdef RE_ENABLE_I18N +- if (input->mb_cur_max > 1) ++ if (string_mb_cur_max (input) > 1) + { + wint_t wc; + int wc_idx = idx; +@@ -1444,7 +1445,7 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) + dfa->nodes[dfa->nodes_len].constraint = 0; + #ifdef RE_ENABLE_I18N + dfa->nodes[dfa->nodes_len].accept_mb = +- (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; ++ (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET; + #endif + dfa->nexts[dfa->nodes_len] = -1; + re_node_set_init_empty (dfa->edests + dfa->nodes_len); +diff --git a/posix/regex_internal.h b/posix/regex_internal.h +index 154e969..c43909a 100644 +--- a/posix/regex_internal.h ++++ b/posix/regex_internal.h +@@ -26,6 +26,10 @@ + #include + #include + ++#if defined _LIBC ++# include ++#endif ++ + #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC + # include + #endif +@@ -369,6 +373,13 @@ struct re_string_t + }; + typedef struct re_string_t re_string_t; + ++/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1; ++ help the compiler make use of that fact. */ ++#if __OPTION_EGLIBC_LOCALE_CODE ++# define string_mb_cur_max(str) ((str)->mb_cur_max + 0) ++#else ++# define string_mb_cur_max(str) (1) ++#endif + + struct re_dfa_t; + typedef struct re_dfa_t re_dfa_t; +@@ -654,6 +665,14 @@ struct re_dfa_t + __libc_lock_define (, lock) + }; + ++/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1; ++ help the compiler make use of that fact. */ ++#if __OPTION_EGLIBC_LOCALE_CODE ++# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0) ++#else ++# define dfa_mb_cur_max(dfa) (1) ++#endif ++ + #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) + #define re_node_set_remove(set,id) \ + (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) +@@ -714,7 +733,7 @@ internal_function __attribute__ ((pure, unused)) + re_string_char_size_at (const re_string_t *pstr, int idx) + { + int byte_idx; +- if (pstr->mb_cur_max == 1) ++ if (string_mb_cur_max (pstr) == 1) + return 1; + for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) + if (pstr->wcs[idx + byte_idx] != WEOF) +@@ -726,7 +745,7 @@ static wint_t + internal_function __attribute__ ((pure, unused)) + re_string_wchar_at (const re_string_t *pstr, int idx) + { +- if (pstr->mb_cur_max == 1) ++ if (string_mb_cur_max (pstr) == 1) + return (wint_t) pstr->mbs[idx]; + return (wint_t) pstr->wcs[idx]; + } +diff --git a/posix/regexec-compat.c b/posix/regexec-compat.c +new file mode 100644 +index 0000000..0f9b7c7 +--- /dev/null ++++ b/posix/regexec-compat.c +@@ -0,0 +1,39 @@ ++/* Extended regular expression matching and search library. ++ Copyright (C) 2008 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Isamu Hasegawa . ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#ifdef _LIBC ++# include ++versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); ++ ++# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) ++__typeof__ (__regexec) __compat_regexec; ++ ++int ++attribute_compat_text_section ++__compat_regexec (const regex_t *__restrict preg, ++ const char *__restrict string, size_t nmatch, ++ regmatch_t pmatch[], int eflags) ++{ ++ return regexec (preg, string, nmatch, pmatch, ++ eflags & (REG_NOTBOL | REG_NOTEOL)); ++} ++compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); ++# endif ++#endif +diff --git a/posix/regexec.c b/posix/regexec.c +index 70cd606..e3b49e4 100644 +--- a/posix/regexec.c ++++ b/posix/regexec.c +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + + static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, + int n) internal_function; +@@ -186,11 +187,11 @@ static int build_trtable (const re_dfa_t *dfa, + static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + const re_string_t *input, int idx) + internal_function; +-# ifdef _LIBC ++# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE + static unsigned int find_collation_sequence_value (const unsigned char *mbs, + size_t name_len) + internal_function; +-# endif /* _LIBC */ ++# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ + #endif /* RE_ENABLE_I18N */ + static int group_nodes_into_DFAstates (const re_dfa_t *dfa, + const re_dfastate_t *state, +@@ -255,25 +256,9 @@ regexec (preg, string, nmatch, pmatch, eflags) + return err != REG_NOERROR; + } + +-#ifdef _LIBC +-# include +-versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); +- +-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +-__typeof__ (__regexec) __compat_regexec; +- +-int +-attribute_compat_text_section +-__compat_regexec (const regex_t *__restrict preg, +- const char *__restrict string, size_t nmatch, +- regmatch_t pmatch[], int eflags) +-{ +- return regexec (preg, string, nmatch, pmatch, +- eflags & (REG_NOTBOL | REG_NOTEOL)); +-} +-compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); +-# endif +-#endif ++/* EGLIBC: The code that used to be here was move to a separate file ++ so that it can be shared with xregex.c. */ ++#include "regexec-compat.c" + + /* Entry points for GNU code. */ + +@@ -728,7 +713,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, + incr = (range < 0) ? -1 : 1; + left_lim = (range < 0) ? start + range : start; + right_lim = (range < 0) ? start : start + range; +- sb = dfa->mb_cur_max == 1; ++ sb = dfa_mb_cur_max (dfa) == 1; + match_kind = + (fastmap + ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) +@@ -3448,7 +3433,7 @@ out_free: + if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + +- if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) ++ if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1) + need_word_trtable = 1; + + dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, +@@ -3590,7 +3575,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + else if (type == OP_PERIOD) + { + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + bitset_merge (accepts, dfa->sb_char); + else + #endif +@@ -3641,7 +3626,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + continue; + } + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); + else +@@ -3660,7 +3645,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + continue; + } + #ifdef RE_ENABLE_I18N +- if (dfa->mb_cur_max > 1) ++ if (dfa_mb_cur_max (dfa) > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); + else +@@ -3836,12 +3821,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + if (node->type == COMPLEX_BRACKET) + { + const re_charset_t *cset = node->opr.mbcset; +-# ifdef _LIBC +- const unsigned char *pin +- = ((const unsigned char *) re_string_get_buffer (input) + str_idx); +- int j; +- uint32_t nrules; +-# endif /* _LIBC */ + int match_len = 0; + wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) + ? re_string_wchar_at (input, str_idx) : 0); +@@ -3853,6 +3832,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + match_len = char_len; + goto check_node_accept_bytes_match; + } ++#if __OPTION_EGLIBC_LOCALE_CODE + /* match with character_class? */ + for (i = 0; i < cset->nchar_classes; ++i) + { +@@ -3863,14 +3843,22 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + goto check_node_accept_bytes_match; + } + } ++#endif ++ ++ /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C ++ locale is supported; it has no collation rules. */ ++# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE ++ const unsigned char *pin ++ = ((const unsigned char *) re_string_get_buffer (input) + str_idx); ++ int j; ++ uint32_t nrules; + +-# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + unsigned int in_collseq = 0; + const int32_t *table, *indirect; +- const unsigned char *weights, *extra; ++ const unsigned char *weights, *extra = NULL; + const char *collseqwc; + + /* match with collating_symbol? */ +@@ -3955,8 +3943,12 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + } + } + else +-# endif /* _LIBC */ ++# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ + { ++ /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is ++ disabled, there can be no multibyte range endpoints, and ++ cset->nranges is always zero. */ ++#if __OPTION_EGLIBC_LOCALE_CODE + /* match with range expression? */ + #if __GNUC__ >= 2 + wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; +@@ -3975,6 +3967,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + goto check_node_accept_bytes_match; + } + } ++#endif /* __OPTION_EGLIBC_LOCALE_CODE */ + } + check_node_accept_bytes_match: + if (!cset->non_match) +@@ -3990,7 +3983,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + return 0; + } + +-# ifdef _LIBC ++# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE + static unsigned int + internal_function + find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) +@@ -4048,7 +4041,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) + return UINT_MAX; + } + } +-# endif /* _LIBC */ ++# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ + #endif /* RE_ENABLE_I18N */ + + /* Check whether the node accepts the byte which is IDX-th +@@ -4139,7 +4132,7 @@ extend_buffers (re_match_context_t *mctx, int min_len) + if (pstr->icase) + { + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + { + ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) +@@ -4152,7 +4145,7 @@ extend_buffers (re_match_context_t *mctx, int min_len) + else + { + #ifdef RE_ENABLE_I18N +- if (pstr->mb_cur_max > 1) ++ if (string_mb_cur_max (pstr) > 1) + build_wcs_buffer (pstr); + else + #endif /* RE_ENABLE_I18N */ +diff --git a/posix/xregex.c b/posix/xregex.c +new file mode 100644 +index 0000000..d3f7ace +--- /dev/null ++++ b/posix/xregex.c +@@ -0,0 +1,8215 @@ ++/* Extended regular expression matching and search library, ++ version 0.12. ++ (Implements POSIX draft P1003.2/D11.2, except for some of the ++ internationalization features.) ++ ++ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, ++ 2002, 2005 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ 02110-1301 USA. */ ++ ++/* AIX requires this to be the first thing in the file. */ ++#if defined _AIX && !defined __GNUC__ && !defined REGEX_MALLOC ++ #pragma alloca ++#endif ++ ++#undef _GNU_SOURCE ++#define _GNU_SOURCE ++ ++#ifndef INSIDE_RECURSION ++# ifdef HAVE_CONFIG_H ++# include ++# endif ++#endif ++ ++/*#include */ ++ ++ ++#ifndef INSIDE_RECURSION ++ ++# if defined STDC_HEADERS && !defined emacs ++# include ++# else ++/* We need this for `regex.h', and perhaps for the Emacs include files. */ ++# include ++# endif ++ ++# if (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_BTOWC) ++# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) ++# else ++# define WIDE_CHAR_SUPPORT 0 ++# endif ++/* For platform which support the ISO C amendement 1 functionality we ++ support user defined character classes. */ ++# if WIDE_CHAR_SUPPORT ++/* Solaris 2.5 has a bug: must be included before . */ ++# include ++# include ++# endif ++ ++# ifdef _LIBC ++/* We have to keep the namespace clean. */ ++# define regfree(preg) __regfree (preg) ++# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) ++# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) ++# define regerror(errcode, preg, errbuf, errbuf_size) \ ++ __regerror(errcode, preg, errbuf, errbuf_size) ++# define re_set_registers(bu, re, nu, st, en) \ ++ __re_set_registers (bu, re, nu, st, en) ++# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ ++ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) ++# define re_match(bufp, string, size, pos, regs) \ ++ __re_match (bufp, string, size, pos, regs) ++# define re_search(bufp, string, size, startpos, range, regs) \ ++ __re_search (bufp, string, size, startpos, range, regs) ++# define re_compile_pattern(pattern, length, bufp) \ ++ __re_compile_pattern (pattern, length, bufp) ++# define re_set_syntax(syntax) __re_set_syntax (syntax) ++# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ ++ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) ++# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) ++ ++# define btowc __btowc ++ ++/* We are also using some library internals. */ ++# include ++# include ++# include ++# include ++# endif ++ ++/* This is for other GNU distributions with internationalized messages. */ ++# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC ++# include ++# ifdef _LIBC ++# undef gettext ++# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) ++# endif ++# else ++# define gettext(msgid) (msgid) ++# endif ++ ++# ifndef gettext_noop ++/* This define is so xgettext can find the internationalizable ++ strings. */ ++# define gettext_noop(String) String ++# endif ++ ++/* The `emacs' switch turns on certain matching commands ++ that make sense only in Emacs. */ ++# ifdef emacs ++ ++# include "lisp.h" ++# include "buffer.h" ++# include "syntax.h" ++ ++# else /* not emacs */ ++ ++/* If we are not linking with Emacs proper, ++ we can't use the relocating allocator ++ even if config.h says that we can. */ ++# undef REL_ALLOC ++ ++# if defined STDC_HEADERS || defined _LIBC ++# include ++# else ++char *malloc (); ++char *realloc (); ++# endif ++ ++/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. ++ If nothing else has been done, use the method below. */ ++# ifdef INHIBIT_STRING_HEADER ++# if !(defined HAVE_BZERO && defined HAVE_BCOPY) ++# if !defined bzero && !defined bcopy ++# undef INHIBIT_STRING_HEADER ++# endif ++# endif ++# endif ++ ++/* This is the normal way of making sure we have a bcopy and a bzero. ++ This is used in most programs--a few other programs avoid this ++ by defining INHIBIT_STRING_HEADER. */ ++# ifndef INHIBIT_STRING_HEADER ++# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC ++# include ++# ifndef bzero ++# ifndef _LIBC ++# define bzero(s, n) (memset (s, '\0', n), (s)) ++# else ++# define bzero(s, n) __bzero (s, n) ++# endif ++# endif ++# else ++# include ++# ifndef memcmp ++# define memcmp(s1, s2, n) bcmp (s1, s2, n) ++# endif ++# ifndef memcpy ++# define memcpy(d, s, n) (bcopy (s, d, n), (d)) ++# endif ++# endif ++# endif ++ ++/* Define the syntax stuff for \<, \>, etc. */ ++ ++/* This must be nonzero for the wordchar and notwordchar pattern ++ commands in re_match_2. */ ++# ifndef Sword ++# define Sword 1 ++# endif ++ ++# ifdef SWITCH_ENUM_BUG ++# define SWITCH_ENUM_CAST(x) ((int)(x)) ++# else ++# define SWITCH_ENUM_CAST(x) (x) ++# endif ++ ++# endif /* not emacs */ ++ ++# if defined _LIBC || HAVE_LIMITS_H ++# include ++# endif ++ ++# ifndef MB_LEN_MAX ++# define MB_LEN_MAX 1 ++# endif ++ ++/* Get the interface, including the syntax bits. */ ++# include "regex.h" ++ ++/* isalpha etc. are used for the character classes. */ ++# include ++ ++/* Jim Meyering writes: ++ ++ "... Some ctype macros are valid only for character codes that ++ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when ++ using /bin/cc or gcc but without giving an ansi option). So, all ++ ctype uses should be through macros like ISPRINT... If ++ STDC_HEADERS is defined, then autoconf has verified that the ctype ++ macros don't need to be guarded with references to isascii. ... ++ Defining isascii to 1 should let any compiler worth its salt ++ eliminate the && through constant folding." ++ Solaris defines some of these symbols so we must undefine them first. */ ++ ++# undef ISASCII ++# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) ++# define ISASCII(c) 1 ++# else ++# define ISASCII(c) isascii(c) ++# endif ++ ++# ifdef isblank ++# define ISBLANK(c) (ISASCII (c) && isblank (c)) ++# else ++# define ISBLANK(c) ((c) == ' ' || (c) == '\t') ++# endif ++# ifdef isgraph ++# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) ++# else ++# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) ++# endif ++ ++# undef ISPRINT ++# define ISPRINT(c) (ISASCII (c) && isprint (c)) ++# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) ++# define ISALNUM(c) (ISASCII (c) && isalnum (c)) ++# define ISALPHA(c) (ISASCII (c) && isalpha (c)) ++# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) ++# define ISLOWER(c) (ISASCII (c) && islower (c)) ++# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) ++# define ISSPACE(c) (ISASCII (c) && isspace (c)) ++# define ISUPPER(c) (ISASCII (c) && isupper (c)) ++# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) ++ ++# ifdef _tolower ++# define TOLOWER(c) _tolower(c) ++# else ++# define TOLOWER(c) tolower(c) ++# endif ++ ++# ifndef NULL ++# define NULL (void *)0 ++# endif ++ ++/* We remove any previous definition of `SIGN_EXTEND_CHAR', ++ since ours (we hope) works properly with all combinations of ++ machines, compilers, `char' and `unsigned char' argument types. ++ (Per Bothner suggested the basic approach.) */ ++# undef SIGN_EXTEND_CHAR ++# if __STDC__ ++# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) ++# else /* not __STDC__ */ ++/* As in Harbison and Steele. */ ++# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) ++# endif ++ ++# ifndef emacs ++/* How many characters in the character set. */ ++# define CHAR_SET_SIZE 256 ++ ++# ifdef SYNTAX_TABLE ++ ++extern char *re_syntax_table; ++ ++# else /* not SYNTAX_TABLE */ ++ ++static char re_syntax_table[CHAR_SET_SIZE]; ++ ++static void init_syntax_once (void); ++ ++static void ++init_syntax_once (void) ++{ ++ register int c; ++ static int done = 0; ++ ++ if (done) ++ return; ++ bzero (re_syntax_table, sizeof re_syntax_table); ++ ++ for (c = 0; c < CHAR_SET_SIZE; ++c) ++ if (ISALNUM (c)) ++ re_syntax_table[c] = Sword; ++ ++ re_syntax_table['_'] = Sword; ++ ++ done = 1; ++} ++ ++# endif /* not SYNTAX_TABLE */ ++ ++# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] ++ ++# endif /* emacs */ ++ ++/* Integer type for pointers. */ ++# if !defined _LIBC && !defined HAVE_UINTPTR_T ++typedef unsigned long int uintptr_t; ++# endif ++ ++/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we ++ use `alloca' instead of `malloc'. This is because using malloc in ++ re_search* or re_match* could cause memory leaks when C-g is used in ++ Emacs; also, malloc is slower and causes storage fragmentation. On ++ the other hand, malloc is more portable, and easier to debug. ++ ++ Because we sometimes use alloca, some routines have to be macros, ++ not functions -- `alloca'-allocated space disappears at the end of the ++ function it is called in. */ ++ ++# ifdef REGEX_MALLOC ++ ++# define REGEX_ALLOCATE malloc ++# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) ++# define REGEX_FREE free ++ ++# else /* not REGEX_MALLOC */ ++ ++/* Emacs already defines alloca, sometimes. */ ++# ifndef alloca ++ ++/* Make alloca work the best possible way. */ ++# ifdef __GNUC__ ++# define alloca __builtin_alloca ++# else /* not __GNUC__ */ ++# if HAVE_ALLOCA_H ++# include ++# endif /* HAVE_ALLOCA_H */ ++# endif /* not __GNUC__ */ ++ ++# endif /* not alloca */ ++ ++# define REGEX_ALLOCATE alloca ++ ++/* Assumes a `char *destination' variable. */ ++# define REGEX_REALLOCATE(source, osize, nsize) \ ++ (destination = (char *) alloca (nsize), \ ++ memcpy (destination, source, osize)) ++ ++/* No need to do anything to free, after alloca. */ ++# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ ++ ++# endif /* not REGEX_MALLOC */ ++ ++/* Define how to allocate the failure stack. */ ++ ++# if defined REL_ALLOC && defined REGEX_MALLOC ++ ++# define REGEX_ALLOCATE_STACK(size) \ ++ r_alloc (&failure_stack_ptr, (size)) ++# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ ++ r_re_alloc (&failure_stack_ptr, (nsize)) ++# define REGEX_FREE_STACK(ptr) \ ++ r_alloc_free (&failure_stack_ptr) ++ ++# else /* not using relocating allocator */ ++ ++# ifdef REGEX_MALLOC ++ ++# define REGEX_ALLOCATE_STACK malloc ++# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) ++# define REGEX_FREE_STACK free ++ ++# else /* not REGEX_MALLOC */ ++ ++# define REGEX_ALLOCATE_STACK alloca ++ ++# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ ++ REGEX_REALLOCATE (source, osize, nsize) ++/* No need to explicitly free anything. */ ++# define REGEX_FREE_STACK(arg) ++ ++# endif /* not REGEX_MALLOC */ ++# endif /* not using relocating allocator */ ++ ++ ++/* True if `size1' is non-NULL and PTR is pointing anywhere inside ++ `string1' or just past its end. This works if PTR is NULL, which is ++ a good thing. */ ++# define FIRST_STRING_P(ptr) \ ++ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) ++ ++/* (Re)Allocate N items of type T using malloc, or fail. */ ++# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) ++# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) ++# define RETALLOC_IF(addr, n, t) \ ++ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) ++# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) ++ ++# define BYTEWIDTH 8 /* In bits. */ ++ ++# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) ++ ++# undef MAX ++# undef MIN ++# define MAX(a, b) ((a) > (b) ? (a) : (b)) ++# define MIN(a, b) ((a) < (b) ? (a) : (b)) ++ ++typedef char boolean; ++# define false 0 ++# define true 1 ++ ++static reg_errcode_t byte_regex_compile (const char *pattern, size_t size, ++ reg_syntax_t syntax, ++ struct re_pattern_buffer *bufp); ++ ++static int byte_re_match_2_internal (struct re_pattern_buffer *bufp, ++ const char *string1, int size1, ++ const char *string2, int size2, ++ int pos, ++ struct re_registers *regs, ++ int stop); ++static int byte_re_search_2 (struct re_pattern_buffer *bufp, ++ const char *string1, int size1, ++ const char *string2, int size2, ++ int startpos, int range, ++ struct re_registers *regs, int stop); ++static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp); ++ ++#ifdef MBS_SUPPORT ++static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size, ++ reg_syntax_t syntax, ++ struct re_pattern_buffer *bufp); ++ ++ ++static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp, ++ const char *cstring1, int csize1, ++ const char *cstring2, int csize2, ++ int pos, ++ struct re_registers *regs, ++ int stop, ++ wchar_t *string1, int size1, ++ wchar_t *string2, int size2, ++ int *mbs_offset1, int *mbs_offset2); ++static int wcs_re_search_2 (struct re_pattern_buffer *bufp, ++ const char *string1, int size1, ++ const char *string2, int size2, ++ int startpos, int range, ++ struct re_registers *regs, int stop); ++static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp); ++#endif ++ ++/* These are the command codes that appear in compiled regular ++ expressions. Some opcodes are followed by argument bytes. A ++ command code can specify any interpretation whatsoever for its ++ arguments. Zero bytes may appear in the compiled regular expression. */ ++ ++typedef enum ++{ ++ no_op = 0, ++ ++ /* Succeed right away--no more backtracking. */ ++ succeed, ++ ++ /* Followed by one byte giving n, then by n literal bytes. */ ++ exactn, ++ ++# ifdef MBS_SUPPORT ++ /* Same as exactn, but contains binary data. */ ++ exactn_bin, ++# endif ++ ++ /* Matches any (more or less) character. */ ++ anychar, ++ ++ /* Matches any one char belonging to specified set. First ++ following byte is number of bitmap bytes. Then come bytes ++ for a bitmap saying which chars are in. Bits in each byte ++ are ordered low-bit-first. A character is in the set if its ++ bit is 1. A character too large to have a bit in the map is ++ automatically not in the set. */ ++ /* ifdef MBS_SUPPORT, following element is length of character ++ classes, length of collating symbols, length of equivalence ++ classes, length of character ranges, and length of characters. ++ Next, character class element, collating symbols elements, ++ equivalence class elements, range elements, and character ++ elements follow. ++ See regex_compile function. */ ++ charset, ++ ++ /* Same parameters as charset, but match any character that is ++ not one of those specified. */ ++ charset_not, ++ ++ /* Start remembering the text that is matched, for storing in a ++ register. Followed by one byte with the register number, in ++ the range 0 to one less than the pattern buffer's re_nsub ++ field. Then followed by one byte with the number of groups ++ inner to this one. (This last has to be part of the ++ start_memory only because we need it in the on_failure_jump ++ of re_match_2.) */ ++ start_memory, ++ ++ /* Stop remembering the text that is matched and store it in a ++ memory register. Followed by one byte with the register ++ number, in the range 0 to one less than `re_nsub' in the ++ pattern buffer, and one byte with the number of inner groups, ++ just like `start_memory'. (We need the number of inner ++ groups here because we don't have any easy way of finding the ++ corresponding start_memory when we're at a stop_memory.) */ ++ stop_memory, ++ ++ /* Match a duplicate of something remembered. Followed by one ++ byte containing the register number. */ ++ duplicate, ++ ++ /* Fail unless at beginning of line. */ ++ begline, ++ ++ /* Fail unless at end of line. */ ++ endline, ++ ++ /* Succeeds if at beginning of buffer (if emacs) or at beginning ++ of string to be matched (if not). */ ++ begbuf, ++ ++ /* Analogously, for end of buffer/string. */ ++ endbuf, ++ ++ /* Followed by two byte relative address to which to jump. */ ++ jump, ++ ++ /* Same as jump, but marks the end of an alternative. */ ++ jump_past_alt, ++ ++ /* Followed by two-byte relative address of place to resume at ++ in case of failure. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ on_failure_jump, ++ ++ /* Like on_failure_jump, but pushes a placeholder instead of the ++ current string position when executed. */ ++ on_failure_keep_string_jump, ++ ++ /* Throw away latest failure point and then jump to following ++ two-byte relative address. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ pop_failure_jump, ++ ++ /* Change to pop_failure_jump if know won't have to backtrack to ++ match; otherwise change to jump. This is used to jump ++ back to the beginning of a repeat. If what follows this jump ++ clearly won't match what the repeat does, such that we can be ++ sure that there is no use backtracking out of repetitions ++ already matched, then we change it to a pop_failure_jump. ++ Followed by two-byte address. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ maybe_pop_jump, ++ ++ /* Jump to following two-byte address, and push a dummy failure ++ point. This failure point will be thrown away if an attempt ++ is made to use it for a failure. A `+' construct makes this ++ before the first repeat. Also used as an intermediary kind ++ of jump when compiling an alternative. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ dummy_failure_jump, ++ ++ /* Push a dummy failure point and continue. Used at the end of ++ alternatives. */ ++ push_dummy_failure, ++ ++ /* Followed by two-byte relative address and two-byte number n. ++ After matching N times, jump to the address upon failure. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ succeed_n, ++ ++ /* Followed by two-byte relative address, and two-byte number n. ++ Jump to the address N times, then fail. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ jump_n, ++ ++ /* Set the following two-byte relative address to the ++ subsequent two-byte number. The address *includes* the two ++ bytes of number. */ ++ /* ifdef MBS_SUPPORT, the size of address is 1. */ ++ set_number_at, ++ ++ wordchar, /* Matches any word-constituent character. */ ++ notwordchar, /* Matches any char that is not a word-constituent. */ ++ ++ wordbeg, /* Succeeds if at word beginning. */ ++ wordend, /* Succeeds if at word end. */ ++ ++ wordbound, /* Succeeds if at a word boundary. */ ++ notwordbound /* Succeeds if not at a word boundary. */ ++ ++# ifdef emacs ++ ,before_dot, /* Succeeds if before point. */ ++ at_dot, /* Succeeds if at point. */ ++ after_dot, /* Succeeds if after point. */ ++ ++ /* Matches any character whose syntax is specified. Followed by ++ a byte which contains a syntax code, e.g., Sword. */ ++ syntaxspec, ++ ++ /* Matches any character whose syntax is not that specified. */ ++ notsyntaxspec ++# endif /* emacs */ ++} re_opcode_t; ++#endif /* not INSIDE_RECURSION */ ++ ++ ++#ifdef BYTE ++# define CHAR_T char ++# define UCHAR_T unsigned char ++# define COMPILED_BUFFER_VAR bufp->buffer ++# define OFFSET_ADDRESS_SIZE 2 ++# define PREFIX(name) byte_##name ++# define ARG_PREFIX(name) name ++# define PUT_CHAR(c) putchar (c) ++# include ++# define FINDIDX findidx ++#else ++# ifdef WCHAR ++# define CHAR_T wchar_t ++# define UCHAR_T wchar_t ++# define COMPILED_BUFFER_VAR wc_buffer ++# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ ++# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) ++# define PREFIX(name) wcs_##name ++# define ARG_PREFIX(name) c##name ++/* Should we use wide stream?? */ ++# define PUT_CHAR(c) printf ("%C", c); ++# define TRUE 1 ++# define FALSE 0 ++# define findidx findidxwc ++# include ++# undef findidx ++# define FINDIDX findidxwc ++# else ++# ifdef MBS_SUPPORT ++# define WCHAR ++# define INSIDE_RECURSION ++# include "xregex.c" ++# undef INSIDE_RECURSION ++# endif ++# define BYTE ++# define INSIDE_RECURSION ++# include "xregex.c" ++# undef INSIDE_RECURSION ++# endif ++#endif ++ ++#ifdef INSIDE_RECURSION ++/* Common operations on the compiled pattern. */ ++ ++/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ ++/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ ++ ++# ifdef WCHAR ++# define STORE_NUMBER(destination, number) \ ++ do { \ ++ *(destination) = (UCHAR_T)(number); \ ++ } while (0) ++# else /* BYTE */ ++# define STORE_NUMBER(destination, number) \ ++ do { \ ++ (destination)[0] = (number) & 0377; \ ++ (destination)[1] = (number) >> 8; \ ++ } while (0) ++# endif /* WCHAR */ ++ ++/* Same as STORE_NUMBER, except increment DESTINATION to ++ the byte after where the number is stored. Therefore, DESTINATION ++ must be an lvalue. */ ++/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ ++ ++# define STORE_NUMBER_AND_INCR(destination, number) \ ++ do { \ ++ STORE_NUMBER (destination, number); \ ++ (destination) += OFFSET_ADDRESS_SIZE; \ ++ } while (0) ++ ++/* Put into DESTINATION a number stored in two contiguous bytes starting ++ at SOURCE. */ ++/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ ++ ++# ifdef WCHAR ++# define EXTRACT_NUMBER(destination, source) \ ++ do { \ ++ (destination) = *(source); \ ++ } while (0) ++# else /* BYTE */ ++# define EXTRACT_NUMBER(destination, source) \ ++ do { \ ++ (destination) = *(source) & 0377; \ ++ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ ++ } while (0) ++# endif ++ ++# ifdef DEBUG ++static void PREFIX(extract_number) (int *dest, UCHAR_T *source); ++static void ++PREFIX(extract_number) (int *dest, UCHAR_T *source) ++{ ++# ifdef WCHAR ++ *dest = *source; ++# else /* BYTE */ ++ int temp = SIGN_EXTEND_CHAR (*(source + 1)); ++ *dest = *source & 0377; ++ *dest += temp << 8; ++# endif ++} ++ ++# ifndef EXTRACT_MACROS /* To debug the macros. */ ++# undef EXTRACT_NUMBER ++# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) ++# endif /* not EXTRACT_MACROS */ ++ ++# endif /* DEBUG */ ++ ++/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. ++ SOURCE must be an lvalue. */ ++ ++# define EXTRACT_NUMBER_AND_INCR(destination, source) \ ++ do { \ ++ EXTRACT_NUMBER (destination, source); \ ++ (source) += OFFSET_ADDRESS_SIZE; \ ++ } while (0) ++ ++# ifdef DEBUG ++static void PREFIX(extract_number_and_incr) (int *destination, ++ UCHAR_T **source); ++static void ++PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source) ++{ ++ PREFIX(extract_number) (destination, *source); ++ *source += OFFSET_ADDRESS_SIZE; ++} ++ ++# ifndef EXTRACT_MACROS ++# undef EXTRACT_NUMBER_AND_INCR ++# define EXTRACT_NUMBER_AND_INCR(dest, src) \ ++ PREFIX(extract_number_and_incr) (&dest, &src) ++# endif /* not EXTRACT_MACROS */ ++ ++# endif /* DEBUG */ ++ ++ ++ ++/* If DEBUG is defined, Regex prints many voluminous messages about what ++ it is doing (if the variable `debug' is nonzero). If linked with the ++ main program in `iregex.c', you can enter patterns and strings ++ interactively. And if linked with the main program in `main.c' and ++ the other test files, you can run the already-written tests. */ ++ ++# ifdef DEBUG ++ ++# ifndef DEFINED_ONCE ++ ++/* We use standard I/O for debugging. */ ++# include ++ ++/* It is useful to test things that ``must'' be true when debugging. */ ++# include ++ ++static int debug; ++ ++# define DEBUG_STATEMENT(e) e ++# define DEBUG_PRINT1(x) if (debug) printf (x) ++# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) ++# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) ++# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) ++# endif /* not DEFINED_ONCE */ ++ ++# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ ++ if (debug) PREFIX(print_partial_compiled_pattern) (s, e) ++# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ ++ if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) ++ ++ ++/* Print the fastmap in human-readable form. */ ++ ++# ifndef DEFINED_ONCE ++void ++print_fastmap (char *fastmap) ++{ ++ unsigned was_a_range = 0; ++ unsigned i = 0; ++ ++ while (i < (1 << BYTEWIDTH)) ++ { ++ if (fastmap[i++]) ++ { ++ was_a_range = 0; ++ putchar (i - 1); ++ while (i < (1 << BYTEWIDTH) && fastmap[i]) ++ { ++ was_a_range = 1; ++ i++; ++ } ++ if (was_a_range) ++ { ++ printf ("-"); ++ putchar (i - 1); ++ } ++ } ++ } ++ putchar ('\n'); ++} ++# endif /* not DEFINED_ONCE */ ++ ++ ++/* Print a compiled pattern string in human-readable form, starting at ++ the START pointer into it and ending just before the pointer END. */ ++ ++void ++PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end) ++{ ++ int mcnt, mcnt2; ++ UCHAR_T *p1; ++ UCHAR_T *p = start; ++ UCHAR_T *pend = end; ++ ++ if (start == NULL) ++ { ++ printf ("(null)\n"); ++ return; ++ } ++ ++ /* Loop over pattern commands. */ ++ while (p < pend) ++ { ++# ifdef _LIBC ++ printf ("%td:\t", p - start); ++# else ++ printf ("%ld:\t", (long int) (p - start)); ++# endif ++ ++ switch ((re_opcode_t) *p++) ++ { ++ case no_op: ++ printf ("/no_op"); ++ break; ++ ++ case exactn: ++ mcnt = *p++; ++ printf ("/exactn/%d", mcnt); ++ do ++ { ++ putchar ('/'); ++ PUT_CHAR (*p++); ++ } ++ while (--mcnt); ++ break; ++ ++# ifdef MBS_SUPPORT ++ case exactn_bin: ++ mcnt = *p++; ++ printf ("/exactn_bin/%d", mcnt); ++ do ++ { ++ printf("/%lx", (long int) *p++); ++ } ++ while (--mcnt); ++ break; ++# endif /* MBS_SUPPORT */ ++ ++ case start_memory: ++ mcnt = *p++; ++ printf ("/start_memory/%d/%ld", mcnt, (long int) *p++); ++ break; ++ ++ case stop_memory: ++ mcnt = *p++; ++ printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++); ++ break; ++ ++ case duplicate: ++ printf ("/duplicate/%ld", (long int) *p++); ++ break; ++ ++ case anychar: ++ printf ("/anychar"); ++ break; ++ ++ case charset: ++ case charset_not: ++ { ++# ifdef WCHAR ++ int i, length; ++ wchar_t *workp = p; ++ printf ("/charset [%s", ++ (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); ++ p += 5; ++ length = *workp++; /* the length of char_classes */ ++ for (i=0 ; ibuffer; ++ ++ PREFIX(print_partial_compiled_pattern) (buffer, buffer ++ + bufp->used / sizeof(UCHAR_T)); ++ printf ("%ld bytes used/%ld bytes allocated.\n", ++ bufp->used, bufp->allocated); ++ ++ if (bufp->fastmap_accurate && bufp->fastmap) ++ { ++ printf ("fastmap: "); ++ print_fastmap (bufp->fastmap); ++ } ++ ++# ifdef _LIBC ++ printf ("re_nsub: %Zd\t", bufp->re_nsub); ++# else ++ printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); ++# endif ++ printf ("regs_alloc: %d\t", bufp->regs_allocated); ++ printf ("can_be_null: %d\t", bufp->can_be_null); ++ printf ("newline_anchor: %d\n", bufp->newline_anchor); ++ printf ("no_sub: %d\t", bufp->no_sub); ++ printf ("not_bol: %d\t", bufp->not_bol); ++ printf ("not_eol: %d\t", bufp->not_eol); ++ printf ("syntax: %lx\n", bufp->syntax); ++ /* Perhaps we should print the translate table? */ ++} ++ ++ ++void ++PREFIX(print_double_string) (const CHAR_T *where, const CHAR_T *string1, ++ int size1, const CHAR_T *string2, int size2) ++{ ++ int this_char; ++ ++ if (where == NULL) ++ printf ("(null)"); ++ else ++ { ++ int cnt; ++ ++ if (FIRST_STRING_P (where)) ++ { ++ for (this_char = where - string1; this_char < size1; this_char++) ++ PUT_CHAR (string1[this_char]); ++ ++ where = string2; ++ } ++ ++ cnt = 0; ++ for (this_char = where - string2; this_char < size2; this_char++) ++ { ++ PUT_CHAR (string2[this_char]); ++ if (++cnt > 100) ++ { ++ fputs ("...", stdout); ++ break; ++ } ++ } ++ } ++} ++ ++# ifndef DEFINED_ONCE ++void ++printchar (int c) ++{ ++ putc (c, stderr); ++} ++# endif ++ ++# else /* not DEBUG */ ++ ++# ifndef DEFINED_ONCE ++# undef assert ++# define assert(e) ++ ++# define DEBUG_STATEMENT(e) ++# define DEBUG_PRINT1(x) ++# define DEBUG_PRINT2(x1, x2) ++# define DEBUG_PRINT3(x1, x2, x3) ++# define DEBUG_PRINT4(x1, x2, x3, x4) ++# endif /* not DEFINED_ONCE */ ++# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) ++# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) ++ ++# endif /* not DEBUG */ ++ ++ ++ ++# ifdef WCHAR ++/* This convert a multibyte string to a wide character string. ++ And write their correspondances to offset_buffer(see below) ++ and write whether each wchar_t is binary data to is_binary. ++ This assume invalid multibyte sequences as binary data. ++ We assume offset_buffer and is_binary is already allocated ++ enough space. */ ++ ++static size_t convert_mbs_to_wcs (CHAR_T *dest, const unsigned char* src, ++ size_t len, int *offset_buffer, ++ char *is_binary); ++static size_t ++convert_mbs_to_wcs (CHAR_T *dest, const unsigned char*src, size_t len, ++ int *offset_buffer, char *is_binary) ++ /* It hold correspondances between src(char string) and ++ dest(wchar_t string) for optimization. ++ e.g. src = "xxxyzz" ++ dest = {'X', 'Y', 'Z'} ++ (each "xxx", "y" and "zz" represent one multibyte character ++ corresponding to 'X', 'Y' and 'Z'.) ++ offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} ++ = {0, 3, 4, 6} ++ */ ++{ ++ wchar_t *pdest = dest; ++ const unsigned char *psrc = src; ++ size_t wc_count = 0; ++ ++ mbstate_t mbs; ++ int i, consumed; ++ size_t mb_remain = len; ++ size_t mb_count = 0; ++ ++ /* Initialize the conversion state. */ ++ memset (&mbs, 0, sizeof (mbstate_t)); ++ ++ offset_buffer[0] = 0; ++ for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, ++ psrc += consumed) ++ { ++#ifdef _LIBC ++ consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs); ++#else ++ consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); ++#endif ++ ++ if (consumed <= 0) ++ /* failed to convert. maybe src contains binary data. ++ So we consume 1 byte manualy. */ ++ { ++ *pdest = *psrc; ++ consumed = 1; ++ is_binary[wc_count] = TRUE; ++ } ++ else ++ is_binary[wc_count] = FALSE; ++ /* In sjis encoding, we use yen sign as escape character in ++ place of reverse solidus. So we convert 0x5c(yen sign in ++ sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse ++ solidus in UCS2). */ ++ if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) ++ *pdest = (wchar_t) *psrc; ++ ++ offset_buffer[wc_count + 1] = mb_count += consumed; ++ } ++ ++ /* Fill remain of the buffer with sentinel. */ ++ for (i = wc_count + 1 ; i <= len ; i++) ++ offset_buffer[i] = mb_count + 1; ++ ++ return wc_count; ++} ++ ++# endif /* WCHAR */ ++ ++#else /* not INSIDE_RECURSION */ ++ ++/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can ++ also be assigned to arbitrarily: each pattern buffer stores its own ++ syntax, so it can be changed between regex compilations. */ ++/* This has no initializer because initialized variables in Emacs ++ become read-only after dumping. */ ++reg_syntax_t re_syntax_options; ++ ++ ++/* Specify the precise syntax of regexps for compilation. This provides ++ for compatibility for various utilities which historically have ++ different, incompatible syntaxes. ++ ++ The argument SYNTAX is a bit mask comprised of the various bits ++ defined in regex.h. We return the old syntax. */ ++ ++reg_syntax_t ++re_set_syntax (reg_syntax_t syntax) ++{ ++ reg_syntax_t ret = re_syntax_options; ++ ++ re_syntax_options = syntax; ++# ifdef DEBUG ++ if (syntax & RE_DEBUG) ++ debug = 1; ++ else if (debug) /* was on but now is not */ ++ debug = 0; ++# endif /* DEBUG */ ++ return ret; ++} ++# ifdef _LIBC ++weak_alias (__re_set_syntax, re_set_syntax) ++# endif ++ ++/* This table gives an error message for each of the error codes listed ++ in regex.h. Obviously the order here has to be same as there. ++ POSIX doesn't require that we do anything for REG_NOERROR, ++ but why not be nice? */ ++ ++static const char *re_error_msgid[] = ++ { ++ gettext_noop ("Success"), /* REG_NOERROR */ ++ gettext_noop ("No match"), /* REG_NOMATCH */ ++ gettext_noop ("Invalid regular expression"), /* REG_BADPAT */ ++ gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */ ++ gettext_noop ("Invalid character class name"), /* REG_ECTYPE */ ++ gettext_noop ("Trailing backslash"), /* REG_EESCAPE */ ++ gettext_noop ("Invalid back reference"), /* REG_ESUBREG */ ++ gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */ ++ gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */ ++ gettext_noop ("Unmatched \\{"), /* REG_EBRACE */ ++ gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */ ++ gettext_noop ("Invalid range end"), /* REG_ERANGE */ ++ gettext_noop ("Memory exhausted"), /* REG_ESPACE */ ++ gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */ ++ gettext_noop ("Premature end of regular expression"), /* REG_EEND */ ++ gettext_noop ("Regular expression too big"), /* REG_ESIZE */ ++ gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ ++ }; ++ ++#endif /* INSIDE_RECURSION */ ++ ++#ifndef DEFINED_ONCE ++/* Avoiding alloca during matching, to placate r_alloc. */ ++ ++/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the ++ searching and matching functions should not call alloca. On some ++ systems, alloca is implemented in terms of malloc, and if we're ++ using the relocating allocator routines, then malloc could cause a ++ relocation, which might (if the strings being searched are in the ++ ralloc heap) shift the data out from underneath the regexp ++ routines. ++ ++ Here's another reason to avoid allocation: Emacs ++ processes input from X in a signal handler; processing X input may ++ call malloc; if input arrives while a matching routine is calling ++ malloc, then we're scrod. But Emacs can't just block input while ++ calling matching routines; then we don't notice interrupts when ++ they come in. So, Emacs blocks input around all regexp calls ++ except the matching calls, which it leaves unprotected, in the ++ faith that they will not malloc. */ ++ ++/* Normally, this is fine. */ ++# define MATCH_MAY_ALLOCATE ++ ++/* When using GNU C, we are not REALLY using the C alloca, no matter ++ what config.h may say. So don't take precautions for it. */ ++# ifdef __GNUC__ ++# undef C_ALLOCA ++# endif ++ ++/* The match routines may not allocate if (1) they would do it with malloc ++ and (2) it's not safe for them to use malloc. ++ Note that if REL_ALLOC is defined, matching would not use malloc for the ++ failure stack, but we would still use it for the register vectors; ++ so REL_ALLOC should not affect this. */ ++# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs ++# undef MATCH_MAY_ALLOCATE ++# endif ++#endif /* not DEFINED_ONCE */ ++ ++#ifdef INSIDE_RECURSION ++/* Failure stack declarations and macros; both re_compile_fastmap and ++ re_match_2 use a failure stack. These have to be macros because of ++ REGEX_ALLOCATE_STACK. */ ++ ++ ++/* Number of failure points for which to initially allocate space ++ when matching. If this number is exceeded, we allocate more ++ space, so it is not a hard limit. */ ++# ifndef INIT_FAILURE_ALLOC ++# define INIT_FAILURE_ALLOC 5 ++# endif ++ ++/* Roughly the maximum number of failure points on the stack. Would be ++ exactly that if always used MAX_FAILURE_ITEMS items each time we failed. ++ This is a variable only so users of regex can assign to it; we never ++ change it ourselves. */ ++ ++ ++# ifndef DEFINED_ONCE ++ ++# ifdef INT_IS_16BIT ++# define RE_M_F_TYPE long int ++# else ++# define RE_M_F_TYPE int ++# endif /* INT_IS_16BIT */ ++ ++# ifdef MATCH_MAY_ALLOCATE ++/* 4400 was enough to cause a crash on Alpha OSF/1, ++ whose default stack limit is 2mb. */ ++# define RE_M_F_DEFAULT 4000 ++# else ++# define RE_M_F_DEFAULT 2000 ++# endif /* MATCH_MAY_ALLOCATE */ ++ ++# include ++ ++# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) ++link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") ++RE_M_F_TYPE re_max_failures = RE_M_F_DEFAULT; ++# else ++RE_M_F_TYPE re_max_failures attribute_hidden = RE_M_F_DEFAULT; ++# endif /* SHLIB_COMPAT */ ++ ++# undef RE_M_F_TYPE ++# undef RE_M_F_DEFAULT ++ ++# endif /* DEFINED_ONCE */ ++ ++# ifdef INT_IS_16BIT ++ ++union PREFIX(fail_stack_elt) ++{ ++ UCHAR_T *pointer; ++ long int integer; ++}; ++ ++typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); ++ ++typedef struct ++{ ++ PREFIX(fail_stack_elt_t) *stack; ++ unsigned long int size; ++ unsigned long int avail; /* Offset of next open position. */ ++} PREFIX(fail_stack_type); ++ ++# else /* not INT_IS_16BIT */ ++ ++union PREFIX(fail_stack_elt) ++{ ++ UCHAR_T *pointer; ++ int integer; ++}; ++ ++typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); ++ ++typedef struct ++{ ++ PREFIX(fail_stack_elt_t) *stack; ++ unsigned size; ++ unsigned avail; /* Offset of next open position. */ ++} PREFIX(fail_stack_type); ++ ++# endif /* INT_IS_16BIT */ ++ ++# ifndef DEFINED_ONCE ++# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) ++# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) ++# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) ++# endif ++ ++ ++/* Define macros to initialize and free the failure stack. ++ Do `return -2' if the alloc fails. */ ++ ++# ifdef MATCH_MAY_ALLOCATE ++# define INIT_FAIL_STACK() \ ++ do { \ ++ fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ ++ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ ++ \ ++ if (fail_stack.stack == NULL) \ ++ return -2; \ ++ \ ++ fail_stack.size = INIT_FAILURE_ALLOC; \ ++ fail_stack.avail = 0; \ ++ } while (0) ++ ++# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) ++# else ++# define INIT_FAIL_STACK() \ ++ do { \ ++ fail_stack.avail = 0; \ ++ } while (0) ++ ++# define RESET_FAIL_STACK() ++# endif ++ ++ ++/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. ++ ++ Return 1 if succeeds, and 0 if either ran out of memory ++ allocating space for it or it was already too large. ++ ++ REGEX_REALLOCATE_STACK requires `destination' be declared. */ ++ ++# define DOUBLE_FAIL_STACK(fail_stack) \ ++ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ ++ ? 0 \ ++ : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ ++ REGEX_REALLOCATE_STACK ((fail_stack).stack, \ ++ (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ ++ ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ ++ \ ++ (fail_stack).stack == NULL \ ++ ? 0 \ ++ : ((fail_stack).size <<= 1, \ ++ 1))) ++ ++ ++/* Push pointer POINTER on FAIL_STACK. ++ Return 1 if was able to do so and 0 if ran out of memory allocating ++ space to do so. */ ++# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ ++ ((FAIL_STACK_FULL () \ ++ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ ++ ? 0 \ ++ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ ++ 1)) ++ ++/* Push a pointer value onto the failure stack. ++ Assumes the variable `fail_stack'. Probably should only ++ be called from within `PUSH_FAILURE_POINT'. */ ++# define PUSH_FAILURE_POINTER(item) \ ++ fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) ++ ++/* This pushes an integer-valued item onto the failure stack. ++ Assumes the variable `fail_stack'. Probably should only ++ be called from within `PUSH_FAILURE_POINT'. */ ++# define PUSH_FAILURE_INT(item) \ ++ fail_stack.stack[fail_stack.avail++].integer = (item) ++ ++/* Push a fail_stack_elt_t value onto the failure stack. ++ Assumes the variable `fail_stack'. Probably should only ++ be called from within `PUSH_FAILURE_POINT'. */ ++# define PUSH_FAILURE_ELT(item) \ ++ fail_stack.stack[fail_stack.avail++] = (item) ++ ++/* These three POP... operations complement the three PUSH... operations. ++ All assume that `fail_stack' is nonempty. */ ++# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer ++# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer ++# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] ++ ++/* Used to omit pushing failure point id's when we're not debugging. */ ++# ifdef DEBUG ++# define DEBUG_PUSH PUSH_FAILURE_INT ++# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () ++# else ++# define DEBUG_PUSH(item) ++# define DEBUG_POP(item_addr) ++# endif ++ ++ ++/* Push the information about the state we will need ++ if we ever fail back to it. ++ ++ Requires variables fail_stack, regstart, regend, reg_info, and ++ num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' ++ be declared. ++ ++ Does `return FAILURE_CODE' if runs out of memory. */ ++ ++# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ ++ do { \ ++ char *destination; \ ++ /* Must be int, so when we don't save any registers, the arithmetic \ ++ of 0 + -1 isn't done as unsigned. */ \ ++ /* Can't be int, since there is not a shred of a guarantee that int \ ++ is wide enough to hold a value of something to which pointer can \ ++ be assigned */ \ ++ active_reg_t this_reg; \ ++ \ ++ DEBUG_STATEMENT (failure_id++); \ ++ DEBUG_STATEMENT (nfailure_points_pushed++); \ ++ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ ++ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ ++ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ ++ \ ++ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ ++ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ ++ \ ++ /* Ensure we have enough space allocated for what we will push. */ \ ++ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ ++ { \ ++ if (!DOUBLE_FAIL_STACK (fail_stack)) \ ++ return failure_code; \ ++ \ ++ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ ++ (fail_stack).size); \ ++ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ ++ } \ ++ \ ++ /* Push the info, starting with the registers. */ \ ++ DEBUG_PRINT1 ("\n"); \ ++ \ ++ if (1) \ ++ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ ++ this_reg++) \ ++ { \ ++ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ ++ DEBUG_STATEMENT (num_regs_pushed++); \ ++ \ ++ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ ++ PUSH_FAILURE_POINTER (regstart[this_reg]); \ ++ \ ++ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ ++ PUSH_FAILURE_POINTER (regend[this_reg]); \ ++ \ ++ DEBUG_PRINT2 (" info: %p\n ", \ ++ reg_info[this_reg].word.pointer); \ ++ DEBUG_PRINT2 (" match_null=%d", \ ++ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ ++ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ ++ DEBUG_PRINT2 (" matched_something=%d", \ ++ MATCHED_SOMETHING (reg_info[this_reg])); \ ++ DEBUG_PRINT2 (" ever_matched=%d", \ ++ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ ++ DEBUG_PRINT1 ("\n"); \ ++ PUSH_FAILURE_ELT (reg_info[this_reg].word); \ ++ } \ ++ \ ++ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ ++ PUSH_FAILURE_INT (lowest_active_reg); \ ++ \ ++ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ ++ PUSH_FAILURE_INT (highest_active_reg); \ ++ \ ++ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ ++ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ ++ PUSH_FAILURE_POINTER (pattern_place); \ ++ \ ++ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ ++ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ ++ size2); \ ++ DEBUG_PRINT1 ("'\n"); \ ++ PUSH_FAILURE_POINTER (string_place); \ ++ \ ++ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ ++ DEBUG_PUSH (failure_id); \ ++ } while (0) ++ ++# ifndef DEFINED_ONCE ++/* This is the number of items that are pushed and popped on the stack ++ for each register. */ ++# define NUM_REG_ITEMS 3 ++ ++/* Individual items aside from the registers. */ ++# ifdef DEBUG ++# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ ++# else ++# define NUM_NONREG_ITEMS 4 ++# endif ++ ++/* We push at most this many items on the stack. */ ++/* We used to use (num_regs - 1), which is the number of registers ++ this regexp will save; but that was changed to 5 ++ to avoid stack overflow for a regexp with lots of parens. */ ++# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) ++ ++/* We actually push this many items. */ ++# define NUM_FAILURE_ITEMS \ ++ (((0 \ ++ ? 0 : highest_active_reg - lowest_active_reg + 1) \ ++ * NUM_REG_ITEMS) \ ++ + NUM_NONREG_ITEMS) ++ ++/* How many items can still be added to the stack without overflowing it. */ ++# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) ++# endif /* not DEFINED_ONCE */ ++ ++ ++/* Pops what PUSH_FAIL_STACK pushes. ++ ++ We restore into the parameters, all of which should be lvalues: ++ STR -- the saved data position. ++ PAT -- the saved pattern position. ++ LOW_REG, HIGH_REG -- the highest and lowest active registers. ++ REGSTART, REGEND -- arrays of string positions. ++ REG_INFO -- array of information about each subexpression. ++ ++ Also assumes the variables `fail_stack' and (if debugging), `bufp', ++ `pend', `string1', `size1', `string2', and `size2'. */ ++# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ ++{ \ ++ DEBUG_STATEMENT (unsigned failure_id;) \ ++ active_reg_t this_reg; \ ++ const UCHAR_T *string_temp; \ ++ \ ++ assert (!FAIL_STACK_EMPTY ()); \ ++ \ ++ /* Remove failure points and point to how many regs pushed. */ \ ++ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ ++ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ ++ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ ++ \ ++ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ ++ \ ++ DEBUG_POP (&failure_id); \ ++ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ ++ \ ++ /* If the saved string location is NULL, it came from an \ ++ on_failure_keep_string_jump opcode, and we want to throw away the \ ++ saved NULL, thus retaining our current position in the string. */ \ ++ string_temp = POP_FAILURE_POINTER (); \ ++ if (string_temp != NULL) \ ++ str = (const CHAR_T *) string_temp; \ ++ \ ++ DEBUG_PRINT2 (" Popping string %p: `", str); \ ++ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ ++ DEBUG_PRINT1 ("'\n"); \ ++ \ ++ pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ ++ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ ++ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ ++ \ ++ /* Restore register info. */ \ ++ high_reg = (active_reg_t) POP_FAILURE_INT (); \ ++ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ ++ \ ++ low_reg = (active_reg_t) POP_FAILURE_INT (); \ ++ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ ++ \ ++ if (1) \ ++ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ ++ { \ ++ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ ++ \ ++ reg_info[this_reg].word = POP_FAILURE_ELT (); \ ++ DEBUG_PRINT2 (" info: %p\n", \ ++ reg_info[this_reg].word.pointer); \ ++ \ ++ regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ ++ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ ++ \ ++ regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ ++ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ ++ } \ ++ else \ ++ { \ ++ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ ++ { \ ++ reg_info[this_reg].word.integer = 0; \ ++ regend[this_reg] = 0; \ ++ regstart[this_reg] = 0; \ ++ } \ ++ highest_active_reg = high_reg; \ ++ } \ ++ \ ++ set_regs_matched_done = 0; \ ++ DEBUG_STATEMENT (nfailure_points_popped++); \ ++} /* POP_FAILURE_POINT */ ++ ++/* Structure for per-register (a.k.a. per-group) information. ++ Other register information, such as the ++ starting and ending positions (which are addresses), and the list of ++ inner groups (which is a bits list) are maintained in separate ++ variables. ++ ++ We are making a (strictly speaking) nonportable assumption here: that ++ the compiler will pack our bit fields into something that fits into ++ the type of `word', i.e., is something that fits into one item on the ++ failure stack. */ ++ ++ ++/* Declarations and macros for re_match_2. */ ++ ++typedef union ++{ ++ PREFIX(fail_stack_elt_t) word; ++ struct ++ { ++ /* This field is one if this group can match the empty string, ++ zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ ++# define MATCH_NULL_UNSET_VALUE 3 ++ unsigned match_null_string_p : 2; ++ unsigned is_active : 1; ++ unsigned matched_something : 1; ++ unsigned ever_matched_something : 1; ++ } bits; ++} PREFIX(register_info_type); ++ ++# ifndef DEFINED_ONCE ++# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) ++# define IS_ACTIVE(R) ((R).bits.is_active) ++# define MATCHED_SOMETHING(R) ((R).bits.matched_something) ++# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) ++ ++ ++/* Call this when have matched a real character; it sets `matched' flags ++ for the subexpressions which we are currently inside. Also records ++ that those subexprs have matched. */ ++# define SET_REGS_MATCHED() \ ++ do \ ++ { \ ++ if (!set_regs_matched_done) \ ++ { \ ++ active_reg_t r; \ ++ set_regs_matched_done = 1; \ ++ for (r = lowest_active_reg; r <= highest_active_reg; r++) \ ++ { \ ++ MATCHED_SOMETHING (reg_info[r]) \ ++ = EVER_MATCHED_SOMETHING (reg_info[r]) \ ++ = 1; \ ++ } \ ++ } \ ++ } \ ++ while (0) ++# endif /* not DEFINED_ONCE */ ++ ++/* Registers are set to a sentinel when they haven't yet matched. */ ++static CHAR_T PREFIX(reg_unset_dummy); ++# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) ++# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) ++ ++/* Subroutine declarations and macros for regex_compile. */ ++static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg); ++static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, ++ int arg1, int arg2); ++static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, ++ int arg, UCHAR_T *end); ++static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, ++ int arg1, int arg2, UCHAR_T *end); ++static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern, ++ const CHAR_T *p, ++ reg_syntax_t syntax); ++static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p, ++ const CHAR_T *pend, ++ reg_syntax_t syntax); ++# ifdef WCHAR ++static reg_errcode_t wcs_compile_range (CHAR_T range_start, ++ const CHAR_T **p_ptr, ++ const CHAR_T *pend, ++ char *translate, ++ reg_syntax_t syntax, ++ UCHAR_T *b, ++ CHAR_T *char_set); ++static void insert_space (int num, CHAR_T *loc, CHAR_T *end); ++# else /* BYTE */ ++static reg_errcode_t byte_compile_range (unsigned int range_start, ++ const char **p_ptr, ++ const char *pend, ++ RE_TRANSLATE_TYPE translate, ++ reg_syntax_t syntax, ++ unsigned char *b); ++# endif /* WCHAR */ ++ ++/* Fetch the next character in the uncompiled pattern---translating it ++ if necessary. Also cast from a signed character in the constant ++ string passed to us by the user to an unsigned char that we can use ++ as an array index (in, e.g., `translate'). */ ++/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, ++ because it is impossible to allocate 4GB array for some encodings ++ which have 4 byte character_set like UCS4. */ ++# ifndef PATFETCH ++# ifdef WCHAR ++# define PATFETCH(c) \ ++ do {if (p == pend) return REG_EEND; \ ++ c = (UCHAR_T) *p++; \ ++ if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ ++ } while (0) ++# else /* BYTE */ ++# define PATFETCH(c) \ ++ do {if (p == pend) return REG_EEND; \ ++ c = (unsigned char) *p++; \ ++ if (translate) c = (unsigned char) translate[c]; \ ++ } while (0) ++# endif /* WCHAR */ ++# endif ++ ++/* Fetch the next character in the uncompiled pattern, with no ++ translation. */ ++# define PATFETCH_RAW(c) \ ++ do {if (p == pend) return REG_EEND; \ ++ c = (UCHAR_T) *p++; \ ++ } while (0) ++ ++/* Go backwards one character in the pattern. */ ++# define PATUNFETCH p-- ++ ++ ++/* If `translate' is non-null, return translate[D], else just D. We ++ cast the subscript to translate because some data is declared as ++ `char *', to avoid warnings when a string constant is passed. But ++ when we use a character as a subscript we must make it unsigned. */ ++/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, ++ because it is impossible to allocate 4GB array for some encodings ++ which have 4 byte character_set like UCS4. */ ++ ++# ifndef TRANSLATE ++# ifdef WCHAR ++# define TRANSLATE(d) \ ++ ((translate && ((UCHAR_T) (d)) <= 0xff) \ ++ ? (char) translate[(unsigned char) (d)] : (d)) ++# else /* BYTE */ ++# define TRANSLATE(d) \ ++ (translate ? (char) translate[(unsigned char) (d)] : (char) (d)) ++# endif /* WCHAR */ ++# endif ++ ++ ++/* Macros for outputting the compiled pattern into `buffer'. */ ++ ++/* If the buffer isn't allocated when it comes in, use this. */ ++# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) ++ ++/* Make sure we have at least N more bytes of space in buffer. */ ++# ifdef WCHAR ++# define GET_BUFFER_SPACE(n) \ ++ while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ ++ + (n)*sizeof(CHAR_T)) > bufp->allocated) \ ++ EXTEND_BUFFER () ++# else /* BYTE */ ++# define GET_BUFFER_SPACE(n) \ ++ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ ++ EXTEND_BUFFER () ++# endif /* WCHAR */ ++ ++/* Make sure we have one more byte of buffer space and then add C to it. */ ++# define BUF_PUSH(c) \ ++ do { \ ++ GET_BUFFER_SPACE (1); \ ++ *b++ = (UCHAR_T) (c); \ ++ } while (0) ++ ++ ++/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ ++# define BUF_PUSH_2(c1, c2) \ ++ do { \ ++ GET_BUFFER_SPACE (2); \ ++ *b++ = (UCHAR_T) (c1); \ ++ *b++ = (UCHAR_T) (c2); \ ++ } while (0) ++ ++ ++/* As with BUF_PUSH_2, except for three bytes. */ ++# define BUF_PUSH_3(c1, c2, c3) \ ++ do { \ ++ GET_BUFFER_SPACE (3); \ ++ *b++ = (UCHAR_T) (c1); \ ++ *b++ = (UCHAR_T) (c2); \ ++ *b++ = (UCHAR_T) (c3); \ ++ } while (0) ++ ++/* Store a jump with opcode OP at LOC to location TO. We store a ++ relative address offset by the three bytes the jump itself occupies. */ ++# define STORE_JUMP(op, loc, to) \ ++ PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) ++ ++/* Likewise, for a two-argument jump. */ ++# define STORE_JUMP2(op, loc, to, arg) \ ++ PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) ++ ++/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ ++# define INSERT_JUMP(op, loc, to) \ ++ PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) ++ ++/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ ++# define INSERT_JUMP2(op, loc, to, arg) \ ++ PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ ++ arg, b) ++ ++/* This is not an arbitrary limit: the arguments which represent offsets ++ into the pattern are two bytes long. So if 2^16 bytes turns out to ++ be too small, many things would have to change. */ ++/* Any other compiler which, like MSC, has allocation limit below 2^16 ++ bytes will have to use approach similar to what was done below for ++ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up ++ reallocating to 0 bytes. Such thing is not going to work too well. ++ You have been warned!! */ ++# ifndef DEFINED_ONCE ++# if defined _MSC_VER && !defined WIN32 ++/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. ++ The REALLOC define eliminates a flurry of conversion warnings, ++ but is not required. */ ++# define MAX_BUF_SIZE 65500L ++# define REALLOC(p,s) realloc ((p), (size_t) (s)) ++# else ++# define MAX_BUF_SIZE (1L << 16) ++# define REALLOC(p,s) realloc ((p), (s)) ++# endif ++ ++/* Extend the buffer by twice its current size via realloc and ++ reset the pointers that pointed into the old block to point to the ++ correct places in the new one. If extending the buffer results in it ++ being larger than MAX_BUF_SIZE, then flag memory exhausted. */ ++# ifndef __BOUNDED_POINTERS__ ++# define __BOUNDED_POINTERS__ 0 ++# endif ++# if __BOUNDED_POINTERS__ ++# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) ++# define MOVE_BUFFER_POINTER(P) \ ++ (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) ++# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ ++ else \ ++ { \ ++ SET_HIGH_BOUND (b); \ ++ SET_HIGH_BOUND (begalt); \ ++ if (fixup_alt_jump) \ ++ SET_HIGH_BOUND (fixup_alt_jump); \ ++ if (laststart) \ ++ SET_HIGH_BOUND (laststart); \ ++ if (pending_exact) \ ++ SET_HIGH_BOUND (pending_exact); \ ++ } ++# else ++# define MOVE_BUFFER_POINTER(P) (P) += incr ++# define ELSE_EXTEND_BUFFER_HIGH_BOUND ++# endif ++# endif /* not DEFINED_ONCE */ ++ ++# ifdef WCHAR ++# define EXTEND_BUFFER() \ ++ do { \ ++ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ ++ int wchar_count; \ ++ if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ ++ return REG_ESIZE; \ ++ bufp->allocated <<= 1; \ ++ if (bufp->allocated > MAX_BUF_SIZE) \ ++ bufp->allocated = MAX_BUF_SIZE; \ ++ /* How many characters the new buffer can have? */ \ ++ wchar_count = bufp->allocated / sizeof(UCHAR_T); \ ++ if (wchar_count == 0) wchar_count = 1; \ ++ /* Truncate the buffer to CHAR_T align. */ \ ++ bufp->allocated = wchar_count * sizeof(UCHAR_T); \ ++ RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ ++ bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ ++ if (COMPILED_BUFFER_VAR == NULL) \ ++ return REG_ESPACE; \ ++ /* If the buffer moved, move all the pointers into it. */ \ ++ if (old_buffer != COMPILED_BUFFER_VAR) \ ++ { \ ++ int incr = COMPILED_BUFFER_VAR - old_buffer; \ ++ MOVE_BUFFER_POINTER (b); \ ++ MOVE_BUFFER_POINTER (begalt); \ ++ if (fixup_alt_jump) \ ++ MOVE_BUFFER_POINTER (fixup_alt_jump); \ ++ if (laststart) \ ++ MOVE_BUFFER_POINTER (laststart); \ ++ if (pending_exact) \ ++ MOVE_BUFFER_POINTER (pending_exact); \ ++ } \ ++ ELSE_EXTEND_BUFFER_HIGH_BOUND \ ++ } while (0) ++# else /* BYTE */ ++# define EXTEND_BUFFER() \ ++ do { \ ++ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ ++ if (bufp->allocated == MAX_BUF_SIZE) \ ++ return REG_ESIZE; \ ++ bufp->allocated <<= 1; \ ++ if (bufp->allocated > MAX_BUF_SIZE) \ ++ bufp->allocated = MAX_BUF_SIZE; \ ++ bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \ ++ bufp->allocated); \ ++ if (COMPILED_BUFFER_VAR == NULL) \ ++ return REG_ESPACE; \ ++ /* If the buffer moved, move all the pointers into it. */ \ ++ if (old_buffer != COMPILED_BUFFER_VAR) \ ++ { \ ++ int incr = COMPILED_BUFFER_VAR - old_buffer; \ ++ MOVE_BUFFER_POINTER (b); \ ++ MOVE_BUFFER_POINTER (begalt); \ ++ if (fixup_alt_jump) \ ++ MOVE_BUFFER_POINTER (fixup_alt_jump); \ ++ if (laststart) \ ++ MOVE_BUFFER_POINTER (laststart); \ ++ if (pending_exact) \ ++ MOVE_BUFFER_POINTER (pending_exact); \ ++ } \ ++ ELSE_EXTEND_BUFFER_HIGH_BOUND \ ++ } while (0) ++# endif /* WCHAR */ ++ ++# ifndef DEFINED_ONCE ++/* Since we have one byte reserved for the register number argument to ++ {start,stop}_memory, the maximum number of groups we can report ++ things about is what fits in that byte. */ ++# define MAX_REGNUM 255 ++ ++/* But patterns can have more than `MAX_REGNUM' registers. We just ++ ignore the excess. */ ++typedef unsigned regnum_t; ++ ++ ++/* Macros for the compile stack. */ ++ ++/* Since offsets can go either forwards or backwards, this type needs to ++ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ ++/* int may be not enough when sizeof(int) == 2. */ ++typedef long pattern_offset_t; ++ ++typedef struct ++{ ++ pattern_offset_t begalt_offset; ++ pattern_offset_t fixup_alt_jump; ++ pattern_offset_t inner_group_offset; ++ pattern_offset_t laststart_offset; ++ regnum_t regnum; ++} compile_stack_elt_t; ++ ++ ++typedef struct ++{ ++ compile_stack_elt_t *stack; ++ unsigned size; ++ unsigned avail; /* Offset of next open position. */ ++} compile_stack_type; ++ ++ ++# define INIT_COMPILE_STACK_SIZE 32 ++ ++# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) ++# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) ++ ++/* The next available element. */ ++# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) ++ ++# endif /* not DEFINED_ONCE */ ++ ++/* Set the bit for character C in a list. */ ++# ifndef DEFINED_ONCE ++# define SET_LIST_BIT(c) \ ++ (b[((unsigned char) (c)) / BYTEWIDTH] \ ++ |= 1 << (((unsigned char) c) % BYTEWIDTH)) ++# endif /* DEFINED_ONCE */ ++ ++/* Get the next unsigned number in the uncompiled pattern. */ ++# define GET_UNSIGNED_NUMBER(num) \ ++ { \ ++ while (p != pend) \ ++ { \ ++ PATFETCH (c); \ ++ if (c < '0' || c > '9') \ ++ break; \ ++ if (num <= RE_DUP_MAX) \ ++ { \ ++ if (num < 0) \ ++ num = 0; \ ++ num = num * 10 + c - '0'; \ ++ } \ ++ } \ ++ } ++ ++# ifndef DEFINED_ONCE ++# if WIDE_CHAR_SUPPORT ++/* The GNU C library provides support for user-defined character classes ++ and the functions from ISO C amendement 1. */ ++# ifdef CHARCLASS_NAME_MAX ++# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX ++# else ++/* This shouldn't happen but some implementation might still have this ++ problem. Use a reasonable default value. */ ++# define CHAR_CLASS_MAX_LENGTH 256 ++# endif ++ ++# ifdef _LIBC ++# define IS_CHAR_CLASS(string) __wctype (string) ++# else ++# define IS_CHAR_CLASS(string) wctype (string) ++# endif ++# else ++# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ ++ ++# define IS_CHAR_CLASS(string) \ ++ (STREQ (string, "alpha") || STREQ (string, "upper") \ ++ || STREQ (string, "lower") || STREQ (string, "digit") \ ++ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ ++ || STREQ (string, "space") || STREQ (string, "print") \ ++ || STREQ (string, "punct") || STREQ (string, "graph") \ ++ || STREQ (string, "cntrl") || STREQ (string, "blank")) ++# endif ++# endif /* DEFINED_ONCE */ ++ ++# ifndef MATCH_MAY_ALLOCATE ++ ++/* If we cannot allocate large objects within re_match_2_internal, ++ we make the fail stack and register vectors global. ++ The fail stack, we grow to the maximum size when a regexp ++ is compiled. ++ The register vectors, we adjust in size each time we ++ compile a regexp, according to the number of registers it needs. */ ++ ++static PREFIX(fail_stack_type) fail_stack; ++ ++/* Size with which the following vectors are currently allocated. ++ That is so we can make them bigger as needed, ++ but never make them smaller. */ ++# ifdef DEFINED_ONCE ++static int regs_allocated_size; ++ ++static const char ** regstart, ** regend; ++static const char ** old_regstart, ** old_regend; ++static const char **best_regstart, **best_regend; ++static const char **reg_dummy; ++# endif /* DEFINED_ONCE */ ++ ++static PREFIX(register_info_type) *PREFIX(reg_info); ++static PREFIX(register_info_type) *PREFIX(reg_info_dummy); ++ ++/* Make the register vectors big enough for NUM_REGS registers, ++ but don't make them smaller. */ ++ ++static void ++PREFIX(regex_grow_registers) (int num_regs) ++{ ++ if (num_regs > regs_allocated_size) ++ { ++ RETALLOC_IF (regstart, num_regs, const char *); ++ RETALLOC_IF (regend, num_regs, const char *); ++ RETALLOC_IF (old_regstart, num_regs, const char *); ++ RETALLOC_IF (old_regend, num_regs, const char *); ++ RETALLOC_IF (best_regstart, num_regs, const char *); ++ RETALLOC_IF (best_regend, num_regs, const char *); ++ RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); ++ RETALLOC_IF (reg_dummy, num_regs, const char *); ++ RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); ++ ++ regs_allocated_size = num_regs; ++ } ++} ++ ++# endif /* not MATCH_MAY_ALLOCATE */ ++ ++# ifndef DEFINED_ONCE ++static boolean group_in_compile_stack (compile_stack_type compile_stack, ++ regnum_t regnum); ++# endif /* not DEFINED_ONCE */ ++ ++/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. ++ Returns one of error codes defined in `regex.h', or zero for success. ++ ++ Assumes the `allocated' (and perhaps `buffer') and `translate' ++ fields are set in BUFP on entry. ++ ++ If it succeeds, results are put in BUFP (if it returns an error, the ++ contents of BUFP are undefined): ++ `buffer' is the compiled pattern; ++ `syntax' is set to SYNTAX; ++ `used' is set to the length of the compiled pattern; ++ `fastmap_accurate' is zero; ++ `re_nsub' is the number of subexpressions in PATTERN; ++ `not_bol' and `not_eol' are zero; ++ ++ The `fastmap' and `newline_anchor' fields are neither ++ examined nor set. */ ++ ++/* Return, freeing storage we allocated. */ ++# ifdef WCHAR ++# define FREE_STACK_RETURN(value) \ ++ return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) ++# else ++# define FREE_STACK_RETURN(value) \ ++ return (free (compile_stack.stack), value) ++# endif /* WCHAR */ ++ ++static reg_errcode_t ++PREFIX(regex_compile) (const char *ARG_PREFIX(pattern), ++ size_t ARG_PREFIX(size), reg_syntax_t syntax, ++ struct re_pattern_buffer *bufp) ++{ ++ /* We fetch characters from PATTERN here. Even though PATTERN is ++ `char *' (i.e., signed), we declare these variables as unsigned, so ++ they can be reliably used as array indices. */ ++ register UCHAR_T c, c1; ++ ++#ifdef WCHAR ++ /* A temporary space to keep wchar_t pattern and compiled pattern. */ ++ CHAR_T *pattern, *COMPILED_BUFFER_VAR; ++ size_t size; ++ /* offset buffer for optimization. See convert_mbs_to_wc. */ ++ int *mbs_offset = NULL; ++ /* It hold whether each wchar_t is binary data or not. */ ++ char *is_binary = NULL; ++ /* A flag whether exactn is handling binary data or not. */ ++ char is_exactn_bin = FALSE; ++#endif /* WCHAR */ ++ ++ /* A random temporary spot in PATTERN. */ ++ const CHAR_T *p1; ++ ++ /* Points to the end of the buffer, where we should append. */ ++ register UCHAR_T *b; ++ ++ /* Keeps track of unclosed groups. */ ++ compile_stack_type compile_stack; ++ ++ /* Points to the current (ending) position in the pattern. */ ++#ifdef WCHAR ++ const CHAR_T *p; ++ const CHAR_T *pend; ++#else /* BYTE */ ++ const CHAR_T *p = pattern; ++ const CHAR_T *pend = pattern + size; ++#endif /* WCHAR */ ++ ++ /* How to translate the characters in the pattern. */ ++ RE_TRANSLATE_TYPE translate = bufp->translate; ++ ++ /* Address of the count-byte of the most recently inserted `exactn' ++ command. This makes it possible to tell if a new exact-match ++ character can be added to that command or if the character requires ++ a new `exactn' command. */ ++ UCHAR_T *pending_exact = 0; ++ ++ /* Address of start of the most recently finished expression. ++ This tells, e.g., postfix * where to find the start of its ++ operand. Reset at the beginning of groups and alternatives. */ ++ UCHAR_T *laststart = 0; ++ ++ /* Address of beginning of regexp, or inside of last group. */ ++ UCHAR_T *begalt; ++ ++ /* Address of the place where a forward jump should go to the end of ++ the containing expression. Each alternative of an `or' -- except the ++ last -- ends with a forward jump of this sort. */ ++ UCHAR_T *fixup_alt_jump = 0; ++ ++ /* Counts open-groups as they are encountered. Remembered for the ++ matching close-group on the compile stack, so the same register ++ number is put in the stop_memory as the start_memory. */ ++ regnum_t regnum = 0; ++ ++#ifdef WCHAR ++ /* Initialize the wchar_t PATTERN and offset_buffer. */ ++ p = pend = pattern = TALLOC(csize + 1, CHAR_T); ++ mbs_offset = TALLOC(csize + 1, int); ++ is_binary = TALLOC(csize + 1, char); ++ if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) ++ { ++ free(pattern); ++ free(mbs_offset); ++ free(is_binary); ++ return REG_ESPACE; ++ } ++ pattern[csize] = L'\0'; /* sentinel */ ++ size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); ++ pend = p + size; ++ if (size < 0) ++ { ++ free(pattern); ++ free(mbs_offset); ++ free(is_binary); ++ return REG_BADPAT; ++ } ++#endif ++ ++#ifdef DEBUG ++ DEBUG_PRINT1 ("\nCompiling pattern: "); ++ if (debug) ++ { ++ unsigned debug_count; ++ ++ for (debug_count = 0; debug_count < size; debug_count++) ++ PUT_CHAR (pattern[debug_count]); ++ putchar ('\n'); ++ } ++#endif /* DEBUG */ ++ ++ /* Initialize the compile stack. */ ++ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); ++ if (compile_stack.stack == NULL) ++ { ++#ifdef WCHAR ++ free(pattern); ++ free(mbs_offset); ++ free(is_binary); ++#endif ++ return REG_ESPACE; ++ } ++ ++ compile_stack.size = INIT_COMPILE_STACK_SIZE; ++ compile_stack.avail = 0; ++ ++ /* Initialize the pattern buffer. */ ++ bufp->syntax = syntax; ++ bufp->fastmap_accurate = 0; ++ bufp->not_bol = bufp->not_eol = 0; ++ ++ /* Set `used' to zero, so that if we return an error, the pattern ++ printer (for debugging) will think there's no pattern. We reset it ++ at the end. */ ++ bufp->used = 0; ++ ++ /* Always count groups, whether or not bufp->no_sub is set. */ ++ bufp->re_nsub = 0; ++ ++#if !defined emacs && !defined SYNTAX_TABLE ++ /* Initialize the syntax table. */ ++ init_syntax_once (); ++#endif ++ ++ if (bufp->allocated == 0) ++ { ++ if (bufp->buffer) ++ { /* If zero allocated, but buffer is non-null, try to realloc ++ enough space. This loses if buffer's address is bogus, but ++ that is the user's responsibility. */ ++#ifdef WCHAR ++ /* Free bufp->buffer and allocate an array for wchar_t pattern ++ buffer. */ ++ free(bufp->buffer); ++ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), ++ UCHAR_T); ++#else ++ RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); ++#endif /* WCHAR */ ++ } ++ else ++ { /* Caller did not allocate a buffer. Do it for them. */ ++ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), ++ UCHAR_T); ++ } ++ ++ if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); ++#ifdef WCHAR ++ bufp->buffer = (char*)COMPILED_BUFFER_VAR; ++#endif /* WCHAR */ ++ bufp->allocated = INIT_BUF_SIZE; ++ } ++#ifdef WCHAR ++ else ++ COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; ++#endif ++ ++ begalt = b = COMPILED_BUFFER_VAR; ++ ++ /* Loop through the uncompiled pattern until we're at the end. */ ++ while (p != pend) ++ { ++ PATFETCH (c); ++ ++ switch (c) ++ { ++ case '^': ++ { ++ if ( /* If at start of pattern, it's an operator. */ ++ p == pattern + 1 ++ /* If context independent, it's an operator. */ ++ || syntax & RE_CONTEXT_INDEP_ANCHORS ++ /* Otherwise, depends on what's come before. */ ++ || PREFIX(at_begline_loc_p) (pattern, p, syntax)) ++ BUF_PUSH (begline); ++ else ++ goto normal_char; ++ } ++ break; ++ ++ ++ case '$': ++ { ++ if ( /* If at end of pattern, it's an operator. */ ++ p == pend ++ /* If context independent, it's an operator. */ ++ || syntax & RE_CONTEXT_INDEP_ANCHORS ++ /* Otherwise, depends on what's next. */ ++ || PREFIX(at_endline_loc_p) (p, pend, syntax)) ++ BUF_PUSH (endline); ++ else ++ goto normal_char; ++ } ++ break; ++ ++ ++ case '+': ++ case '?': ++ if ((syntax & RE_BK_PLUS_QM) ++ || (syntax & RE_LIMITED_OPS)) ++ goto normal_char; ++ handle_plus: ++ case '*': ++ /* If there is no previous pattern... */ ++ if (!laststart) ++ { ++ if (syntax & RE_CONTEXT_INVALID_OPS) ++ FREE_STACK_RETURN (REG_BADRPT); ++ else if (!(syntax & RE_CONTEXT_INDEP_OPS)) ++ goto normal_char; ++ } ++ ++ { ++ /* Are we optimizing this jump? */ ++ boolean keep_string_p = false; ++ ++ /* 1 means zero (many) matches is allowed. */ ++ char zero_times_ok = 0, many_times_ok = 0; ++ ++ /* If there is a sequence of repetition chars, collapse it ++ down to just one (the right one). We can't combine ++ interval operators with these because of, e.g., `a{2}*', ++ which should only match an even number of `a's. */ ++ ++ for (;;) ++ { ++ zero_times_ok |= c != '+'; ++ many_times_ok |= c != '?'; ++ ++ if (p == pend) ++ break; ++ ++ PATFETCH (c); ++ ++ if (c == '*' ++ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) ++ ; ++ ++ else if (syntax & RE_BK_PLUS_QM && c == '\\') ++ { ++ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); ++ ++ PATFETCH (c1); ++ if (!(c1 == '+' || c1 == '?')) ++ { ++ PATUNFETCH; ++ PATUNFETCH; ++ break; ++ } ++ ++ c = c1; ++ } ++ else ++ { ++ PATUNFETCH; ++ break; ++ } ++ ++ /* If we get here, we found another repeat character. */ ++ } ++ ++ /* Star, etc. applied to an empty pattern is equivalent ++ to an empty pattern. */ ++ if (!laststart) ++ break; ++ ++ /* Now we know whether or not zero matches is allowed ++ and also whether or not two or more matches is allowed. */ ++ if (many_times_ok) ++ { /* More than one repetition is allowed, so put in at the ++ end a backward relative jump from `b' to before the next ++ jump we're going to put in below (which jumps from ++ laststart to after this jump). ++ ++ But if we are at the `*' in the exact sequence `.*\n', ++ insert an unconditional jump backwards to the ., ++ instead of the beginning of the loop. This way we only ++ push a failure point once, instead of every time ++ through the loop. */ ++ assert (p - 1 > pattern); ++ ++ /* Allocate the space for the jump. */ ++ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); ++ ++ /* We know we are not at the first character of the pattern, ++ because laststart was nonzero. And we've already ++ incremented `p', by the way, to be the character after ++ the `*'. Do we have to do something analogous here ++ for null bytes, because of RE_DOT_NOT_NULL? */ ++ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') ++ && zero_times_ok ++ && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') ++ && !(syntax & RE_DOT_NEWLINE)) ++ { /* We have .*\n. */ ++ STORE_JUMP (jump, b, laststart); ++ keep_string_p = true; ++ } ++ else ++ /* Anything else. */ ++ STORE_JUMP (maybe_pop_jump, b, laststart - ++ (1 + OFFSET_ADDRESS_SIZE)); ++ ++ /* We've added more stuff to the buffer. */ ++ b += 1 + OFFSET_ADDRESS_SIZE; ++ } ++ ++ /* On failure, jump from laststart to b + 3, which will be the ++ end of the buffer after this jump is inserted. */ ++ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of ++ 'b + 3'. */ ++ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); ++ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump ++ : on_failure_jump, ++ laststart, b + 1 + OFFSET_ADDRESS_SIZE); ++ pending_exact = 0; ++ b += 1 + OFFSET_ADDRESS_SIZE; ++ ++ if (!zero_times_ok) ++ { ++ /* At least one repetition is required, so insert a ++ `dummy_failure_jump' before the initial ++ `on_failure_jump' instruction of the loop. This ++ effects a skip over that instruction the first time ++ we hit that loop. */ ++ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); ++ INSERT_JUMP (dummy_failure_jump, laststart, laststart + ++ 2 + 2 * OFFSET_ADDRESS_SIZE); ++ b += 1 + OFFSET_ADDRESS_SIZE; ++ } ++ } ++ break; ++ ++ ++ case '.': ++ laststart = b; ++ BUF_PUSH (anychar); ++ break; ++ ++ ++ case '[': ++ { ++ boolean had_char_class = false; ++#ifdef WCHAR ++ CHAR_T range_start = 0xffffffff; ++#else ++ unsigned int range_start = 0xffffffff; ++#endif ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++#ifdef WCHAR ++ /* We assume a charset(_not) structure as a wchar_t array. ++ charset[0] = (re_opcode_t) charset(_not) ++ charset[1] = l (= length of char_classes) ++ charset[2] = m (= length of collating_symbols) ++ charset[3] = n (= length of equivalence_classes) ++ charset[4] = o (= length of char_ranges) ++ charset[5] = p (= length of chars) ++ ++ charset[6] = char_class (wctype_t) ++ charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t) ++ ... ++ charset[l+5] = char_class (wctype_t) ++ ++ charset[l+6] = collating_symbol (wchar_t) ++ ... ++ charset[l+m+5] = collating_symbol (wchar_t) ++ ifdef _LIBC we use the index if ++ _NL_COLLATE_SYMB_EXTRAMB instead of ++ wchar_t string. ++ ++ charset[l+m+6] = equivalence_classes (wchar_t) ++ ... ++ charset[l+m+n+5] = equivalence_classes (wchar_t) ++ ifdef _LIBC we use the index in ++ _NL_COLLATE_WEIGHT instead of ++ wchar_t string. ++ ++ charset[l+m+n+6] = range_start ++ charset[l+m+n+7] = range_end ++ ... ++ charset[l+m+n+2o+4] = range_start ++ charset[l+m+n+2o+5] = range_end ++ ifdef _LIBC we use the value looked up ++ in _NL_COLLATE_COLLSEQ instead of ++ wchar_t character. ++ ++ charset[l+m+n+2o+6] = char ++ ... ++ charset[l+m+n+2o+p+5] = char ++ ++ */ ++ ++ /* We need at least 6 spaces: the opcode, the length of ++ char_classes, the length of collating_symbols, the length of ++ equivalence_classes, the length of char_ranges, the length of ++ chars. */ ++ GET_BUFFER_SPACE (6); ++ ++ /* Save b as laststart. And We use laststart as the pointer ++ to the first element of the charset here. ++ In other words, laststart[i] indicates charset[i]. */ ++ laststart = b; ++ ++ /* We test `*p == '^' twice, instead of using an if ++ statement, so we only need one BUF_PUSH. */ ++ BUF_PUSH (*p == '^' ? charset_not : charset); ++ if (*p == '^') ++ p++; ++ ++ /* Push the length of char_classes, the length of ++ collating_symbols, the length of equivalence_classes, the ++ length of char_ranges and the length of chars. */ ++ BUF_PUSH_3 (0, 0, 0); ++ BUF_PUSH_2 (0, 0); ++ ++ /* Remember the first position in the bracket expression. */ ++ p1 = p; ++ ++ /* charset_not matches newline according to a syntax bit. */ ++ if ((re_opcode_t) b[-6] == charset_not ++ && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) ++ { ++ BUF_PUSH('\n'); ++ laststart[5]++; /* Update the length of characters */ ++ } ++ ++ /* Read in characters and ranges, setting map bits. */ ++ for (;;) ++ { ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ PATFETCH (c); ++ ++ /* \ might escape characters inside [...] and [^...]. */ ++ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') ++ { ++ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); ++ ++ PATFETCH (c1); ++ BUF_PUSH(c1); ++ laststart[5]++; /* Update the length of chars */ ++ range_start = c1; ++ continue; ++ } ++ ++ /* Could be the end of the bracket expression. If it's ++ not (i.e., when the bracket expression is `[]' so ++ far), the ']' character bit gets set way below. */ ++ if (c == ']' && p != p1 + 1) ++ break; ++ ++ /* Look ahead to see if it's a range when the last thing ++ was a character class. */ ++ if (had_char_class && c == '-' && *p != ']') ++ FREE_STACK_RETURN (REG_ERANGE); ++ ++ /* Look ahead to see if it's a range when the last thing ++ was a character: if this is a hyphen not at the ++ beginning or the end of a list, then it's the range ++ operator. */ ++ if (c == '-' ++ && !(p - 2 >= pattern && p[-2] == '[') ++ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') ++ && *p != ']') ++ { ++ reg_errcode_t ret; ++ /* Allocate the space for range_start and range_end. */ ++ GET_BUFFER_SPACE (2); ++ /* Update the pointer to indicate end of buffer. */ ++ b += 2; ++ ret = wcs_compile_range (range_start, &p, pend, translate, ++ syntax, b, laststart); ++ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); ++ range_start = 0xffffffff; ++ } ++ else if (p[0] == '-' && p[1] != ']') ++ { /* This handles ranges made up of characters only. */ ++ reg_errcode_t ret; ++ ++ /* Move past the `-'. */ ++ PATFETCH (c1); ++ /* Allocate the space for range_start and range_end. */ ++ GET_BUFFER_SPACE (2); ++ /* Update the pointer to indicate end of buffer. */ ++ b += 2; ++ ret = wcs_compile_range (c, &p, pend, translate, syntax, b, ++ laststart); ++ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); ++ range_start = 0xffffffff; ++ } ++ ++ /* See if we're at the beginning of a possible character ++ class. */ ++ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') ++ { /* Leave room for the null. */ ++ char str[CHAR_CLASS_MAX_LENGTH + 1]; ++ ++ PATFETCH (c); ++ c1 = 0; ++ ++ /* If pattern is `[[:'. */ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (;;) ++ { ++ PATFETCH (c); ++ if ((c == ':' && *p == ']') || p == pend) ++ break; ++ if (c1 < CHAR_CLASS_MAX_LENGTH) ++ str[c1++] = c; ++ else ++ /* This is in any case an invalid class name. */ ++ str[0] = '\0'; ++ } ++ str[c1] = '\0'; ++ ++ /* If isn't a word bracketed by `[:' and `:]': ++ undo the ending character, the letters, and leave ++ the leading `:' and `[' (but store them as character). */ ++ if (c == ':' && *p == ']') ++ { ++ wctype_t wt; ++ uintptr_t alignedp; ++ ++ /* Query the character class as wctype_t. */ ++ wt = IS_CHAR_CLASS (str); ++ if (wt == 0) ++ FREE_STACK_RETURN (REG_ECTYPE); ++ ++ /* Throw away the ] at the end of the character ++ class. */ ++ PATFETCH (c); ++ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ /* Allocate the space for character class. */ ++ GET_BUFFER_SPACE(CHAR_CLASS_SIZE); ++ /* Update the pointer to indicate end of buffer. */ ++ b += CHAR_CLASS_SIZE; ++ /* Move data which follow character classes ++ not to violate the data. */ ++ insert_space(CHAR_CLASS_SIZE, ++ laststart + 6 + laststart[1], ++ b - 1); ++ alignedp = ((uintptr_t)(laststart + 6 + laststart[1]) ++ + __alignof__(wctype_t) - 1) ++ & ~(uintptr_t)(__alignof__(wctype_t) - 1); ++ /* Store the character class. */ ++ *((wctype_t*)alignedp) = wt; ++ /* Update length of char_classes */ ++ laststart[1] += CHAR_CLASS_SIZE; ++ ++ had_char_class = true; ++ } ++ else ++ { ++ c1++; ++ while (c1--) ++ PATUNFETCH; ++ BUF_PUSH ('['); ++ BUF_PUSH (':'); ++ laststart[5] += 2; /* Update the length of characters */ ++ range_start = ':'; ++ had_char_class = false; ++ } ++ } ++ else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' ++ || *p == '.')) ++ { ++ CHAR_T str[128]; /* Should be large enough. */ ++ CHAR_T delim = *p; /* '=' or '.' */ ++# ifdef _LIBC ++ uint32_t nrules = ++ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); ++# endif ++ PATFETCH (c); ++ c1 = 0; ++ ++ /* If pattern is `[[=' or '[[.'. */ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (;;) ++ { ++ PATFETCH (c); ++ if ((c == delim && *p == ']') || p == pend) ++ break; ++ if (c1 < sizeof (str) - 1) ++ str[c1++] = c; ++ else ++ /* This is in any case an invalid class name. */ ++ str[0] = '\0'; ++ } ++ str[c1] = '\0'; ++ ++ if (c == delim && *p == ']' && str[0] != '\0') ++ { ++ unsigned int i, offset; ++ /* If we have no collation data we use the default ++ collation in which each character is in a class ++ by itself. It also means that ASCII is the ++ character set and therefore we cannot have character ++ with more than one byte in the multibyte ++ representation. */ ++ ++ /* If not defined _LIBC, we push the name and ++ `\0' for the sake of matching performance. */ ++ int datasize = c1 + 1; ++ ++# ifdef _LIBC ++ int32_t idx = 0; ++ if (nrules == 0) ++# endif ++ { ++ if (c1 != 1) ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ } ++# ifdef _LIBC ++ else ++ { ++ const int32_t *table; ++ const int32_t *weights; ++ const int32_t *extra; ++ const int32_t *indirect; ++ wint_t *cp; ++ ++ if(delim == '=') ++ { ++ /* We push the index for equivalence class. */ ++ cp = (wint_t*)str; ++ ++ table = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_TABLEWC); ++ weights = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_WEIGHTWC); ++ extra = (const wint_t *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_EXTRAWC); ++ indirect = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_INDIRECTWC); ++ ++ idx = FINDIDX (table, indirect, extra, &cp, 1); ++ if (idx == 0 || cp < (wint_t*) str + c1) ++ /* This is no valid character. */ ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ ++ str[0] = (wchar_t)idx; ++ } ++ else /* delim == '.' */ ++ { ++ /* We push collation sequence value ++ for collating symbol. */ ++ int32_t table_size; ++ const int32_t *symb_table; ++ const unsigned char *extra; ++ int32_t idx; ++ int32_t elem; ++ int32_t second; ++ int32_t hash; ++ char char_str[c1]; ++ ++ /* We have to convert the name to a single-byte ++ string. This is possible since the names ++ consist of ASCII characters and the internal ++ representation is UCS4. */ ++ for (i = 0; i < c1; ++i) ++ char_str[i] = str[i]; ++ ++ table_size = ++ _NL_CURRENT_WORD (LC_COLLATE, ++ _NL_COLLATE_SYMB_HASH_SIZEMB); ++ symb_table = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_SYMB_TABLEMB); ++ extra = (const unsigned char *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_SYMB_EXTRAMB); ++ ++ /* Locate the character in the hashing table. */ ++ hash = elem_hash (char_str, c1); ++ ++ idx = 0; ++ elem = hash % table_size; ++ second = hash % (table_size - 2); ++ while (symb_table[2 * elem] != 0) ++ { ++ /* First compare the hashing value. */ ++ if (symb_table[2 * elem] == hash ++ && c1 == extra[symb_table[2 * elem + 1]] ++ && memcmp (char_str, ++ &extra[symb_table[2 * elem + 1] ++ + 1], c1) == 0) ++ { ++ /* Yep, this is the entry. */ ++ idx = symb_table[2 * elem + 1]; ++ idx += 1 + extra[idx]; ++ break; ++ } ++ ++ /* Next entry. */ ++ elem += second; ++ } ++ ++ if (symb_table[2 * elem] != 0) ++ { ++ /* Compute the index of the byte sequence ++ in the table. */ ++ idx += 1 + extra[idx]; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; ++ ++ str[0] = (wchar_t) idx + 4; ++ } ++ else if (symb_table[2 * elem] == 0 && c1 == 1) ++ { ++ /* No valid character. Match it as a ++ single byte character. */ ++ had_char_class = false; ++ BUF_PUSH(str[0]); ++ /* Update the length of characters */ ++ laststart[5]++; ++ range_start = str[0]; ++ ++ /* Throw away the ] at the end of the ++ collating symbol. */ ++ PATFETCH (c); ++ /* exit from the switch block. */ ++ continue; ++ } ++ else ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ } ++ datasize = 1; ++ } ++# endif ++ /* Throw away the ] at the end of the equivalence ++ class (or collating symbol). */ ++ PATFETCH (c); ++ ++ /* Allocate the space for the equivalence class ++ (or collating symbol) (and '\0' if needed). */ ++ GET_BUFFER_SPACE(datasize); ++ /* Update the pointer to indicate end of buffer. */ ++ b += datasize; ++ ++ if (delim == '=') ++ { /* equivalence class */ ++ /* Calculate the offset of char_ranges, ++ which is next to equivalence_classes. */ ++ offset = laststart[1] + laststart[2] ++ + laststart[3] +6; ++ /* Insert space. */ ++ insert_space(datasize, laststart + offset, b - 1); ++ ++ /* Write the equivalence_class and \0. */ ++ for (i = 0 ; i < datasize ; i++) ++ laststart[offset + i] = str[i]; ++ ++ /* Update the length of equivalence_classes. */ ++ laststart[3] += datasize; ++ had_char_class = true; ++ } ++ else /* delim == '.' */ ++ { /* collating symbol */ ++ /* Calculate the offset of the equivalence_classes, ++ which is next to collating_symbols. */ ++ offset = laststart[1] + laststart[2] + 6; ++ /* Insert space and write the collationg_symbol ++ and \0. */ ++ insert_space(datasize, laststart + offset, b-1); ++ for (i = 0 ; i < datasize ; i++) ++ laststart[offset + i] = str[i]; ++ ++ /* In re_match_2_internal if range_start < -1, we ++ assume -range_start is the offset of the ++ collating symbol which is specified as ++ the character of the range start. So we assign ++ -(laststart[1] + laststart[2] + 6) to ++ range_start. */ ++ range_start = -(laststart[1] + laststart[2] + 6); ++ /* Update the length of collating_symbol. */ ++ laststart[2] += datasize; ++ had_char_class = false; ++ } ++ } ++ else ++ { ++ c1++; ++ while (c1--) ++ PATUNFETCH; ++ BUF_PUSH ('['); ++ BUF_PUSH (delim); ++ laststart[5] += 2; /* Update the length of characters */ ++ range_start = delim; ++ had_char_class = false; ++ } ++ } ++ else ++ { ++ had_char_class = false; ++ BUF_PUSH(c); ++ laststart[5]++; /* Update the length of characters */ ++ range_start = c; ++ } ++ } ++ ++#else /* BYTE */ ++ /* Ensure that we have enough space to push a charset: the ++ opcode, the length count, and the bitset; 34 bytes in all. */ ++ GET_BUFFER_SPACE (34); ++ ++ laststart = b; ++ ++ /* We test `*p == '^' twice, instead of using an if ++ statement, so we only need one BUF_PUSH. */ ++ BUF_PUSH (*p == '^' ? charset_not : charset); ++ if (*p == '^') ++ p++; ++ ++ /* Remember the first position in the bracket expression. */ ++ p1 = p; ++ ++ /* Push the number of bytes in the bitmap. */ ++ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); ++ ++ /* Clear the whole map. */ ++ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); ++ ++ /* charset_not matches newline according to a syntax bit. */ ++ if ((re_opcode_t) b[-2] == charset_not ++ && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) ++ SET_LIST_BIT ('\n'); ++ ++ /* Read in characters and ranges, setting map bits. */ ++ for (;;) ++ { ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ PATFETCH (c); ++ ++ /* \ might escape characters inside [...] and [^...]. */ ++ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') ++ { ++ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); ++ ++ PATFETCH (c1); ++ SET_LIST_BIT (c1); ++ range_start = c1; ++ continue; ++ } ++ ++ /* Could be the end of the bracket expression. If it's ++ not (i.e., when the bracket expression is `[]' so ++ far), the ']' character bit gets set way below. */ ++ if (c == ']' && p != p1 + 1) ++ break; ++ ++ /* Look ahead to see if it's a range when the last thing ++ was a character class. */ ++ if (had_char_class && c == '-' && *p != ']') ++ FREE_STACK_RETURN (REG_ERANGE); ++ ++ /* Look ahead to see if it's a range when the last thing ++ was a character: if this is a hyphen not at the ++ beginning or the end of a list, then it's the range ++ operator. */ ++ if (c == '-' ++ && !(p - 2 >= pattern && p[-2] == '[') ++ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') ++ && *p != ']') ++ { ++ reg_errcode_t ret ++ = byte_compile_range (range_start, &p, pend, translate, ++ syntax, b); ++ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); ++ range_start = 0xffffffff; ++ } ++ ++ else if (p[0] == '-' && p[1] != ']') ++ { /* This handles ranges made up of characters only. */ ++ reg_errcode_t ret; ++ ++ /* Move past the `-'. */ ++ PATFETCH (c1); ++ ++ ret = byte_compile_range (c, &p, pend, translate, syntax, b); ++ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); ++ range_start = 0xffffffff; ++ } ++ ++ /* See if we're at the beginning of a possible character ++ class. */ ++ ++ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') ++ { /* Leave room for the null. */ ++ char str[CHAR_CLASS_MAX_LENGTH + 1]; ++ ++ PATFETCH (c); ++ c1 = 0; ++ ++ /* If pattern is `[[:'. */ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (;;) ++ { ++ PATFETCH (c); ++ if ((c == ':' && *p == ']') || p == pend) ++ break; ++ if (((int) c1) < CHAR_CLASS_MAX_LENGTH) ++ str[c1++] = c; ++ else ++ /* This is in any case an invalid class name. */ ++ str[0] = '\0'; ++ } ++ str[c1] = '\0'; ++ ++ /* If isn't a word bracketed by `[:' and `:]': ++ undo the ending character, the letters, and leave ++ the leading `:' and `[' (but set bits for them). */ ++ if (c == ':' && *p == ']') ++ { ++# if WIDE_CHAR_SUPPORT ++ boolean is_lower = STREQ (str, "lower"); ++ boolean is_upper = STREQ (str, "upper"); ++ wctype_t wt; ++ int ch; ++ ++ wt = IS_CHAR_CLASS (str); ++ if (wt == 0) ++ FREE_STACK_RETURN (REG_ECTYPE); ++ ++ /* Throw away the ] at the end of the character ++ class. */ ++ PATFETCH (c); ++ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) ++ { ++# ifdef _LIBC ++ if (__iswctype (__btowc (ch), wt)) ++ SET_LIST_BIT (ch); ++# else ++ if (iswctype (btowc (ch), wt)) ++ SET_LIST_BIT (ch); ++# endif ++ ++ if (translate && (is_upper || is_lower) ++ && (ISUPPER (ch) || ISLOWER (ch))) ++ SET_LIST_BIT (ch); ++ } ++ ++ had_char_class = true; ++# else ++ int ch; ++ boolean is_alnum = STREQ (str, "alnum"); ++ boolean is_alpha = STREQ (str, "alpha"); ++ boolean is_blank = STREQ (str, "blank"); ++ boolean is_cntrl = STREQ (str, "cntrl"); ++ boolean is_digit = STREQ (str, "digit"); ++ boolean is_graph = STREQ (str, "graph"); ++ boolean is_lower = STREQ (str, "lower"); ++ boolean is_print = STREQ (str, "print"); ++ boolean is_punct = STREQ (str, "punct"); ++ boolean is_space = STREQ (str, "space"); ++ boolean is_upper = STREQ (str, "upper"); ++ boolean is_xdigit = STREQ (str, "xdigit"); ++ ++ if (!IS_CHAR_CLASS (str)) ++ FREE_STACK_RETURN (REG_ECTYPE); ++ ++ /* Throw away the ] at the end of the character ++ class. */ ++ PATFETCH (c); ++ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (ch = 0; ch < 1 << BYTEWIDTH; ch++) ++ { ++ /* This was split into 3 if's to ++ avoid an arbitrary limit in some compiler. */ ++ if ( (is_alnum && ISALNUM (ch)) ++ || (is_alpha && ISALPHA (ch)) ++ || (is_blank && ISBLANK (ch)) ++ || (is_cntrl && ISCNTRL (ch))) ++ SET_LIST_BIT (ch); ++ if ( (is_digit && ISDIGIT (ch)) ++ || (is_graph && ISGRAPH (ch)) ++ || (is_lower && ISLOWER (ch)) ++ || (is_print && ISPRINT (ch))) ++ SET_LIST_BIT (ch); ++ if ( (is_punct && ISPUNCT (ch)) ++ || (is_space && ISSPACE (ch)) ++ || (is_upper && ISUPPER (ch)) ++ || (is_xdigit && ISXDIGIT (ch))) ++ SET_LIST_BIT (ch); ++ if ( translate && (is_upper || is_lower) ++ && (ISUPPER (ch) || ISLOWER (ch))) ++ SET_LIST_BIT (ch); ++ } ++ had_char_class = true; ++# endif /* libc || wctype.h */ ++ } ++ else ++ { ++ c1++; ++ while (c1--) ++ PATUNFETCH; ++ SET_LIST_BIT ('['); ++ SET_LIST_BIT (':'); ++ range_start = ':'; ++ had_char_class = false; ++ } ++ } ++ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=') ++ { ++ unsigned char str[MB_LEN_MAX + 1]; ++# ifdef _LIBC ++ uint32_t nrules = ++ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); ++# endif ++ ++ PATFETCH (c); ++ c1 = 0; ++ ++ /* If pattern is `[[='. */ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (;;) ++ { ++ PATFETCH (c); ++ if ((c == '=' && *p == ']') || p == pend) ++ break; ++ if (c1 < MB_LEN_MAX) ++ str[c1++] = c; ++ else ++ /* This is in any case an invalid class name. */ ++ str[0] = '\0'; ++ } ++ str[c1] = '\0'; ++ ++ if (c == '=' && *p == ']' && str[0] != '\0') ++ { ++ /* If we have no collation data we use the default ++ collation in which each character is in a class ++ by itself. It also means that ASCII is the ++ character set and therefore we cannot have character ++ with more than one byte in the multibyte ++ representation. */ ++# ifdef _LIBC ++ if (nrules == 0) ++# endif ++ { ++ if (c1 != 1) ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ ++ /* Throw away the ] at the end of the equivalence ++ class. */ ++ PATFETCH (c); ++ ++ /* Set the bit for the character. */ ++ SET_LIST_BIT (str[0]); ++ } ++# ifdef _LIBC ++ else ++ { ++ /* Try to match the byte sequence in `str' against ++ those known to the collate implementation. ++ First find out whether the bytes in `str' are ++ actually from exactly one character. */ ++ const int32_t *table; ++ const unsigned char *weights; ++ const unsigned char *extra; ++ const int32_t *indirect; ++ int32_t idx; ++ const unsigned char *cp = str; ++ int ch; ++ ++ table = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); ++ weights = (const unsigned char *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); ++ extra = (const unsigned char *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); ++ indirect = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); ++ idx = FINDIDX (table, indirect, extra, &cp, 1); ++ if (idx == 0 || cp < str + c1) ++ /* This is no valid character. */ ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ ++ /* Throw away the ] at the end of the equivalence ++ class. */ ++ PATFETCH (c); ++ ++ /* Now we have to go throught the whole table ++ and find all characters which have the same ++ first level weight. ++ ++ XXX Note that this is not entirely correct. ++ we would have to match multibyte sequences ++ but this is not possible with the current ++ implementation. */ ++ for (ch = 1; ch < 256; ++ch) ++ /* XXX This test would have to be changed if we ++ would allow matching multibyte sequences. */ ++ if (table[ch] > 0) ++ { ++ int32_t idx2 = table[ch]; ++ size_t len = weights[idx2]; ++ ++ /* Test whether the lenghts match. */ ++ if (weights[idx] == len) ++ { ++ /* They do. New compare the bytes of ++ the weight. */ ++ size_t cnt = 0; ++ ++ while (cnt < len ++ && (weights[idx + 1 + cnt] ++ == weights[idx2 + 1 + cnt])) ++ ++cnt; ++ ++ if (cnt == len) ++ /* They match. Mark the character as ++ acceptable. */ ++ SET_LIST_BIT (ch); ++ } ++ } ++ } ++# endif ++ had_char_class = true; ++ } ++ else ++ { ++ c1++; ++ while (c1--) ++ PATUNFETCH; ++ SET_LIST_BIT ('['); ++ SET_LIST_BIT ('='); ++ range_start = '='; ++ had_char_class = false; ++ } ++ } ++ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.') ++ { ++ unsigned char str[128]; /* Should be large enough. */ ++# ifdef _LIBC ++ uint32_t nrules = ++ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); ++# endif ++ ++ PATFETCH (c); ++ c1 = 0; ++ ++ /* If pattern is `[[.'. */ ++ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); ++ ++ for (;;) ++ { ++ PATFETCH (c); ++ if ((c == '.' && *p == ']') || p == pend) ++ break; ++ if (c1 < sizeof (str)) ++ str[c1++] = c; ++ else ++ /* This is in any case an invalid class name. */ ++ str[0] = '\0'; ++ } ++ str[c1] = '\0'; ++ ++ if (c == '.' && *p == ']' && str[0] != '\0') ++ { ++ /* If we have no collation data we use the default ++ collation in which each character is the name ++ for its own class which contains only the one ++ character. It also means that ASCII is the ++ character set and therefore we cannot have character ++ with more than one byte in the multibyte ++ representation. */ ++# ifdef _LIBC ++ if (nrules == 0) ++# endif ++ { ++ if (c1 != 1) ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ ++ /* Throw away the ] at the end of the equivalence ++ class. */ ++ PATFETCH (c); ++ ++ /* Set the bit for the character. */ ++ SET_LIST_BIT (str[0]); ++ range_start = ((const unsigned char *) str)[0]; ++ } ++# ifdef _LIBC ++ else ++ { ++ /* Try to match the byte sequence in `str' against ++ those known to the collate implementation. ++ First find out whether the bytes in `str' are ++ actually from exactly one character. */ ++ int32_t table_size; ++ const int32_t *symb_table; ++ const unsigned char *extra; ++ int32_t idx; ++ int32_t elem; ++ int32_t second; ++ int32_t hash; ++ ++ table_size = ++ _NL_CURRENT_WORD (LC_COLLATE, ++ _NL_COLLATE_SYMB_HASH_SIZEMB); ++ symb_table = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_SYMB_TABLEMB); ++ extra = (const unsigned char *) ++ _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_SYMB_EXTRAMB); ++ ++ /* Locate the character in the hashing table. */ ++ hash = elem_hash ((const char *) str, c1); ++ ++ idx = 0; ++ elem = hash % table_size; ++ second = hash % (table_size - 2); ++ while (symb_table[2 * elem] != 0) ++ { ++ /* First compare the hashing value. */ ++ if (symb_table[2 * elem] == hash ++ && c1 == extra[symb_table[2 * elem + 1]] ++ && memcmp (str, ++ &extra[symb_table[2 * elem + 1] ++ + 1], ++ c1) == 0) ++ { ++ /* Yep, this is the entry. */ ++ idx = symb_table[2 * elem + 1]; ++ idx += 1 + extra[idx]; ++ break; ++ } ++ ++ /* Next entry. */ ++ elem += second; ++ } ++ ++ if (symb_table[2 * elem] == 0) ++ /* This is no valid character. */ ++ FREE_STACK_RETURN (REG_ECOLLATE); ++ ++ /* Throw away the ] at the end of the equivalence ++ class. */ ++ PATFETCH (c); ++ ++ /* Now add the multibyte character(s) we found ++ to the accept list. ++ ++ XXX Note that this is not entirely correct. ++ we would have to match multibyte sequences ++ but this is not possible with the current ++ implementation. Also, we have to match ++ collating symbols, which expand to more than ++ one file, as a whole and not allow the ++ individual bytes. */ ++ c1 = extra[idx++]; ++ if (c1 == 1) ++ range_start = extra[idx]; ++ while (c1-- > 0) ++ { ++ SET_LIST_BIT (extra[idx]); ++ ++idx; ++ } ++ } ++# endif ++ had_char_class = false; ++ } ++ else ++ { ++ c1++; ++ while (c1--) ++ PATUNFETCH; ++ SET_LIST_BIT ('['); ++ SET_LIST_BIT ('.'); ++ range_start = '.'; ++ had_char_class = false; ++ } ++ } ++ else ++ { ++ had_char_class = false; ++ SET_LIST_BIT (c); ++ range_start = c; ++ } ++ } ++ ++ /* Discard any (non)matching list bytes that are all 0 at the ++ end of the map. Decrease the map-length byte too. */ ++ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) ++ b[-1]--; ++ b += b[-1]; ++#endif /* WCHAR */ ++ } ++ break; ++ ++ ++ case '(': ++ if (syntax & RE_NO_BK_PARENS) ++ goto handle_open; ++ else ++ goto normal_char; ++ ++ ++ case ')': ++ if (syntax & RE_NO_BK_PARENS) ++ goto handle_close; ++ else ++ goto normal_char; ++ ++ ++ case '\n': ++ if (syntax & RE_NEWLINE_ALT) ++ goto handle_alt; ++ else ++ goto normal_char; ++ ++ ++ case '|': ++ if (syntax & RE_NO_BK_VBAR) ++ goto handle_alt; ++ else ++ goto normal_char; ++ ++ ++ case '{': ++ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) ++ goto handle_interval; ++ else ++ goto normal_char; ++ ++ ++ case '\\': ++ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); ++ ++ /* Do not translate the character after the \, so that we can ++ distinguish, e.g., \B from \b, even if we normally would ++ translate, e.g., B to b. */ ++ PATFETCH_RAW (c); ++ ++ switch (c) ++ { ++ case '(': ++ if (syntax & RE_NO_BK_PARENS) ++ goto normal_backslash; ++ ++ handle_open: ++ bufp->re_nsub++; ++ regnum++; ++ ++ if (COMPILE_STACK_FULL) ++ { ++ RETALLOC (compile_stack.stack, compile_stack.size << 1, ++ compile_stack_elt_t); ++ if (compile_stack.stack == NULL) return REG_ESPACE; ++ ++ compile_stack.size <<= 1; ++ } ++ ++ /* These are the values to restore when we hit end of this ++ group. They are all relative offsets, so that if the ++ whole pattern moves because of realloc, they will still ++ be valid. */ ++ COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR; ++ COMPILE_STACK_TOP.fixup_alt_jump ++ = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0; ++ COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR; ++ COMPILE_STACK_TOP.regnum = regnum; ++ ++ /* We will eventually replace the 0 with the number of ++ groups inner to this one. But do not push a ++ start_memory for groups beyond the last one we can ++ represent in the compiled pattern. */ ++ if (regnum <= MAX_REGNUM) ++ { ++ COMPILE_STACK_TOP.inner_group_offset = b ++ - COMPILED_BUFFER_VAR + 2; ++ BUF_PUSH_3 (start_memory, regnum, 0); ++ } ++ ++ compile_stack.avail++; ++ ++ fixup_alt_jump = 0; ++ laststart = 0; ++ begalt = b; ++ /* If we've reached MAX_REGNUM groups, then this open ++ won't actually generate any code, so we'll have to ++ clear pending_exact explicitly. */ ++ pending_exact = 0; ++ break; ++ ++ ++ case ')': ++ if (syntax & RE_NO_BK_PARENS) goto normal_backslash; ++ ++ if (COMPILE_STACK_EMPTY) ++ { ++ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) ++ goto normal_backslash; ++ else ++ FREE_STACK_RETURN (REG_ERPAREN); ++ } ++ ++ handle_close: ++ if (fixup_alt_jump) ++ { /* Push a dummy failure point at the end of the ++ alternative for a possible future ++ `pop_failure_jump' to pop. See comments at ++ `push_dummy_failure' in `re_match_2'. */ ++ BUF_PUSH (push_dummy_failure); ++ ++ /* We allocated space for this jump when we assigned ++ to `fixup_alt_jump', in the `handle_alt' case below. */ ++ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); ++ } ++ ++ /* See similar code for backslashed left paren above. */ ++ if (COMPILE_STACK_EMPTY) ++ { ++ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) ++ goto normal_char; ++ else ++ FREE_STACK_RETURN (REG_ERPAREN); ++ } ++ ++ /* Since we just checked for an empty stack above, this ++ ``can't happen''. */ ++ assert (compile_stack.avail != 0); ++ { ++ /* We don't just want to restore into `regnum', because ++ later groups should continue to be numbered higher, ++ as in `(ab)c(de)' -- the second group is #2. */ ++ regnum_t this_group_regnum; ++ ++ compile_stack.avail--; ++ begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset; ++ fixup_alt_jump ++ = COMPILE_STACK_TOP.fixup_alt_jump ++ ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1 ++ : 0; ++ laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset; ++ this_group_regnum = COMPILE_STACK_TOP.regnum; ++ /* If we've reached MAX_REGNUM groups, then this open ++ won't actually generate any code, so we'll have to ++ clear pending_exact explicitly. */ ++ pending_exact = 0; ++ ++ /* We're at the end of the group, so now we know how many ++ groups were inside this one. */ ++ if (this_group_regnum <= MAX_REGNUM) ++ { ++ UCHAR_T *inner_group_loc ++ = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; ++ ++ *inner_group_loc = regnum - this_group_regnum; ++ BUF_PUSH_3 (stop_memory, this_group_regnum, ++ regnum - this_group_regnum); ++ } ++ } ++ break; ++ ++ ++ case '|': /* `\|'. */ ++ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) ++ goto normal_backslash; ++ handle_alt: ++ if (syntax & RE_LIMITED_OPS) ++ goto normal_char; ++ ++ /* Insert before the previous alternative a jump which ++ jumps to this alternative if the former fails. */ ++ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); ++ INSERT_JUMP (on_failure_jump, begalt, ++ b + 2 + 2 * OFFSET_ADDRESS_SIZE); ++ pending_exact = 0; ++ b += 1 + OFFSET_ADDRESS_SIZE; ++ ++ /* The alternative before this one has a jump after it ++ which gets executed if it gets matched. Adjust that ++ jump so it will jump to this alternative's analogous ++ jump (put in below, which in turn will jump to the next ++ (if any) alternative's such jump, etc.). The last such ++ jump jumps to the correct final destination. A picture: ++ _____ _____ ++ | | | | ++ | v | v ++ a | b | c ++ ++ If we are at `b', then fixup_alt_jump right now points to a ++ three-byte space after `a'. We'll put in the jump, set ++ fixup_alt_jump to right after `b', and leave behind three ++ bytes which we'll fill in when we get to after `c'. */ ++ ++ if (fixup_alt_jump) ++ STORE_JUMP (jump_past_alt, fixup_alt_jump, b); ++ ++ /* Mark and leave space for a jump after this alternative, ++ to be filled in later either by next alternative or ++ when know we're at the end of a series of alternatives. */ ++ fixup_alt_jump = b; ++ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); ++ b += 1 + OFFSET_ADDRESS_SIZE; ++ ++ laststart = 0; ++ begalt = b; ++ break; ++ ++ ++ case '{': ++ /* If \{ is a literal. */ ++ if (!(syntax & RE_INTERVALS) ++ /* If we're at `\{' and it's not the open-interval ++ operator. */ ++ || (syntax & RE_NO_BK_BRACES)) ++ goto normal_backslash; ++ ++ handle_interval: ++ { ++ /* If got here, then the syntax allows intervals. */ ++ ++ /* At least (most) this many matches must be made. */ ++ int lower_bound = -1, upper_bound = -1; ++ ++ /* Place in the uncompiled pattern (i.e., just after ++ the '{') to go back to if the interval is invalid. */ ++ const CHAR_T *beg_interval = p; ++ ++ if (p == pend) ++ goto invalid_interval; ++ ++ GET_UNSIGNED_NUMBER (lower_bound); ++ ++ if (c == ',') ++ { ++ GET_UNSIGNED_NUMBER (upper_bound); ++ if (upper_bound < 0) ++ upper_bound = RE_DUP_MAX; ++ } ++ else ++ /* Interval such as `{1}' => match exactly once. */ ++ upper_bound = lower_bound; ++ ++ if (! (0 <= lower_bound && lower_bound <= upper_bound)) ++ goto invalid_interval; ++ ++ if (!(syntax & RE_NO_BK_BRACES)) ++ { ++ if (c != '\\' || p == pend) ++ goto invalid_interval; ++ PATFETCH (c); ++ } ++ ++ if (c != '}') ++ goto invalid_interval; ++ ++ /* If it's invalid to have no preceding re. */ ++ if (!laststart) ++ { ++ if (syntax & RE_CONTEXT_INVALID_OPS ++ && !(syntax & RE_INVALID_INTERVAL_ORD)) ++ FREE_STACK_RETURN (REG_BADRPT); ++ else if (syntax & RE_CONTEXT_INDEP_OPS) ++ laststart = b; ++ else ++ goto unfetch_interval; ++ } ++ ++ /* We just parsed a valid interval. */ ++ ++ if (RE_DUP_MAX < upper_bound) ++ FREE_STACK_RETURN (REG_BADBR); ++ ++ /* If the upper bound is zero, don't want to succeed at ++ all; jump from `laststart' to `b + 3', which will be ++ the end of the buffer after we insert the jump. */ ++ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' ++ instead of 'b + 3'. */ ++ if (upper_bound == 0) ++ { ++ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); ++ INSERT_JUMP (jump, laststart, b + 1 ++ + OFFSET_ADDRESS_SIZE); ++ b += 1 + OFFSET_ADDRESS_SIZE; ++ } ++ ++ /* Otherwise, we have a nontrivial interval. When ++ we're all done, the pattern will look like: ++ set_number_at ++ set_number_at ++ succeed_n ++ ++ jump_n ++ (The upper bound and `jump_n' are omitted if ++ `upper_bound' is 1, though.) */ ++ else ++ { /* If the upper bound is > 1, we need to insert ++ more at the end of the loop. */ ++ unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE + ++ (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE); ++ ++ GET_BUFFER_SPACE (nbytes); ++ ++ /* Initialize lower bound of the `succeed_n', even ++ though it will be set during matching by its ++ attendant `set_number_at' (inserted next), ++ because `re_compile_fastmap' needs to know. ++ Jump to the `jump_n' we might insert below. */ ++ INSERT_JUMP2 (succeed_n, laststart, ++ b + 1 + 2 * OFFSET_ADDRESS_SIZE ++ + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE) ++ , lower_bound); ++ b += 1 + 2 * OFFSET_ADDRESS_SIZE; ++ ++ /* Code to initialize the lower bound. Insert ++ before the `succeed_n'. The `5' is the last two ++ bytes of this `set_number_at', plus 3 bytes of ++ the following `succeed_n'. */ ++ /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' ++ is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' ++ of the following `succeed_n'. */ ++ PREFIX(insert_op2) (set_number_at, laststart, 1 ++ + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); ++ b += 1 + 2 * OFFSET_ADDRESS_SIZE; ++ ++ if (upper_bound > 1) ++ { /* More than one repetition is allowed, so ++ append a backward jump to the `succeed_n' ++ that starts this interval. ++ ++ When we've reached this during matching, ++ we'll have matched the interval once, so ++ jump back only `upper_bound - 1' times. */ ++ STORE_JUMP2 (jump_n, b, laststart ++ + 2 * OFFSET_ADDRESS_SIZE + 1, ++ upper_bound - 1); ++ b += 1 + 2 * OFFSET_ADDRESS_SIZE; ++ ++ /* The location we want to set is the second ++ parameter of the `jump_n'; that is `b-2' as ++ an absolute address. `laststart' will be ++ the `set_number_at' we're about to insert; ++ `laststart+3' the number to set, the source ++ for the relative address. But we are ++ inserting into the middle of the pattern -- ++ so everything is getting moved up by 5. ++ Conclusion: (b - 2) - (laststart + 3) + 5, ++ i.e., b - laststart. ++ ++ We insert this at the beginning of the loop ++ so that if we fail during matching, we'll ++ reinitialize the bounds. */ ++ PREFIX(insert_op2) (set_number_at, laststart, ++ b - laststart, ++ upper_bound - 1, b); ++ b += 1 + 2 * OFFSET_ADDRESS_SIZE; ++ } ++ } ++ pending_exact = 0; ++ break; ++ ++ invalid_interval: ++ if (!(syntax & RE_INVALID_INTERVAL_ORD)) ++ FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR); ++ unfetch_interval: ++ /* Match the characters as literals. */ ++ p = beg_interval; ++ c = '{'; ++ if (syntax & RE_NO_BK_BRACES) ++ goto normal_char; ++ else ++ goto normal_backslash; ++ } ++ ++#ifdef emacs ++ /* There is no way to specify the before_dot and after_dot ++ operators. rms says this is ok. --karl */ ++ case '=': ++ BUF_PUSH (at_dot); ++ break; ++ ++ case 's': ++ laststart = b; ++ PATFETCH (c); ++ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); ++ break; ++ ++ case 'S': ++ laststart = b; ++ PATFETCH (c); ++ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); ++ break; ++#endif /* emacs */ ++ ++ ++ case 'w': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ laststart = b; ++ BUF_PUSH (wordchar); ++ break; ++ ++ ++ case 'W': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ laststart = b; ++ BUF_PUSH (notwordchar); ++ break; ++ ++ ++ case '<': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ BUF_PUSH (wordbeg); ++ break; ++ ++ case '>': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ BUF_PUSH (wordend); ++ break; ++ ++ case 'b': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ BUF_PUSH (wordbound); ++ break; ++ ++ case 'B': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ BUF_PUSH (notwordbound); ++ break; ++ ++ case '`': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ BUF_PUSH (begbuf); ++ break; ++ ++ case '\'': ++ if (syntax & RE_NO_GNU_OPS) ++ goto normal_char; ++ BUF_PUSH (endbuf); ++ break; ++ ++ case '1': case '2': case '3': case '4': case '5': ++ case '6': case '7': case '8': case '9': ++ if (syntax & RE_NO_BK_REFS) ++ goto normal_char; ++ ++ c1 = c - '0'; ++ ++ if (c1 > regnum) ++ FREE_STACK_RETURN (REG_ESUBREG); ++ ++ /* Can't back reference to a subexpression if inside of it. */ ++ if (group_in_compile_stack (compile_stack, (regnum_t) c1)) ++ goto normal_char; ++ ++ laststart = b; ++ BUF_PUSH_2 (duplicate, c1); ++ break; ++ ++ ++ case '+': ++ case '?': ++ if (syntax & RE_BK_PLUS_QM) ++ goto handle_plus; ++ else ++ goto normal_backslash; ++ ++ default: ++ normal_backslash: ++ /* You might think it would be useful for \ to mean ++ not to translate; but if we don't translate it ++ it will never match anything. */ ++ c = TRANSLATE (c); ++ goto normal_char; ++ } ++ break; ++ ++ ++ default: ++ /* Expects the character in `c'. */ ++ normal_char: ++ /* If no exactn currently being built. */ ++ if (!pending_exact ++#ifdef WCHAR ++ /* If last exactn handle binary(or character) and ++ new exactn handle character(or binary). */ ++ || is_exactn_bin != is_binary[p - 1 - pattern] ++#endif /* WCHAR */ ++ ++ /* If last exactn not at current position. */ ++ || pending_exact + *pending_exact + 1 != b ++ ++ /* We have only one byte following the exactn for the count. */ ++ || *pending_exact == (1 << BYTEWIDTH) - 1 ++ ++ /* If followed by a repetition operator. */ ++ || *p == '*' || *p == '^' ++ || ((syntax & RE_BK_PLUS_QM) ++ ? *p == '\\' && (p[1] == '+' || p[1] == '?') ++ : (*p == '+' || *p == '?')) ++ || ((syntax & RE_INTERVALS) ++ && ((syntax & RE_NO_BK_BRACES) ++ ? *p == '{' ++ : (p[0] == '\\' && p[1] == '{')))) ++ { ++ /* Start building a new exactn. */ ++ ++ laststart = b; ++ ++#ifdef WCHAR ++ /* Is this exactn binary data or character? */ ++ is_exactn_bin = is_binary[p - 1 - pattern]; ++ if (is_exactn_bin) ++ BUF_PUSH_2 (exactn_bin, 0); ++ else ++ BUF_PUSH_2 (exactn, 0); ++#else ++ BUF_PUSH_2 (exactn, 0); ++#endif /* WCHAR */ ++ pending_exact = b - 1; ++ } ++ ++ BUF_PUSH (c); ++ (*pending_exact)++; ++ break; ++ } /* switch (c) */ ++ } /* while p != pend */ ++ ++ ++ /* Through the pattern now. */ ++ ++ if (fixup_alt_jump) ++ STORE_JUMP (jump_past_alt, fixup_alt_jump, b); ++ ++ if (!COMPILE_STACK_EMPTY) ++ FREE_STACK_RETURN (REG_EPAREN); ++ ++ /* If we don't want backtracking, force success ++ the first time we reach the end of the compiled pattern. */ ++ if (syntax & RE_NO_POSIX_BACKTRACKING) ++ BUF_PUSH (succeed); ++ ++#ifdef WCHAR ++ free (pattern); ++ free (mbs_offset); ++ free (is_binary); ++#endif ++ free (compile_stack.stack); ++ ++ /* We have succeeded; set the length of the buffer. */ ++#ifdef WCHAR ++ bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; ++#else ++ bufp->used = b - bufp->buffer; ++#endif ++ ++#ifdef DEBUG ++ if (debug) ++ { ++ DEBUG_PRINT1 ("\nCompiled pattern: \n"); ++ PREFIX(print_compiled_pattern) (bufp); ++ } ++#endif /* DEBUG */ ++ ++#ifndef MATCH_MAY_ALLOCATE ++ /* Initialize the failure stack to the largest possible stack. This ++ isn't necessary unless we're trying to avoid calling alloca in ++ the search and match routines. */ ++ { ++ int num_regs = bufp->re_nsub + 1; ++ ++ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size ++ is strictly greater than re_max_failures, the largest possible stack ++ is 2 * re_max_failures failure points. */ ++ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) ++ { ++ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); ++ ++# ifdef emacs ++ if (! fail_stack.stack) ++ fail_stack.stack ++ = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size ++ * sizeof (PREFIX(fail_stack_elt_t))); ++ else ++ fail_stack.stack ++ = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, ++ (fail_stack.size ++ * sizeof (PREFIX(fail_stack_elt_t)))); ++# else /* not emacs */ ++ if (! fail_stack.stack) ++ fail_stack.stack ++ = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size ++ * sizeof (PREFIX(fail_stack_elt_t))); ++ else ++ fail_stack.stack ++ = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack, ++ (fail_stack.size ++ * sizeof (PREFIX(fail_stack_elt_t)))); ++# endif /* not emacs */ ++ } ++ ++ PREFIX(regex_grow_registers) (num_regs); ++ } ++#endif /* not MATCH_MAY_ALLOCATE */ ++ ++ return REG_NOERROR; ++} /* regex_compile */ ++ ++/* Subroutines for `regex_compile'. */ ++ ++/* Store OP at LOC followed by two-byte integer parameter ARG. */ ++/* ifdef WCHAR, integer parameter is 1 wchar_t. */ ++ ++static void ++PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg) ++{ ++ *loc = (UCHAR_T) op; ++ STORE_NUMBER (loc + 1, arg); ++} ++ ++ ++/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ ++/* ifdef WCHAR, integer parameter is 1 wchar_t. */ ++ ++static void ++PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2) ++{ ++ *loc = (UCHAR_T) op; ++ STORE_NUMBER (loc + 1, arg1); ++ STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); ++} ++ ++ ++/* Copy the bytes from LOC to END to open up three bytes of space at LOC ++ for OP followed by two-byte integer parameter ARG. */ ++/* ifdef WCHAR, integer parameter is 1 wchar_t. */ ++ ++static void ++PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end) ++{ ++ register UCHAR_T *pfrom = end; ++ register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; ++ ++ while (pfrom != loc) ++ *--pto = *--pfrom; ++ ++ PREFIX(store_op1) (op, loc, arg); ++} ++ ++ ++/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ ++/* ifdef WCHAR, integer parameter is 1 wchar_t. */ ++ ++static void ++PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, ++ int arg2, UCHAR_T *end) ++{ ++ register UCHAR_T *pfrom = end; ++ register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; ++ ++ while (pfrom != loc) ++ *--pto = *--pfrom; ++ ++ PREFIX(store_op2) (op, loc, arg1, arg2); ++} ++ ++ ++/* P points to just after a ^ in PATTERN. Return true if that ^ comes ++ after an alternative or a begin-subexpression. We assume there is at ++ least one character before the ^. */ ++ ++static boolean ++PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p, ++ reg_syntax_t syntax) ++{ ++ const CHAR_T *prev = p - 2; ++ boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; ++ ++ return ++ /* After a subexpression? */ ++ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) ++ /* After an alternative? */ ++ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); ++} ++ ++ ++/* The dual of at_begline_loc_p. This one is for $. We assume there is ++ at least one character after the $, i.e., `P < PEND'. */ ++ ++static boolean ++PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend, ++ reg_syntax_t syntax) ++{ ++ const CHAR_T *next = p; ++ boolean next_backslash = *next == '\\'; ++ const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; ++ ++ return ++ /* Before a subexpression? */ ++ (syntax & RE_NO_BK_PARENS ? *next == ')' ++ : next_backslash && next_next && *next_next == ')') ++ /* Before an alternative? */ ++ || (syntax & RE_NO_BK_VBAR ? *next == '|' ++ : next_backslash && next_next && *next_next == '|'); ++} ++ ++#else /* not INSIDE_RECURSION */ ++ ++/* Returns true if REGNUM is in one of COMPILE_STACK's elements and ++ false if it's not. */ ++ ++static boolean ++group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum) ++{ ++ int this_element; ++ ++ for (this_element = compile_stack.avail - 1; ++ this_element >= 0; ++ this_element--) ++ if (compile_stack.stack[this_element].regnum == regnum) ++ return true; ++ ++ return false; ++} ++#endif /* not INSIDE_RECURSION */ ++ ++#ifdef INSIDE_RECURSION ++ ++#ifdef WCHAR ++/* This insert space, which size is "num", into the pattern at "loc". ++ "end" must point the end of the allocated buffer. */ ++static void ++insert_space (int num, CHAR_T *loc, CHAR_T *end) ++{ ++ register CHAR_T *pto = end; ++ register CHAR_T *pfrom = end - num; ++ ++ while (pfrom >= loc) ++ *pto-- = *pfrom--; ++} ++#endif /* WCHAR */ ++ ++#ifdef WCHAR ++static reg_errcode_t ++wcs_compile_range (CHAR_T range_start_char, const CHAR_T **p_ptr, ++ const CHAR_T *pend, RE_TRANSLATE_TYPE translate, ++ reg_syntax_t syntax, CHAR_T *b, CHAR_T *char_set) ++{ ++ const CHAR_T *p = *p_ptr; ++ CHAR_T range_start, range_end; ++ reg_errcode_t ret; ++# ifdef _LIBC ++ uint32_t nrules; ++ uint32_t start_val, end_val; ++# endif ++ if (p == pend) ++ return REG_ERANGE; ++ ++# ifdef _LIBC ++ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); ++ if (nrules != 0) ++ { ++ const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, ++ _NL_COLLATE_COLLSEQWC); ++ const unsigned char *extra = (const unsigned char *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); ++ ++ if (range_start_char < -1) ++ { ++ /* range_start is a collating symbol. */ ++ int32_t *wextra; ++ /* Retreive the index and get collation sequence value. */ ++ wextra = (int32_t*)(extra + char_set[-range_start_char]); ++ start_val = wextra[1 + *wextra]; ++ } ++ else ++ start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char)); ++ ++ end_val = collseq_table_lookup (collseq, TRANSLATE (p[0])); ++ ++ /* Report an error if the range is empty and the syntax prohibits ++ this. */ ++ ret = ((syntax & RE_NO_EMPTY_RANGES) ++ && (start_val > end_val))? REG_ERANGE : REG_NOERROR; ++ ++ /* Insert space to the end of the char_ranges. */ ++ insert_space(2, b - char_set[5] - 2, b - 1); ++ *(b - char_set[5] - 2) = (wchar_t)start_val; ++ *(b - char_set[5] - 1) = (wchar_t)end_val; ++ char_set[4]++; /* ranges_index */ ++ } ++ else ++# endif ++ { ++ range_start = (range_start_char >= 0)? TRANSLATE (range_start_char): ++ range_start_char; ++ range_end = TRANSLATE (p[0]); ++ /* Report an error if the range is empty and the syntax prohibits ++ this. */ ++ ret = ((syntax & RE_NO_EMPTY_RANGES) ++ && (range_start > range_end))? REG_ERANGE : REG_NOERROR; ++ ++ /* Insert space to the end of the char_ranges. */ ++ insert_space(2, b - char_set[5] - 2, b - 1); ++ *(b - char_set[5] - 2) = range_start; ++ *(b - char_set[5] - 1) = range_end; ++ char_set[4]++; /* ranges_index */ ++ } ++ /* Have to increment the pointer into the pattern string, so the ++ caller isn't still at the ending character. */ ++ (*p_ptr)++; ++ ++ return ret; ++} ++#else /* BYTE */ ++/* Read the ending character of a range (in a bracket expression) from the ++ uncompiled pattern *P_PTR (which ends at PEND). We assume the ++ starting character is in `P[-2]'. (`P[-1]' is the character `-'.) ++ Then we set the translation of all bits between the starting and ++ ending characters (inclusive) in the compiled pattern B. ++ ++ Return an error code. ++ ++ We use these short variable names so we can use the same macros as ++ `regex_compile' itself. */ ++ ++static reg_errcode_t ++byte_compile_range (unsigned int range_start_char, const char **p_ptr, ++ const char *pend, RE_TRANSLATE_TYPE translate, ++ reg_syntax_t syntax, unsigned char *b) ++{ ++ unsigned this_char; ++ const char *p = *p_ptr; ++ reg_errcode_t ret; ++# if _LIBC ++ const unsigned char *collseq; ++ unsigned int start_colseq; ++ unsigned int end_colseq; ++# else ++ unsigned end_char; ++# endif ++ ++ if (p == pend) ++ return REG_ERANGE; ++ ++ /* Have to increment the pointer into the pattern string, so the ++ caller isn't still at the ending character. */ ++ (*p_ptr)++; ++ ++ /* Report an error if the range is empty and the syntax prohibits this. */ ++ ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; ++ ++# if _LIBC ++ collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, ++ _NL_COLLATE_COLLSEQMB); ++ ++ start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)]; ++ end_colseq = collseq[(unsigned char) TRANSLATE (p[0])]; ++ for (this_char = 0; this_char <= (unsigned char) -1; ++this_char) ++ { ++ unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)]; ++ ++ if (start_colseq <= this_colseq && this_colseq <= end_colseq) ++ { ++ SET_LIST_BIT (TRANSLATE (this_char)); ++ ret = REG_NOERROR; ++ } ++ } ++# else ++ /* Here we see why `this_char' has to be larger than an `unsigned ++ char' -- we would otherwise go into an infinite loop, since all ++ characters <= 0xff. */ ++ range_start_char = TRANSLATE (range_start_char); ++ /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE, ++ and some compilers cast it to int implicitly, so following for_loop ++ may fall to (almost) infinite loop. ++ e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff. ++ To avoid this, we cast p[0] to unsigned int and truncate it. */ ++ end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1)); ++ ++ for (this_char = range_start_char; this_char <= end_char; ++this_char) ++ { ++ SET_LIST_BIT (TRANSLATE (this_char)); ++ ret = REG_NOERROR; ++ } ++# endif ++ ++ return ret; ++} ++#endif /* WCHAR */ ++ ++/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in ++ BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible ++ characters can start a string that matches the pattern. This fastmap ++ is used by re_search to skip quickly over impossible starting points. ++ ++ The caller must supply the address of a (1 << BYTEWIDTH)-byte data ++ area as BUFP->fastmap. ++ ++ We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in ++ the pattern buffer. ++ ++ Returns 0 if we succeed, -2 if an internal error. */ ++ ++#ifdef WCHAR ++/* local function for re_compile_fastmap. ++ truncate wchar_t character to char. */ ++static unsigned char truncate_wchar (CHAR_T c); ++ ++static unsigned char ++truncate_wchar (CHAR_T c) ++{ ++ unsigned char buf[MB_CUR_MAX]; ++ mbstate_t state; ++ int retval; ++ memset (&state, '\0', sizeof (state)); ++# ifdef _LIBC ++ retval = __wcrtomb (buf, c, &state); ++# else ++ retval = wcrtomb (buf, c, &state); ++# endif ++ return retval > 0 ? buf[0] : (unsigned char) c; ++} ++#endif /* WCHAR */ ++ ++static int ++PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp) ++{ ++ int j, k; ++#ifdef MATCH_MAY_ALLOCATE ++ PREFIX(fail_stack_type) fail_stack; ++#endif ++#ifndef REGEX_MALLOC ++ char *destination; ++#endif ++ ++ register char *fastmap = bufp->fastmap; ++ ++#ifdef WCHAR ++ /* We need to cast pattern to (wchar_t*), because we casted this compiled ++ pattern to (char*) in regex_compile. */ ++ UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; ++ register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); ++#else /* BYTE */ ++ UCHAR_T *pattern = bufp->buffer; ++ register UCHAR_T *pend = pattern + bufp->used; ++#endif /* WCHAR */ ++ UCHAR_T *p = pattern; ++ ++#ifdef REL_ALLOC ++ /* This holds the pointer to the failure stack, when ++ it is allocated relocatably. */ ++ fail_stack_elt_t *failure_stack_ptr; ++#endif ++ ++ /* Assume that each path through the pattern can be null until ++ proven otherwise. We set this false at the bottom of switch ++ statement, to which we get only if a particular path doesn't ++ match the empty string. */ ++ boolean path_can_be_null = true; ++ ++ /* We aren't doing a `succeed_n' to begin with. */ ++ boolean succeed_n_p = false; ++ ++ assert (fastmap != NULL && p != NULL); ++ ++ INIT_FAIL_STACK (); ++ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ ++ bufp->fastmap_accurate = 1; /* It will be when we're done. */ ++ bufp->can_be_null = 0; ++ ++ while (1) ++ { ++ if (p == pend || *p == (UCHAR_T) succeed) ++ { ++ /* We have reached the (effective) end of pattern. */ ++ if (!FAIL_STACK_EMPTY ()) ++ { ++ bufp->can_be_null |= path_can_be_null; ++ ++ /* Reset for next path. */ ++ path_can_be_null = true; ++ ++ p = fail_stack.stack[--fail_stack.avail].pointer; ++ ++ continue; ++ } ++ else ++ break; ++ } ++ ++ /* We should never be about to go beyond the end of the pattern. */ ++ assert (p < pend); ++ ++ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) ++ { ++ ++ /* I guess the idea here is to simply not bother with a fastmap ++ if a backreference is used, since it's too hard to figure out ++ the fastmap for the corresponding group. Setting ++ `can_be_null' stops `re_search_2' from using the fastmap, so ++ that is all we do. */ ++ case duplicate: ++ bufp->can_be_null = 1; ++ goto done; ++ ++ ++ /* Following are the cases which match a character. These end ++ with `break'. */ ++ ++#ifdef WCHAR ++ case exactn: ++ fastmap[truncate_wchar(p[1])] = 1; ++ break; ++#else /* BYTE */ ++ case exactn: ++ fastmap[p[1]] = 1; ++ break; ++#endif /* WCHAR */ ++#ifdef MBS_SUPPORT ++ case exactn_bin: ++ fastmap[p[1]] = 1; ++ break; ++#endif ++ ++#ifdef WCHAR ++ /* It is hard to distinguish fastmap from (multi byte) characters ++ which depends on current locale. */ ++ case charset: ++ case charset_not: ++ case wordchar: ++ case notwordchar: ++ bufp->can_be_null = 1; ++ goto done; ++#else /* BYTE */ ++ case charset: ++ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) ++ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ++ fastmap[j] = 1; ++ break; ++ ++ ++ case charset_not: ++ /* Chars beyond end of map must be allowed. */ ++ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) ++ fastmap[j] = 1; ++ ++ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) ++ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) ++ fastmap[j] = 1; ++ break; ++ ++ ++ case wordchar: ++ for (j = 0; j < (1 << BYTEWIDTH); j++) ++ if (SYNTAX (j) == Sword) ++ fastmap[j] = 1; ++ break; ++ ++ ++ case notwordchar: ++ for (j = 0; j < (1 << BYTEWIDTH); j++) ++ if (SYNTAX (j) != Sword) ++ fastmap[j] = 1; ++ break; ++#endif /* WCHAR */ ++ ++ case anychar: ++ { ++ int fastmap_newline = fastmap['\n']; ++ ++ /* `.' matches anything ... */ ++ for (j = 0; j < (1 << BYTEWIDTH); j++) ++ fastmap[j] = 1; ++ ++ /* ... except perhaps newline. */ ++ if (!(bufp->syntax & RE_DOT_NEWLINE)) ++ fastmap['\n'] = fastmap_newline; ++ ++ /* Return if we have already set `can_be_null'; if we have, ++ then the fastmap is irrelevant. Something's wrong here. */ ++ else if (bufp->can_be_null) ++ goto done; ++ ++ /* Otherwise, have to check alternative paths. */ ++ break; ++ } ++ ++#ifdef emacs ++ case syntaxspec: ++ k = *p++; ++ for (j = 0; j < (1 << BYTEWIDTH); j++) ++ if (SYNTAX (j) == (enum syntaxcode) k) ++ fastmap[j] = 1; ++ break; ++ ++ ++ case notsyntaxspec: ++ k = *p++; ++ for (j = 0; j < (1 << BYTEWIDTH); j++) ++ if (SYNTAX (j) != (enum syntaxcode) k) ++ fastmap[j] = 1; ++ break; ++ ++ ++ /* All cases after this match the empty string. These end with ++ `continue'. */ ++ ++ ++ case before_dot: ++ case at_dot: ++ case after_dot: ++ continue; ++#endif /* emacs */ ++ ++ ++ case no_op: ++ case begline: ++ case endline: ++ case begbuf: ++ case endbuf: ++ case wordbound: ++ case notwordbound: ++ case wordbeg: ++ case wordend: ++ case push_dummy_failure: ++ continue; ++ ++ ++ case jump_n: ++ case pop_failure_jump: ++ case maybe_pop_jump: ++ case jump: ++ case jump_past_alt: ++ case dummy_failure_jump: ++ EXTRACT_NUMBER_AND_INCR (j, p); ++ p += j; ++ if (j > 0) ++ continue; ++ ++ /* Jump backward implies we just went through the body of a ++ loop and matched nothing. Opcode jumped to should be ++ `on_failure_jump' or `succeed_n'. Just treat it like an ++ ordinary jump. For a * loop, it has pushed its failure ++ point already; if so, discard that as redundant. */ ++ if ((re_opcode_t) *p != on_failure_jump ++ && (re_opcode_t) *p != succeed_n) ++ continue; ++ ++ p++; ++ EXTRACT_NUMBER_AND_INCR (j, p); ++ p += j; ++ ++ /* If what's on the stack is where we are now, pop it. */ ++ if (!FAIL_STACK_EMPTY () ++ && fail_stack.stack[fail_stack.avail - 1].pointer == p) ++ fail_stack.avail--; ++ ++ continue; ++ ++ ++ case on_failure_jump: ++ case on_failure_keep_string_jump: ++ handle_on_failure_jump: ++ EXTRACT_NUMBER_AND_INCR (j, p); ++ ++ /* For some patterns, e.g., `(a?)?', `p+j' here points to the ++ end of the pattern. We don't want to push such a point, ++ since when we restore it above, entering the switch will ++ increment `p' past the end of the pattern. We don't need ++ to push such a point since we obviously won't find any more ++ fastmap entries beyond `pend'. Such a pattern can match ++ the null string, though. */ ++ if (p + j < pend) ++ { ++ if (!PUSH_PATTERN_OP (p + j, fail_stack)) ++ { ++ RESET_FAIL_STACK (); ++ return -2; ++ } ++ } ++ else ++ bufp->can_be_null = 1; ++ ++ if (succeed_n_p) ++ { ++ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ ++ succeed_n_p = false; ++ } ++ ++ continue; ++ ++ ++ case succeed_n: ++ /* Get to the number of times to succeed. */ ++ p += OFFSET_ADDRESS_SIZE; ++ ++ /* Increment p past the n for when k != 0. */ ++ EXTRACT_NUMBER_AND_INCR (k, p); ++ if (k == 0) ++ { ++ p -= 2 * OFFSET_ADDRESS_SIZE; ++ succeed_n_p = true; /* Spaghetti code alert. */ ++ goto handle_on_failure_jump; ++ } ++ continue; ++ ++ ++ case set_number_at: ++ p += 2 * OFFSET_ADDRESS_SIZE; ++ continue; ++ ++ ++ case start_memory: ++ case stop_memory: ++ p += 2; ++ continue; ++ ++ ++ default: ++ abort (); /* We have listed all the cases. */ ++ } /* switch *p++ */ ++ ++ /* Getting here means we have found the possible starting ++ characters for one path of the pattern -- and that the empty ++ string does not match. We need not follow this path further. ++ Instead, look at the next alternative (remembered on the ++ stack), or quit if no more. The test at the top of the loop ++ does these things. */ ++ path_can_be_null = false; ++ p = pend; ++ } /* while p */ ++ ++ /* Set `can_be_null' for the last path (also the first path, if the ++ pattern is empty). */ ++ bufp->can_be_null |= path_can_be_null; ++ ++ done: ++ RESET_FAIL_STACK (); ++ return 0; ++} ++ ++#else /* not INSIDE_RECURSION */ ++ ++int ++re_compile_fastmap (struct re_pattern_buffer *bufp) ++{ ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ return wcs_re_compile_fastmap(bufp); ++ else ++# endif ++ return byte_re_compile_fastmap(bufp); ++} /* re_compile_fastmap */ ++#ifdef _LIBC ++weak_alias (__re_compile_fastmap, re_compile_fastmap) ++#endif ++ ++ ++/* Set REGS to hold NUM_REGS registers, storing them in STARTS and ++ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use ++ this memory for recording register information. STARTS and ENDS ++ must be allocated using the malloc library routine, and must each ++ be at least NUM_REGS * sizeof (regoff_t) bytes long. ++ ++ If NUM_REGS == 0, then subsequent matches should allocate their own ++ register data. ++ ++ Unless this function is called, the first search or match using ++ PATTERN_BUFFER will allocate its own register data, without ++ freeing the old data. */ ++ ++void ++re_set_registers (struct re_pattern_buffer *bufp, ++ struct re_registers *regs, unsigned num_regs, ++ regoff_t *starts, regoff_t *ends) ++{ ++ if (num_regs) ++ { ++ bufp->regs_allocated = REGS_REALLOCATE; ++ regs->num_regs = num_regs; ++ regs->start = starts; ++ regs->end = ends; ++ } ++ else ++ { ++ bufp->regs_allocated = REGS_UNALLOCATED; ++ regs->num_regs = 0; ++ regs->start = regs->end = (regoff_t *) 0; ++ } ++} ++#ifdef _LIBC ++weak_alias (__re_set_registers, re_set_registers) ++#endif ++ ++/* Searching routines. */ ++ ++/* Like re_search_2, below, but only one string is specified, and ++ doesn't let you say where to stop matching. */ ++ ++int ++re_search (struct re_pattern_buffer *bufp, const char *string, int size, ++ int startpos, int range, struct re_registers *regs) ++{ ++ return re_search_2 (bufp, NULL, 0, string, size, startpos, range, ++ regs, size); ++} ++#ifdef _LIBC ++weak_alias (__re_search, re_search) ++#endif ++ ++ ++/* Using the compiled pattern in BUFP->buffer, first tries to match the ++ virtual concatenation of STRING1 and STRING2, starting first at index ++ STARTPOS, then at STARTPOS + 1, and so on. ++ ++ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. ++ ++ RANGE is how far to scan while trying to match. RANGE = 0 means try ++ only at STARTPOS; in general, the last start tried is STARTPOS + ++ RANGE. ++ ++ In REGS, return the indices of the virtual concatenation of STRING1 ++ and STRING2 that matched the entire BUFP->buffer and its contained ++ subexpressions. ++ ++ Do not consider matching one past the index STOP in the virtual ++ concatenation of STRING1 and STRING2. ++ ++ We return either the position in the strings at which the match was ++ found, -1 if no match, or -2 if error (such as failure ++ stack overflow). */ ++ ++int ++re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, ++ const char *string2, int size2, int startpos, int range, ++ struct re_registers *regs, int stop) ++{ ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, ++ range, regs, stop); ++ else ++# endif ++ return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, ++ range, regs, stop); ++} /* re_search_2 */ ++#ifdef _LIBC ++weak_alias (__re_search_2, re_search_2) ++#endif ++ ++#endif /* not INSIDE_RECURSION */ ++ ++#ifdef INSIDE_RECURSION ++ ++#ifdef MATCH_MAY_ALLOCATE ++# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL ++#else ++# define FREE_VAR(var) if (var) free (var); var = NULL ++#endif ++ ++#ifdef WCHAR ++# define MAX_ALLOCA_SIZE 2000 ++ ++# define FREE_WCS_BUFFERS() \ ++ do { \ ++ if (size1 > MAX_ALLOCA_SIZE) \ ++ { \ ++ free (wcs_string1); \ ++ free (mbs_offset1); \ ++ } \ ++ else \ ++ { \ ++ FREE_VAR (wcs_string1); \ ++ FREE_VAR (mbs_offset1); \ ++ } \ ++ if (size2 > MAX_ALLOCA_SIZE) \ ++ { \ ++ free (wcs_string2); \ ++ free (mbs_offset2); \ ++ } \ ++ else \ ++ { \ ++ FREE_VAR (wcs_string2); \ ++ FREE_VAR (mbs_offset2); \ ++ } \ ++ } while (0) ++ ++#endif ++ ++ ++static int ++PREFIX(re_search_2) (struct re_pattern_buffer *bufp, const char *string1, ++ int size1, const char *string2, int size2, ++ int startpos, int range, ++ struct re_registers *regs, int stop) ++{ ++ int val; ++ register char *fastmap = bufp->fastmap; ++ register RE_TRANSLATE_TYPE translate = bufp->translate; ++ int total_size = size1 + size2; ++ int endpos = startpos + range; ++#ifdef WCHAR ++ /* We need wchar_t* buffers correspond to cstring1, cstring2. */ ++ wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; ++ /* We need the size of wchar_t buffers correspond to csize1, csize2. */ ++ int wcs_size1 = 0, wcs_size2 = 0; ++ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ ++ int *mbs_offset1 = NULL, *mbs_offset2 = NULL; ++ /* They hold whether each wchar_t is binary data or not. */ ++ char *is_binary = NULL; ++#endif /* WCHAR */ ++ ++ /* Check for out-of-range STARTPOS. */ ++ if (startpos < 0 || startpos > total_size) ++ return -1; ++ ++ /* Fix up RANGE if it might eventually take us outside ++ the virtual concatenation of STRING1 and STRING2. ++ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ ++ if (endpos < 0) ++ range = 0 - startpos; ++ else if (endpos > total_size) ++ range = total_size - startpos; ++ ++ /* If the search isn't to be a backwards one, don't waste time in a ++ search for a pattern that must be anchored. */ ++ if (bufp->used > 0 && range > 0 ++ && ((re_opcode_t) bufp->buffer[0] == begbuf ++ /* `begline' is like `begbuf' if it cannot match at newlines. */ ++ || ((re_opcode_t) bufp->buffer[0] == begline ++ && !bufp->newline_anchor))) ++ { ++ if (startpos > 0) ++ return -1; ++ else ++ range = 1; ++ } ++ ++#ifdef emacs ++ /* In a forward search for something that starts with \=. ++ don't keep searching past point. */ ++ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) ++ { ++ range = PT - startpos; ++ if (range <= 0) ++ return -1; ++ } ++#endif /* emacs */ ++ ++ /* Update the fastmap now if not correct already. */ ++ if (fastmap && !bufp->fastmap_accurate) ++ if (re_compile_fastmap (bufp) == -2) ++ return -2; ++ ++#ifdef WCHAR ++ /* Allocate wchar_t array for wcs_string1 and wcs_string2 and ++ fill them with converted string. */ ++ if (size1 != 0) ++ { ++ if (size1 > MAX_ALLOCA_SIZE) ++ { ++ wcs_string1 = TALLOC (size1 + 1, CHAR_T); ++ mbs_offset1 = TALLOC (size1 + 1, int); ++ is_binary = TALLOC (size1 + 1, char); ++ } ++ else ++ { ++ wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); ++ mbs_offset1 = REGEX_TALLOC (size1 + 1, int); ++ is_binary = REGEX_TALLOC (size1 + 1, char); ++ } ++ if (!wcs_string1 || !mbs_offset1 || !is_binary) ++ { ++ if (size1 > MAX_ALLOCA_SIZE) ++ { ++ free (wcs_string1); ++ free (mbs_offset1); ++ free (is_binary); ++ } ++ else ++ { ++ FREE_VAR (wcs_string1); ++ FREE_VAR (mbs_offset1); ++ FREE_VAR (is_binary); ++ } ++ return -2; ++ } ++ wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, ++ mbs_offset1, is_binary); ++ wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ ++ if (size1 > MAX_ALLOCA_SIZE) ++ free (is_binary); ++ else ++ FREE_VAR (is_binary); ++ } ++ if (size2 != 0) ++ { ++ if (size2 > MAX_ALLOCA_SIZE) ++ { ++ wcs_string2 = TALLOC (size2 + 1, CHAR_T); ++ mbs_offset2 = TALLOC (size2 + 1, int); ++ is_binary = TALLOC (size2 + 1, char); ++ } ++ else ++ { ++ wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); ++ mbs_offset2 = REGEX_TALLOC (size2 + 1, int); ++ is_binary = REGEX_TALLOC (size2 + 1, char); ++ } ++ if (!wcs_string2 || !mbs_offset2 || !is_binary) ++ { ++ FREE_WCS_BUFFERS (); ++ if (size2 > MAX_ALLOCA_SIZE) ++ free (is_binary); ++ else ++ FREE_VAR (is_binary); ++ return -2; ++ } ++ wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, ++ mbs_offset2, is_binary); ++ wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ ++ if (size2 > MAX_ALLOCA_SIZE) ++ free (is_binary); ++ else ++ FREE_VAR (is_binary); ++ } ++#endif /* WCHAR */ ++ ++ ++ /* Loop through the string, looking for a place to start matching. */ ++ for (;;) ++ { ++ /* If a fastmap is supplied, skip quickly over characters that ++ cannot be the start of a match. If the pattern can match the ++ null string, however, we don't need to skip characters; we want ++ the first null string. */ ++ if (fastmap && startpos < total_size && !bufp->can_be_null) ++ { ++ if (range > 0) /* Searching forwards. */ ++ { ++ register const char *d; ++ register int lim = 0; ++ int irange = range; ++ ++ if (startpos < size1 && startpos + range >= size1) ++ lim = range - (size1 - startpos); ++ ++ d = (startpos >= size1 ? string2 - size1 : string1) + startpos; ++ ++ /* Written out as an if-else to avoid testing `translate' ++ inside the loop. */ ++ if (translate) ++ while (range > lim ++ && !fastmap[(unsigned char) ++ translate[(unsigned char) *d++]]) ++ range--; ++ else ++ while (range > lim && !fastmap[(unsigned char) *d++]) ++ range--; ++ ++ startpos += irange - range; ++ } ++ else /* Searching backwards. */ ++ { ++ register CHAR_T c = (size1 == 0 || startpos >= size1 ++ ? string2[startpos - size1] ++ : string1[startpos]); ++ ++ if (!fastmap[(unsigned char) TRANSLATE (c)]) ++ goto advance; ++ } ++ } ++ ++ /* If can't match the null string, and that's all we have left, fail. */ ++ if (range >= 0 && startpos == total_size && fastmap ++ && !bufp->can_be_null) ++ { ++#ifdef WCHAR ++ FREE_WCS_BUFFERS (); ++#endif ++ return -1; ++ } ++ ++#ifdef WCHAR ++ val = wcs_re_match_2_internal (bufp, string1, size1, string2, ++ size2, startpos, regs, stop, ++ wcs_string1, wcs_size1, ++ wcs_string2, wcs_size2, ++ mbs_offset1, mbs_offset2); ++#else /* BYTE */ ++ val = byte_re_match_2_internal (bufp, string1, size1, string2, ++ size2, startpos, regs, stop); ++#endif /* BYTE */ ++ ++#ifndef REGEX_MALLOC ++# ifdef C_ALLOCA ++ alloca (0); ++# endif ++#endif ++ ++ if (val >= 0) ++ { ++#ifdef WCHAR ++ FREE_WCS_BUFFERS (); ++#endif ++ return startpos; ++ } ++ ++ if (val == -2) ++ { ++#ifdef WCHAR ++ FREE_WCS_BUFFERS (); ++#endif ++ return -2; ++ } ++ ++ advance: ++ if (!range) ++ break; ++ else if (range > 0) ++ { ++ range--; ++ startpos++; ++ } ++ else ++ { ++ range++; ++ startpos--; ++ } ++ } ++#ifdef WCHAR ++ FREE_WCS_BUFFERS (); ++#endif ++ return -1; ++} ++ ++#ifdef WCHAR ++/* This converts PTR, a pointer into one of the search wchar_t strings ++ `string1' and `string2' into an multibyte string offset from the ++ beginning of that string. We use mbs_offset to optimize. ++ See convert_mbs_to_wcs. */ ++# define POINTER_TO_OFFSET(ptr) \ ++ (FIRST_STRING_P (ptr) \ ++ ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ ++ : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ ++ + csize1))) ++#else /* BYTE */ ++/* This converts PTR, a pointer into one of the search strings `string1' ++ and `string2' into an offset from the beginning of that string. */ ++# define POINTER_TO_OFFSET(ptr) \ ++ (FIRST_STRING_P (ptr) \ ++ ? ((regoff_t) ((ptr) - string1)) \ ++ : ((regoff_t) ((ptr) - string2 + size1))) ++#endif /* WCHAR */ ++ ++/* Macros for dealing with the split strings in re_match_2. */ ++ ++#define MATCHING_IN_FIRST_STRING (dend == end_match_1) ++ ++/* Call before fetching a character with *d. This switches over to ++ string2 if necessary. */ ++#define PREFETCH() \ ++ while (d == dend) \ ++ { \ ++ /* End of string2 => fail. */ \ ++ if (dend == end_match_2) \ ++ goto fail; \ ++ /* End of string1 => advance to string2. */ \ ++ d = string2; \ ++ dend = end_match_2; \ ++ } ++ ++/* Test if at very beginning or at very end of the virtual concatenation ++ of `string1' and `string2'. If only one string, it's `string2'. */ ++#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) ++#define AT_STRINGS_END(d) ((d) == end2) ++ ++ ++/* Test if D points to a character which is word-constituent. We have ++ two special cases to check for: if past the end of string1, look at ++ the first character in string2; and if before the beginning of ++ string2, look at the last character in string1. */ ++#ifdef WCHAR ++/* Use internationalized API instead of SYNTAX. */ ++# define WORDCHAR_P(d) \ ++ (iswalnum ((wint_t)((d) == end1 ? *string2 \ ++ : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ ++ || ((d) == end1 ? *string2 \ ++ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') ++#else /* BYTE */ ++# define WORDCHAR_P(d) \ ++ (SYNTAX ((d) == end1 ? *string2 \ ++ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ ++ == Sword) ++#endif /* WCHAR */ ++ ++/* Disabled due to a compiler bug -- see comment at case wordbound */ ++#if 0 ++/* Test if the character before D and the one at D differ with respect ++ to being word-constituent. */ ++#define AT_WORD_BOUNDARY(d) \ ++ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ ++ || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) ++#endif ++ ++/* Free everything we malloc. */ ++#ifdef MATCH_MAY_ALLOCATE ++# ifdef WCHAR ++# define FREE_VARIABLES() \ ++ do { \ ++ REGEX_FREE_STACK (fail_stack.stack); \ ++ FREE_VAR (regstart); \ ++ FREE_VAR (regend); \ ++ FREE_VAR (old_regstart); \ ++ FREE_VAR (old_regend); \ ++ FREE_VAR (best_regstart); \ ++ FREE_VAR (best_regend); \ ++ FREE_VAR (reg_info); \ ++ FREE_VAR (reg_dummy); \ ++ FREE_VAR (reg_info_dummy); \ ++ if (!cant_free_wcs_buf) \ ++ { \ ++ FREE_VAR (string1); \ ++ FREE_VAR (string2); \ ++ FREE_VAR (mbs_offset1); \ ++ FREE_VAR (mbs_offset2); \ ++ } \ ++ } while (0) ++# else /* BYTE */ ++# define FREE_VARIABLES() \ ++ do { \ ++ REGEX_FREE_STACK (fail_stack.stack); \ ++ FREE_VAR (regstart); \ ++ FREE_VAR (regend); \ ++ FREE_VAR (old_regstart); \ ++ FREE_VAR (old_regend); \ ++ FREE_VAR (best_regstart); \ ++ FREE_VAR (best_regend); \ ++ FREE_VAR (reg_info); \ ++ FREE_VAR (reg_dummy); \ ++ FREE_VAR (reg_info_dummy); \ ++ } while (0) ++# endif /* WCHAR */ ++#else ++# ifdef WCHAR ++# define FREE_VARIABLES() \ ++ do { \ ++ if (!cant_free_wcs_buf) \ ++ { \ ++ FREE_VAR (string1); \ ++ FREE_VAR (string2); \ ++ FREE_VAR (mbs_offset1); \ ++ FREE_VAR (mbs_offset2); \ ++ } \ ++ } while (0) ++# else /* BYTE */ ++# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ ++# endif /* WCHAR */ ++#endif /* not MATCH_MAY_ALLOCATE */ ++ ++/* These values must meet several constraints. They must not be valid ++ register values; since we have a limit of 255 registers (because ++ we use only one byte in the pattern for the register number), we can ++ use numbers larger than 255. They must differ by 1, because of ++ NUM_FAILURE_ITEMS above. And the value for the lowest register must ++ be larger than the value for the highest register, so we do not try ++ to actually save any registers when none are active. */ ++#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) ++#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) ++ ++#else /* not INSIDE_RECURSION */ ++/* Matching routines. */ ++ ++#ifndef emacs /* Emacs never uses this. */ ++/* re_match is like re_match_2 except it takes only a single string. */ ++ ++int ++re_match (struct re_pattern_buffer *bufp, const char *string, ++ int size, int pos, struct re_registers *regs) ++{ ++ int result; ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, ++ pos, regs, size, ++ NULL, 0, NULL, 0, NULL, NULL); ++ else ++# endif ++ result = byte_re_match_2_internal (bufp, NULL, 0, string, size, ++ pos, regs, size); ++# ifndef REGEX_MALLOC ++# ifdef C_ALLOCA ++ alloca (0); ++# endif ++# endif ++ return result; ++} ++# ifdef _LIBC ++weak_alias (__re_match, re_match) ++# endif ++#endif /* not emacs */ ++ ++#endif /* not INSIDE_RECURSION */ ++ ++#ifdef INSIDE_RECURSION ++static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p, ++ UCHAR_T *end, ++ PREFIX(register_info_type) *reg_info); ++static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p, ++ UCHAR_T *end, ++ PREFIX(register_info_type) *reg_info); ++static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p, ++ UCHAR_T *end, ++ PREFIX(register_info_type) *reg_info); ++static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, ++ register int len, ++ RE_TRANSLATE_TYPE translate); ++#else /* not INSIDE_RECURSION */ ++ ++/* re_match_2 matches the compiled pattern in BUFP against the ++ the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 ++ and SIZE2, respectively). We start matching at POS, and stop ++ matching at STOP. ++ ++ If REGS is non-null and the `no_sub' field of BUFP is nonzero, we ++ store offsets for the substring each group matched in REGS. See the ++ documentation for exactly how many groups we fill. ++ ++ We return -1 if no match, -2 if an internal error (such as the ++ failure stack overflowing). Otherwise, we return the length of the ++ matched substring. */ ++ ++int ++re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, ++ const char *string2, int size2, int pos, ++ struct re_registers *regs, int stop) ++{ ++ int result; ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, ++ pos, regs, stop, ++ NULL, 0, NULL, 0, NULL, NULL); ++ else ++# endif ++ result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, ++ pos, regs, stop); ++ ++#ifndef REGEX_MALLOC ++# ifdef C_ALLOCA ++ alloca (0); ++# endif ++#endif ++ return result; ++} ++#ifdef _LIBC ++weak_alias (__re_match_2, re_match_2) ++#endif ++ ++#endif /* not INSIDE_RECURSION */ ++ ++#ifdef INSIDE_RECURSION ++ ++#ifdef WCHAR ++static int count_mbs_length (int *, int); ++ ++/* This check the substring (from 0, to length) of the multibyte string, ++ to which offset_buffer correspond. And count how many wchar_t_characters ++ the substring occupy. We use offset_buffer to optimization. ++ See convert_mbs_to_wcs. */ ++ ++static int ++count_mbs_length(int *offset_buffer, int length) ++{ ++ int upper, lower; ++ ++ /* Check whether the size is valid. */ ++ if (length < 0) ++ return -1; ++ ++ if (offset_buffer == NULL) ++ return 0; ++ ++ /* If there are no multibyte character, offset_buffer[i] == i. ++ Optmize for this case. */ ++ if (offset_buffer[length] == length) ++ return length; ++ ++ /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ ++ upper = length; ++ lower = 0; ++ ++ while (true) ++ { ++ int middle = (lower + upper) / 2; ++ if (middle == lower || middle == upper) ++ break; ++ if (offset_buffer[middle] > length) ++ upper = middle; ++ else if (offset_buffer[middle] < length) ++ lower = middle; ++ else ++ return middle; ++ } ++ ++ return -1; ++} ++#endif /* WCHAR */ ++ ++/* This is a separate function so that we can force an alloca cleanup ++ afterwards. */ ++#ifdef WCHAR ++static int ++wcs_re_match_2_internal (struct re_pattern_buffer *bufp, ++ const char *cstring1, int csize1, ++ const char *cstring2, int csize2, ++ int pos, ++ struct re_registers *regs, ++ int stop, ++ /* string1 == string2 == NULL means string1/2, size1/2 and ++ mbs_offset1/2 need seting up in this function. */ ++ /* We need wchar_t* buffers correspond to cstring1, cstring2. */ ++ wchar_t *string1, int size1, ++ wchar_t *string2, int size2, ++ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ ++ int *mbs_offset1, int *mbs_offset2) ++#else /* BYTE */ ++static int ++byte_re_match_2_internal (struct re_pattern_buffer *bufp, ++ const char *string1, int size1, ++ const char *string2, int size2, ++ int pos, ++ struct re_registers *regs, int stop) ++#endif /* BYTE */ ++{ ++ /* General temporaries. */ ++ int mcnt; ++ UCHAR_T *p1; ++#ifdef WCHAR ++ /* They hold whether each wchar_t is binary data or not. */ ++ char *is_binary = NULL; ++ /* If true, we can't free string1/2, mbs_offset1/2. */ ++ int cant_free_wcs_buf = 1; ++#endif /* WCHAR */ ++ ++ /* Just past the end of the corresponding string. */ ++ const CHAR_T *end1, *end2; ++ ++ /* Pointers into string1 and string2, just past the last characters in ++ each to consider matching. */ ++ const CHAR_T *end_match_1, *end_match_2; ++ ++ /* Where we are in the data, and the end of the current string. */ ++ const CHAR_T *d, *dend; ++ ++ /* Where we are in the pattern, and the end of the pattern. */ ++#ifdef WCHAR ++ UCHAR_T *pattern, *p; ++ register UCHAR_T *pend; ++#else /* BYTE */ ++ UCHAR_T *p = bufp->buffer; ++ register UCHAR_T *pend = p + bufp->used; ++#endif /* WCHAR */ ++ ++ /* Mark the opcode just after a start_memory, so we can test for an ++ empty subpattern when we get to the stop_memory. */ ++ UCHAR_T *just_past_start_mem = 0; ++ ++ /* We use this to map every character in the string. */ ++ RE_TRANSLATE_TYPE translate = bufp->translate; ++ ++ /* Failure point stack. Each place that can handle a failure further ++ down the line pushes a failure point on this stack. It consists of ++ restart, regend, and reg_info for all registers corresponding to ++ the subexpressions we're currently inside, plus the number of such ++ registers, and, finally, two char *'s. The first char * is where ++ to resume scanning the pattern; the second one is where to resume ++ scanning the strings. If the latter is zero, the failure point is ++ a ``dummy''; if a failure happens and the failure point is a dummy, ++ it gets discarded and the next next one is tried. */ ++#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ ++ PREFIX(fail_stack_type) fail_stack; ++#endif ++#ifdef DEBUG ++ static unsigned failure_id; ++ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; ++#endif ++ ++#ifdef REL_ALLOC ++ /* This holds the pointer to the failure stack, when ++ it is allocated relocatably. */ ++ fail_stack_elt_t *failure_stack_ptr; ++#endif ++ ++ /* We fill all the registers internally, independent of what we ++ return, for use in backreferences. The number here includes ++ an element for register zero. */ ++ size_t num_regs = bufp->re_nsub + 1; ++ ++ /* The currently active registers. */ ++ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; ++ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; ++ ++ /* Information on the contents of registers. These are pointers into ++ the input strings; they record just what was matched (on this ++ attempt) by a subexpression part of the pattern, that is, the ++ regnum-th regstart pointer points to where in the pattern we began ++ matching and the regnum-th regend points to right after where we ++ stopped matching the regnum-th subexpression. (The zeroth register ++ keeps track of what the whole pattern matches.) */ ++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ ++ const CHAR_T **regstart, **regend; ++#endif ++ ++ /* If a group that's operated upon by a repetition operator fails to ++ match anything, then the register for its start will need to be ++ restored because it will have been set to wherever in the string we ++ are when we last see its open-group operator. Similarly for a ++ register's end. */ ++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ ++ const CHAR_T **old_regstart, **old_regend; ++#endif ++ ++ /* The is_active field of reg_info helps us keep track of which (possibly ++ nested) subexpressions we are currently in. The matched_something ++ field of reg_info[reg_num] helps us tell whether or not we have ++ matched any of the pattern so far this time through the reg_num-th ++ subexpression. These two fields get reset each time through any ++ loop their register is in. */ ++#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ ++ PREFIX(register_info_type) *reg_info; ++#endif ++ ++ /* The following record the register info as found in the above ++ variables when we find a match better than any we've seen before. ++ This happens as we backtrack through the failure points, which in ++ turn happens only if we have not yet matched the entire string. */ ++ unsigned best_regs_set = false; ++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ ++ const CHAR_T **best_regstart, **best_regend; ++#endif ++ ++ /* Logically, this is `best_regend[0]'. But we don't want to have to ++ allocate space for that if we're not allocating space for anything ++ else (see below). Also, we never need info about register 0 for ++ any of the other register vectors, and it seems rather a kludge to ++ treat `best_regend' differently than the rest. So we keep track of ++ the end of the best match so far in a separate variable. We ++ initialize this to NULL so that when we backtrack the first time ++ and need to test it, it's not garbage. */ ++ const CHAR_T *match_end = NULL; ++ ++ /* This helps SET_REGS_MATCHED avoid doing redundant work. */ ++ int set_regs_matched_done = 0; ++ ++ /* Used when we pop values we don't care about. */ ++#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ ++ const CHAR_T **reg_dummy; ++ PREFIX(register_info_type) *reg_info_dummy; ++#endif ++ ++#ifdef DEBUG ++ /* Counts the total number of registers pushed. */ ++ unsigned num_regs_pushed = 0; ++#endif ++ ++ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); ++ ++ INIT_FAIL_STACK (); ++ ++#ifdef MATCH_MAY_ALLOCATE ++ /* Do not bother to initialize all the register variables if there are ++ no groups in the pattern, as it takes a fair amount of time. If ++ there are groups, we include space for register 0 (the whole ++ pattern), even though we never use it, since it simplifies the ++ array indexing. We should fix this. */ ++ if (bufp->re_nsub) ++ { ++ regstart = REGEX_TALLOC (num_regs, const CHAR_T *); ++ regend = REGEX_TALLOC (num_regs, const CHAR_T *); ++ old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); ++ old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); ++ best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); ++ best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); ++ reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); ++ reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); ++ reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); ++ ++ if (!(regstart && regend && old_regstart && old_regend && reg_info ++ && best_regstart && best_regend && reg_dummy && reg_info_dummy)) ++ { ++ FREE_VARIABLES (); ++ return -2; ++ } ++ } ++ else ++ { ++ /* We must initialize all our variables to NULL, so that ++ `FREE_VARIABLES' doesn't try to free them. */ ++ regstart = regend = old_regstart = old_regend = best_regstart ++ = best_regend = reg_dummy = NULL; ++ reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; ++ } ++#endif /* MATCH_MAY_ALLOCATE */ ++ ++ /* The starting position is bogus. */ ++#ifdef WCHAR ++ if (pos < 0 || pos > csize1 + csize2) ++#else /* BYTE */ ++ if (pos < 0 || pos > size1 + size2) ++#endif ++ { ++ FREE_VARIABLES (); ++ return -1; ++ } ++ ++#ifdef WCHAR ++ /* Allocate wchar_t array for string1 and string2 and ++ fill them with converted string. */ ++ if (string1 == NULL && string2 == NULL) ++ { ++ /* We need seting up buffers here. */ ++ ++ /* We must free wcs buffers in this function. */ ++ cant_free_wcs_buf = 0; ++ ++ if (csize1 != 0) ++ { ++ string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); ++ mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); ++ is_binary = REGEX_TALLOC (csize1 + 1, char); ++ if (!string1 || !mbs_offset1 || !is_binary) ++ { ++ FREE_VAR (string1); ++ FREE_VAR (mbs_offset1); ++ FREE_VAR (is_binary); ++ return -2; ++ } ++ } ++ if (csize2 != 0) ++ { ++ string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); ++ mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); ++ is_binary = REGEX_TALLOC (csize2 + 1, char); ++ if (!string2 || !mbs_offset2 || !is_binary) ++ { ++ FREE_VAR (string1); ++ FREE_VAR (mbs_offset1); ++ FREE_VAR (string2); ++ FREE_VAR (mbs_offset2); ++ FREE_VAR (is_binary); ++ return -2; ++ } ++ size2 = convert_mbs_to_wcs(string2, cstring2, csize2, ++ mbs_offset2, is_binary); ++ string2[size2] = L'\0'; /* for a sentinel */ ++ FREE_VAR (is_binary); ++ } ++ } ++ ++ /* We need to cast pattern to (wchar_t*), because we casted this compiled ++ pattern to (char*) in regex_compile. */ ++ p = pattern = (CHAR_T*)bufp->buffer; ++ pend = (CHAR_T*)(bufp->buffer + bufp->used); ++ ++#endif /* WCHAR */ ++ ++ /* Initialize subexpression text positions to -1 to mark ones that no ++ start_memory/stop_memory has been seen for. Also initialize the ++ register information struct. */ ++ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) ++ { ++ regstart[mcnt] = regend[mcnt] ++ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; ++ ++ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; ++ IS_ACTIVE (reg_info[mcnt]) = 0; ++ MATCHED_SOMETHING (reg_info[mcnt]) = 0; ++ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; ++ } ++ ++ /* We move `string1' into `string2' if the latter's empty -- but not if ++ `string1' is null. */ ++ if (size2 == 0 && string1 != NULL) ++ { ++ string2 = string1; ++ size2 = size1; ++ string1 = 0; ++ size1 = 0; ++#ifdef WCHAR ++ mbs_offset2 = mbs_offset1; ++ csize2 = csize1; ++ mbs_offset1 = NULL; ++ csize1 = 0; ++#endif ++ } ++ end1 = string1 + size1; ++ end2 = string2 + size2; ++ ++ /* Compute where to stop matching, within the two strings. */ ++#ifdef WCHAR ++ if (stop <= csize1) ++ { ++ mcnt = count_mbs_length(mbs_offset1, stop); ++ end_match_1 = string1 + mcnt; ++ end_match_2 = string2; ++ } ++ else ++ { ++ if (stop > csize1 + csize2) ++ stop = csize1 + csize2; ++ end_match_1 = end1; ++ mcnt = count_mbs_length(mbs_offset2, stop-csize1); ++ end_match_2 = string2 + mcnt; ++ } ++ if (mcnt < 0) ++ { /* count_mbs_length return error. */ ++ FREE_VARIABLES (); ++ return -1; ++ } ++#else ++ if (stop <= size1) ++ { ++ end_match_1 = string1 + stop; ++ end_match_2 = string2; ++ } ++ else ++ { ++ end_match_1 = end1; ++ end_match_2 = string2 + stop - size1; ++ } ++#endif /* WCHAR */ ++ ++ /* `p' scans through the pattern as `d' scans through the data. ++ `dend' is the end of the input string that `d' points within. `d' ++ is advanced into the following input string whenever necessary, but ++ this happens before fetching; therefore, at the beginning of the ++ loop, `d' can be pointing at the end of a string, but it cannot ++ equal `string2'. */ ++#ifdef WCHAR ++ if (size1 > 0 && pos <= csize1) ++ { ++ mcnt = count_mbs_length(mbs_offset1, pos); ++ d = string1 + mcnt; ++ dend = end_match_1; ++ } ++ else ++ { ++ mcnt = count_mbs_length(mbs_offset2, pos-csize1); ++ d = string2 + mcnt; ++ dend = end_match_2; ++ } ++ ++ if (mcnt < 0) ++ { /* count_mbs_length return error. */ ++ FREE_VARIABLES (); ++ return -1; ++ } ++#else ++ if (size1 > 0 && pos <= size1) ++ { ++ d = string1 + pos; ++ dend = end_match_1; ++ } ++ else ++ { ++ d = string2 + pos - size1; ++ dend = end_match_2; ++ } ++#endif /* WCHAR */ ++ ++ DEBUG_PRINT1 ("The compiled pattern is:\n"); ++ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); ++ DEBUG_PRINT1 ("The string to match is: `"); ++ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); ++ DEBUG_PRINT1 ("'\n"); ++ ++ /* This loops over pattern commands. It exits by returning from the ++ function if the match is complete, or it drops through if the match ++ fails at this starting point in the input data. */ ++ for (;;) ++ { ++#ifdef _LIBC ++ DEBUG_PRINT2 ("\n%p: ", p); ++#else ++ DEBUG_PRINT2 ("\n0x%x: ", p); ++#endif ++ ++ if (p == pend) ++ { /* End of pattern means we might have succeeded. */ ++ DEBUG_PRINT1 ("end of pattern ... "); ++ ++ /* If we haven't matched the entire string, and we want the ++ longest match, try backtracking. */ ++ if (d != end_match_2) ++ { ++ /* 1 if this match ends in the same string (string1 or string2) ++ as the best previous match. */ ++ boolean same_str_p = (FIRST_STRING_P (match_end) ++ == MATCHING_IN_FIRST_STRING); ++ /* 1 if this match is the best seen so far. */ ++ boolean best_match_p; ++ ++ /* AIX compiler got confused when this was combined ++ with the previous declaration. */ ++ if (same_str_p) ++ best_match_p = d > match_end; ++ else ++ best_match_p = !MATCHING_IN_FIRST_STRING; ++ ++ DEBUG_PRINT1 ("backtracking.\n"); ++ ++ if (!FAIL_STACK_EMPTY ()) ++ { /* More failure points to try. */ ++ ++ /* If exceeds best match so far, save it. */ ++ if (!best_regs_set || best_match_p) ++ { ++ best_regs_set = true; ++ match_end = d; ++ ++ DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); ++ ++ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) ++ { ++ best_regstart[mcnt] = regstart[mcnt]; ++ best_regend[mcnt] = regend[mcnt]; ++ } ++ } ++ goto fail; ++ } ++ ++ /* If no failure points, don't restore garbage. And if ++ last match is real best match, don't restore second ++ best one. */ ++ else if (best_regs_set && !best_match_p) ++ { ++ restore_best_regs: ++ /* Restore best match. It may happen that `dend == ++ end_match_1' while the restored d is in string2. ++ For example, the pattern `x.*y.*z' against the ++ strings `x-' and `y-z-', if the two strings are ++ not consecutive in memory. */ ++ DEBUG_PRINT1 ("Restoring best registers.\n"); ++ ++ d = match_end; ++ dend = ((d >= string1 && d <= end1) ++ ? end_match_1 : end_match_2); ++ ++ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) ++ { ++ regstart[mcnt] = best_regstart[mcnt]; ++ regend[mcnt] = best_regend[mcnt]; ++ } ++ } ++ } /* d != end_match_2 */ ++ ++ succeed_label: ++ DEBUG_PRINT1 ("Accepting match.\n"); ++ /* If caller wants register contents data back, do it. */ ++ if (regs && !bufp->no_sub) ++ { ++ /* Have the register data arrays been allocated? */ ++ if (bufp->regs_allocated == REGS_UNALLOCATED) ++ { /* No. So allocate them with malloc. We need one ++ extra element beyond `num_regs' for the `-1' marker ++ GNU code uses. */ ++ regs->num_regs = MAX (RE_NREGS, num_regs + 1); ++ regs->start = TALLOC (regs->num_regs, regoff_t); ++ regs->end = TALLOC (regs->num_regs, regoff_t); ++ if (regs->start == NULL || regs->end == NULL) ++ { ++ FREE_VARIABLES (); ++ return -2; ++ } ++ bufp->regs_allocated = REGS_REALLOCATE; ++ } ++ else if (bufp->regs_allocated == REGS_REALLOCATE) ++ { /* Yes. If we need more elements than were already ++ allocated, reallocate them. If we need fewer, just ++ leave it alone. */ ++ if (regs->num_regs < num_regs + 1) ++ { ++ regs->num_regs = num_regs + 1; ++ RETALLOC (regs->start, regs->num_regs, regoff_t); ++ RETALLOC (regs->end, regs->num_regs, regoff_t); ++ if (regs->start == NULL || regs->end == NULL) ++ { ++ FREE_VARIABLES (); ++ return -2; ++ } ++ } ++ } ++ else ++ { ++ /* These braces fend off a "empty body in an else-statement" ++ warning under GCC when assert expands to nothing. */ ++ assert (bufp->regs_allocated == REGS_FIXED); ++ } ++ ++ /* Convert the pointer data in `regstart' and `regend' to ++ indices. Register zero has to be set differently, ++ since we haven't kept track of any info for it. */ ++ if (regs->num_regs > 0) ++ { ++ regs->start[0] = pos; ++#ifdef WCHAR ++ if (MATCHING_IN_FIRST_STRING) ++ regs->end[0] = mbs_offset1 != NULL ? ++ mbs_offset1[d-string1] : 0; ++ else ++ regs->end[0] = csize1 + (mbs_offset2 != NULL ? ++ mbs_offset2[d-string2] : 0); ++#else ++ regs->end[0] = (MATCHING_IN_FIRST_STRING ++ ? ((regoff_t) (d - string1)) ++ : ((regoff_t) (d - string2 + size1))); ++#endif /* WCHAR */ ++ } ++ ++ /* Go through the first `min (num_regs, regs->num_regs)' ++ registers, since that is all we initialized. */ ++ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); ++ mcnt++) ++ { ++ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) ++ regs->start[mcnt] = regs->end[mcnt] = -1; ++ else ++ { ++ regs->start[mcnt] ++ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); ++ regs->end[mcnt] ++ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); ++ } ++ } ++ ++ /* If the regs structure we return has more elements than ++ were in the pattern, set the extra elements to -1. If ++ we (re)allocated the registers, this is the case, ++ because we always allocate enough to have at least one ++ -1 at the end. */ ++ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) ++ regs->start[mcnt] = regs->end[mcnt] = -1; ++ } /* regs && !bufp->no_sub */ ++ ++ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", ++ nfailure_points_pushed, nfailure_points_popped, ++ nfailure_points_pushed - nfailure_points_popped); ++ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); ++ ++#ifdef WCHAR ++ if (MATCHING_IN_FIRST_STRING) ++ mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; ++ else ++ mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + ++ csize1; ++ mcnt -= pos; ++#else ++ mcnt = d - pos - (MATCHING_IN_FIRST_STRING ++ ? string1 ++ : string2 - size1); ++#endif /* WCHAR */ ++ ++ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); ++ ++ FREE_VARIABLES (); ++ return mcnt; ++ } ++ ++ /* Otherwise match next pattern command. */ ++ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) ++ { ++ /* Ignore these. Used to ignore the n of succeed_n's which ++ currently have n == 0. */ ++ case no_op: ++ DEBUG_PRINT1 ("EXECUTING no_op.\n"); ++ break; ++ ++ case succeed: ++ DEBUG_PRINT1 ("EXECUTING succeed.\n"); ++ goto succeed_label; ++ ++ /* Match the next n pattern characters exactly. The following ++ byte in the pattern defines n, and the n bytes after that ++ are the characters to match. */ ++ case exactn: ++#ifdef MBS_SUPPORT ++ case exactn_bin: ++#endif ++ mcnt = *p++; ++ DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); ++ ++ /* This is written out as an if-else so we don't waste time ++ testing `translate' inside the loop. */ ++ if (translate) ++ { ++ do ++ { ++ PREFETCH (); ++#ifdef WCHAR ++ if (*d <= 0xff) ++ { ++ if ((UCHAR_T) translate[(unsigned char) *d++] ++ != (UCHAR_T) *p++) ++ goto fail; ++ } ++ else ++ { ++ if (*d++ != (CHAR_T) *p++) ++ goto fail; ++ } ++#else ++ if ((UCHAR_T) translate[(unsigned char) *d++] ++ != (UCHAR_T) *p++) ++ goto fail; ++#endif /* WCHAR */ ++ } ++ while (--mcnt); ++ } ++ else ++ { ++ do ++ { ++ PREFETCH (); ++ if (*d++ != (CHAR_T) *p++) goto fail; ++ } ++ while (--mcnt); ++ } ++ SET_REGS_MATCHED (); ++ break; ++ ++ ++ /* Match any character except possibly a newline or a null. */ ++ case anychar: ++ DEBUG_PRINT1 ("EXECUTING anychar.\n"); ++ ++ PREFETCH (); ++ ++ if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') ++ || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) ++ goto fail; ++ ++ SET_REGS_MATCHED (); ++ DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); ++ d++; ++ break; ++ ++ ++ case charset: ++ case charset_not: ++ { ++ register UCHAR_T c; ++#ifdef WCHAR ++ unsigned int i, char_class_length, coll_symbol_length, ++ equiv_class_length, ranges_length, chars_length, length; ++ CHAR_T *workp, *workp2, *charset_top; ++#define WORK_BUFFER_SIZE 128 ++ CHAR_T str_buf[WORK_BUFFER_SIZE]; ++# ifdef _LIBC ++ uint32_t nrules; ++# endif /* _LIBC */ ++#endif /* WCHAR */ ++ boolean negate = (re_opcode_t) *(p - 1) == charset_not; ++ ++ DEBUG_PRINT2 ("EXECUTING charset%s.\n", negate ? "_not" : ""); ++ PREFETCH (); ++ c = TRANSLATE (*d); /* The character to match. */ ++#ifdef WCHAR ++# ifdef _LIBC ++ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); ++# endif /* _LIBC */ ++ charset_top = p - 1; ++ char_class_length = *p++; ++ coll_symbol_length = *p++; ++ equiv_class_length = *p++; ++ ranges_length = *p++; ++ chars_length = *p++; ++ /* p points charset[6], so the address of the next instruction ++ (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'], ++ where l=length of char_classes, m=length of collating_symbol, ++ n=equivalence_class, o=length of char_range, ++ p'=length of character. */ ++ workp = p; ++ /* Update p to indicate the next instruction. */ ++ p += char_class_length + coll_symbol_length+ equiv_class_length + ++ 2*ranges_length + chars_length; ++ ++ /* match with char_class? */ ++ for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE) ++ { ++ wctype_t wctype; ++ uintptr_t alignedp = ((uintptr_t)workp ++ + __alignof__(wctype_t) - 1) ++ & ~(uintptr_t)(__alignof__(wctype_t) - 1); ++ wctype = *((wctype_t*)alignedp); ++ workp += CHAR_CLASS_SIZE; ++# ifdef _LIBC ++ if (__iswctype((wint_t)c, wctype)) ++ goto char_set_matched; ++# else ++ if (iswctype((wint_t)c, wctype)) ++ goto char_set_matched; ++# endif ++ } ++ ++ /* match with collating_symbol? */ ++# ifdef _LIBC ++ if (nrules != 0) ++ { ++ const unsigned char *extra = (const unsigned char *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); ++ ++ for (workp2 = workp + coll_symbol_length ; workp < workp2 ; ++ workp++) ++ { ++ int32_t *wextra; ++ wextra = (int32_t*)(extra + *workp++); ++ for (i = 0; i < *wextra; ++i) ++ if (TRANSLATE(d[i]) != wextra[1 + i]) ++ break; ++ ++ if (i == *wextra) ++ { ++ /* Update d, however d will be incremented at ++ char_set_matched:, we decrement d here. */ ++ d += i - 1; ++ goto char_set_matched; ++ } ++ } ++ } ++ else /* (nrules == 0) */ ++# endif ++ /* If we can't look up collation data, we use wcscoll ++ instead. */ ++ { ++ for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) ++ { ++ const CHAR_T *backup_d = d, *backup_dend = dend; ++# ifdef _LIBC ++ length = __wcslen (workp); ++# else ++ length = wcslen (workp); ++# endif ++ ++ /* If wcscoll(the collating symbol, whole string) > 0, ++ any substring of the string never match with the ++ collating symbol. */ ++# ifdef _LIBC ++ if (__wcscoll (workp, d) > 0) ++# else ++ if (wcscoll (workp, d) > 0) ++# endif ++ { ++ workp += length + 1; ++ continue; ++ } ++ ++ /* First, we compare the collating symbol with ++ the first character of the string. ++ If it don't match, we add the next character to ++ the compare buffer in turn. */ ++ for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++) ++ { ++ int match; ++ if (d == dend) ++ { ++ if (dend == end_match_2) ++ break; ++ d = string2; ++ dend = end_match_2; ++ } ++ ++ /* add next character to the compare buffer. */ ++ str_buf[i] = TRANSLATE(*d); ++ str_buf[i+1] = '\0'; ++ ++# ifdef _LIBC ++ match = __wcscoll (workp, str_buf); ++# else ++ match = wcscoll (workp, str_buf); ++# endif ++ if (match == 0) ++ goto char_set_matched; ++ ++ if (match < 0) ++ /* (str_buf > workp) indicate (str_buf + X > workp), ++ because for all X (str_buf + X > str_buf). ++ So we don't need continue this loop. */ ++ break; ++ ++ /* Otherwise(str_buf < workp), ++ (str_buf+next_character) may equals (workp). ++ So we continue this loop. */ ++ } ++ /* not matched */ ++ d = backup_d; ++ dend = backup_dend; ++ workp += length + 1; ++ } ++ } ++ /* match with equivalence_class? */ ++# ifdef _LIBC ++ if (nrules != 0) ++ { ++ const CHAR_T *backup_d = d, *backup_dend = dend; ++ /* Try to match the equivalence class against ++ those known to the collate implementation. */ ++ const int32_t *table; ++ const int32_t *weights; ++ const int32_t *extra; ++ const int32_t *indirect; ++ int32_t idx, idx2; ++ wint_t *cp; ++ size_t len; ++ ++ table = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); ++ weights = (const wint_t *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); ++ extra = (const wint_t *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); ++ indirect = (const int32_t *) ++ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); ++ ++ /* Write 1 collating element to str_buf, and ++ get its index. */ ++ idx2 = 0; ++ ++ for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++) ++ { ++ cp = (wint_t*)str_buf; ++ if (d == dend) ++ { ++ if (dend == end_match_2) ++ break; ++ d = string2; ++ dend = end_match_2; ++ } ++ str_buf[i] = TRANSLATE(*(d+i)); ++ str_buf[i+1] = '\0'; /* sentinel */ ++ idx2 = FINDIDX (table, indirect, extra, &cp, 1); ++ } ++ ++ /* Update d, however d will be incremented at ++ char_set_matched:, we decrement d here. */ ++ d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1); ++ if (d >= dend) ++ { ++ if (dend == end_match_2) ++ d = dend; ++ else ++ { ++ d = string2; ++ dend = end_match_2; ++ } ++ } ++ ++ len = weights[idx2]; ++ ++ for (workp2 = workp + equiv_class_length ; workp < workp2 ; ++ workp++) ++ { ++ idx = (int32_t)*workp; ++ /* We already checked idx != 0 in regex_compile. */ ++ ++ if (idx2 != 0 && len == weights[idx]) ++ { ++ int cnt = 0; ++ while (cnt < len && (weights[idx + 1 + cnt] ++ == weights[idx2 + 1 + cnt])) ++ ++cnt; ++ ++ if (cnt == len) ++ goto char_set_matched; ++ } ++ } ++ /* not matched */ ++ d = backup_d; ++ dend = backup_dend; ++ } ++ else /* (nrules == 0) */ ++# endif ++ /* If we can't look up collation data, we use wcscoll ++ instead. */ ++ { ++ for (workp2 = workp + equiv_class_length ; workp < workp2 ;) ++ { ++ const CHAR_T *backup_d = d, *backup_dend = dend; ++# ifdef _LIBC ++ length = __wcslen (workp); ++# else ++ length = wcslen (workp); ++# endif ++ ++ /* If wcscoll(the collating symbol, whole string) > 0, ++ any substring of the string never match with the ++ collating symbol. */ ++# ifdef _LIBC ++ if (__wcscoll (workp, d) > 0) ++# else ++ if (wcscoll (workp, d) > 0) ++# endif ++ { ++ workp += length + 1; ++ break; ++ } ++ ++ /* First, we compare the equivalence class with ++ the first character of the string. ++ If it don't match, we add the next character to ++ the compare buffer in turn. */ ++ for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++) ++ { ++ int match; ++ if (d == dend) ++ { ++ if (dend == end_match_2) ++ break; ++ d = string2; ++ dend = end_match_2; ++ } ++ ++ /* add next character to the compare buffer. */ ++ str_buf[i] = TRANSLATE(*d); ++ str_buf[i+1] = '\0'; ++ ++# ifdef _LIBC ++ match = __wcscoll (workp, str_buf); ++# else ++ match = wcscoll (workp, str_buf); ++# endif ++ ++ if (match == 0) ++ goto char_set_matched; ++ ++ if (match < 0) ++ /* (str_buf > workp) indicate (str_buf + X > workp), ++ because for all X (str_buf + X > str_buf). ++ So we don't need continue this loop. */ ++ break; ++ ++ /* Otherwise(str_buf < workp), ++ (str_buf+next_character) may equals (workp). ++ So we continue this loop. */ ++ } ++ /* not matched */ ++ d = backup_d; ++ dend = backup_dend; ++ workp += length + 1; ++ } ++ } ++ ++ /* match with char_range? */ ++# ifdef _LIBC ++ if (nrules != 0) ++ { ++ uint32_t collseqval; ++ const char *collseq = (const char *) ++ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); ++ ++ collseqval = collseq_table_lookup (collseq, c); ++ ++ for (; workp < p - chars_length ;) ++ { ++ uint32_t start_val, end_val; ++ ++ /* We already compute the collation sequence value ++ of the characters (or collating symbols). */ ++ start_val = (uint32_t) *workp++; /* range_start */ ++ end_val = (uint32_t) *workp++; /* range_end */ ++ ++ if (start_val <= collseqval && collseqval <= end_val) ++ goto char_set_matched; ++ } ++ } ++ else ++# endif ++ { ++ /* We set range_start_char at str_buf[0], range_end_char ++ at str_buf[4], and compared char at str_buf[2]. */ ++ str_buf[1] = 0; ++ str_buf[2] = c; ++ str_buf[3] = 0; ++ str_buf[5] = 0; ++ for (; workp < p - chars_length ;) ++ { ++ wchar_t *range_start_char, *range_end_char; ++ ++ /* match if (range_start_char <= c <= range_end_char). */ ++ ++ /* If range_start(or end) < 0, we assume -range_start(end) ++ is the offset of the collating symbol which is specified ++ as the character of the range start(end). */ ++ ++ /* range_start */ ++ if (*workp < 0) ++ range_start_char = charset_top - (*workp++); ++ else ++ { ++ str_buf[0] = *workp++; ++ range_start_char = str_buf; ++ } ++ ++ /* range_end */ ++ if (*workp < 0) ++ range_end_char = charset_top - (*workp++); ++ else ++ { ++ str_buf[4] = *workp++; ++ range_end_char = str_buf + 4; ++ } ++ ++# ifdef _LIBC ++ if (__wcscoll (range_start_char, str_buf+2) <= 0 ++ && __wcscoll (str_buf+2, range_end_char) <= 0) ++# else ++ if (wcscoll (range_start_char, str_buf+2) <= 0 ++ && wcscoll (str_buf+2, range_end_char) <= 0) ++# endif ++ goto char_set_matched; ++ } ++ } ++ ++ /* match with char? */ ++ for (; workp < p ; workp++) ++ if (c == *workp) ++ goto char_set_matched; ++ ++ negate = !negate; ++ ++ char_set_matched: ++ if (negate) goto fail; ++#else ++ /* Cast to `unsigned' instead of `unsigned char' in case the ++ bit list is a full 32 bytes long. */ ++ if (c < (unsigned) (*p * BYTEWIDTH) ++ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) ++ negate = !negate; ++ ++ p += 1 + *p; ++ ++ if (!negate) goto fail; ++#undef WORK_BUFFER_SIZE ++#endif /* WCHAR */ ++ SET_REGS_MATCHED (); ++ d++; ++ break; ++ } ++ ++ ++ /* The beginning of a group is represented by start_memory. ++ The arguments are the register number in the next byte, and the ++ number of groups inner to this one in the next. The text ++ matched within the group is recorded (in the internal ++ registers data structure) under the register number. */ ++ case start_memory: ++ DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", ++ (long int) *p, (long int) p[1]); ++ ++ /* Find out if this group can match the empty string. */ ++ p1 = p; /* To send to group_match_null_string_p. */ ++ ++ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) ++ REG_MATCH_NULL_STRING_P (reg_info[*p]) ++ = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); ++ ++ /* Save the position in the string where we were the last time ++ we were at this open-group operator in case the group is ++ operated upon by a repetition operator, e.g., with `(a*)*b' ++ against `ab'; then we want to ignore where we are now in ++ the string in case this attempt to match fails. */ ++ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ++ ? REG_UNSET (regstart[*p]) ? d : regstart[*p] ++ : regstart[*p]; ++ DEBUG_PRINT2 (" old_regstart: %d\n", ++ POINTER_TO_OFFSET (old_regstart[*p])); ++ ++ regstart[*p] = d; ++ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); ++ ++ IS_ACTIVE (reg_info[*p]) = 1; ++ MATCHED_SOMETHING (reg_info[*p]) = 0; ++ ++ /* Clear this whenever we change the register activity status. */ ++ set_regs_matched_done = 0; ++ ++ /* This is the new highest active register. */ ++ highest_active_reg = *p; ++ ++ /* If nothing was active before, this is the new lowest active ++ register. */ ++ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) ++ lowest_active_reg = *p; ++ ++ /* Move past the register number and inner group count. */ ++ p += 2; ++ just_past_start_mem = p; ++ ++ break; ++ ++ ++ /* The stop_memory opcode represents the end of a group. Its ++ arguments are the same as start_memory's: the register ++ number, and the number of inner groups. */ ++ case stop_memory: ++ DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", ++ (long int) *p, (long int) p[1]); ++ ++ /* We need to save the string position the last time we were at ++ this close-group operator in case the group is operated ++ upon by a repetition operator, e.g., with `((a*)*(b*)*)*' ++ against `aba'; then we want to ignore where we are now in ++ the string in case this attempt to match fails. */ ++ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ++ ? REG_UNSET (regend[*p]) ? d : regend[*p] ++ : regend[*p]; ++ DEBUG_PRINT2 (" old_regend: %d\n", ++ POINTER_TO_OFFSET (old_regend[*p])); ++ ++ regend[*p] = d; ++ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); ++ ++ /* This register isn't active anymore. */ ++ IS_ACTIVE (reg_info[*p]) = 0; ++ ++ /* Clear this whenever we change the register activity status. */ ++ set_regs_matched_done = 0; ++ ++ /* If this was the only register active, nothing is active ++ anymore. */ ++ if (lowest_active_reg == highest_active_reg) ++ { ++ lowest_active_reg = NO_LOWEST_ACTIVE_REG; ++ highest_active_reg = NO_HIGHEST_ACTIVE_REG; ++ } ++ else ++ { /* We must scan for the new highest active register, since ++ it isn't necessarily one less than now: consider ++ (a(b)c(d(e)f)g). When group 3 ends, after the f), the ++ new highest active register is 1. */ ++ UCHAR_T r = *p - 1; ++ while (r > 0 && !IS_ACTIVE (reg_info[r])) ++ r--; ++ ++ /* If we end up at register zero, that means that we saved ++ the registers as the result of an `on_failure_jump', not ++ a `start_memory', and we jumped to past the innermost ++ `stop_memory'. For example, in ((.)*) we save ++ registers 1 and 2 as a result of the *, but when we pop ++ back to the second ), we are at the stop_memory 1. ++ Thus, nothing is active. */ ++ if (r == 0) ++ { ++ lowest_active_reg = NO_LOWEST_ACTIVE_REG; ++ highest_active_reg = NO_HIGHEST_ACTIVE_REG; ++ } ++ else ++ highest_active_reg = r; ++ } ++ ++ /* If just failed to match something this time around with a ++ group that's operated on by a repetition operator, try to ++ force exit from the ``loop'', and restore the register ++ information for this group that we had before trying this ++ last match. */ ++ if ((!MATCHED_SOMETHING (reg_info[*p]) ++ || just_past_start_mem == p - 1) ++ && (p + 2) < pend) ++ { ++ boolean is_a_jump_n = false; ++ ++ p1 = p + 2; ++ mcnt = 0; ++ switch ((re_opcode_t) *p1++) ++ { ++ case jump_n: ++ is_a_jump_n = true; ++ case pop_failure_jump: ++ case maybe_pop_jump: ++ case jump: ++ case dummy_failure_jump: ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ if (is_a_jump_n) ++ p1 += OFFSET_ADDRESS_SIZE; ++ break; ++ ++ default: ++ /* do nothing */ ; ++ } ++ p1 += mcnt; ++ ++ /* If the next operation is a jump backwards in the pattern ++ to an on_failure_jump right before the start_memory ++ corresponding to this stop_memory, exit from the loop ++ by forcing a failure after pushing on the stack the ++ on_failure_jump's jump in the pattern, and d. */ ++ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump ++ && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory ++ && p1[2+OFFSET_ADDRESS_SIZE] == *p) ++ { ++ /* If this group ever matched anything, then restore ++ what its registers were before trying this last ++ failed match, e.g., with `(a*)*b' against `ab' for ++ regstart[1], and, e.g., with `((a*)*(b*)*)*' ++ against `aba' for regend[3]. ++ ++ Also restore the registers for inner groups for, ++ e.g., `((a*)(b*))*' against `aba' (register 3 would ++ otherwise get trashed). */ ++ ++ if (EVER_MATCHED_SOMETHING (reg_info[*p])) ++ { ++ unsigned r; ++ ++ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; ++ ++ /* Restore this and inner groups' (if any) registers. */ ++ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); ++ r++) ++ { ++ regstart[r] = old_regstart[r]; ++ ++ /* xx why this test? */ ++ if (old_regend[r] >= regstart[r]) ++ regend[r] = old_regend[r]; ++ } ++ } ++ p1++; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ PUSH_FAILURE_POINT (p1 + mcnt, d, -2); ++ ++ goto fail; ++ } ++ } ++ ++ /* Move past the register number and the inner group count. */ ++ p += 2; ++ break; ++ ++ ++ /* \ has been turned into a `duplicate' command which is ++ followed by the numeric value of as the register number. */ ++ case duplicate: ++ { ++ register const CHAR_T *d2, *dend2; ++ int regno = *p++; /* Get which register to match against. */ ++ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); ++ ++ /* Can't back reference a group which we've never matched. */ ++ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) ++ goto fail; ++ ++ /* Where in input to try to start matching. */ ++ d2 = regstart[regno]; ++ ++ /* Where to stop matching; if both the place to start and ++ the place to stop matching are in the same string, then ++ set to the place to stop, otherwise, for now have to use ++ the end of the first string. */ ++ ++ dend2 = ((FIRST_STRING_P (regstart[regno]) ++ == FIRST_STRING_P (regend[regno])) ++ ? regend[regno] : end_match_1); ++ for (;;) ++ { ++ /* If necessary, advance to next segment in register ++ contents. */ ++ while (d2 == dend2) ++ { ++ if (dend2 == end_match_2) break; ++ if (dend2 == regend[regno]) break; ++ ++ /* End of string1 => advance to string2. */ ++ d2 = string2; ++ dend2 = regend[regno]; ++ } ++ /* At end of register contents => success */ ++ if (d2 == dend2) break; ++ ++ /* If necessary, advance to next segment in data. */ ++ PREFETCH (); ++ ++ /* How many characters left in this segment to match. */ ++ mcnt = dend - d; ++ ++ /* Want how many consecutive characters we can match in ++ one shot, so, if necessary, adjust the count. */ ++ if (mcnt > dend2 - d2) ++ mcnt = dend2 - d2; ++ ++ /* Compare that many; failure if mismatch, else move ++ past them. */ ++ if (translate ++ ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) ++ : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) ++ goto fail; ++ d += mcnt, d2 += mcnt; ++ ++ /* Do this because we've match some characters. */ ++ SET_REGS_MATCHED (); ++ } ++ } ++ break; ++ ++ ++ /* begline matches the empty string at the beginning of the string ++ (unless `not_bol' is set in `bufp'), and, if ++ `newline_anchor' is set, after newlines. */ ++ case begline: ++ DEBUG_PRINT1 ("EXECUTING begline.\n"); ++ ++ if (AT_STRINGS_BEG (d)) ++ { ++ if (!bufp->not_bol) break; ++ } ++ else if (d[-1] == '\n' && bufp->newline_anchor) ++ { ++ break; ++ } ++ /* In all other cases, we fail. */ ++ goto fail; ++ ++ ++ /* endline is the dual of begline. */ ++ case endline: ++ DEBUG_PRINT1 ("EXECUTING endline.\n"); ++ ++ if (AT_STRINGS_END (d)) ++ { ++ if (!bufp->not_eol) break; ++ } ++ ++ /* We have to ``prefetch'' the next character. */ ++ else if ((d == end1 ? *string2 : *d) == '\n' ++ && bufp->newline_anchor) ++ { ++ break; ++ } ++ goto fail; ++ ++ ++ /* Match at the very beginning of the data. */ ++ case begbuf: ++ DEBUG_PRINT1 ("EXECUTING begbuf.\n"); ++ if (AT_STRINGS_BEG (d)) ++ break; ++ goto fail; ++ ++ ++ /* Match at the very end of the data. */ ++ case endbuf: ++ DEBUG_PRINT1 ("EXECUTING endbuf.\n"); ++ if (AT_STRINGS_END (d)) ++ break; ++ goto fail; ++ ++ ++ /* on_failure_keep_string_jump is used to optimize `.*\n'. It ++ pushes NULL as the value for the string on the stack. Then ++ `pop_failure_point' will keep the current value for the ++ string, instead of restoring it. To see why, consider ++ matching `foo\nbar' against `.*\n'. The .* matches the foo; ++ then the . fails against the \n. But the next thing we want ++ to do is match the \n against the \n; if we restored the ++ string value, we would be back at the foo. ++ ++ Because this is used only in specific cases, we don't need to ++ check all the things that `on_failure_jump' does, to make ++ sure the right things get saved on the stack. Hence we don't ++ share its code. The only reason to push anything on the ++ stack at all is that otherwise we would have to change ++ `anychar's code to do something besides goto fail in this ++ case; that seems worse than this. */ ++ case on_failure_keep_string_jump: ++ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); ++ ++ EXTRACT_NUMBER_AND_INCR (mcnt, p); ++#ifdef _LIBC ++ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); ++#else ++ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); ++#endif ++ ++ PUSH_FAILURE_POINT (p + mcnt, NULL, -2); ++ break; ++ ++ ++ /* Uses of on_failure_jump: ++ ++ Each alternative starts with an on_failure_jump that points ++ to the beginning of the next alternative. Each alternative ++ except the last ends with a jump that in effect jumps past ++ the rest of the alternatives. (They really jump to the ++ ending jump of the following alternative, because tensioning ++ these jumps is a hassle.) ++ ++ Repeats start with an on_failure_jump that points past both ++ the repetition text and either the following jump or ++ pop_failure_jump back to this on_failure_jump. */ ++ case on_failure_jump: ++ on_failure: ++ DEBUG_PRINT1 ("EXECUTING on_failure_jump"); ++ ++ EXTRACT_NUMBER_AND_INCR (mcnt, p); ++#ifdef _LIBC ++ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); ++#else ++ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); ++#endif ++ ++ /* If this on_failure_jump comes right before a group (i.e., ++ the original * applied to a group), save the information ++ for that group and all inner ones, so that if we fail back ++ to this point, the group's information will be correct. ++ For example, in \(a*\)*\1, we need the preceding group, ++ and in \(zz\(a*\)b*\)\2, we need the inner group. */ ++ ++ /* We can't use `p' to check ahead because we push ++ a failure point to `p + mcnt' after we do this. */ ++ p1 = p; ++ ++ /* We need to skip no_op's before we look for the ++ start_memory in case this on_failure_jump is happening as ++ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 ++ against aba. */ ++ while (p1 < pend && (re_opcode_t) *p1 == no_op) ++ p1++; ++ ++ if (p1 < pend && (re_opcode_t) *p1 == start_memory) ++ { ++ /* We have a new highest active register now. This will ++ get reset at the start_memory we are about to get to, ++ but we will have saved all the registers relevant to ++ this repetition op, as described above. */ ++ highest_active_reg = *(p1 + 1) + *(p1 + 2); ++ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) ++ lowest_active_reg = *(p1 + 1); ++ } ++ ++ DEBUG_PRINT1 (":\n"); ++ PUSH_FAILURE_POINT (p + mcnt, d, -2); ++ break; ++ ++ ++ /* A smart repeat ends with `maybe_pop_jump'. ++ We change it to either `pop_failure_jump' or `jump'. */ ++ case maybe_pop_jump: ++ EXTRACT_NUMBER_AND_INCR (mcnt, p); ++ DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); ++ { ++ register UCHAR_T *p2 = p; ++ ++ /* Compare the beginning of the repeat with what in the ++ pattern follows its end. If we can establish that there ++ is nothing that they would both match, i.e., that we ++ would have to backtrack because of (as in, e.g., `a*a') ++ then we can change to pop_failure_jump, because we'll ++ never have to backtrack. ++ ++ This is not true in the case of alternatives: in ++ `(a|ab)*' we do need to backtrack to the `ab' alternative ++ (e.g., if the string was `ab'). But instead of trying to ++ detect that here, the alternative has put on a dummy ++ failure point which is what we will end up popping. */ ++ ++ /* Skip over open/close-group commands. ++ If what follows this loop is a ...+ construct, ++ look at what begins its body, since we will have to ++ match at least one of that. */ ++ while (1) ++ { ++ if (p2 + 2 < pend ++ && ((re_opcode_t) *p2 == stop_memory ++ || (re_opcode_t) *p2 == start_memory)) ++ p2 += 3; ++ else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend ++ && (re_opcode_t) *p2 == dummy_failure_jump) ++ p2 += 2 + 2 * OFFSET_ADDRESS_SIZE; ++ else ++ break; ++ } ++ ++ p1 = p + mcnt; ++ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding ++ to the `maybe_finalize_jump' of this case. Examine what ++ follows. */ ++ ++ /* If we're at the end of the pattern, we can change. */ ++ if (p2 == pend) ++ { ++ /* Consider what happens when matching ":\(.*\)" ++ against ":/". I don't really understand this code ++ yet. */ ++ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) ++ pop_failure_jump; ++ DEBUG_PRINT1 ++ (" End of pattern: change to `pop_failure_jump'.\n"); ++ } ++ ++ else if ((re_opcode_t) *p2 == exactn ++#ifdef MBS_SUPPORT ++ || (re_opcode_t) *p2 == exactn_bin ++#endif ++ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) ++ { ++ register UCHAR_T c ++ = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; ++ ++ if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn ++#ifdef MBS_SUPPORT ++ || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin ++#endif ++ ) && p1[3+OFFSET_ADDRESS_SIZE] != c) ++ { ++ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) ++ pop_failure_jump; ++#ifdef WCHAR ++ DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", ++ (wint_t) c, ++ (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); ++#else ++ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", ++ (char) c, ++ (char) p1[3+OFFSET_ADDRESS_SIZE]); ++#endif ++ } ++ ++#ifndef WCHAR ++ else if ((re_opcode_t) p1[3] == charset ++ || (re_opcode_t) p1[3] == charset_not) ++ { ++ int negate = (re_opcode_t) p1[3] == charset_not; ++ ++ if (c < (unsigned) (p1[4] * BYTEWIDTH) ++ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) ++ negate = !negate; ++ ++ /* `negate' is equal to 1 if c would match, which means ++ that we can't change to pop_failure_jump. */ ++ if (!negate) ++ { ++ p[-3] = (unsigned char) pop_failure_jump; ++ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); ++ } ++ } ++#endif /* not WCHAR */ ++ } ++#ifndef WCHAR ++ else if ((re_opcode_t) *p2 == charset) ++ { ++ /* We win if the first character of the loop is not part ++ of the charset. */ ++ if ((re_opcode_t) p1[3] == exactn ++ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] ++ && (p2[2 + p1[5] / BYTEWIDTH] ++ & (1 << (p1[5] % BYTEWIDTH))))) ++ { ++ p[-3] = (unsigned char) pop_failure_jump; ++ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); ++ } ++ ++ else if ((re_opcode_t) p1[3] == charset_not) ++ { ++ int idx; ++ /* We win if the charset_not inside the loop ++ lists every character listed in the charset after. */ ++ for (idx = 0; idx < (int) p2[1]; idx++) ++ if (! (p2[2 + idx] == 0 ++ || (idx < (int) p1[4] ++ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) ++ break; ++ ++ if (idx == p2[1]) ++ { ++ p[-3] = (unsigned char) pop_failure_jump; ++ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); ++ } ++ } ++ else if ((re_opcode_t) p1[3] == charset) ++ { ++ int idx; ++ /* We win if the charset inside the loop ++ has no overlap with the one after the loop. */ ++ for (idx = 0; ++ idx < (int) p2[1] && idx < (int) p1[4]; ++ idx++) ++ if ((p2[2 + idx] & p1[5 + idx]) != 0) ++ break; ++ ++ if (idx == p2[1] || idx == p1[4]) ++ { ++ p[-3] = (unsigned char) pop_failure_jump; ++ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); ++ } ++ } ++ } ++#endif /* not WCHAR */ ++ } ++ p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ ++ if ((re_opcode_t) p[-1] != pop_failure_jump) ++ { ++ p[-1] = (UCHAR_T) jump; ++ DEBUG_PRINT1 (" Match => jump.\n"); ++ goto unconditional_jump; ++ } ++ /* Note fall through. */ ++ ++ ++ /* The end of a simple repeat has a pop_failure_jump back to ++ its matching on_failure_jump, where the latter will push a ++ failure point. The pop_failure_jump takes off failure ++ points put on by this pop_failure_jump's matching ++ on_failure_jump; we got through the pattern to here from the ++ matching on_failure_jump, so didn't fail. */ ++ case pop_failure_jump: ++ { ++ /* We need to pass separate storage for the lowest and ++ highest registers, even though we don't care about the ++ actual values. Otherwise, we will restore only one ++ register from the stack, since lowest will == highest in ++ `pop_failure_point'. */ ++ active_reg_t dummy_low_reg, dummy_high_reg; ++ UCHAR_T *pdummy __attribute__ ((unused)) = NULL; ++ const CHAR_T *sdummy __attribute__ ((unused)) = NULL; ++ ++ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); ++ POP_FAILURE_POINT (sdummy, pdummy, ++ dummy_low_reg, dummy_high_reg, ++ reg_dummy, reg_dummy, reg_info_dummy); ++ } ++ /* Note fall through. */ ++ ++ unconditional_jump: ++#ifdef _LIBC ++ DEBUG_PRINT2 ("\n%p: ", p); ++#else ++ DEBUG_PRINT2 ("\n0x%x: ", p); ++#endif ++ /* Note fall through. */ ++ ++ /* Unconditionally jump (without popping any failure points). */ ++ case jump: ++ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ ++ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); ++ p += mcnt; /* Do the jump. */ ++#ifdef _LIBC ++ DEBUG_PRINT2 ("(to %p).\n", p); ++#else ++ DEBUG_PRINT2 ("(to 0x%x).\n", p); ++#endif ++ break; ++ ++ ++ /* We need this opcode so we can detect where alternatives end ++ in `group_match_null_string_p' et al. */ ++ case jump_past_alt: ++ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); ++ goto unconditional_jump; ++ ++ ++ /* Normally, the on_failure_jump pushes a failure point, which ++ then gets popped at pop_failure_jump. We will end up at ++ pop_failure_jump, also, and with a pattern of, say, `a+', we ++ are skipping over the on_failure_jump, so we have to push ++ something meaningless for pop_failure_jump to pop. */ ++ case dummy_failure_jump: ++ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); ++ /* It doesn't matter what we push for the string here. What ++ the code at `fail' tests is the value for the pattern. */ ++ PUSH_FAILURE_POINT (NULL, NULL, -2); ++ goto unconditional_jump; ++ ++ ++ /* At the end of an alternative, we need to push a dummy failure ++ point in case we are followed by a `pop_failure_jump', because ++ we don't want the failure point for the alternative to be ++ popped. For example, matching `(a|ab)*' against `aab' ++ requires that we match the `ab' alternative. */ ++ case push_dummy_failure: ++ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); ++ /* See comments just above at `dummy_failure_jump' about the ++ two zeroes. */ ++ PUSH_FAILURE_POINT (NULL, NULL, -2); ++ break; ++ ++ /* Have to succeed matching what follows at least n times. ++ After that, handle like `on_failure_jump'. */ ++ case succeed_n: ++ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); ++ DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); ++ ++ assert (mcnt >= 0); ++ /* Originally, this is how many times we HAVE to succeed. */ ++ if (mcnt > 0) ++ { ++ mcnt--; ++ p += OFFSET_ADDRESS_SIZE; ++ STORE_NUMBER_AND_INCR (p, mcnt); ++#ifdef _LIBC ++ DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE ++ , mcnt); ++#else ++ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE ++ , mcnt); ++#endif ++ } ++ else if (mcnt == 0) ++ { ++#ifdef _LIBC ++ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", ++ p + OFFSET_ADDRESS_SIZE); ++#else ++ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", ++ p + OFFSET_ADDRESS_SIZE); ++#endif /* _LIBC */ ++ ++#ifdef WCHAR ++ p[1] = (UCHAR_T) no_op; ++#else ++ p[2] = (UCHAR_T) no_op; ++ p[3] = (UCHAR_T) no_op; ++#endif /* WCHAR */ ++ goto on_failure; ++ } ++ break; ++ ++ case jump_n: ++ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); ++ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); ++ ++ /* Originally, this is how many times we CAN jump. */ ++ if (mcnt) ++ { ++ mcnt--; ++ STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt); ++ ++#ifdef _LIBC ++ DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE, ++ mcnt); ++#else ++ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE, ++ mcnt); ++#endif /* _LIBC */ ++ goto unconditional_jump; ++ } ++ /* If don't have to jump any more, skip over the rest of command. */ ++ else ++ p += 2 * OFFSET_ADDRESS_SIZE; ++ break; ++ ++ case set_number_at: ++ { ++ DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); ++ ++ EXTRACT_NUMBER_AND_INCR (mcnt, p); ++ p1 = p + mcnt; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p); ++#ifdef _LIBC ++ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); ++#else ++ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); ++#endif ++ STORE_NUMBER (p1, mcnt); ++ break; ++ } ++ ++#if 0 ++ /* The DEC Alpha C compiler 3.x generates incorrect code for the ++ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of ++ AT_WORD_BOUNDARY, so this code is disabled. Expanding the ++ macro and introducing temporary variables works around the bug. */ ++ ++ case wordbound: ++ DEBUG_PRINT1 ("EXECUTING wordbound.\n"); ++ if (AT_WORD_BOUNDARY (d)) ++ break; ++ goto fail; ++ ++ case notwordbound: ++ DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); ++ if (AT_WORD_BOUNDARY (d)) ++ goto fail; ++ break; ++#else ++ case wordbound: ++ { ++ boolean prevchar, thischar; ++ ++ DEBUG_PRINT1 ("EXECUTING wordbound.\n"); ++ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) ++ break; ++ ++ prevchar = WORDCHAR_P (d - 1); ++ thischar = WORDCHAR_P (d); ++ if (prevchar != thischar) ++ break; ++ goto fail; ++ } ++ ++ case notwordbound: ++ { ++ boolean prevchar, thischar; ++ ++ DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); ++ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) ++ goto fail; ++ ++ prevchar = WORDCHAR_P (d - 1); ++ thischar = WORDCHAR_P (d); ++ if (prevchar != thischar) ++ goto fail; ++ break; ++ } ++#endif ++ ++ case wordbeg: ++ DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); ++ if (!AT_STRINGS_END (d) && WORDCHAR_P (d) ++ && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) ++ break; ++ goto fail; ++ ++ case wordend: ++ DEBUG_PRINT1 ("EXECUTING wordend.\n"); ++ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) ++ && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) ++ break; ++ goto fail; ++ ++#ifdef emacs ++ case before_dot: ++ DEBUG_PRINT1 ("EXECUTING before_dot.\n"); ++ if (PTR_CHAR_POS ((unsigned char *) d) >= point) ++ goto fail; ++ break; ++ ++ case at_dot: ++ DEBUG_PRINT1 ("EXECUTING at_dot.\n"); ++ if (PTR_CHAR_POS ((unsigned char *) d) != point) ++ goto fail; ++ break; ++ ++ case after_dot: ++ DEBUG_PRINT1 ("EXECUTING after_dot.\n"); ++ if (PTR_CHAR_POS ((unsigned char *) d) <= point) ++ goto fail; ++ break; ++ ++ case syntaxspec: ++ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); ++ mcnt = *p++; ++ goto matchsyntax; ++ ++ case wordchar: ++ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); ++ mcnt = (int) Sword; ++ matchsyntax: ++ PREFETCH (); ++ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ ++ d++; ++ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) ++ goto fail; ++ SET_REGS_MATCHED (); ++ break; ++ ++ case notsyntaxspec: ++ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); ++ mcnt = *p++; ++ goto matchnotsyntax; ++ ++ case notwordchar: ++ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); ++ mcnt = (int) Sword; ++ matchnotsyntax: ++ PREFETCH (); ++ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ ++ d++; ++ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) ++ goto fail; ++ SET_REGS_MATCHED (); ++ break; ++ ++#else /* not emacs */ ++ case wordchar: ++ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); ++ PREFETCH (); ++ if (!WORDCHAR_P (d)) ++ goto fail; ++ SET_REGS_MATCHED (); ++ d++; ++ break; ++ ++ case notwordchar: ++ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); ++ PREFETCH (); ++ if (WORDCHAR_P (d)) ++ goto fail; ++ SET_REGS_MATCHED (); ++ d++; ++ break; ++#endif /* not emacs */ ++ ++ default: ++ abort (); ++ } ++ continue; /* Successfully executed one pattern command; keep going. */ ++ ++ ++ /* We goto here if a matching operation fails. */ ++ fail: ++ if (!FAIL_STACK_EMPTY ()) ++ { /* A restart point is known. Restore to that state. */ ++ DEBUG_PRINT1 ("\nFAIL:\n"); ++ POP_FAILURE_POINT (d, p, ++ lowest_active_reg, highest_active_reg, ++ regstart, regend, reg_info); ++ ++ /* If this failure point is a dummy, try the next one. */ ++ if (!p) ++ goto fail; ++ ++ /* If we failed to the end of the pattern, don't examine *p. */ ++ assert (p <= pend); ++ if (p < pend) ++ { ++ boolean is_a_jump_n = false; ++ ++ /* If failed to a backwards jump that's part of a repetition ++ loop, need to pop this failure point and use the next one. */ ++ switch ((re_opcode_t) *p) ++ { ++ case jump_n: ++ is_a_jump_n = true; ++ case maybe_pop_jump: ++ case pop_failure_jump: ++ case jump: ++ p1 = p + 1; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ p1 += mcnt; ++ ++ if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) ++ || (!is_a_jump_n ++ && (re_opcode_t) *p1 == on_failure_jump)) ++ goto fail; ++ break; ++ default: ++ /* do nothing */ ; ++ } ++ } ++ ++ if (d >= string1 && d <= end1) ++ dend = end_match_1; ++ } ++ else ++ break; /* Matching at this starting point really fails. */ ++ } /* for (;;) */ ++ ++ if (best_regs_set) ++ goto restore_best_regs; ++ ++ FREE_VARIABLES (); ++ ++ return -1; /* Failure to match. */ ++} /* re_match_2 */ ++ ++/* Subroutine definitions for re_match_2. */ ++ ++ ++/* We are passed P pointing to a register number after a start_memory. ++ ++ Return true if the pattern up to the corresponding stop_memory can ++ match the empty string, and false otherwise. ++ ++ If we find the matching stop_memory, sets P to point to one past its number. ++ Otherwise, sets P to an undefined byte less than or equal to END. ++ ++ We don't handle duplicates properly (yet). */ ++ ++static boolean ++PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, ++ PREFIX(register_info_type) *reg_info) ++{ ++ int mcnt; ++ /* Point to after the args to the start_memory. */ ++ UCHAR_T *p1 = *p + 2; ++ ++ while (p1 < end) ++ { ++ /* Skip over opcodes that can match nothing, and return true or ++ false, as appropriate, when we get to one that can't, or to the ++ matching stop_memory. */ ++ ++ switch ((re_opcode_t) *p1) ++ { ++ /* Could be either a loop or a series of alternatives. */ ++ case on_failure_jump: ++ p1++; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ ++ /* If the next operation is not a jump backwards in the ++ pattern. */ ++ ++ if (mcnt >= 0) ++ { ++ /* Go through the on_failure_jumps of the alternatives, ++ seeing if any of the alternatives cannot match nothing. ++ The last alternative starts with only a jump, ++ whereas the rest start with on_failure_jump and end ++ with a jump, e.g., here is the pattern for `a|b|c': ++ ++ /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 ++ /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 ++ /exactn/1/c ++ ++ So, we have to first go through the first (n-1) ++ alternatives and then deal with the last one separately. */ ++ ++ ++ /* Deal with the first (n-1) alternatives, which start ++ with an on_failure_jump (see above) that jumps to right ++ past a jump_past_alt. */ ++ ++ while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] == ++ jump_past_alt) ++ { ++ /* `mcnt' holds how many bytes long the alternative ++ is, including the ending `jump_past_alt' and ++ its number. */ ++ ++ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - ++ (1 + OFFSET_ADDRESS_SIZE), ++ reg_info)) ++ return false; ++ ++ /* Move to right after this alternative, including the ++ jump_past_alt. */ ++ p1 += mcnt; ++ ++ /* Break if it's the beginning of an n-th alternative ++ that doesn't begin with an on_failure_jump. */ ++ if ((re_opcode_t) *p1 != on_failure_jump) ++ break; ++ ++ /* Still have to check that it's not an n-th ++ alternative that starts with an on_failure_jump. */ ++ p1++; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] != ++ jump_past_alt) ++ { ++ /* Get to the beginning of the n-th alternative. */ ++ p1 -= 1 + OFFSET_ADDRESS_SIZE; ++ break; ++ } ++ } ++ ++ /* Deal with the last alternative: go back and get number ++ of the `jump_past_alt' just before it. `mcnt' contains ++ the length of the alternative. */ ++ EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); ++ ++ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) ++ return false; ++ ++ p1 += mcnt; /* Get past the n-th alternative. */ ++ } /* if mcnt > 0 */ ++ break; ++ ++ ++ case stop_memory: ++ assert (p1[1] == **p); ++ *p = p1 + 2; ++ return true; ++ ++ ++ default: ++ if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) ++ return false; ++ } ++ } /* while p1 < end */ ++ ++ return false; ++} /* group_match_null_string_p */ ++ ++ ++/* Similar to group_match_null_string_p, but doesn't deal with alternatives: ++ It expects P to be the first byte of a single alternative and END one ++ byte past the last. The alternative can contain groups. */ ++ ++static boolean ++PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end, ++ PREFIX(register_info_type) *reg_info) ++{ ++ int mcnt; ++ UCHAR_T *p1 = p; ++ ++ while (p1 < end) ++ { ++ /* Skip over opcodes that can match nothing, and break when we get ++ to one that can't. */ ++ ++ switch ((re_opcode_t) *p1) ++ { ++ /* It's a loop. */ ++ case on_failure_jump: ++ p1++; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ p1 += mcnt; ++ break; ++ ++ default: ++ if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) ++ return false; ++ } ++ } /* while p1 < end */ ++ ++ return true; ++} /* alt_match_null_string_p */ ++ ++ ++/* Deals with the ops common to group_match_null_string_p and ++ alt_match_null_string_p. ++ ++ Sets P to one after the op and its arguments, if any. */ ++ ++static boolean ++PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, ++ PREFIX(register_info_type) *reg_info) ++{ ++ int mcnt; ++ boolean ret; ++ int reg_no; ++ UCHAR_T *p1 = *p; ++ ++ switch ((re_opcode_t) *p1++) ++ { ++ case no_op: ++ case begline: ++ case endline: ++ case begbuf: ++ case endbuf: ++ case wordbeg: ++ case wordend: ++ case wordbound: ++ case notwordbound: ++#ifdef emacs ++ case before_dot: ++ case at_dot: ++ case after_dot: ++#endif ++ break; ++ ++ case start_memory: ++ reg_no = *p1; ++ assert (reg_no > 0 && reg_no <= MAX_REGNUM); ++ ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); ++ ++ /* Have to set this here in case we're checking a group which ++ contains a group and a back reference to it. */ ++ ++ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) ++ REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; ++ ++ if (!ret) ++ return false; ++ break; ++ ++ /* If this is an optimized succeed_n for zero times, make the jump. */ ++ case jump: ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ if (mcnt >= 0) ++ p1 += mcnt; ++ else ++ return false; ++ break; ++ ++ case succeed_n: ++ /* Get to the number of times to succeed. */ ++ p1 += OFFSET_ADDRESS_SIZE; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ ++ if (mcnt == 0) ++ { ++ p1 -= 2 * OFFSET_ADDRESS_SIZE; ++ EXTRACT_NUMBER_AND_INCR (mcnt, p1); ++ p1 += mcnt; ++ } ++ else ++ return false; ++ break; ++ ++ case duplicate: ++ if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) ++ return false; ++ break; ++ ++ case set_number_at: ++ p1 += 2 * OFFSET_ADDRESS_SIZE; ++ ++ default: ++ /* All other opcodes mean we cannot match the empty string. */ ++ return false; ++ } ++ ++ *p = p1; ++ return true; ++} /* common_op_match_null_string_p */ ++ ++ ++/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN ++ bytes; nonzero otherwise. */ ++ ++static int ++PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, register int len, ++ RE_TRANSLATE_TYPE translate) ++{ ++ register const UCHAR_T *p1 = (const UCHAR_T *) s1; ++ register const UCHAR_T *p2 = (const UCHAR_T *) s2; ++ while (len) ++ { ++#ifdef WCHAR ++ if (((*p1<=0xff)?translate[*p1++]:*p1++) ++ != ((*p2<=0xff)?translate[*p2++]:*p2++)) ++ return 1; ++#else /* BYTE */ ++ if (translate[*p1++] != translate[*p2++]) return 1; ++#endif /* WCHAR */ ++ len--; ++ } ++ return 0; ++} ++ ++ ++#else /* not INSIDE_RECURSION */ ++ ++/* Entry points for GNU code. */ ++ ++/* re_compile_pattern is the GNU regular expression compiler: it ++ compiles PATTERN (of length SIZE) and puts the result in BUFP. ++ Returns 0 if the pattern was valid, otherwise an error string. ++ ++ Assumes the `allocated' (and perhaps `buffer') and `translate' fields ++ are set in BUFP on entry. ++ ++ We call regex_compile to do the actual compilation. */ ++ ++const char * ++re_compile_pattern (const char *pattern, size_t length, ++ struct re_pattern_buffer *bufp) ++{ ++ reg_errcode_t ret; ++ ++ /* GNU code is written to assume at least RE_NREGS registers will be set ++ (and at least one extra will be -1). */ ++ bufp->regs_allocated = REGS_UNALLOCATED; ++ ++ /* And GNU code determines whether or not to get register information ++ by passing null for the REGS argument to re_match, etc., not by ++ setting no_sub. */ ++ bufp->no_sub = 0; ++ ++ /* Match anchors at newline. */ ++ bufp->newline_anchor = 1; ++ ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); ++ else ++# endif ++ ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); ++ ++ if (!ret) ++ return NULL; ++ return gettext (re_error_msgid[(int) ret]); ++} ++#ifdef _LIBC ++weak_alias (__re_compile_pattern, re_compile_pattern) ++#endif ++ ++/* Entry points compatible with 4.2 BSD regex library. We don't define ++ them unless specifically requested. */ ++ ++#if defined _REGEX_RE_COMP || defined _LIBC ++ ++/* BSD has one and only one pattern buffer. */ ++static struct re_pattern_buffer re_comp_buf; ++ ++char * ++#ifdef _LIBC ++/* Make these definitions weak in libc, so POSIX programs can redefine ++ these names if they don't use our functions, and still use ++ regcomp/regexec below without link errors. */ ++weak_function ++#endif ++re_comp (const char *s) ++{ ++ reg_errcode_t ret; ++ ++ if (!s) ++ { ++ if (!re_comp_buf.buffer) ++ return (char *) gettext ("No previous regular expression"); ++ return 0; ++ } ++ ++ if (!re_comp_buf.buffer) ++ { ++ re_comp_buf.buffer = (unsigned char *) malloc (200); ++ if (re_comp_buf.buffer == NULL) ++ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); ++ re_comp_buf.allocated = 200; ++ ++ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); ++ if (re_comp_buf.fastmap == NULL) ++ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); ++ } ++ ++ /* Since `re_exec' always passes NULL for the `regs' argument, we ++ don't need to initialize the pattern buffer fields which affect it. */ ++ ++ /* Match anchors at newlines. */ ++ re_comp_buf.newline_anchor = 1; ++ ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); ++ else ++# endif ++ ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); ++ ++ if (!ret) ++ return NULL; ++ ++ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ ++ return (char *) gettext (re_error_msgid[(int) ret]); ++} ++ ++ ++int ++#ifdef _LIBC ++weak_function ++#endif ++re_exec (const char *s) ++{ ++ const int len = strlen (s); ++ return ++ 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); ++} ++ ++#endif /* _REGEX_RE_COMP */ ++ ++/* POSIX.2 functions. Don't define these for Emacs. */ ++ ++#ifndef emacs ++ ++/* regcomp takes a regular expression as a string and compiles it. ++ ++ PREG is a regex_t *. We do not expect any fields to be initialized, ++ since POSIX says we shouldn't. Thus, we set ++ ++ `buffer' to the compiled pattern; ++ `used' to the length of the compiled pattern; ++ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the ++ REG_EXTENDED bit in CFLAGS is set; otherwise, to ++ RE_SYNTAX_POSIX_BASIC; ++ `newline_anchor' to REG_NEWLINE being set in CFLAGS; ++ `fastmap' to an allocated space for the fastmap; ++ `fastmap_accurate' to zero; ++ `re_nsub' to the number of subexpressions in PATTERN. ++ ++ PATTERN is the address of the pattern string. ++ ++ CFLAGS is a series of bits which affect compilation. ++ ++ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we ++ use POSIX basic syntax. ++ ++ If REG_NEWLINE is set, then . and [^...] don't match newline. ++ Also, regexec will try a match beginning after every newline. ++ ++ If REG_ICASE is set, then we considers upper- and lowercase ++ versions of letters to be equivalent when matching. ++ ++ If REG_NOSUB is set, then when PREG is passed to regexec, that ++ routine will report only success or failure, and nothing about the ++ registers. ++ ++ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for ++ the return codes and their meanings.) */ ++ ++int ++regcomp (regex_t *preg, const char *pattern, int cflags) ++{ ++ reg_errcode_t ret; ++ reg_syntax_t syntax ++ = (cflags & REG_EXTENDED) ? ++ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; ++ ++ /* regex_compile will allocate the space for the compiled pattern. */ ++ preg->buffer = 0; ++ preg->allocated = 0; ++ preg->used = 0; ++ ++ /* Try to allocate space for the fastmap. */ ++ preg->fastmap = (char *) malloc (1 << BYTEWIDTH); ++ ++ if (cflags & REG_ICASE) ++ { ++ int i; ++ ++ preg->translate ++ = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE ++ * sizeof (*(RE_TRANSLATE_TYPE)0)); ++ if (preg->translate == NULL) ++ return (int) REG_ESPACE; ++ ++ /* Map uppercase characters to corresponding lowercase ones. */ ++ for (i = 0; i < CHAR_SET_SIZE; i++) ++ preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; ++ } ++ else ++ preg->translate = NULL; ++ ++ /* If REG_NEWLINE is set, newlines are treated differently. */ ++ if (cflags & REG_NEWLINE) ++ { /* REG_NEWLINE implies neither . nor [^...] match newline. */ ++ syntax &= ~RE_DOT_NEWLINE; ++ syntax |= RE_HAT_LISTS_NOT_NEWLINE; ++ /* It also changes the matching behavior. */ ++ preg->newline_anchor = 1; ++ } ++ else ++ preg->newline_anchor = 0; ++ ++ preg->no_sub = !!(cflags & REG_NOSUB); ++ ++ /* POSIX says a null character in the pattern terminates it, so we ++ can use strlen here in compiling the pattern. */ ++# ifdef MBS_SUPPORT ++ if (MB_CUR_MAX != 1) ++ ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); ++ else ++# endif ++ ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); ++ ++ /* POSIX doesn't distinguish between an unmatched open-group and an ++ unmatched close-group: both are REG_EPAREN. */ ++ if (ret == REG_ERPAREN) ret = REG_EPAREN; ++ ++ if (ret == REG_NOERROR && preg->fastmap) ++ { ++ /* Compute the fastmap now, since regexec cannot modify the pattern ++ buffer. */ ++ if (re_compile_fastmap (preg) == -2) ++ { ++ /* Some error occurred while computing the fastmap, just forget ++ about it. */ ++ free (preg->fastmap); ++ preg->fastmap = NULL; ++ } ++ } ++ ++ return (int) ret; ++} ++#ifdef _LIBC ++weak_alias (__regcomp, regcomp) ++#endif ++ ++ ++/* regexec searches for a given pattern, specified by PREG, in the ++ string STRING. ++ ++ If NMATCH is zero or REG_NOSUB was set in the cflags argument to ++ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at ++ least NMATCH elements, and we set them to the offsets of the ++ corresponding matched substrings. ++ ++ EFLAGS specifies `execution flags' which affect matching: if ++ REG_NOTBOL is set, then ^ does not match at the beginning of the ++ string; if REG_NOTEOL is set, then $ does not match at the end. ++ ++ We return 0 if we find a match and REG_NOMATCH if not. */ ++ ++int ++regexec (const regex_t *preg, const char *string, size_t nmatch, ++ regmatch_t pmatch[], int eflags) ++{ ++ int ret; ++ struct re_registers regs; ++ regex_t private_preg; ++ int len = strlen (string); ++ boolean want_reg_info = !preg->no_sub && nmatch > 0; ++ ++ private_preg = *preg; ++ ++ private_preg.not_bol = !!(eflags & REG_NOTBOL); ++ private_preg.not_eol = !!(eflags & REG_NOTEOL); ++ ++ /* The user has told us exactly how many registers to return ++ information about, via `nmatch'. We have to pass that on to the ++ matching routines. */ ++ private_preg.regs_allocated = REGS_FIXED; ++ ++ if (want_reg_info) ++ { ++ regs.num_regs = nmatch; ++ regs.start = TALLOC (nmatch * 2, regoff_t); ++ if (regs.start == NULL) ++ return (int) REG_NOMATCH; ++ regs.end = regs.start + nmatch; ++ } ++ ++ /* Perform the searching operation. */ ++ ret = re_search (&private_preg, string, len, ++ /* start: */ 0, /* range: */ len, ++ want_reg_info ? ®s : (struct re_registers *) 0); ++ ++ /* Copy the register information to the POSIX structure. */ ++ if (want_reg_info) ++ { ++ if (ret >= 0) ++ { ++ unsigned r; ++ ++ for (r = 0; r < nmatch; r++) ++ { ++ pmatch[r].rm_so = regs.start[r]; ++ pmatch[r].rm_eo = regs.end[r]; ++ } ++ } ++ ++ /* If we needed the temporary register info, free the space now. */ ++ free (regs.start); ++ } ++ ++ /* We want zero return to mean success, unlike `re_search'. */ ++ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; ++} ++#ifdef _LIBC ++/* EGLIBC: This is handled in regexec-compat.c. */ ++/*weak_alias (__regexec, regexec)*/ ++#include "regexec-compat.c" ++#endif ++ ++ ++/* Returns a message corresponding to an error code, ERRCODE, returned ++ from either regcomp or regexec. We don't use PREG here. */ ++ ++size_t ++regerror (int errcode, const regex_t *preg __attribute__ ((unused)), ++ char *errbuf, size_t errbuf_size) ++{ ++ const char *msg; ++ size_t msg_size; ++ ++ if (errcode < 0 ++ || errcode >= (int) (sizeof (re_error_msgid) ++ / sizeof (re_error_msgid[0]))) ++ /* Only error codes returned by the rest of the code should be passed ++ to this routine. If we are given anything else, or if other regex ++ code generates an invalid error code, then the program has a bug. ++ Dump core so we can fix it. */ ++ abort (); ++ ++ msg = gettext (re_error_msgid[errcode]); ++ ++ msg_size = strlen (msg) + 1; /* Includes the null. */ ++ ++ if (errbuf_size != 0) ++ { ++ if (msg_size > errbuf_size) ++ { ++#if defined HAVE_MEMPCPY || defined _LIBC ++ *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; ++#else ++ memcpy (errbuf, msg, errbuf_size - 1); ++ errbuf[errbuf_size - 1] = 0; ++#endif ++ } ++ else ++ memcpy (errbuf, msg, msg_size); ++ } ++ ++ return msg_size; ++} ++#ifdef _LIBC ++weak_alias (__regerror, regerror) ++#endif ++ ++ ++/* Free dynamically allocated space used by PREG. */ ++ ++void ++regfree (regex_t *preg) ++{ ++ if (preg->buffer != NULL) ++ free (preg->buffer); ++ preg->buffer = NULL; ++ ++ preg->allocated = 0; ++ preg->used = 0; ++ ++ if (preg->fastmap != NULL) ++ free (preg->fastmap); ++ preg->fastmap = NULL; ++ preg->fastmap_accurate = 0; ++ ++ if (preg->translate != NULL) ++ free (preg->translate); ++ preg->translate = NULL; ++} ++#ifdef _LIBC ++weak_alias (__regfree, regfree) ++#endif ++ ++#endif /* not emacs */ ++ ++#endif /* not INSIDE_RECURSION */ ++ ++ ++#undef STORE_NUMBER ++#undef STORE_NUMBER_AND_INCR ++#undef EXTRACT_NUMBER ++#undef EXTRACT_NUMBER_AND_INCR ++ ++#undef DEBUG_PRINT_COMPILED_PATTERN ++#undef DEBUG_PRINT_DOUBLE_STRING ++ ++#undef INIT_FAIL_STACK ++#undef RESET_FAIL_STACK ++#undef DOUBLE_FAIL_STACK ++#undef PUSH_PATTERN_OP ++#undef PUSH_FAILURE_POINTER ++#undef PUSH_FAILURE_INT ++#undef PUSH_FAILURE_ELT ++#undef POP_FAILURE_POINTER ++#undef POP_FAILURE_INT ++#undef POP_FAILURE_ELT ++#undef DEBUG_PUSH ++#undef DEBUG_POP ++#undef PUSH_FAILURE_POINT ++#undef POP_FAILURE_POINT ++ ++#undef REG_UNSET_VALUE ++#undef REG_UNSET ++ ++#undef PATFETCH ++#undef PATFETCH_RAW ++#undef PATUNFETCH ++#undef TRANSLATE ++ ++#undef INIT_BUF_SIZE ++#undef GET_BUFFER_SPACE ++#undef BUF_PUSH ++#undef BUF_PUSH_2 ++#undef BUF_PUSH_3 ++#undef STORE_JUMP ++#undef STORE_JUMP2 ++#undef INSERT_JUMP ++#undef INSERT_JUMP2 ++#undef EXTEND_BUFFER ++#undef GET_UNSIGNED_NUMBER ++#undef FREE_STACK_RETURN ++ ++# undef POINTER_TO_OFFSET ++# undef MATCHING_IN_FRST_STRING ++# undef PREFETCH ++# undef AT_STRINGS_BEG ++# undef AT_STRINGS_END ++# undef WORDCHAR_P ++# undef FREE_VAR ++# undef FREE_VARIABLES ++# undef NO_HIGHEST_ACTIVE_REG ++# undef NO_LOWEST_ACTIVE_REG ++ ++# undef CHAR_T ++# undef UCHAR_T ++# undef COMPILED_BUFFER_VAR ++# undef OFFSET_ADDRESS_SIZE ++# undef CHAR_CLASS_SIZE ++# undef PREFIX ++# undef ARG_PREFIX ++# undef PUT_CHAR ++# undef BYTE ++# undef WCHAR ++ ++# define DEFINED_ONCE +diff --git a/pwd/Makefile b/pwd/Makefile +index 7f6de03..916d546 100644 +--- a/pwd/Makefile ++++ b/pwd/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for pwd portion of the library. + # ++include ../option-groups.mak ++ + subdir := pwd + + include ../Makeconfig +diff --git a/resolv/Makefile b/resolv/Makefile +index 1dcb75f..2e4b630 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for resolv portion of the library. + # ++include ../option-groups.mak ++ + subdir := resolv + + include ../Makeconfig +@@ -27,21 +29,22 @@ headers := resolv.h \ + arpa/nameser.h arpa/nameser_compat.h \ + sys/bitypes.h + +-routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ +- res_hconf res_libc res-state ++routines-$(OPTION_EGLIBC_INET) \ ++ += herror inet_addr inet_ntop inet_pton nsap_addr res_init \ ++ res_hconf res_libc res-state + +-tests = tst-aton tst-leaks tst-inet_ntop +-xtests = tst-leaks2 ++tests-$(OPTION_EGLIBC_INET) += tst-aton tst-leaks tst-inet_ntop ++xtests-$(OPTION_EGLIBC_INET) += tst-leaks2 + + generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace + +-extra-libs := libresolv libnss_dns ++extra-libs-$(OPTION_EGLIBC_INET) += libresolv libnss_dns + ifeq ($(have-thread-library),yes) +-extra-libs += libanl +-routines += gai_sigqueue ++extra-libs-$(OPTION_EGLIBC_INET_ANL) += libanl ++routines-$(OPTION_EGLIBC_INET) += gai_sigqueue + tests += tst-res_hconf_reorder + endif +-extra-libs-others = $(extra-libs) ++extra-libs-others-y += $(extra-libs-y) + libresolv-routines := gethnamaddr res_comp res_debug \ + res_data res_mkquery res_query res_send \ + inet_net_ntop inet_net_pton inet_neta base64 \ +@@ -61,7 +64,7 @@ routines += $(libnss_dns-routines) $(libresolv-routines) + static-only-routines += $(libnss_dns-routines) $(libresolv-routines) + endif + +-ifeq (yesyes,$(build-shared)$(have-thread-library)) ++ifeq (yesyesy,$(build-shared)$(have-thread-library)$(OPTION_EGLIBC_INET_ANL)) + tests: $(objpfx)ga_test + endif + +diff --git a/stdio-common/Makefile b/stdio-common/Makefile +index d0bf0e1..8655801 100644 +--- a/stdio-common/Makefile ++++ b/stdio-common/Makefile +@@ -18,6 +18,8 @@ + # + # Specific makefile for stdio-common. + # ++include ../option-groups.mak ++ + subdir := stdio-common + + include ../Makeconfig +@@ -30,7 +32,7 @@ routines := \ + vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \ + reg-modifier reg-type \ + printf_size fprintf printf snprintf sprintf asprintf dprintf \ +- vfwprintf vfscanf vfwscanf \ ++ vfscanf \ + fscanf scanf sscanf \ + perror psignal \ + tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ +@@ -41,23 +43,36 @@ routines := \ + isoc99_vsscanf \ + psiginfo + +-aux := errlist siglist printf-parsemb printf-parsewc fxprintf ++# Ideally, _itowa and itowa-digits would be in this option group as ++# well, but it is used unconditionally by printf_fp and printf_fphex, ++# and it didn't seem straightforward to disentangle it. ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += vfwprintf vfwscanf ++ ++aux := errlist siglist printf-parsemb fxprintf ++aux-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += printf-parsewc + + tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ + temptest tst-fileno test-fwrite tst-ungetc tst-ferror \ + xbug errnobug \ + bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \ +- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \ ++ tfformat tiformat tllformat tstdiomisc tst-printfsz \ + scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \ +- scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ +- tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ +- tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \ ++ scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf \ ++ tst-fseek tst-fmemopen tst-gets \ ++ tst-sprintf tst-rndseek tst-fdopen tst-fphex \ + tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ +- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \ +- bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ +- scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ +- bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ ++ tst-fwrite bug16 bug17 tst-sprintf2 bug18 \ ++ bug19 tst-popen2 scanf14 scanf15 bug21 bug22 \ ++ scanf16 scanf17 tst-setvbuf1 bug23 bug24 \ ++ bug-vfprintf-nargs tst-sprintf3 \ + bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-sscanf tst-swprintf test-vfprintf bug14 scanf13 tst-grouping ++tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ ++ += tst-perror bug19a bug20 tst-long-dbl-fphex tst-fphex-wide ++tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += bug18a tst-swscanf tst-wc-printf + + test-srcs = tst-unbputc tst-printf + +diff --git a/stdio-common/_i18n_number.h b/stdio-common/_i18n_number.h +index 3c73044..ac62b3a 100644 +--- a/stdio-common/_i18n_number.h ++++ b/stdio-common/_i18n_number.h +@@ -19,10 +19,13 @@ + #include + #include + #include ++#include + + #include "../locale/outdigits.h" + #include "../locale/outdigitswc.h" + ++#if __OPTION_EGLIBC_LOCALE_CODE ++ + static CHAR_T * + _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) + { +@@ -115,3 +118,13 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) + + return w; + } ++ ++#else ++ ++static CHAR_T * ++_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) ++{ ++ return w; ++} ++ ++#endif +diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c +index 7b2eb94..8476076 100644 +--- a/stdio-common/fxprintf.c ++++ b/stdio-common/fxprintf.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + + int +@@ -37,6 +38,7 @@ __fxprintf (FILE *fp, const char *fmt, ...) + int res; + if (_IO_fwide (fp, 0) > 0) + { ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + size_t len = strlen (fmt) + 1; + wchar_t wfmt[len]; + for (size_t i = 0; i < len; ++i) +@@ -45,6 +47,9 @@ __fxprintf (FILE *fp, const char *fmt, ...) + wfmt[i] = fmt[i]; + } + res = __vfwprintf (fp, wfmt, ap); ++#else ++ abort(); ++#endif + } + else + res = _IO_vfprintf (fp, fmt, ap); +diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c +index 3023b20..bd0df66 100644 +--- a/stdio-common/printf_fp.c ++++ b/stdio-common/printf_fp.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -142,6 +143,10 @@ extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, + extern unsigned int __guess_grouping (unsigned int intdig_max, + const char *grouping); + ++/* Ideally, when OPTION_EGLIBC_LOCALE_CODE is disabled, this should do ++ all its work in ordinary characters, rather than doing it in wide ++ characters and then converting at the end. But that is a challenge ++ for another day. */ + + static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, + unsigned int intdig_no, const char *grouping, +@@ -251,7 +256,14 @@ ___printf_fp (FILE *fp, + mp_limb_t cy; + + /* Nonzero if this is output on a wide character stream. */ ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + int wide = info->wide; ++#else ++ /* This should never be called on a wide-oriented stream when ++ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't ++ be trusted to figure that out. */ ++ const int wide = 0; ++#endif + + /* Buffer in which we produce the output. */ + wchar_t *wbuffer = NULL; +@@ -261,6 +273,7 @@ ___printf_fp (FILE *fp, + p.expsign = 0; + + /* Figure out the decimal point character. */ ++#if __OPTION_EGLIBC_LOCALE_CODE + if (info->extra == 0) + { + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); +@@ -280,7 +293,13 @@ ___printf_fp (FILE *fp, + /* The decimal point character must not be zero. */ + assert (*decimal != '\0'); + assert (decimalwc != L'\0'); ++#else ++ /* Hard-code values from 'C' locale. */ ++ decimal = "."; ++ decimalwc = L'.'; ++#endif + ++#if __OPTION_EGLIBC_LOCALE_CODE + if (info->group) + { + if (info->extra == 0) +@@ -324,6 +343,9 @@ ___printf_fp (FILE *fp, + } + else + grouping = NULL; ++#else ++ grouping = NULL; ++#endif + + /* Fetch the argument value. */ + #ifndef __NO_LONG_DOUBLE_MATH +diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c +index 6c3b5e9..f660ce0 100644 +--- a/stdio-common/printf_fphex.c ++++ b/stdio-common/printf_fphex.c +@@ -28,6 +28,7 @@ + #include <_itoa.h> + #include <_itowa.h> + #include ++#include + #include + #include + +@@ -139,10 +140,18 @@ __printf_fphex (FILE *fp, + int done = 0; + + /* Nonzero if this is output on a wide character stream. */ ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + int wide = info->wide; ++#else ++ /* This should never be called on a wide-oriented stream when ++ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't ++ be trusted to figure that out. */ ++ const int wide = 0; ++#endif + + + /* Figure out the decimal point character. */ ++#if __OPTION_EGLIBC_LOCALE_CODE + if (info->extra == 0) + { + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); +@@ -156,6 +165,10 @@ __printf_fphex (FILE *fp, + } + /* The decimal point character must never be zero. */ + assert (*decimal != '\0' && decimalwc != L'\0'); ++#else ++ decimal = "."; ++ decimalwc = L'.'; ++#endif + + + /* Fetch the argument value. */ +diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c +index 7dcd58e..6fb7491 100644 +--- a/stdio-common/printf_size.c ++++ b/stdio-common/printf_size.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + + /* This defines make it possible to use the same code for GNU C library and +@@ -116,7 +117,14 @@ __printf_size (FILE *fp, const struct printf_info *info, + + struct printf_info fp_info; + int done = 0; ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + int wide = info->wide; ++#else ++ /* This should never be called on a wide-oriented stream when ++ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't ++ be trusted to figure that out. */ ++ const int wide = 0; ++#endif + int res; + + /* Fetch the argument value. */ +diff --git a/stdio-common/scanf14.c b/stdio-common/scanf14.c +index cffccb0..6cc260a 100644 +--- a/stdio-common/scanf14.c ++++ b/stdio-common/scanf14.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + #define FAIL() \ + do { \ +@@ -48,6 +49,7 @@ main (void) + /* See explanation above. */ + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat"); ++#if __OPTION_EGLIBC_LOCALE_CODE + if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2) + FAIL (); + else +@@ -57,6 +59,7 @@ main (void) + memset (lsp, 'x', sizeof L"3.25"); + free (lsp); + } ++#endif + if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2) + FAIL (); + else +diff --git a/stdio-common/tst-popen.c b/stdio-common/tst-popen.c +index 5def27f..7c9b91e 100644 +--- a/stdio-common/tst-popen.c ++++ b/stdio-common/tst-popen.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + static int + do_test (void) +@@ -34,12 +35,14 @@ do_test (void) + return 1; + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + /* POSIX says that pipe streams are byte-oriented. */ + if (fwide (f, 0) >= 0) + { + puts ("popen did not return byte-oriented stream"); + result = 1; + } ++#endif + + if (getline (&line, &len, f) != 5) + { +diff --git a/stdio-common/tst-sprintf.c b/stdio-common/tst-sprintf.c +index d5284b9..f1e3d21 100644 +--- a/stdio-common/tst-sprintf.c ++++ b/stdio-common/tst-sprintf.c +@@ -3,7 +3,7 @@ + #include + #include + #include +- ++#include + + static int + do_test (void) +@@ -11,12 +11,14 @@ do_test (void) + char buf[100]; + int result = 0; + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + if (sprintf (buf, "%.0ls", L"foo") != 0 + || strlen (buf) != 0) + { + puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output"); + result = 1; + } ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + + #define SIZE (1024*70000) + #define STR(x) #x +diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c +index 5548a71..31ed024 100644 +--- a/stdio-common/tstdiomisc.c ++++ b/stdio-common/tstdiomisc.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + static int + t1 (void) +@@ -134,6 +135,7 @@ F (void) + printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", + buf); + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + qnanval, qnanval, qnanval, qnanval, + qnanval, qnanval, qnanval, qnanval); +@@ -171,6 +173,7 @@ F (void) + result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; + printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", + wbuf); ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + + lqnanval = NAN; + +@@ -215,6 +218,7 @@ F (void) + printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", + buf); + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR + swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + L"%La %LA %Le %LE %Lf %LF %Lg %LG", + lqnanval, lqnanval, lqnanval, lqnanval, +@@ -259,6 +263,7 @@ F (void) + result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; + printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", + wbuf); ++#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ + + return result; + } +diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c +index 0592e70..f21d973 100644 +--- a/stdio-common/vfprintf.c ++++ b/stdio-common/vfprintf.c +@@ -29,6 +29,7 @@ + #include <_itoa.h> + #include + #include ++#include + + /* This code is shared between the standard stdio implementation found + in GNU C library and the libio implementation originally found in +@@ -140,6 +141,18 @@ typedef wchar_t THOUSANDS_SEP_T; + # define EOF WEOF + #endif + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR ++# define MULTIBYTE_SUPPORT (1) ++#else ++# define MULTIBYTE_SUPPORT (0) ++#endif ++ ++#if __OPTION_EGLIBC_LOCALE_CODE ++# define LOCALE_SUPPORT (1) ++#else ++# define LOCALE_SUPPORT (0) ++#endif ++ + #include "_i18n_number.h" + + /* Include the shared code for parsing the format string. */ +@@ -1065,8 +1078,11 @@ static const uint8_t jump_table[] = + # define process_string_arg(fspec) \ + LABEL (form_character): \ + /* Character. */ \ +- if (is_long) \ +- goto LABEL (form_wcharacter); \ ++ if (is_long) \ ++ { \ ++ assert (MULTIBYTE_SUPPORT); \ ++ goto LABEL (form_wcharacter); \ ++ } \ + --width; /* Account for the character itself. */ \ + if (!left) \ + PAD (' '); \ +@@ -1079,6 +1095,7 @@ static const uint8_t jump_table[] = + break; \ + \ + LABEL (form_wcharacter): \ ++ assert (MULTIBYTE_SUPPORT); \ + { \ + /* Wide character. */ \ + char buf[MB_CUR_MAX]; \ +@@ -1145,6 +1162,7 @@ static const uint8_t jump_table[] = + } \ + else \ + { \ ++ assert (MULTIBYTE_SUPPORT); \ + const wchar_t *s2 = (const wchar_t *) string; \ + mbstate_t mbstate; \ + \ +@@ -1399,7 +1417,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) + LABEL (flag_quote): + group = 1; + +- if (grouping == (const char *) -1) ++ if (! LOCALE_SUPPORT) ++ grouping = NULL; ++ else if (grouping == (const char *) -1) + { + #ifdef COMPILE_WPRINTF + thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, +@@ -1728,8 +1748,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, + size_t cnt; + + CHAR_T *workstart = NULL; +- +- if (grouping == (const char *) -1) ++ if (! LOCALE_SUPPORT) ++ grouping = NULL; ++ else if (grouping == (const char *) -1) + { + #ifdef COMPILE_WPRINTF + thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, +diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c +index 0e204e7..66cc0af 100644 +--- a/stdio-common/vfscanf.c ++++ b/stdio-common/vfscanf.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #ifdef __GNUC__ + # define HAVE_LONGLONG +@@ -133,6 +134,12 @@ + # define WINT_T int + #endif + ++#if __OPTION_POSIX_C_LANG_WIDE_CHAR ++# define MULTIBYTE_SUPPORT (1) ++#else ++# define MULTIBYTE_SUPPORT (0) ++#endif ++ + #define encode_error() do { \ + errval = 4; \ + __set_errno (EILSEQ); \ +@@ -316,24 +323,35 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + ARGCHECK (s, format); + + { +-#ifndef COMPILE_WSCANF ++#if __OPTION_EGLIBC_LOCALE_CODE && !defined (COMPILE_WSCANF) + struct __locale_data *const curnumeric = loc->__locales[LC_NUMERIC]; + #endif + ++#if __OPTION_EGLIBC_LOCALE_CODE + /* Figure out the decimal point character. */ +-#ifdef COMPILE_WSCANF ++# ifdef COMPILE_WSCANF + decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); +-#else ++# else + decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string; +-#endif ++# endif + /* Figure out the thousands separator character. */ +-#ifdef COMPILE_WSCANF ++# ifdef COMPILE_WSCANF + thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); +-#else ++# else + thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string; + if (*thousands == '\0') + thousands = NULL; +-#endif ++# endif ++#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */ ++ /* Hard-code values from the C locale. */ ++# ifdef COMPILE_WSCANF ++ decimal = L'.'; ++ thousands = L'\0'; ++# else ++ decimal = "."; ++ thousands = NULL; ++# endif ++#endif /* __OPTION_EGLIBC_LOCALE_CODE */ + } + + /* Lock the stream. */ +@@ -385,6 +403,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + #ifndef COMPILE_WSCANF + if (!isascii ((unsigned char) *f)) + { ++ assert (MULTIBYTE_SUPPORT); ++ + /* Non-ASCII, may be a multibyte. */ + int len = __mbrlen (f, strlen (f), &state); + if (len > 0) +@@ -830,6 +850,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + } + /* FALLTHROUGH */ + case L_('C'): ++ assert (MULTIBYTE_SUPPORT); ++ + if (width == -1) + width = 1; + +@@ -1172,6 +1194,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + /* FALLTHROUGH */ + + case L_('S'): ++ assert (MULTIBYTE_SUPPORT); ++ + { + #ifndef COMPILE_WSCANF + mbstate_t cstate; +@@ -1419,10 +1443,17 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + const char *mbdigits[10]; + const char *mbdigits_extended[10]; + #endif ++#if __OPTION_EGLIBC_LOCALE_CODE + /* "to_inpunct" is a map from ASCII digits to their + equivalent in locale. This is defined for locales + which use an extra digits set. */ + wctrans_t map = __wctrans ("to_inpunct"); ++#else ++ /* This will always be the case when ++ OPTION_EGLIBC_LOCALE_CODE is disabled, but the ++ compiler can't figure that out. */ ++ wctrans_t map = NULL; ++#endif + int n; + + from_level = 0; +@@ -2088,6 +2119,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + --width; + } + ++#if __OPTION_EGLIBC_LOCALE_CODE + wctrans_t map; + if (__builtin_expect ((flags & I18N) != 0, 0) + /* Hexadecimal floats make no sense, fixing localized +@@ -2304,6 +2336,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + ; + #endif + } ++#endif /* __OPTION_EGLIBC_LOCALE_CODE */ + + /* Have we read any character? If we try to read a number + in hexadecimal notation and we have read only the `0x' +@@ -2343,7 +2376,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + + case L_('['): /* Character class. */ + if (flags & LONG) +- STRING_ARG (wstr, wchar_t, 100); ++ { ++ assert (MULTIBYTE_SUPPORT); ++ STRING_ARG (wstr, wchar_t, 100); ++ } + else + STRING_ARG (str, char, 100); + +@@ -2417,6 +2453,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + if (flags & LONG) + { + size_t now = read_in; ++ assert (MULTIBYTE_SUPPORT); + #ifdef COMPILE_WSCANF + if (__glibc_unlikely (inchar () == WEOF)) + input_error (); +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 402466a..7e7e304 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -18,6 +18,8 @@ + # + # Makefile for stdlib routines + # ++include ../option-groups.mak ++ + subdir := stdlib + + include ../Makeconfig +@@ -30,7 +32,7 @@ headers := stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h \ + alloca.h fmtmsg.h \ + bits/stdlib-bsearch.h + +-routines := \ ++routines-y := \ + atof atoi atol atoll \ + abort \ + bsearch qsort msort \ +@@ -39,7 +41,6 @@ routines := \ + quick_exit at_quick_exit cxa_at_quick_exit cxa_thread_atexit_impl \ + abs labs llabs \ + div ldiv lldiv \ +- mblen mbstowcs mbtowc wcstombs wctomb \ + random random_r rand rand_r \ + drand48 erand48 lrand48 nrand48 mrand48 jrand48 \ + srand48 seed48 lcong48 \ +@@ -52,9 +53,18 @@ routines := \ + strtof_l strtod_l strtold_l \ + system canonicalize \ + a64l l64a \ +- rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \ +- strtoimax strtoumax wcstoimax wcstoumax \ ++ getsubopt xpg_basename \ ++ strtoimax strtoumax \ + getcontext setcontext makecontext swapcontext ++routines-$(OPTION_EGLIBC_LOCALE_CODE) += \ ++ strfmon strfmon_l ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \ ++ mblen mbstowcs mbtowc wcstombs wctomb \ ++ wcstoimax wcstoumax ++ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP)) ++routines-y += rpmatch ++endif ++routines-$(OPTION_EGLIBC_FMTMSG) += fmtmsg + aux = grouping groupingwc tens_in_limb + + # These routines will be omitted from the libc shared object. +@@ -62,20 +72,24 @@ aux = grouping groupingwc tens_in_limb + # linked against when the shared library will be used. + static-only-routines = atexit at_quick_exit + +-test-srcs := tst-fmtmsg +-tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ ++test-srcs-$(OPTION_EGLIBC_FMTMSG) := tst-fmtmsg ++tests := tst-strtol tst-strtod testrand testsort testdiv \ + test-canon test-canon2 tst-strtoll tst-environ \ + tst-xpg-basename tst-random tst-random2 tst-bsearch \ + tst-limits tst-rand48 bug-strtod tst-setcontext \ +- tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \ +- bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 \ +- tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5 \ ++ tst-setcontext2 test-a64l tst-qsort tst-system \ ++ bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \ ++ tst-rand48-2 tst-makecontext \ + tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \ + tst-makecontext3 bug-getcontext bug-fmtmsg1 \ + tst-secure-getenv tst-strtod-overflow tst-strtod-round \ + tst-tininess tst-strtod-underflow tst-tls-atexit \ + tst-setcontext3 tst-tls-atexit-nodelete + tests-static := tst-secure-getenv ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-strtod3 tst-strtod4 tst-strtod5 testmb2 ++tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += testmb + + modules-names = tst-tls-atexit-lib + +@@ -116,8 +130,10 @@ CFLAGS-tst-makecontext2.c = $(stack-align-test-flags) + tests-special += $(objpfx)isomac.out + + ifeq ($(run-built-tests),yes) ++ifeq (y,$(OPTION_EGLIBC_FMTMSG)) + tests-special += $(objpfx)tst-fmtmsg.out + endif ++endif + + include ../Rules + +diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c +index e13ab1e..63efe41 100644 +--- a/stdlib/strtod_l.c ++++ b/stdlib/strtod_l.c +@@ -17,6 +17,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + extern double ____strtod_l_internal (const char *, char **, int, __locale_t); +@@ -548,6 +549,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc) + /* Used in several places. */ + int cnt; + ++#if __OPTION_EGLIBC_LOCALE_CODE + struct __locale_data *current = loc->__locales[LC_NUMERIC]; + + if (__glibc_unlikely (group)) +@@ -586,6 +588,17 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc) + decimal_len = strlen (decimal); + assert (decimal_len > 0); + #endif ++#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */ ++ /* Hard-code values from the 'C' locale. */ ++ grouping = NULL; ++#ifdef USE_WIDE_CHAR ++ decimal = L'.'; ++# define decimal_len 1 ++#else ++ decimal = "."; ++ decimal_len = 1; ++#endif ++#endif /* __OPTION_EGLIBC_LOCALE_CODE */ + + /* Prepare number representation. */ + exponent = 0; +diff --git a/stdlib/tst-strtod.c b/stdlib/tst-strtod.c +index a469208..28fb423 100644 +--- a/stdlib/tst-strtod.c ++++ b/stdlib/tst-strtod.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + struct ltest + { +@@ -176,7 +177,9 @@ main (int argc, char ** argv) + + status |= long_dbl (); + ++#if __OPTION_EGLIBC_LOCALE_CODE + status |= locale_test (); ++#endif + + return status ? EXIT_FAILURE : EXIT_SUCCESS; + } +@@ -219,6 +222,7 @@ long_dbl (void) + return 0; + } + ++#if __OPTION_EGLIBC_LOCALE_CODE + /* Perform a few tests in a locale with thousands separators. */ + static int + locale_test (void) +@@ -276,3 +280,4 @@ locale_test (void) + + return result; + } ++#endif /* __OPTION_EGLIBC_LOCALE_CODE */ +diff --git a/streams/Makefile b/streams/Makefile +index a8a6162..ceb423f 100644 +--- a/streams/Makefile ++++ b/streams/Makefile +@@ -18,11 +18,14 @@ + # + # Makefile for streams. + # ++include ../option-groups.mak ++ + subdir := streams + + include ../Makeconfig + + headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h +-routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach ++routines-$(OPTION_EGLIBC_STREAMS) \ ++ += isastream getmsg getpmsg putmsg putpmsg fattach fdetach + + include ../Rules +diff --git a/string/Makefile b/string/Makefile +index 8424a61..5988834 100644 +--- a/string/Makefile ++++ b/string/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for string portion of library. + # ++include ../option-groups.mak ++ + subdir := string + + include ../Makeconfig +@@ -39,10 +41,12 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ + $(addprefix argz-,append count create ctsep next \ + delete extract insert stringify \ + addsep replace) \ +- envz basename \ ++ basename \ + strcoll_l strxfrm_l string-inlines memrchr \ + xpg-strerror strerror_l + ++routines-$(OPTION_EGLIBC_ENVZ) += envz ++ + strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ + stpcpy stpncpy strcat strchr strcmp strcpy strcspn \ + strlen strncmp strncpy strpbrk strrchr strspn memmem \ +@@ -51,10 +55,12 @@ strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ + tests := tester inl-tester noinl-tester testcopy test-ffs \ + tst-strlen stratcliff tst-svc tst-inlcall \ + bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \ +- tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ ++ tst-strtok tst-strfry \ + bug-strtok1 $(addprefix test-,$(strop-tests)) \ +- bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ +- tst-strtok_r ++ tst-strxfrm2 tst-endian tst-svc2 tst-strtok_r ++tests-$(OPTION_EGLIBC_ENVZ) += bug-envz1 ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-strxfrm bug-strcoll1 + + xtests = tst-strcoll-overflow + +diff --git a/string/strcoll_l.c b/string/strcoll_l.c +index 8f1225f..b36b18c 100644 +--- a/string/strcoll_l.c ++++ b/string/strcoll_l.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #ifndef STRING_TYPE + # define STRING_TYPE char +@@ -260,7 +261,11 @@ int + STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) + { + struct __locale_data *current = l->__locales[LC_COLLATE]; ++#if __OPTION_EGLIBC_LOCALE_CODE + uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; ++#else ++ const uint_fast32_t nrules = 0; ++#endif + /* We don't assign the following values right away since it might be + unnecessary in case there are no rules. */ + const unsigned char *rulesets; +diff --git a/string/strerror_l.c b/string/strerror_l.c +index 2ed78b5..6584813 100644 +--- a/string/strerror_l.c ++++ b/string/strerror_l.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + + static __thread char *last_value; +@@ -29,10 +30,14 @@ static __thread char *last_value; + static const char * + translate (const char *str, locale_t loc) + { ++#if __OPTION_EGLIBC_LOCALE_CODE + locale_t oldloc = __uselocale (loc); + const char *res = _(str); + __uselocale (oldloc); + return res; ++#else ++ return str; ++#endif + } + + +diff --git a/string/strxfrm_l.c b/string/strxfrm_l.c +index 8b61ea2..41fdc22 100644 +--- a/string/strxfrm_l.c ++++ b/string/strxfrm_l.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #ifndef STRING_TYPE + # define STRING_TYPE char +@@ -669,7 +670,11 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l) + { + locale_data_t l_data; + struct __locale_data *current = l->__locales[LC_COLLATE]; ++#if __OPTION_EGLIBC_LOCALE_CODE + l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; ++#else ++ l_data.nrules = 0; ++#endif + + /* Handle byte comparison case. */ + if (l_data.nrules == 0) +diff --git a/string/test-strcmp.c b/string/test-strcmp.c +index dc4ba6f..a978656 100644 +--- a/string/test-strcmp.c ++++ b/string/test-strcmp.c +@@ -329,34 +329,6 @@ check (void) + FOR_EACH_IMPL (impl, 0) + check_result (impl, s1 + i1, s2 + i2, exp_result); + } +- +- /* Test cases where there are multiple zero bytes after the first. */ +- +- for (size_t i = 0; i < 16 + 1; i++) +- { +- s1[i] = 0x00; +- s2[i] = 0x00; +- } +- +- for (size_t i = 0; i < 16; i++) +- { +- int exp_result; +- +- for (int val = 0x01; val < 0x100; val++) +- { +- for (size_t j = 0; j < i; j++) +- { +- s1[j] = val; +- s2[j] = val; +- } +- +- s2[i] = val; +- +- exp_result = SIMPLE_STRCMP (s1, s2); +- FOR_EACH_IMPL (impl, 0) +- check_result (impl, s1, s2, exp_result); +- } +- } + } + + +diff --git a/string/tst-strxfrm.c b/string/tst-strxfrm.c +index f48cfc0..c3a51f9 100644 +--- a/string/tst-strxfrm.c ++++ b/string/tst-strxfrm.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + + char const string[] = ""; +@@ -64,8 +65,10 @@ do_test (void) + int result = 0; + + result |= test ("C"); ++#if __OPTION_EGLIBC_LOCALE_CODE + result |= test ("en_US.ISO-8859-1"); + result |= test ("de_DE.UTF-8"); ++#endif + + return result; + } +diff --git a/string/tst-strxfrm2.c b/string/tst-strxfrm2.c +index d5a1115..19c7f30 100644 +--- a/string/tst-strxfrm2.c ++++ b/string/tst-strxfrm2.c +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + + static int + do_test (void) +@@ -38,6 +39,7 @@ do_test (void) + res = 1; + } + ++#if __OPTION_EGLIBC_LOCALE_CODE + if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) + { + puts ("setlocale failed"); +@@ -75,6 +77,7 @@ do_test (void) + res = 1; + } + } ++#endif + + return res; + } +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 60caa0a..5bc70ab 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -18,6 +18,8 @@ + # + # Sub-makefile for sunrpc portion of the library. + # ++include ../option-groups.mak ++ + subdir := sunrpc + + include ../Makeconfig +@@ -55,7 +57,6 @@ headers-in-tirpc = $(addprefix rpc/,auth.h auth_unix.h clnt.h pmap_clnt.h \ + headers-not-in-tirpc = $(addprefix rpc/,key_prot.h rpc_des.h) \ + $(rpcsvc:%=rpcsvc/%) rpcsvc/bootparam.h + headers = rpc/netdb.h +-install-others = $(inst_sysconfdir)/rpc + generated += $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \ + $(rpcsvc:%.x=rpcsvc/%.stmp) rpcgen + generated-dirs += rpcsvc +@@ -65,20 +66,28 @@ headers += $(headers-in-tirpc) $(headers-not-in-tirpc) + endif + + ifeq ($(build-shared),yes) +-need-export-routines := auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ ++need-export-routines-$(OPTION_EGLIBC_SUNRPC) := \ ++ auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ + clnt_udp get_myaddr key_call netname pm_getport \ +- rpc_thread svc svc_tcp svc_udp xcrypt xdr_array xdr \ ++ rpc_thread svc svc_tcp svc_udp xdr_array xdr \ + xdr_intXX_t xdr_mem xdr_ref xdr_sizeof xdr_stdio \ + svc_run ++need-export-routines-y += xcrypt ++need-export-routines := $(need-export-routines-y) + +-routines := auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ ++routines-$(OPTION_EGLIBC_SUNRPC) := \ ++ auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ + rpc_dtable getrpcport pmap_clnt pm_getmaps pmap_prot pmap_prot2 \ + pmap_rmt rpc_prot rpc_common rpc_cmsg svc_auth svc_authux svc_raw \ + svc_simple xdr_float xdr_rec publickey authdes_prot \ +- des_crypt des_impl des_soft key_prot openchild rtime svcauth_des \ ++ key_prot openchild rtime svcauth_des \ + getrpcent getrpcbyname getrpcbynumber \ + getrpcent_r getrpcbyname_r getrpcbynumber_r \ +- clnt_unix svc_unix create_xid $(need-export-routines) ++ clnt_unix svc_unix create_xid ++ ++# xdecrypt is also used by nss/nss_files/files-key.c. ++routines-y += des_crypt des_impl des_soft $(need-export-routines) ++ + ifneq ($(link-obsolete-rpc),yes) + # We only add the RPC for compatibility to libc.so. + shared-only-routines = $(routines) +@@ -87,25 +96,28 @@ endif + + # We do not build rpcinfo anymore. It is not needed for a bootstrap + # and not wanted on complete systems. +-# others := rpcinfo +-# install-sbin := rpcinfo +-install-bin := rpcgen ++# others-$(OPTION_EGLIBC_SUNRPC) += rpcinfo ++# install-sbin-$(OPTION_EGLIBC_SUNRPC) += rpcinfo ++install-bin-$(OPTION_EGLIBC_SUNRPC) += rpcgen + rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ + rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \ + rpc_tblout.o rpc_sample.o +-extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) +-others += rpcgen ++extra-objs-$(OPTION_EGLIBC_SUNRPC) = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) ++others-$(OPTION_EGLIBC_SUNRPC) += rpcgen ++ ++install-others-$(OPTION_EGLIBC_SUNRPC) += $(inst_sysconfdir)/rpc + +-tests = tst-xdrmem tst-xdrmem2 test-rpcent +-xtests := tst-getmyaddr ++tests-$(OPTION_EGLIBC_SUNRPC) = tst-xdrmem tst-xdrmem2 test-rpcent ++xtests-$(OPTION_EGLIBC_SUNRPC) := tst-getmyaddr + + ifeq ($(have-thread-library),yes) +-xtests += thrsvc ++xtests-$(OPTION_EGLIBC_SUNRPC) += thrsvc + endif + + headers += $(rpcsvc:%.x=rpcsvc/%.h) +-extra-libs := librpcsvc +-extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass. ++extra-libs-$(OPTION_EGLIBC_SUNRPC) += librpcsvc ++# Make it in `others' pass, not `lib' pass. ++extra-libs-others-y += $(extra-libs-y) + librpcsvc-routines = $(rpcsvc:%.x=x%) + librpcsvc-inhibit-o = .os # Build no shared rpcsvc library. + omit-deps = $(librpcsvc-routines) +diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile +index 17c129b..543791a 100644 +--- a/sysdeps/arm/Makefile ++++ b/sysdeps/arm/Makefile +@@ -37,10 +37,13 @@ ifeq ($(subdir),csu) + # get offset to rtld_global._dl_hwcap + gen-as-const-headers += rtld-global-offsets.sym tlsdesc.sym + aeabi_constants = aeabi_lcsts aeabi_sighandlers aeabi_math +-aeabi_routines = aeabi_assert aeabi_localeconv aeabi_errno_addr \ ++aeabi_routines = aeabi_assert aeabi_errno_addr \ + aeabi_mb_cur_max aeabi_atexit aeabi_memclr aeabi_memcpy \ + aeabi_memmove aeabi_memset \ + aeabi_read_tp libc-aeabi_read_tp ++ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) ++aeabi_routines += aeabi_localeconv ++endif + + sysdep_routines += $(aeabi_constants) $(aeabi_routines) + static-only-routines += $(aeabi_constants) aeabi_read_tp +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 7a0fe8d..a3e2c0a 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -435,6 +435,12 @@ extern struct rtld_global _rtld_global __rtld_global_attribute__; + # undef __rtld_global_attribute__ + #endif + ++#if __OPTION_EGLIBC_RTLD_DEBUG ++# define GLRO_dl_debug_mask GLRO(dl_debug_mask) ++#else ++# define GLRO_dl_debug_mask 0 ++#endif ++ + #ifndef SHARED + # define GLRO(name) _##name + #else +@@ -447,8 +453,10 @@ struct rtld_global_ro + { + #endif + ++#if __OPTION_EGLIBC_RTLD_DEBUG + /* If nonzero the appropriate debug information is printed. */ + EXTERN int _dl_debug_mask; ++#endif + #define DL_DEBUG_LIBS (1 << 0) + #define DL_DEBUG_IMPCALLS (1 << 1) + #define DL_DEBUG_BINDINGS (1 << 2) +diff --git a/sysdeps/gnu/Makefile b/sysdeps/gnu/Makefile +index ea68037..3175cc3 100644 +--- a/sysdeps/gnu/Makefile ++++ b/sysdeps/gnu/Makefile +@@ -59,7 +59,8 @@ $(foreach o,$(object-suffixes) $(object-suffixes:=.d),\ + endif + + ifeq ($(subdir),login) +-sysdep_routines += setutxent getutxent endutxent getutxid getutxline \ ++sysdep_routines-$(OPTION_EGLIBC_UTMPX) \ ++ += setutxent getutxent endutxent getutxid getutxline \ + pututxline utmpxname updwtmpx getutmpx getutmp + + sysdep_headers += utmpx.h bits/utmpx.h +diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile +index 222122d..4509357 100644 +--- a/sysdeps/ieee754/ldbl-opt/Makefile ++++ b/sysdeps/ieee754/ldbl-opt/Makefile +@@ -11,19 +11,18 @@ libm-routines += s_nexttowardfd + routines += math_ldbl_opt nldbl-compat + + extra-libs += libnldbl +-libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \ ++libnldbl-calls = asprintf dprintf fprintf fscanf iovfscanf \ + obstack_printf obstack_vprintf printf scanf snprintf \ +- sprintf sscanf swprintf swscanf vasprintf vdprintf vfprintf \ +- vfscanf vfwprintf vfwscanf vprintf vscanf vsnprintf \ +- vsprintf vsscanf vswprintf vswscanf vwprintf vwscanf \ +- wprintf wscanf printf_fp printf_size \ +- fprintf_chk fwprintf_chk printf_chk snprintf_chk sprintf_chk \ +- swprintf_chk vfprintf_chk vfwprintf_chk vprintf_chk \ +- vsnprintf_chk vsprintf_chk vswprintf_chk vwprintf_chk \ +- wprintf_chk asprintf_chk vasprintf_chk dprintf_chk \ ++ sprintf sscanf vasprintf vdprintf vfprintf \ ++ vfscanf vprintf vscanf vsnprintf \ ++ vsprintf vsscanf \ ++ printf_fp printf_size \ ++ fprintf_chk printf_chk snprintf_chk sprintf_chk \ ++ vfprintf_chk vprintf_chk \ ++ vsnprintf_chk vsprintf_chk \ ++ asprintf_chk vasprintf_chk dprintf_chk \ + vdprintf_chk obstack_printf_chk obstack_vprintf_chk \ + syslog syslog_chk vsyslog vsyslog_chk \ +- strfmon strfmon_l \ + strtold strtold_l strtoldint wcstold wcstold_l wcstoldint \ + qecvt qfcvt qgcvt qecvt_r qfcvt_r \ + isinf isnan finite signbit scalb log2 lgamma_r ceil \ +@@ -38,9 +37,15 @@ libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \ + casinh cexp clog cproj csin csinh csqrt ctan ctanh cpow \ + cabs carg cimag creal clog10 \ + isoc99_scanf isoc99_fscanf isoc99_sscanf \ +- isoc99_vscanf isoc99_vfscanf isoc99_vsscanf \ ++ isoc99_vscanf isoc99_vfscanf isoc99_vsscanf ++libnldbl-calls-$(OPTION_EGLIBC_LOCALE_CODE) += strfmon strfmon_l ++libnldbl-calls-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += fwprintf fwscanf \ ++ swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf \ ++ vwprintf vwscanf wprintf wscanf fwprintf_chk swprintf_chk \ ++ vfwprintf_chk vswprintf_chk vwprintf_chk wprintf_chk \ + isoc99_wscanf isoc99_fwscanf isoc99_swscanf \ + isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf ++libnldbl-calls += $(libnldbl-calls-y) + libnldbl-routines = $(libnldbl-calls:%=nldbl-%) + libnldbl-inhibit-o = $(object-suffixes) + libnldbl-static-only-routines = $(libnldbl-routines) +diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c +index 0198886..55501cd 100644 +--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c ++++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include "nldbl-compat.h" + +@@ -33,20 +34,14 @@ libc_hidden_proto (__nldbl_vfprintf) + libc_hidden_proto (__nldbl_vsscanf) + libc_hidden_proto (__nldbl_vsprintf) + libc_hidden_proto (__nldbl_vfscanf) +-libc_hidden_proto (__nldbl_vfwscanf) + libc_hidden_proto (__nldbl_vdprintf) +-libc_hidden_proto (__nldbl_vswscanf) +-libc_hidden_proto (__nldbl_vfwprintf) +-libc_hidden_proto (__nldbl_vswprintf) + libc_hidden_proto (__nldbl_vsnprintf) + libc_hidden_proto (__nldbl_vasprintf) + libc_hidden_proto (__nldbl_obstack_vprintf) +-libc_hidden_proto (__nldbl___vfwprintf_chk) + libc_hidden_proto (__nldbl___vsnprintf_chk) + libc_hidden_proto (__nldbl___vfprintf_chk) + libc_hidden_proto (__nldbl___vsyslog_chk) + libc_hidden_proto (__nldbl___vsprintf_chk) +-libc_hidden_proto (__nldbl___vswprintf_chk) + libc_hidden_proto (__nldbl___vasprintf_chk) + libc_hidden_proto (__nldbl___vdprintf_chk) + libc_hidden_proto (__nldbl___obstack_vprintf_chk) +@@ -54,8 +49,17 @@ libc_hidden_proto (__nldbl___vstrfmon) + libc_hidden_proto (__nldbl___vstrfmon_l) + libc_hidden_proto (__nldbl___isoc99_vsscanf) + libc_hidden_proto (__nldbl___isoc99_vfscanf) ++ ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO ++libc_hidden_proto (__nldbl_vfwscanf) ++libc_hidden_proto (__nldbl_vswscanf) ++libc_hidden_proto (__nldbl_vfwprintf) ++libc_hidden_proto (__nldbl_vswprintf) ++libc_hidden_proto (__nldbl___vfwprintf_chk) ++libc_hidden_proto (__nldbl___vswprintf_chk) + libc_hidden_proto (__nldbl___isoc99_vswscanf) + libc_hidden_proto (__nldbl___isoc99_vfwscanf) ++#endif + + static void + __nldbl_cleanup (void *arg) +@@ -117,6 +121,7 @@ __nldbl_fprintf (FILE *stream, const char *fmt, ...) + } + weak_alias (__nldbl_fprintf, __nldbl__IO_fprintf) + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section weak_function + __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...) +@@ -130,6 +135,7 @@ __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...) + + return done; + } ++#endif + + int + attribute_compat_text_section +@@ -226,6 +232,7 @@ __nldbl_snprintf (char *s, size_t maxlen, const char *fmt, ...) + return done; + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...) +@@ -239,6 +246,7 @@ __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...) + + return done; + } ++#endif + + int + attribute_compat_text_section weak_function +@@ -264,6 +272,7 @@ __nldbl_vdprintf (int d, const char *fmt, va_list arg) + } + libc_hidden_def (__nldbl_vdprintf) + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section weak_function + __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap) +@@ -275,6 +284,7 @@ __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap) + return res; + } + libc_hidden_def (__nldbl_vfwprintf) ++#endif + + int + attribute_compat_text_section +@@ -297,6 +307,7 @@ __nldbl_vsnprintf (char *string, size_t maxlen, const char *fmt, + libc_hidden_def (__nldbl_vsnprintf) + weak_alias (__nldbl_vsnprintf, __nldbl___vsnprintf) + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section weak_function + __nldbl_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *fmt, +@@ -330,6 +341,7 @@ __nldbl_wprintf (const wchar_t *fmt, ...) + + return done; + } ++#endif + + int + attribute_compat_text_section +@@ -419,6 +431,7 @@ __nldbl_scanf (const char *fmt, ...) + return done; + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) +@@ -491,6 +504,7 @@ __nldbl_wscanf (const wchar_t *fmt, ...) + + return done; + } ++#endif + + int + attribute_compat_text_section +@@ -506,6 +520,7 @@ __nldbl___fprintf_chk (FILE *stream, int flag, const char *fmt, ...) + return done; + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...) +@@ -519,6 +534,7 @@ __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...) + + return done; + } ++#endif + + int + attribute_compat_text_section +@@ -563,6 +579,7 @@ __nldbl___sprintf_chk (char *s, int flag, size_t slen, const char *fmt, ...) + return done; + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen, +@@ -577,6 +594,7 @@ __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen, + + return done; + } ++#endif + + int + attribute_compat_text_section +@@ -590,6 +608,7 @@ __nldbl___vfprintf_chk (FILE *s, int flag, const char *fmt, va_list ap) + } + libc_hidden_def (__nldbl___vfprintf_chk) + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap) +@@ -601,6 +620,7 @@ __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap) + return res; + } + libc_hidden_def (__nldbl___vfwprintf_chk) ++#endif + + int + attribute_compat_text_section +@@ -635,6 +655,7 @@ __nldbl___vsprintf_chk (char *string, int flag, size_t slen, const char *fmt, + } + libc_hidden_def (__nldbl___vsprintf_chk) + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl___vswprintf_chk (wchar_t *string, size_t maxlen, int flag, size_t slen, +@@ -668,6 +689,7 @@ __nldbl___wprintf_chk (int flag, const wchar_t *fmt, ...) + + return done; + } ++#endif + + int + attribute_compat_text_section +@@ -775,6 +797,7 @@ __nldbl___printf_fp (FILE *fp, const struct printf_info *info, + return ___printf_fp (fp, &info_no_ldbl, args); + } + ++#if __OPTION_EGLIBC_LOCALE_CODE + ssize_t + attribute_compat_text_section + __nldbl_strfmon (char *s, size_t maxsize, const char *format, ...) +@@ -829,6 +852,7 @@ __nldbl___vstrfmon_l (char *s, size_t maxsize, __locale_t loc, + return res; + } + libc_hidden_def (__nldbl___vstrfmon_l) ++#endif + + void + attribute_compat_text_section +@@ -941,6 +965,7 @@ __nldbl___isoc99_scanf (const char *fmt, ...) + return done; + } + ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + int + attribute_compat_text_section + __nldbl___isoc99_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) +@@ -1014,6 +1039,7 @@ __nldbl___isoc99_wscanf (const wchar_t *fmt, ...) + + return done; + } ++#endif + + #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0) + compat_symbol (libc, __nldbl__IO_printf, _IO_printf, GLIBC_2_0); +@@ -1057,6 +1083,7 @@ compat_symbol (libc, __nldbl_printf_size, printf_size, GLIBC_2_1); + compat_symbol (libc, __nldbl___strfmon_l, __strfmon_l, GLIBC_2_1); + #endif + #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_2) ++# if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO + compat_symbol (libc, __nldbl_swprintf, swprintf, GLIBC_2_2); + compat_symbol (libc, __nldbl_vwprintf, vwprintf, GLIBC_2_2); + compat_symbol (libc, __nldbl_wprintf, wprintf, GLIBC_2_2); +@@ -1069,6 +1096,7 @@ compat_symbol (libc, __nldbl_vfwscanf, vfwscanf, GLIBC_2_2); + compat_symbol (libc, __nldbl_vswscanf, vswscanf, GLIBC_2_2); + compat_symbol (libc, __nldbl_vwscanf, vwscanf, GLIBC_2_2); + compat_symbol (libc, __nldbl_wscanf, wscanf, GLIBC_2_2); ++# endif + #endif + #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_3) + compat_symbol (libc, __nldbl_strfmon_l, strfmon_l, GLIBC_2_3); +diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h +index 0d2c8af..f4cea50 100644 +--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h ++++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + + /* Declare the __nldbl_NAME function the wrappers call that's in libc.so. */ +@@ -37,19 +38,15 @@ + + NLDBL_DECL (_IO_vfscanf); + NLDBL_DECL (vfscanf); +-NLDBL_DECL (vfwscanf); + NLDBL_DECL (obstack_vprintf); + NLDBL_DECL (vasprintf); + NLDBL_DECL (dprintf); + NLDBL_DECL (vdprintf); + NLDBL_DECL (fprintf); + NLDBL_DECL (vfprintf); +-NLDBL_DECL (vfwprintf); + NLDBL_DECL (vsnprintf); + NLDBL_DECL (vsprintf); + NLDBL_DECL (vsscanf); +-NLDBL_DECL (vswprintf); +-NLDBL_DECL (vswscanf); + NLDBL_DECL (__asprintf); + NLDBL_DECL (asprintf); + NLDBL_DECL (__printf_fp); +@@ -66,12 +63,18 @@ NLDBL_DECL (__isoc99_sscanf); + NLDBL_DECL (__isoc99_vscanf); + NLDBL_DECL (__isoc99_vfscanf); + NLDBL_DECL (__isoc99_vsscanf); ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO ++NLDBL_DECL (vfwscanf); ++NLDBL_DECL (vfwprintf); ++NLDBL_DECL (vswprintf); ++NLDBL_DECL (vswscanf); + NLDBL_DECL (__isoc99_wscanf); + NLDBL_DECL (__isoc99_fwscanf); + NLDBL_DECL (__isoc99_swscanf); + NLDBL_DECL (__isoc99_vwscanf); + NLDBL_DECL (__isoc99_vfwscanf); + NLDBL_DECL (__isoc99_vswscanf); ++#endif + + /* This one does not exist in the normal interface, only + __nldbl___vstrfmon really exists. */ +@@ -82,22 +85,23 @@ extern ssize_t __nldbl___vstrfmon (char *, size_t, const char *, va_list) + since we don't compile with _FORTIFY_SOURCE. */ + extern int __nldbl___vfprintf_chk (FILE *__restrict, int, + const char *__restrict, _G_va_list); +-extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, +- const wchar_t *__restrict, __gnuc_va_list); + extern int __nldbl___vsprintf_chk (char *__restrict, int, size_t, + const char *__restrict, _G_va_list) __THROW; + extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t, + const char *__restrict, _G_va_list) + __THROW; +-extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, +- const wchar_t *__restrict, __gnuc_va_list) +- __THROW; + extern int __nldbl___vasprintf_chk (char **, int, const char *, _G_va_list) + __THROW; + extern int __nldbl___vdprintf_chk (int, int, const char *, _G_va_list); + extern int __nldbl___obstack_vprintf_chk (struct obstack *, int, const char *, + _G_va_list) __THROW; + extern void __nldbl___vsyslog_chk (int, int, const char *, va_list); +- ++#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO ++extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, ++ const wchar_t *__restrict, __gnuc_va_list); ++extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, ++ const wchar_t *__restrict, __gnuc_va_list) ++ __THROW; ++#endif + + #endif /* __NLDBL_COMPAT_H */ +diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile +index e9339a3..782009b 100644 +--- a/sysdeps/nptl/Makefile ++++ b/sysdeps/nptl/Makefile +@@ -18,6 +18,9 @@ + + ifeq ($(subdir),nptl) + libpthread-sysdep_routines += errno-loc ++ifeq ($(OPTION_EGLIBC_BIG_MACROS),n) ++sysdep_routines += small-macros-fns ++endif + endif + + ifeq ($(subdir),rt) +diff --git a/sysdeps/nptl/bits/libc-lock.h b/sysdeps/nptl/bits/libc-lock.h +index 5599cf1..b839378 100644 +--- a/sysdeps/nptl/bits/libc-lock.h ++++ b/sysdeps/nptl/bits/libc-lock.h +@@ -24,6 +24,14 @@ + #include + + ++#ifdef _LIBC ++# include ++# include ++# include ++# include /* For EBUSY. */ ++# include /* For __OPTION_EGLIBC_BIG_MACROS. */ ++#endif ++ + /* Mutex type. */ + #if defined _LIBC || defined _IO_MTSAFE_IO + # if (!IS_IN (libc) && !IS_IN (libpthread)) || !defined _LIBC +@@ -87,6 +95,15 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; + + /* Lock the recursive named lock variable. */ + #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) ++# if __OPTION_EGLIBC_BIG_MACROS != 1 ++/* EGLIBC: Declare wrapper function for a big macro if either ++ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from ++ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ ++extern void __libc_lock_lock_recursive_fn (__libc_lock_recursive_t *); ++libc_hidden_proto (__libc_lock_lock_recursive_fn); ++# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ ++# if __OPTION_EGLIBC_BIG_MACROS ++ + # define __libc_lock_lock_recursive(NAME) \ + do { \ + void *self = THREAD_SELF; \ +@@ -97,6 +114,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; + } \ + ++(NAME).cnt; \ + } while (0) ++# else ++# define __libc_lock_lock_recursive(NAME) \ ++ __libc_lock_lock_recursive_fn (&(NAME)) ++# endif /* __OPTION_EGLIBC_BIG_MACROS */ + #else + # define __libc_lock_lock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) +@@ -104,6 +125,14 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; + + /* Try to lock the recursive named lock variable. */ + #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) ++# if __OPTION_EGLIBC_BIG_MACROS != 1 ++/* EGLIBC: Declare wrapper function for a big macro if either ++ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from ++ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ ++extern int __libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *); ++libc_hidden_proto (__libc_lock_trylock_recursive_fn); ++# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ ++# if __OPTION_EGLIBC_BIG_MACROS + # define __libc_lock_trylock_recursive(NAME) \ + ({ \ + int result = 0; \ +@@ -122,6 +151,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; + ++(NAME).cnt; \ + result; \ + }) ++# else ++# define __libc_lock_trylock_recursive(NAME) \ ++ __libc_lock_trylock_recursive_fn (&(NAME)) ++# endif /* __OPTION_EGLIBC_BIG_MACROS */ + #else + # define __libc_lock_trylock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) +@@ -129,6 +162,14 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; + + /* Unlock the recursive named lock variable. */ + #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) ++# if __OPTION_EGLIBC_BIG_MACROS != 1 ++/* EGLIBC: Declare wrapper function for a big macro if either ++ !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from ++ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ ++extern void __libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *); ++libc_hidden_proto (__libc_lock_unlock_recursive_fn); ++# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ ++# if __OPTION_EGLIBC_BIG_MACROS + /* We do no error checking here. */ + # define __libc_lock_unlock_recursive(NAME) \ + do { \ +@@ -138,6 +179,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; + lll_unlock ((NAME).lock, LLL_PRIVATE); \ + } \ + } while (0) ++# else ++# define __libc_lock_unlock_recursive(NAME) \ ++ __libc_lock_unlock_recursive_fn (&(NAME)) ++# endif /* __OPTION_EGLIBC_BIG_MACROS */ + #else + # define __libc_lock_unlock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) +diff --git a/sysdeps/nptl/bits/libc-lockP.h b/sysdeps/nptl/bits/libc-lockP.h +index f55f621..da98869 100644 +--- a/sysdeps/nptl/bits/libc-lockP.h ++++ b/sysdeps/nptl/bits/libc-lockP.h +@@ -33,6 +33,8 @@ + #include + #include + #include ++#include /* For EBUSY. */ ++#include /* For __OPTION_EGLIBC_BIG_MACROS. */ + + #if IS_IN (libpthread) + /* This gets us the declarations of the __pthread_* internal names, +@@ -171,10 +173,22 @@ typedef pthread_key_t __libc_key_t; + + /* Lock the named lock variable. */ + #if IS_IN (libc) || IS_IN (libpthread) +-# ifndef __libc_lock_lock +-# define __libc_lock_lock(NAME) \ ++# if __OPTION_EGLIBC_BIG_MACROS != 1 ++/* EGLIBC: Declare wrapper function for a big macro if either ++ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from ++ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ ++extern void __libc_lock_lock_fn (__libc_lock_t *); ++libc_hidden_proto (__libc_lock_lock_fn); ++# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ ++# if __OPTION_EGLIBC_BIG_MACROS ++# ifndef __libc_lock_lock ++# define __libc_lock_lock(NAME) \ + ({ lll_lock (NAME, LLL_PRIVATE); 0; }) +-# endif ++# endif ++# else ++# define __libc_lock_lock(NAME) \ ++ __libc_lock_lock_fn (&(NAME)) ++# endif /* __OPTION_EGLIBC_BIG_MACROS */ + #else + # undef __libc_lock_lock + # define __libc_lock_lock(NAME) \ +@@ -187,10 +201,22 @@ typedef pthread_key_t __libc_key_t; + + /* Try to lock the named lock variable. */ + #if IS_IN (libc) || IS_IN (libpthread) +-# ifndef __libc_lock_trylock +-# define __libc_lock_trylock(NAME) \ ++# if __OPTION_EGLIBC_BIG_MACROS != 1 ++/* EGLIBC: Declare wrapper function for a big macro if either ++ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from ++ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ ++extern int __libc_lock_trylock_fn (__libc_lock_t *); ++libc_hidden_proto (__libc_lock_trylock_fn); ++# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ ++# if __OPTION_EGLIBC_BIG_MACROS ++# ifndef __libc_lock_trylock ++# define __libc_lock_trylock(NAME) \ + lll_trylock (NAME) +-# endif ++# endif ++# else ++# define __libc_lock_trylock(NAME) \ ++ __libc_lock_trylock_fn (&(NAME)) ++# endif /* __OPTION_EGLIBC_BIG_MACROS */ + #else + # undef __libc_lock_trylock + # define __libc_lock_trylock(NAME) \ +@@ -206,8 +232,20 @@ typedef pthread_key_t __libc_key_t; + + /* Unlock the named lock variable. */ + #if IS_IN (libc) || IS_IN (libpthread) ++# if __OPTION_EGLIBC_BIG_MACROS != 1 ++/* EGLIBC: Declare wrapper function for a big macro if either ++ !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from ++ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ ++extern void __libc_lock_unlock_fn (__libc_lock_t *); ++libc_hidden_proto (__libc_lock_unlock_fn); ++# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ ++# if __OPTION_EGLIBC_BIG_MACROS + # define __libc_lock_unlock(NAME) \ + lll_unlock (NAME, LLL_PRIVATE) ++# else ++# define __libc_lock_unlock(NAME) \ ++ __libc_lock_unlock_fn (&(NAME)) ++# endif /* __OPTION_EGLIBC_BIG_MACROS */ + #else + # define __libc_lock_unlock(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +diff --git a/sysdeps/nptl/small-macros-fns.c b/sysdeps/nptl/small-macros-fns.c +new file mode 100644 +index 0000000..f751053 +--- /dev/null ++++ b/sysdeps/nptl/small-macros-fns.c +@@ -0,0 +1,72 @@ ++/* EGLIBC: function wrappers for big macros. ++ Copyright (C) 2009 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++#include ++ ++/* Handle macros from ./bits/libc-lock.h. */ ++#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) ++ ++/* Get the macros for function bodies through a back door. */ ++# undef __OPTION_EGLIBC_BIG_MACROS ++# define __OPTION_EGLIBC_BIG_MACROS 2 ++# include ++ ++void ++__libc_lock_lock_fn (__libc_lock_t *name) ++{ ++ __libc_lock_lock (*name); ++} ++libc_hidden_def (__libc_lock_lock_fn); ++ ++void ++__libc_lock_lock_recursive_fn (__libc_lock_recursive_t *name) ++{ ++ __libc_lock_lock_recursive (*name); ++} ++libc_hidden_def (__libc_lock_lock_recursive_fn); ++ ++int ++__libc_lock_trylock_fn (__libc_lock_t *name) ++{ ++ return __libc_lock_trylock (*name); ++} ++libc_hidden_def (__libc_lock_trylock_fn); ++ ++int ++__libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *name) ++{ ++ return __libc_lock_trylock_recursive (*name); ++} ++libc_hidden_def (__libc_lock_trylock_recursive_fn); ++ ++void ++__libc_lock_unlock_fn (__libc_lock_t *name) ++{ ++ __libc_lock_unlock (*name); ++} ++libc_hidden_def (__libc_lock_unlock_fn); ++ ++void ++__libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *name) ++{ ++ __libc_lock_unlock_recursive (*name); ++} ++libc_hidden_def (__libc_lock_unlock_recursive_fn); ++ ++#endif /*defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)*/ +diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c +index 26e4692..d0a26c8 100644 +--- a/sysdeps/unix/sysv/linux/gethostid.c ++++ b/sysdeps/unix/sysv/linux/gethostid.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #define HOSTIDFILE "/etc/hostid" + +@@ -89,6 +90,7 @@ gethostid (void) + return id; + } + ++#if __OPTION_EGLIBC_INET + /* Getting from the file was not successful. An intelligent guess for + a unique number of a host is its IP address. Return this. */ + if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0') +@@ -115,5 +117,9 @@ gethostid (void) + /* For the return value to be not exactly the IP address we do some + bit fiddling. */ + return (int32_t) (in.s_addr << 16 | in.s_addr >> 16); ++#else ++ /* Return an arbitrary value. */ ++ return 0; ++#endif + } + #endif +diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c +index 53a8bbb..cb110d4 100644 +--- a/sysdeps/unix/sysv/linux/libc_fatal.c ++++ b/sysdeps/unix/sysv/linux/libc_fatal.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + static bool + writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total) +@@ -40,6 +41,7 @@ writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total) + static void + backtrace_and_maps (int do_abort, bool written, int fd) + { ++#if __OPTION_EGLIBC_BACKTRACE + if (do_abort > 1 && written) + { + void *addrs[64]; +@@ -62,6 +64,7 @@ backtrace_and_maps (int do_abort, bool written, int fd) + close_not_cancel_no_status (fd2); + } + } ++#endif /* __OPTION_EGLIBC_BACKTRACE */ + } + #define BEFORE_ABORT backtrace_and_maps + +diff --git a/time/Makefile b/time/Makefile +index a411f62..2d022ca 100644 +--- a/time/Makefile ++++ b/time/Makefile +@@ -18,6 +18,8 @@ + # + # Makefile for time routines + # ++include ../option-groups.mak ++ + subdir := time + + include ../Makeconfig +@@ -30,15 +32,23 @@ routines := offtime asctime clock ctime ctime_r difftime \ + tzfile getitimer setitimer \ + stime dysize timegm ftime \ + getdate strptime strptime_l \ +- strftime wcsftime strftime_l wcsftime_l \ ++ strftime strftime_l \ + timespec_get +-aux := era alt_digit lc-time-cleanup + +-tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ +- tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ := wcsftime wcsftime_l ++aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup ++ ++tests := test_time clocktest tst-posixtz \ ++ tst-getdate tst-mktime tst-mktime2 tst-strftime \ + tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ + tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime + ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-strptime tst-ftime_l ++tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ ++ += tst_wcsftime ++ + include ../Rules + + tz-cflags = -DTZDIR='"$(zonedir)"' \ +diff --git a/time/strftime_l.c b/time/strftime_l.c +index b48ef34..bfdd618 100644 +--- a/time/strftime_l.c ++++ b/time/strftime_l.c +@@ -35,6 +35,10 @@ + # include "../locale/localeinfo.h" + #endif + ++#ifdef _LIBC ++# include ++#endif ++ + #if defined emacs && !defined HAVE_BCOPY + # define HAVE_MEMCPY 1 + #endif +@@ -882,7 +886,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument + case L_('C'): + if (modifier == L_('E')) + { +-#if HAVE_STRUCT_ERA_ENTRY ++#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +@@ -955,7 +959,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument + + if (modifier == L_('O') && 0 <= number_value) + { +-#ifdef _NL_CURRENT ++#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT) + /* Get the locale specific alternate representation of + the number NUMBER_VALUE. If none exist NULL is returned. */ + const CHAR_T *cp = nl_get_alt_digit (number_value +@@ -1260,7 +1264,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument + case L_('Y'): + if (modifier == 'E') + { +-#if HAVE_STRUCT_ERA_ENTRY ++#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +@@ -1285,7 +1289,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument + case L_('y'): + if (modifier == L_('E')) + { +-#if HAVE_STRUCT_ERA_ENTRY ++#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +diff --git a/time/strptime_l.c b/time/strptime_l.c +index 5640cce..784ccbc 100644 +--- a/time/strptime_l.c ++++ b/time/strptime_l.c +@@ -29,6 +29,7 @@ + + #ifdef _LIBC + # define HAVE_LOCALTIME_R 0 ++# include + # include "../locale/localeinfo.h" + #endif + +@@ -84,7 +85,7 @@ localtime_r (t, tp) + if (val < from || val > to) \ + return NULL; \ + } while (0) +-#ifdef _NL_CURRENT ++#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT) + # define get_alt_number(from, to, n) \ + ({ \ + __label__ do_normal; \ +@@ -257,8 +258,10 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + int cnt; + int cnt_longest; + size_t val; ++#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE + size_t num_eras; + struct era_entry *era = NULL; ++#endif + enum ptime_locale_status { not, loc, raw } decided_longest; + struct __strptime_state + { +@@ -820,6 +823,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + s.want_xday = 1; + break; + case 'C': ++#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE + if (s.decided != raw) + { + if (s.era_cnt >= 0) +@@ -856,10 +860,12 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + + s.decided = raw; + } ++#endif + /* The C locale has no era information, so use the + normal representation. */ + goto match_century; + case 'y': ++#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE + if (s.decided != raw) + { + get_number(0, 9999, 4); +@@ -918,9 +924,10 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + + s.decided = raw; + } +- ++#endif + goto match_year_in_century; + case 'Y': ++#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE + if (s.decided != raw) + { + num_eras = _NL_CURRENT_WORD (LC_TIME, +@@ -948,6 +955,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + + s.decided = raw; + } ++#endif + get_number (0, 9999, 4); + tm->tm_year = val - 1900; + s.want_century = 0; +@@ -1118,6 +1126,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + tm->tm_year = (s.century - 19) * 100; + } + ++#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE + if (s.era_cnt != -1) + { + era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG); +@@ -1132,6 +1141,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) + tm->tm_year = era->start_date[0]; + } + else ++#endif + if (s.want_era) + { + /* No era found but we have seen an E modifier. Rectify some +diff --git a/timezone/Makefile b/timezone/Makefile +index 886b06e..f922684 100644 +--- a/timezone/Makefile ++++ b/timezone/Makefile +@@ -127,7 +127,7 @@ $(testdata)/XT%: testdata/XT% + + $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make + sed -e 's|/bin/bash|/bin/sh|' \ +- -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ ++ -e '/TZDIR=/s|\$$(pwd)|$(zonedir)|' \ + -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \ + -e '/PKGVERSION=/s|=.*|="$(PKGVERSION)"|' \ + -e '/REPORT_BUGS_TO=/s|=.*|="$(REPORT_BUGS_TO)"|' \ +diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile +index 44a4494..db9fc24 100644 +--- a/wcsmbs/Makefile ++++ b/wcsmbs/Makefile +@@ -18,15 +18,21 @@ + # + # Sub-makefile for wcsmbs portion of the library. + # ++include ../option-groups.mak ++ + subdir := wcsmbs + + include ../Makeconfig + + headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h + +-routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ ++# These functions are used by printf_fp.c, even in the plain case; see ++# comments there for OPTION_EGLIBC_LOCALE_CODE. ++routines := wmemcpy wmemset ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ + wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \ +- wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \ ++ wmemcmp wmemmove wcpcpy wcpncpy wmempcpy \ + btowc wctob mbsinit \ + mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \ + mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \ +@@ -38,14 +44,21 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ + wcscoll_l wcsxfrm_l \ + wcscasecmp wcsncase wcscasecmp_l wcsncase_l \ + wcsmbsload mbsrtowcs_l \ +- isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \ + isoc99_swscanf isoc99_vswscanf \ + mbrtoc16 c16rtomb + +-strop-tests := wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy +-tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \ +- tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \ +- tst-c16c32-1 wcsatcliff $(addprefix test-,$(strop-tests)) ++routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ ++ += isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf ++ ++strop-tests := wcscmp wmemcmp wmemcmp wcslen wcschr wcsrchr wcscpy ++ ++tests := tst-wchar-h ++tests-$(OPTION_EGLIBC_LOCALE_CODE) \ ++ += tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb tst-c16c32-1 ++tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += tst-wcstof wcsmbs-tst1 tst-wcsnlen \ ++ tst-wcpncpy tst-mbsrtowcs \ ++ wcsatcliff $(addprefix test-,$(strop-tests)) + + include ../Rules + +diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c +index 6bb49bc..2ab9d07 100644 +--- a/wcsmbs/wcsmbsload.c ++++ b/wcsmbs/wcsmbsload.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -143,6 +144,7 @@ __wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp) + }) + + ++#if __OPTION_EGLIBC_LOCALE_CODE + /* Some of the functions here must not be used while setlocale is called. */ + __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) + +@@ -211,6 +213,17 @@ __wcsmbs_load_conv (struct __locale_data *new_category) + + __libc_rwlock_unlock (__libc_setlocale_lock); + } ++#else ++void ++internal_function ++__wcsmbs_load_conv (struct __locale_data *new_category) ++{ ++ /* When OPTION_EGLIBC_LOCALE_CODE is disabled, we should never reach ++ this point: there is no way to change locales, so every locale ++ passed to get_gconv_fcts should be _nl_C_LC_CTYPE. */ ++ abort (); ++} ++#endif + + + /* Clone the current conversion function set. */ +diff --git a/wctype/Makefile b/wctype/Makefile +index c56f07c..4e8af43 100644 +--- a/wctype/Makefile ++++ b/wctype/Makefile +@@ -18,14 +18,20 @@ + # + # Sub-makefile for wctype portion of the library. + # ++include ../option-groups.mak ++ + subdir := wctype + + include ../Makeconfig + + headers := wctype.h +-routines := wcfuncs wctype iswctype wctrans towctrans \ +- wcfuncs_l wctype_l iswctype_l wctrans_l towctrans_l +- +-tests := test_wctype test_wcfuncs bug-wctypeh ++routines := wctrans towctrans towctrans_l ++routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ := wcfuncs wctype iswctype \ ++ wcfuncs_l wctype_l iswctype_l wctrans_l ++ ++tests := ++tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ ++ += test_wctype test_wcfuncs bug-wctypeh + + include ../Rules +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0025-eglibc-Install-PIC-archives.patch b/meta/recipes-core/glibc/glibc/0025-eglibc-Install-PIC-archives.patch new file mode 100644 index 0000000000..c359cce9c5 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0025-eglibc-Install-PIC-archives.patch @@ -0,0 +1,123 @@ +From 5773417fa91a18cd39fb35c9907d72af0ed9ea33 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 01:57:01 +0000 +Subject: [PATCH 25/27] eglibc: Install PIC archives + +Forward port from eglibc + +2008-02-07 Joseph Myers + + * Makerules (install-extras, install-map): New variables. + (installed-libcs): Add libc_pic.a. + (install-lib): Include _pic.a files for versioned shared + libraries. + (install-map-nosubdir, install-extras-nosubdir): Add rules for + installing extra files. + (install-no-libc.a-nosubdir): Depend on install-map-nosubdir and + install-extras-nosubdir. + +2008-04-01 Maxim Kuvyrkov + + * Makerules (install-lib): Don't install libpthread_pic.a. + (install-map): Don't install libpthread_pic.map. + +Upstream-Status: Pending + +Signed-off-by: Khem Raj +--- + Makerules | 42 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/Makerules b/Makerules +index 1dd41aa..41778e1 100644 +--- a/Makerules ++++ b/Makerules +@@ -713,6 +713,9 @@ ifeq ($(build-shared),yes) + $(common-objpfx)libc.so: $(common-objpfx)libc.map + endif + common-generated += libc.so libc_pic.os ++ifndef subdir ++install-extras := soinit.o sofini.o ++endif + ifdef libc.so-version + $(common-objpfx)libc.so$(libc.so-version): $(common-objpfx)libc.so + $(make-link) +@@ -955,6 +958,7 @@ endif + + install: check-install-supported + ++installed-libcs := $(installed-libcs) $(inst_libdir)/libc_pic.a + install: $(installed-libcs) + $(installed-libcs): $(inst_libdir)/lib$(libprefix)%: lib $(+force) + $(make-target-directory) +@@ -983,6 +987,22 @@ versioned := $(strip $(foreach so,$(install-lib.so),\ + install-lib.so-versioned := $(filter $(versioned), $(install-lib.so)) + install-lib.so-unversioned := $(filter-out $(versioned), $(install-lib.so)) + ++# Install the _pic.a files for versioned libraries, and corresponding ++# .map files. ++# libpthread_pic.a breaks mklibs, so don't install it and its map. ++install-lib := $(install-lib) $(install-lib.so-versioned:%.so=%_pic.a) ++install-lib := $(filter-out libpthread_pic.a,$(install-lib)) ++# Despite having a soname libhurduser and libmachuser do not use symbol ++# versioning, so don't install the corresponding .map files. ++ifeq ($(build-shared),yes) ++install-map := $(patsubst %.so,%.map,\ ++ $(foreach L,$(install-lib.so-versioned),$(notdir $L))) ++install-map := $(filter-out libhurduser.map libmachuser.map libpthread.map,$(install-map)) ++ifndef subdir ++install-map := $(install-map) libc.map ++endif ++endif ++ + # For versioned libraries, we install three files: + # $(inst_libdir)/libfoo.so -- for linking, symlink or ld script + # $(inst_slibdir)/libfoo.so.NN -- for loading by SONAME, symlink +@@ -1225,9 +1245,22 @@ $(addprefix $(inst_includedir)/,$(headers-nonh)): $(inst_includedir)/%: \ + endif # headers-nonh + endif # headers + ++ifdef install-map ++$(addprefix $(inst_libdir)/,$(patsubst lib%.map,lib%_pic.map,$(install-map))): \ ++ $(inst_libdir)/lib%_pic.map: $(common-objpfx)lib%.map $(+force) ++ $(do-install) ++endif ++ ++ifdef install-extras ++$(addprefix $(inst_libdir)/libc_pic/,$(install-extras)): \ ++ $(inst_libdir)/libc_pic/%.o: $(elf-objpfx)%.os $(+force) ++ $(do-install) ++endif ++ + .PHONY: install-bin-nosubdir install-bin-script-nosubdir \ + install-rootsbin-nosubdir install-sbin-nosubdir install-lib-nosubdir \ +- install-data-nosubdir install-headers-nosubdir ++ install-data-nosubdir install-headers-nosubdir install-map-nosubdir \ ++ install-extras-nosubdir + install-bin-nosubdir: $(addprefix $(inst_bindir)/,$(install-bin)) + install-bin-script-nosubdir: $(addprefix $(inst_bindir)/,$(install-bin-script)) + install-rootsbin-nosubdir: \ +@@ -1240,6 +1273,10 @@ install-data-nosubdir: $(addprefix $(inst_datadir)/,$(install-data)) + install-headers-nosubdir: $(addprefix $(inst_includedir)/,$(headers)) + install-others-nosubdir: $(install-others) + install-others-programs-nosubdir: $(install-others-programs) ++install-map-nosubdir: $(addprefix $(inst_libdir)/,\ ++ $(patsubst lib%.map,lib%_pic.map,$(install-map))) ++install-extras-nosubdir: $(addprefix $(inst_libdir)/libc_pic/,\ ++ $(install-extras)) + + # We need all the `-nosubdir' targets so that `install' in the parent + # doesn't depend on several things which each iterate over the subdirs. +@@ -1249,7 +1286,8 @@ install-%:: install-%-nosubdir ; + + .PHONY: install install-no-libc.a-nosubdir + install-no-libc.a-nosubdir: install-headers-nosubdir install-data-nosubdir \ +- install-lib-nosubdir install-others-nosubdir ++ install-lib-nosubdir install-others-nosubdir \ ++ install-map-nosubdir install-extras-nosubdir + ifeq ($(build-programs),yes) + install-no-libc.a-nosubdir: install-bin-nosubdir install-bin-script-nosubdir \ + install-rootsbin-nosubdir install-sbin-nosubdir \ +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch b/meta/recipes-core/glibc/glibc/0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch new file mode 100644 index 0000000000..6b611dbde7 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch @@ -0,0 +1,556 @@ +From ba069b3107f5ad200c4ab95e69cf368e2353b00a Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Mar 2015 00:46:50 +0000 +Subject: [PATCH 26/27] eglibc: dl_debug_mask is controlled by + __OPTION_EGLIBC_RTLD_DEBUG + +use GLRO_dl_debug_mask + +Singed-off-by: Khem Raj + +Upstream-Status: Pending +--- + csu/libc-start.c | 4 ++-- + elf/dl-cache.c | 4 ++-- + elf/dl-close.c | 6 +++--- + elf/dl-conflict.c | 2 +- + elf/dl-deps.c | 6 +++--- + elf/dl-error.c | 2 +- + elf/dl-fini.c | 4 ++-- + elf/dl-init.c | 4 ++-- + elf/dl-load.c | 16 ++++++++-------- + elf/dl-lookup.c | 14 +++++++------- + elf/dl-object.c | 2 +- + elf/dl-open.c | 10 +++++----- + elf/dl-reloc.c | 2 +- + elf/dl-version.c | 2 +- + elf/get-dynamic-info.h | 2 +- + elf/rtld.c | 22 +++++++++++----------- + 16 files changed, 51 insertions(+), 51 deletions(-) + +diff --git a/csu/libc-start.c b/csu/libc-start.c +index 0afa7c0..2151fb6 100644 +--- a/csu/libc-start.c ++++ b/csu/libc-start.c +@@ -238,7 +238,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + + /* Call the initializer of the program, if any. */ + #ifdef SHARED +- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) ++ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS, 0)) + GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]); + #endif + if (init) +@@ -261,7 +261,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + #endif + + #ifdef SHARED +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS)) + GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]); + #endif + +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index 862f1d8..dab9c51 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -194,7 +194,7 @@ _dl_load_cache_lookup (const char *name) + const char *best; + + /* Print a message if the loading of libs is traced. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) + _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE); + + if (cache == NULL) +@@ -292,7 +292,7 @@ _dl_load_cache_lookup (const char *name) + } + + /* Print our result if wanted. */ +- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0) ++ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, 0) + && best != NULL) + _dl_debug_printf (" trying file=%s\n", best); + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index c897247..b1b4bd5 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -125,7 +125,7 @@ _dl_close_worker (struct link_map *map, bool force) + dl_close_state = rerun; + + /* There are still references to this object. Do nothing more. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n", + map->l_name, map->l_direct_opencount); + +@@ -269,7 +269,7 @@ _dl_close_worker (struct link_map *map, bool force) + if (imap->l_init_called) + { + /* When debugging print a message first. */ +- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, ++ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS, + 0)) + _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", + imap->l_name, nsid); +@@ -711,7 +711,7 @@ _dl_close_worker (struct link_map *map, bool force) + free (imap->l_reldeps); + + /* Print debugging message. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("\nfile=%s [%lu]; destroying link map\n", + imap->l_name, imap->l_ns); + +diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c +index 47a946e..e6a3f21 100644 +--- a/elf/dl-conflict.c ++++ b/elf/dl-conflict.c +@@ -32,7 +32,7 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict, + ElfW(Rela) *conflictend) + { + #if ! ELF_MACHINE_NO_RELA +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_RELOC)) + _dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name)); + + { +diff --git a/elf/dl-deps.c b/elf/dl-deps.c +index eee146a..1a4b004 100644 +--- a/elf/dl-deps.c ++++ b/elf/dl-deps.c +@@ -127,7 +127,7 @@ empty dynamic string token substitution")); \ + else \ + { \ + /* This is for DT_AUXILIARY. */ \ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) \ ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) \ + _dl_debug_printf (N_("\ + cannot load auxiliary `%s' because of empty dynamic string token " \ + "substitution\n"), __str); \ +@@ -303,7 +303,7 @@ _dl_map_object_deps (struct link_map *map, + args.name = name; + + /* Say that we are about to load an auxiliary library. */ +- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, ++ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, + 0)) + _dl_debug_printf ("load auxiliary object=%s" + " requested by file=%s\n", +@@ -520,7 +520,7 @@ _dl_map_object_deps (struct link_map *map, + runp->map->l_reserved = 0; + } + +- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0 ++ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_PRELINK, 0) != 0 + && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded) + { + /* If we are to compute conflicts, we have to build local scope +diff --git a/elf/dl-error.c b/elf/dl-error.c +index 0fc3fd8..ea82f4d 100644 +--- a/elf/dl-error.c ++++ b/elf/dl-error.c +@@ -139,7 +139,7 @@ internal_function + _dl_signal_cerror (int errcode, const char *objname, const char *occation, + const char *errstring) + { +- if (__builtin_expect (GLRO(dl_debug_mask) ++ if (__builtin_expect (GLRO_dl_debug_mask + & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) + _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, + errstring, receiver ? "continued" : "fatal"); +diff --git a/elf/dl-fini.c b/elf/dl-fini.c +index 6cfe651..f59f7fe 100644 +--- a/elf/dl-fini.c ++++ b/elf/dl-fini.c +@@ -234,7 +234,7 @@ _dl_fini (void) + || l->l_info[DT_FINI] != NULL) + { + /* When debugging print a message first. */ +- if (__builtin_expect (GLRO(dl_debug_mask) ++ if (__builtin_expect (GLRO_dl_debug_mask + & DL_DEBUG_IMPCALLS, 0)) + _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", + DSO_FILENAME (l->l_name), +@@ -286,7 +286,7 @@ _dl_fini (void) + goto again; + } + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_STATISTICS)) + _dl_debug_printf ("\nruntime linker statistics:\n" + " final number of relocations: %lu\n" + "final number of relocations from cache: %lu\n", +diff --git a/elf/dl-init.c b/elf/dl-init.c +index 2f85731..e46e8b6 100644 +--- a/elf/dl-init.c ++++ b/elf/dl-init.c +@@ -46,7 +46,7 @@ call_init (struct link_map *l, int argc, char **argv, char **env) + return; + + /* Print a debug message if wanted. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS)) + _dl_debug_printf ("\ncalling init: %s\n\n", + DSO_FILENAME (l->l_name)); + +@@ -96,7 +96,7 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env) + ElfW(Addr) *addrs; + unsigned int cnt; + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS)) + _dl_debug_printf ("\ncalling preinit: %s\n\n", + DSO_FILENAME (main_map->l_name)); + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index f664f50..8c28744 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -943,7 +943,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, + } + + /* Print debugging message. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("file=%s [%lu]; generating link map\n", name, nsid); + + /* This is the ELF header. We read it in `open_verify'. */ +@@ -1347,7 +1347,7 @@ cannot enable executable stack as shared object requires"); + + l->l_entry += l->l_addr; + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("\ + dynamic: 0x%0*lx base: 0x%0*lx size: 0x%0*Zx\n\ + entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u\n\n", +@@ -1789,7 +1789,7 @@ open_path (const char *name, size_t namelen, int mode, + + /* If we are debugging the search for libraries print the path + now if it hasn't happened now. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS) + && current_what != this_dir->what) + { + current_what = this_dir->what; +@@ -1810,7 +1810,7 @@ open_path (const char *name, size_t namelen, int mode, + - buf); + + /* Print name we try if this is wanted. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) + _dl_debug_printf (" trying file=%s\n", buf); + + fd = open_verify (buf, fbp, loader, whatcode, mode, +@@ -1955,7 +1955,7 @@ _dl_map_object (struct link_map *loader, const char *name, + } + + /* Display information if we are debugging. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES) + && loader != NULL) + _dl_debug_printf ((mode & __RTLD_CALLMAP) == 0 + ? "\nfile=%s [%lu]; needed by %s [%lu]\n" +@@ -1997,7 +1997,7 @@ _dl_map_object (struct link_map *loader, const char *name, + + size_t namelen = strlen (name) + 1; + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) + _dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid); + + fd = -1; +@@ -2119,7 +2119,7 @@ _dl_map_object (struct link_map *loader, const char *name, + #endif + + /* Add another newline when we are tracing the library loading. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) + _dl_debug_printf ("\n"); + } + else +@@ -2152,7 +2152,7 @@ _dl_map_object (struct link_map *loader, const char *name, + if (__glibc_unlikely (fd == -1)) + { + if (trace_mode +- && __glibc_likely ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) == 0)) ++ && __glibc_likely ((GLRO_dl_debug_mask & DL_DEBUG_PRELINK) == 0)) + { + /* We haven't found an appropriate library. But since we + are only interested in the list of libraries this isn't +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 11cb44b..588c3e4 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -302,7 +302,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + hash table. */ + if (__glibc_unlikely (tab->size)) + { +- assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK); ++ assert (GLRO_dl_debug_mask & DL_DEBUG_PRELINK); + goto success; + } + #endif +@@ -378,7 +378,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, + continue; + + /* Print some debugging info if wanted. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SYMBOLS)) + _dl_debug_printf ("symbol=%s; lookup in file=%s [%lu]\n", + undef_name, DSO_FILENAME (map->l_name), + map->l_ns); +@@ -755,7 +755,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags) + } + + /* Display information if we are debugging. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("\ + \nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n", + DSO_FILENAME (map->l_name), +@@ -859,7 +859,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, + { + if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) + && skip_map == NULL +- && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) ++ && !(GLRO_dl_debug_mask & DL_DEBUG_UNUSED)) + { + /* We could find no value for a strong reference. */ + const char *reference_name = undef_map ? undef_map->l_name : ""; +@@ -935,7 +935,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, + if (__glibc_unlikely (current_value.m->l_used == 0)) + current_value.m->l_used = 1; + +- if (__glibc_unlikely (GLRO(dl_debug_mask) ++ if (__glibc_unlikely (GLRO_dl_debug_mask + & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK))) + _dl_debug_bindings (undef_name, undef_map, ref, + ¤t_value, version, type_class, protected); +@@ -1000,7 +1000,7 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, + { + const char *reference_name = undef_map->l_name; + +- if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS) ++ if (GLRO_dl_debug_mask & DL_DEBUG_BINDINGS) + { + _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'", + DSO_FILENAME (reference_name), +@@ -1014,7 +1014,7 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, + _dl_debug_printf_c ("\n"); + } + #ifdef SHARED +- if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) ++ if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK) + { + int conflict = 0; + struct sym_val val = { NULL, NULL }; +diff --git a/elf/dl-object.c b/elf/dl-object.c +index 1d58bbc..938a257 100644 +--- a/elf/dl-object.c ++++ b/elf/dl-object.c +@@ -98,7 +98,7 @@ _dl_new_object (char *realname, const char *libname, int type, + new->l_type = type; + /* If we set the bit now since we know it is never used we avoid + dirtying the cache line later. */ +- if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0) ++ if ((GLRO_dl_debug_mask & DL_DEBUG_UNUSED) == 0) + new->l_used = 1; + new->l_loader = loader; + #if NO_TLS_OFFSET != 0 +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 2db1c02..1288604 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -147,7 +147,7 @@ add_to_global (struct link_map *new) + ns->_ns_main_searchlist->r_list[new_nlist++] = map; + + /* We modify the global scope. Report this. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) + _dl_debug_printf ("\nadd %s [%lu] to global scope\n", + map->l_name, map->l_ns); + } +@@ -251,7 +251,7 @@ dl_open_worker (void *a) + if (__glibc_unlikely (new->l_searchlist.r_list != NULL)) + { + /* Let the user know about the opencount. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + +@@ -302,7 +302,7 @@ dl_open_worker (void *a) + LIBC_PROBE (map_complete, 3, args->nsid, r, new); + + /* Print scope information. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) + _dl_show_scope (new, 0); + + /* Only do lazy relocation if `LD_BIND_NOW' is not set. */ +@@ -519,7 +519,7 @@ dl_open_worker (void *a) + } + + /* Print scope information. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) + _dl_show_scope (imap, from_scope); + } + +@@ -577,7 +577,7 @@ TLS generation counter wrapped! Please report this.")); + #endif + + /* Let the user know about the opencount. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) + _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + } +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index 61252d7..4c83815 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -178,7 +178,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0)) + lazy = 0; + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_RELOC)) + _dl_debug_printf ("\nrelocation processing: %s%s\n", + DSO_FILENAME (l->l_name), lazy ? " (lazy)" : ""); + +diff --git a/elf/dl-version.c b/elf/dl-version.c +index f6e5cd9..320628c 100644 +--- a/elf/dl-version.c ++++ b/elf/dl-version.c +@@ -82,7 +82,7 @@ match_symbol (const char *name, Lmid_t ns, ElfW(Word) hash, const char *string, + int result = 0; + + /* Display information about what we are doing while debugging. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_VERSIONS)) + _dl_debug_printf ("\ + checking for version `%s' in file %s [%lu] required by file %s [%lu]\n", + string, DSO_FILENAME (map->l_name), +diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h +index dc8359d..7774fda 100644 +--- a/elf/get-dynamic-info.h ++++ b/elf/get-dynamic-info.h +@@ -166,7 +166,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) + them. Therefore to avoid breaking existing applications the + best we can do is add a warning during debugging with the + intent of notifying the user of the problem. */ +- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) ++ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_FILES, 0) + && l->l_flags_1 & ~DT_1_SUPPORTED_MASK) + _dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n", + l->l_flags_1 & ~DT_1_SUPPORTED_MASK); +diff --git a/elf/rtld.c b/elf/rtld.c +index fc3a2db..59c4637 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -323,7 +323,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) + } + #endif + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_STATISTICS)) + { + #ifndef HP_TIMING_NONAVAIL + print_statistics (&rtld_total_time); +@@ -1701,7 +1701,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + after relocation. */ + struct link_map *l; + +- if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) ++ if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK) + { + struct r_scope_elem *scope = &main_map->l_searchlist; + +@@ -1731,7 +1731,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + _dl_printf ("\n"); + } + } +- else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) ++ else if (GLRO_dl_debug_mask & DL_DEBUG_UNUSED) + { + /* Look through the dependencies of the main executable + and determine which of them is not actually +@@ -1839,7 +1839,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + } + } + +- if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) ++ if ((GLRO_dl_debug_mask & DL_DEBUG_PRELINK) + && rtld_multiple_ref) + { + /* Mark the link map as not yet relocated again. */ +@@ -1972,7 +1972,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + if (r_list == r_listend && liblist == liblistend) + prelinked = true; + +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) + _dl_debug_printf ("\nprelink checking: %s\n", + prelinked ? "ok" : "failed"); + } +@@ -1990,7 +1990,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + GLRO(dl_init_all_dirs) = GL(dl_all_dirs); + + /* Print scope information. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) ++ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) + { + _dl_debug_printf ("\nInitial object scopes\n"); + +@@ -2265,7 +2265,7 @@ process_dl_debug (const char *dl_debug) + if (debopts[cnt].len == len + && memcmp (dl_debug, debopts[cnt].name, len) == 0) + { +- GLRO(dl_debug_mask) |= debopts[cnt].mask; ++ GLRO_dl_debug_mask |= debopts[cnt].mask; + any_debug = 1; + break; + } +@@ -2286,7 +2286,7 @@ warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy); + ++dl_debug; + } + +- if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) ++ if (GLRO_dl_debug_mask & DL_DEBUG_UNUSED) + { + /* In order to get an accurate picture of whether a particular + DT_NEEDED entry is actually used we have to process both +@@ -2294,7 +2294,7 @@ warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy); + GLRO(dl_lazy) = 0; + } + +- if (GLRO(dl_debug_mask) & DL_DEBUG_HELP) ++ if (GLRO_dl_debug_mask & DL_DEBUG_HELP) + { + size_t cnt; + +@@ -2499,7 +2499,7 @@ process_envvars (enum mode *modep) + mode = trace; + GLRO(dl_verbose) = 1; + #if __OPTION_EGLIBC_RTLD_DEBUG +- GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK; ++ GLRO_dl_debug_mask |= DL_DEBUG_PRELINK; + #endif + GLRO(dl_trace_prelink) = &envline[17]; + } +@@ -2548,7 +2548,7 @@ process_envvars (enum mode *modep) + { + unsetenv ("MALLOC_CHECK_"); + #if __OPTION_EGLIBC_RTLD_DEBUG +- GLRO(dl_debug_mask) = 0; ++ GLRO_dl_debug_mask = 0; + #endif + } + +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch b/meta/recipes-core/glibc/glibc/0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch new file mode 100644 index 0000000000..4106167df5 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch @@ -0,0 +1,145 @@ +From e98779aa56fae0346dff2d0b72acadd0eaf01891 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 27 May 2015 16:10:50 -0700 +Subject: [PATCH 27/27] eglibc-use-option-groups: Conditionally exclude c++ + tests + + Some test programs written in c++ are still included in spite of + "libc-cxx-tests" being omitted from DISTRO_FEATURES_LIBC. + All .cc programs are compiled with g++. + g++ automatically specifies linking against the C++ library. + This patch conditionally excludes the following tests as well: + + bug-atexit3-lib.cc + tst-cancel24.cc + tst-cancel24-static.cc + tst-unique3lib.cc + tst-unique3lib2.cc + tst-unique4lib.cc + tst-unique3.cc + tst-unique4.cc + + Tested with DISTRO_FEATURES_LIBC_remove = " libc-cxx-tests" + + [YOCTO #7003] + +Signed-off-by: Juro Bystricky +Signed-off-by: Khem Raj +--- + dlfcn/Makefile | 8 ++++++-- + elf/Makefile | 19 ++++++++++++++----- + nptl/Makefile | 12 ++++++++++-- + 3 files changed, 30 insertions(+), 9 deletions(-) + +diff --git a/dlfcn/Makefile b/dlfcn/Makefile +index 3827607..920bd58 100644 +--- a/dlfcn/Makefile ++++ b/dlfcn/Makefile +@@ -39,16 +39,20 @@ ifeq (yes,$(build-shared)) + tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \ + bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ + tstatexit bug-dl-leaf tst-rec-dlopen +-endif +- + tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3 + ++endif ++ + modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \ + defaultmod2 errmsg1mod modatexit modcxaatexit \ + bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ + bug-atexit2-lib bug-dl-leaf-lib \ + bug-dl-leaf-lib-cb moddummy1 moddummy2 + ++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) ++modules-names += bug-atexit3-lib ++endif ++ + failtestmod.so-no-z-defs = yes + glreflib2.so-no-z-defs = yes + errmsg1mod.so-no-z-defs = yes +diff --git a/elf/Makefile b/elf/Makefile +index 71a18a1..26fe3c5 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -17,6 +17,8 @@ + + # Makefile for elf subdirectory of GNU C Library. + ++include ../option-groups.mak ++ + subdir := elf + + include ../Makeconfig +@@ -145,12 +147,15 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ + unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ + tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ + tst-stackguard1 tst-addr1 tst-thrlock \ +- tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ +- tst-nodelete) \ ++ tst-unique1 tst-unique2 \ + tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ + tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ + tst-nodelete2 + # reldep9 ++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) ++tests += $(if $(CXX),tst-unique3 tst-unique4 tst-nodelete) ++endif ++ + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout + LDFLAGS-tst-dlopen-aout = $(no-pie-ldflag) +@@ -209,9 +214,6 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-unique1mod1 tst-unique1mod2 \ + tst-unique2mod1 tst-unique2mod2 \ + tst-auditmod9a tst-auditmod9b \ +- $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ +- tst-nodelete-uniquemod tst-nodelete-rtldmod \ +- tst-nodelete-zmod) \ + tst-initordera1 tst-initorderb1 \ + tst-initordera2 tst-initorderb2 \ + tst-initordera3 tst-initordera4 \ +@@ -220,6 +222,13 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ + tst-array5dep tst-null-argv-lib \ + tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod ++ ++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) ++modules-names += $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ ++ tst-nodelete-uniquemod tst-nodelete-rtldmod \ ++ tst-nodelete-zmod) ++endif ++ + ifeq (yes,$(have-protected-data)) + modules-names += tst-protected1moda tst-protected1modb + tests += tst-protected1a tst-protected1b +diff --git a/nptl/Makefile b/nptl/Makefile +index 596ca3c..50a708b 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -390,12 +390,20 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \ + $(common-objpfx)libc.a + + tests-static += tst-locale1 tst-locale2 tst-stackguard1-static \ +- tst-cancel21-static tst-cancel24-static tst-cond8-static \ ++ tst-cancel21-static tst-cond8-static \ + tst-mutex8-static tst-mutexpi8-static tst-sem11-static \ + tst-sem12-static +-tests += tst-stackguard1-static tst-cancel21-static tst-cancel24-static \ ++ ++ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) ++tests-static += tst-cancel24-static ++endif ++ ++tests += tst-stackguard1-static tst-cancel21-static \ + tst-cond8-static tst-mutex8-static tst-mutexpi8-static \ + tst-sem11-static tst-sem12-static ++ ++tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24-static ++ + xtests-static += tst-setuid1-static + + # These tests are linked with libc before libpthread +-- +2.1.4 + diff --git a/meta/recipes-core/glibc/glibc/CVE-2015-1781-resolv-nss_dns-dns-host.c-buffer-overf.patch b/meta/recipes-core/glibc/glibc/CVE-2015-1781-resolv-nss_dns-dns-host.c-buffer-overf.patch deleted file mode 100644 index c02fa127cd..0000000000 --- a/meta/recipes-core/glibc/glibc/CVE-2015-1781-resolv-nss_dns-dns-host.c-buffer-overf.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 2959eda9272a033863c271aff62095abd01bd4e3 Mon Sep 17 00:00:00 2001 -From: Arjun Shankar -Date: Tue, 21 Apr 2015 14:06:31 +0200 -Subject: [PATCH] CVE-2015-1781: resolv/nss_dns/dns-host.c buffer overflow - [BZ#18287] - -Upstream-Status: Backport -https://sourceware.org/bugzilla/show_bug.cgi?id=18287 ---- - resolv/nss_dns/dns-host.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c -index b16b0ddf110907a0086b86612e544d3dc75182b8..d8c55791591750567f00e616e5d7b378dec934a0 100644 ---- a/resolv/nss_dns/dns-host.c -+++ b/resolv/nss_dns/dns-host.c -@@ -608,21 +608,22 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, - int n, ancount, qdcount; - int haveanswer, had_error; - char *bp, **ap, **hap; - char tbuf[MAXDNAME]; - const char *tname; - int (*name_ok) (const char *); - u_char packtmp[NS_MAXCDNAME]; - int have_to_map = 0; - uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); - buffer += pad; -- if (__glibc_unlikely (buflen < sizeof (struct host_data) + pad)) -+ buflen = buflen > pad ? buflen - pad : 0; -+ if (__glibc_unlikely (buflen < sizeof (struct host_data))) - { - /* The buffer is too small. */ - too_small: - *errnop = ERANGE; - *h_errnop = NETDB_INTERNAL; - return NSS_STATUS_TRYAGAIN; - } - host_data = (struct host_data *) buffer; - linebuflen = buflen - sizeof (struct host_data); - if (buflen - sizeof (struct host_data) != linebuflen) --- -2.2.2 - diff --git a/meta/recipes-core/glibc/glibc/Fix-__memcpy_chk-on-non-SSE2-CPUs.patch b/meta/recipes-core/glibc/glibc/Fix-__memcpy_chk-on-non-SSE2-CPUs.patch deleted file mode 100644 index 2e768bb6e8..0000000000 --- a/meta/recipes-core/glibc/glibc/Fix-__memcpy_chk-on-non-SSE2-CPUs.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 132a1328eccd20621b77f7810eebbeec0a1af187 Mon Sep 17 00:00:00 2001 -From: Evangelos Foutras -Date: Tue, 10 Feb 2015 03:22:58 +0000 -Subject: [PATCH] Fix __memcpy_chk on non-SSE2 CPUs - -In commit 8b4416d, the 1: jump label in __mempcpy_chk was accidentally -moved. This resulted in failures of mempcpy on CPU without SSE2. - -Upstream-Status: Backport - - https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=132a1328eccd20621b77f7810eebbeec0a1af187 - -Signed-off-by: Andre McCurdy - ---- - sysdeps/i386/i686/multiarch/mempcpy_chk.S | 4 ++-- - 3 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/sysdeps/i386/i686/multiarch/mempcpy_chk.S b/sysdeps/i386/i686/multiarch/mempcpy_chk.S -index 207b648..b6fa202 100644 ---- a/sysdeps/i386/i686/multiarch/mempcpy_chk.S -+++ b/sysdeps/i386/i686/multiarch/mempcpy_chk.S -@@ -36,8 +36,8 @@ ENTRY(__mempcpy_chk) - cmpl $0, KIND_OFFSET+__cpu_features@GOTOFF(%ebx) - jne 1f - call __init_cpu_features -- leal __mempcpy_chk_ia32@GOTOFF(%ebx), %eax --1: testl $bit_SSE2, CPUID_OFFSET+index_SSE2+__cpu_features@GOTOFF(%ebx) -+1: leal __mempcpy_chk_ia32@GOTOFF(%ebx), %eax -+ testl $bit_SSE2, CPUID_OFFSET+index_SSE2+__cpu_features@GOTOFF(%ebx) - jz 2f - leal __mempcpy_chk_sse2_unaligned@GOTOFF(%ebx), %eax - testl $bit_Fast_Unaligned_Load, FEATURE_OFFSET+index_Fast_Unaligned_Load+__cpu_features@GOTOFF(%ebx) --- -1.9.1 - diff --git a/meta/recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch b/meta/recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch deleted file mode 100644 index e858bfaeda..0000000000 --- a/meta/recipes-core/glibc/glibc/GLRO_dl_debug_mask.patch +++ /dev/null @@ -1,529 +0,0 @@ -Its controlled by __OPTION_EGLIBC_RTLD_DEBUG -so we should use GLRO_dl_debug_mask - -Singed-off-by: Khem Raj - -Upstream-Status: Pending -Index: git/elf/dl-open.c -=================================================================== ---- git.orig/elf/dl-open.c 2014-08-27 05:03:59.732070587 +0000 -+++ git/elf/dl-open.c 2014-08-27 05:05:25.656070587 +0000 -@@ -147,7 +147,7 @@ - ns->_ns_main_searchlist->r_list[new_nlist++] = map; - - /* We modify the global scope. Report this. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) - _dl_debug_printf ("\nadd %s [%lu] to global scope\n", - map->l_name, map->l_ns); - } -@@ -243,7 +243,7 @@ - if (__glibc_unlikely (new->l_searchlist.r_list != NULL)) - { - /* Let the user know about the opencount. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", - new->l_name, new->l_ns, new->l_direct_opencount); - -@@ -294,7 +294,7 @@ - LIBC_PROBE (map_complete, 3, args->nsid, r, new); - - /* Print scope information. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) - _dl_show_scope (new, 0); - - /* Only do lazy relocation if `LD_BIND_NOW' is not set. */ -@@ -511,7 +511,7 @@ - } - - /* Print scope information. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) - _dl_show_scope (imap, from_scope); - } - -@@ -584,7 +584,7 @@ - #endif - - /* Let the user know about the opencount. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", - new->l_name, new->l_ns, new->l_direct_opencount); - } -Index: git/elf/rtld.c -=================================================================== ---- git.orig/elf/rtld.c 2014-08-27 05:03:59.732070587 +0000 -+++ git/elf/rtld.c 2014-08-27 05:12:33.812070587 +0000 -@@ -321,7 +321,7 @@ - } - #endif - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_STATISTICS)) - { - #ifndef HP_TIMING_NONAVAIL - print_statistics (&rtld_total_time); -@@ -1699,7 +1699,7 @@ - after relocation. */ - struct link_map *l; - -- if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) -+ if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK) - { - struct r_scope_elem *scope = &main_map->l_searchlist; - -@@ -1729,7 +1729,7 @@ - _dl_printf ("\n"); - } - } -- else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) -+ else if (GLRO_dl_debug_mask & DL_DEBUG_UNUSED) - { - /* Look through the dependencies of the main executable - and determine which of them is not actually -@@ -1837,7 +1837,7 @@ - } - } - -- if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) -+ if ((GLRO_dl_debug_mask & DL_DEBUG_PRELINK) - && rtld_multiple_ref) - { - /* Mark the link map as not yet relocated again. */ -@@ -1970,7 +1970,7 @@ - if (r_list == r_listend && liblist == liblistend) - prelinked = true; - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) - _dl_debug_printf ("\nprelink checking: %s\n", - prelinked ? "ok" : "failed"); - } -@@ -1988,7 +1988,7 @@ - GLRO(dl_init_all_dirs) = GL(dl_all_dirs); - - /* Print scope information. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SCOPES)) - { - _dl_debug_printf ("\nInitial object scopes\n"); - -@@ -2262,7 +2262,7 @@ - if (debopts[cnt].len == len - && memcmp (dl_debug, debopts[cnt].name, len) == 0) - { -- GLRO(dl_debug_mask) |= debopts[cnt].mask; -+ GLRO_dl_debug_mask |= debopts[cnt].mask; - any_debug = 1; - break; - } -@@ -2283,7 +2283,7 @@ - ++dl_debug; - } - -- if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) -+ if (GLRO_dl_debug_mask & DL_DEBUG_UNUSED) - { - /* In order to get an accurate picture of whether a particular - DT_NEEDED entry is actually used we have to process both -@@ -2291,7 +2291,7 @@ - GLRO(dl_lazy) = 0; - } - -- if (GLRO(dl_debug_mask) & DL_DEBUG_HELP) -+ if (GLRO_dl_debug_mask & DL_DEBUG_HELP) - { - size_t cnt; - -@@ -2490,7 +2490,7 @@ - { - mode = trace; - GLRO(dl_verbose) = 1; -- GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK; -+ GLRO_dl_debug_mask |= DL_DEBUG_PRELINK; - GLRO(dl_trace_prelink) = &envline[17]; - } - break; -@@ -2537,7 +2537,7 @@ - if (__access ("/etc/suid-debug", F_OK) != 0) - { - unsetenv ("MALLOC_CHECK_"); -- GLRO(dl_debug_mask) = 0; -+ GLRO_dl_debug_mask = 0; - } - - if (mode != normal) -Index: git/elf/dl-lookup.c -=================================================================== ---- git.orig/elf/dl-lookup.c 2014-08-27 05:03:59.732070587 +0000 -+++ git/elf/dl-lookup.c 2014-08-27 05:13:07.644070587 +0000 -@@ -300,7 +300,7 @@ - hash table. */ - if (__glibc_unlikely (tab->size)) - { -- assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK); -+ assert (GLRO_dl_debug_mask & DL_DEBUG_PRELINK); - goto success; - } - #endif -@@ -375,7 +375,7 @@ - continue; - - /* Print some debugging info if wanted. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_SYMBOLS)) - _dl_debug_printf ("symbol=%s; lookup in file=%s [%lu]\n", - undef_name, DSO_FILENAME (map->l_name), - map->l_ns); -@@ -698,7 +698,7 @@ - } - - /* Display information if we are debugging. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("\ - \nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n", - DSO_FILENAME (map->l_name), -@@ -802,7 +802,7 @@ - { - if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) - && skip_map == NULL -- && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) -+ && !(GLRO_dl_debug_mask & DL_DEBUG_UNUSED)) - { - /* We could find no value for a strong reference. */ - const char *reference_name = undef_map ? undef_map->l_name : ""; -@@ -873,7 +873,7 @@ - if (__glibc_unlikely (current_value.m->l_used == 0)) - current_value.m->l_used = 1; - -- if (__glibc_unlikely (GLRO(dl_debug_mask) -+ if (__glibc_unlikely (GLRO_dl_debug_mask - & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK))) - _dl_debug_bindings (undef_name, undef_map, ref, - ¤t_value, version, type_class, protected); -@@ -938,7 +938,7 @@ - { - const char *reference_name = undef_map->l_name; - -- if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS) -+ if (GLRO_dl_debug_mask & DL_DEBUG_BINDINGS) - { - _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'", - DSO_FILENAME (reference_name), -@@ -952,7 +952,7 @@ - _dl_debug_printf_c ("\n"); - } - #ifdef SHARED -- if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) -+ if (GLRO_dl_debug_mask & DL_DEBUG_PRELINK) - { - int conflict = 0; - struct sym_val val = { NULL, NULL }; -Index: git/elf/get-dynamic-info.h -=================================================================== ---- git.orig/elf/get-dynamic-info.h 2014-08-27 05:03:59.732070587 +0000 -+++ git/elf/get-dynamic-info.h 2014-08-27 05:03:59.728070587 +0000 -@@ -157,7 +157,7 @@ - them. Therefore to avoid breaking existing applications the - best we can do is add a warning during debugging with the - intent of notifying the user of the problem. */ -- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) -+ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_FILES, 0) - && l->l_flags_1 & ~DT_1_SUPPORTED_MASK) - _dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n", - l->l_flags_1 & ~DT_1_SUPPORTED_MASK); -Index: git/csu/libc-start.c -=================================================================== ---- git.orig/csu/libc-start.c 2014-08-27 04:59:01.412070587 +0000 -+++ git/csu/libc-start.c 2014-08-27 05:09:28.936070587 +0000 -@@ -238,7 +238,7 @@ - - /* Call the initializer of the program, if any. */ - #ifdef SHARED -- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) -+ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS, 0)) - GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]); - #endif - if (init) -@@ -261,7 +261,7 @@ - #endif - - #ifdef SHARED -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS)) - GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]); - #endif - -Index: git/elf/dl-cache.c -=================================================================== ---- git.orig/elf/dl-cache.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-cache.c 2014-08-27 05:10:14.384070587 +0000 -@@ -187,7 +187,7 @@ - const char *best; - - /* Print a message if the loading of libs is traced. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) - _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE); - - if (cache == NULL) -@@ -285,7 +285,7 @@ - } - - /* Print our result if wanted. */ -- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0) -+ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, 0) - && best != NULL) - _dl_debug_printf (" trying file=%s\n", best); - -Index: git/elf/dl-close.c -=================================================================== ---- git.orig/elf/dl-close.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-close.c 2014-08-27 05:10:26.456070587 +0000 -@@ -125,7 +125,7 @@ - dl_close_state = rerun; - - /* There are still references to this object. Do nothing more. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n", - map->l_name, map->l_direct_opencount); - -@@ -257,7 +257,7 @@ - if (imap->l_init_called) - { - /* When debugging print a message first. */ -- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, -+ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS, - 0)) - _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", - imap->l_name, nsid); -@@ -664,7 +664,7 @@ - free (imap->l_reldeps); - - /* Print debugging message. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("\nfile=%s [%lu]; destroying link map\n", - imap->l_name, imap->l_ns); - -Index: git/elf/dl-conflict.c -=================================================================== ---- git.orig/elf/dl-conflict.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-conflict.c 2014-08-27 05:10:37.652070587 +0000 -@@ -32,7 +32,7 @@ - ElfW(Rela) *conflictend) - { - #if ! ELF_MACHINE_NO_RELA -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_RELOC)) - _dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name)); - - { -Index: git/elf/dl-deps.c -=================================================================== ---- git.orig/elf/dl-deps.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-deps.c 2014-08-27 05:10:48.260070587 +0000 -@@ -127,7 +127,7 @@ - else \ - { \ - /* This is for DT_AUXILIARY. */ \ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) \ -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) \ - _dl_debug_printf (N_("\ - cannot load auxiliary `%s' because of empty dynamic string token " \ - "substitution\n"), __str); \ -@@ -303,7 +303,7 @@ - args.name = name; - - /* Say that we are about to load an auxiliary library. */ -- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, -+ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, - 0)) - _dl_debug_printf ("load auxiliary object=%s" - " requested by file=%s\n", -@@ -520,7 +520,7 @@ - runp->map->l_reserved = 0; - } - -- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0 -+ if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_PRELINK, 0) != 0 - && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded) - { - /* If we are to compute conflicts, we have to build local scope -Index: git/elf/dl-error.c -=================================================================== ---- git.orig/elf/dl-error.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-error.c 2014-08-27 05:11:06.752070587 +0000 -@@ -139,7 +139,7 @@ - _dl_signal_cerror (int errcode, const char *objname, const char *occation, - const char *errstring) - { -- if (__builtin_expect (GLRO(dl_debug_mask) -+ if (__builtin_expect (GLRO_dl_debug_mask - & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) - _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, - errstring, receiver ? "continued" : "fatal"); -Index: git/elf/dl-fini.c -=================================================================== ---- git.orig/elf/dl-fini.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-fini.c 2014-08-27 05:11:17.544070587 +0000 -@@ -234,7 +234,7 @@ - || l->l_info[DT_FINI] != NULL) - { - /* When debugging print a message first. */ -- if (__builtin_expect (GLRO(dl_debug_mask) -+ if (__builtin_expect (GLRO_dl_debug_mask - & DL_DEBUG_IMPCALLS, 0)) - _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", - DSO_FILENAME (l->l_name), -@@ -286,7 +286,7 @@ - goto again; - } - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_STATISTICS)) - _dl_debug_printf ("\nruntime linker statistics:\n" - " final number of relocations: %lu\n" - "final number of relocations from cache: %lu\n", -Index: git/elf/dl-init.c -=================================================================== ---- git.orig/elf/dl-init.c 2014-08-27 04:59:01.568070587 +0000 -+++ git/elf/dl-init.c 2014-08-27 05:11:28.372070587 +0000 -@@ -52,7 +52,7 @@ - return; - - /* Print a debug message if wanted. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS)) - _dl_debug_printf ("\ncalling init: %s\n\n", - DSO_FILENAME (l->l_name)); - -@@ -102,7 +102,7 @@ - ElfW(Addr) *addrs; - unsigned int cnt; - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_IMPCALLS)) - _dl_debug_printf ("\ncalling preinit: %s\n\n", - DSO_FILENAME (main_map->l_name)); - -Index: git/elf/dl-load.c -=================================================================== ---- git.orig/elf/dl-load.c 2014-08-27 04:59:01.572070587 +0000 -+++ git/elf/dl-load.c 2014-08-27 05:11:41.156070587 +0000 -@@ -957,7 +957,7 @@ - } - - /* Print debugging message. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("file=%s [%lu]; generating link map\n", name, nsid); - - /* This is the ELF header. We read it in `open_verify'. */ -@@ -1361,7 +1361,7 @@ - - l->l_entry += l->l_addr; - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES)) - _dl_debug_printf ("\ - dynamic: 0x%0*lx base: 0x%0*lx size: 0x%0*Zx\n\ - entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u\n\n", -@@ -1787,7 +1787,7 @@ - - /* If we are debugging the search for libraries print the path - now if it hasn't happened now. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS) - && current_what != this_dir->what) - { - current_what = this_dir->what; -@@ -1808,7 +1808,7 @@ - - buf); - - /* Print name we try if this is wanted. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) - _dl_debug_printf (" trying file=%s\n", buf); - - fd = open_verify (buf, fbp, loader, whatcode, mode, -@@ -1953,7 +1953,7 @@ - } - - /* Display information if we are debugging. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_FILES) - && loader != NULL) - _dl_debug_printf ((mode & __RTLD_CALLMAP) == 0 - ? "\nfile=%s [%lu]; needed by %s [%lu]\n" -@@ -1995,7 +1995,7 @@ - - size_t namelen = strlen (name) + 1; - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) - _dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid); - - fd = -1; -@@ -2122,7 +2122,7 @@ - &realname, &fb, l, LA_SER_DEFAULT, &found_other_class); - - /* Add another newline when we are tracing the library loading. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) - _dl_debug_printf ("\n"); - } - else -@@ -2155,7 +2155,7 @@ - if (__glibc_unlikely (fd == -1)) - { - if (trace_mode -- && __glibc_likely ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) == 0)) -+ && __glibc_likely ((GLRO_dl_debug_mask & DL_DEBUG_PRELINK) == 0)) - { - /* We haven't found an appropriate library. But since we - are only interested in the list of libraries this isn't -Index: git/elf/dl-object.c -=================================================================== ---- git.orig/elf/dl-object.c 2014-08-27 04:59:01.572070587 +0000 -+++ git/elf/dl-object.c 2014-08-27 05:11:51.756070587 +0000 -@@ -98,7 +98,7 @@ - new->l_type = type; - /* If we set the bit now since we know it is never used we avoid - dirtying the cache line later. */ -- if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0) -+ if ((GLRO_dl_debug_mask & DL_DEBUG_UNUSED) == 0) - new->l_used = 1; - new->l_loader = loader; - #if NO_TLS_OFFSET != 0 -Index: git/elf/dl-reloc.c -=================================================================== ---- git.orig/elf/dl-reloc.c 2014-08-27 04:59:01.572070587 +0000 -+++ git/elf/dl-reloc.c 2014-08-27 05:12:07.056070587 +0000 -@@ -183,7 +183,7 @@ - && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0)) - lazy = 0; - -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_RELOC)) - _dl_debug_printf ("\nrelocation processing: %s%s\n", - DSO_FILENAME (l->l_name), lazy ? " (lazy)" : ""); - -Index: git/elf/dl-version.c -=================================================================== ---- git.orig/elf/dl-version.c 2014-08-27 04:59:01.608070587 +0000 -+++ git/elf/dl-version.c 2014-08-27 05:12:19.568070587 +0000 -@@ -82,7 +82,7 @@ - int result = 0; - - /* Display information about what we are doing while debugging. */ -- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS)) -+ if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_VERSIONS)) - _dl_debug_printf ("\ - checking for version `%s' in file %s [%lu] required by file %s [%lu]\n", - string, DSO_FILENAME (map->l_name), diff --git a/meta/recipes-core/glibc/glibc/IO-acquire-lock-fix.patch b/meta/recipes-core/glibc/glibc/IO-acquire-lock-fix.patch deleted file mode 100644 index ffbaba14a2..0000000000 --- a/meta/recipes-core/glibc/glibc/IO-acquire-lock-fix.patch +++ /dev/null @@ -1,17 +0,0 @@ -import http://sourceware.org/ml/libc-ports/2007-12/msg00000.html - -Upstream-Status: Pending - -Index: git/bits/stdio-lock.h -=================================================================== ---- git.orig/bits/stdio-lock.h 2014-08-29 10:33:57.960070587 -0700 -+++ git/bits/stdio-lock.h 2014-08-29 10:33:57.952070587 -0700 -@@ -49,6 +49,8 @@ - _IO_cleanup_region_start ((void (*) (void *)) _IO_funlockfile, (_fp)); \ - _IO_flockfile (_fp) - -+# define _IO_acquire_lock_clear_flags2(_fp) _IO_acquire_lock (_fp) -+ - # define _IO_release_lock(_fp) \ - _IO_funlockfile (_fp); \ - _IO_cleanup_region_end (0) diff --git a/meta/recipes-core/glibc/glibc/add_resource_h_to_wait_h.patch b/meta/recipes-core/glibc/glibc/add_resource_h_to_wait_h.patch deleted file mode 100644 index 70f57c4979..0000000000 --- a/meta/recipes-core/glibc/glibc/add_resource_h_to_wait_h.patch +++ /dev/null @@ -1,20 +0,0 @@ -The older versions of perf still require sys/resource.h to be -present in this header, the newer version of perf in 3.2 and -beyond directly include sys/resource.h - -Upstream-Status: Inappropriate [older kernel/perf specific] - -Signed-off-by: Saul Wold - -Index: git/posix/sys/wait.h -=================================================================== ---- git.orig/posix/sys/wait.h 2014-08-29 10:35:10.432070587 -0700 -+++ git/posix/sys/wait.h 2014-08-29 10:35:10.424070587 -0700 -@@ -27,6 +27,7 @@ - __BEGIN_DECLS - - #include -+#include - - /* These macros could also be defined in . */ - #if !defined _STDLIB_H || (!defined __USE_XOPEN && !defined __USE_XOPEN2K8) diff --git a/meta/recipes-core/glibc/glibc/eglibc-header-bootstrap.patch b/meta/recipes-core/glibc/glibc/eglibc-header-bootstrap.patch deleted file mode 100644 index e1aa13926a..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc-header-bootstrap.patch +++ /dev/null @@ -1,85 +0,0 @@ -Taken from EGLIBC, r1484 + r1525 - - 2007-02-20 Jim Blandy - - * Makefile (install-headers): Preserve old behavior: depend on - $(inst_includedir)/gnu/stubs.h only if install-bootstrap-headers - is set; otherwise, place gnu/stubs.h on the 'install-others' list. - - 2007-02-16 Jim Blandy - - * Makefile: Amend make install-headers to install everything - necessary for building a cross-compiler. Install gnu/stubs.h as - part of 'install-headers', not 'install-others'. - If install-bootstrap-headers is 'yes', install a dummy copy of - gnu/stubs.h, instead of computing the real thing. - * include/stubs-bootstrap.h: New file. - -Upstream-Status: Pending - -Index: git/Makefile -=================================================================== ---- git.orig/Makefile 2014-08-27 18:35:18.908070587 +0000 -+++ git/Makefile 2014-08-27 18:35:19.340070587 +0000 -@@ -69,9 +69,18 @@ - vpath %.h $(subdir-dirs) - - # What to install. --install-others = $(inst_includedir)/gnu/stubs.h - install-bin-script = - -+# If we're bootstrapping, install a dummy gnu/stubs.h along with the -+# other headers, so 'make install-headers' produces a useable include -+# tree. Otherwise, install gnu/stubs.h later, after the rest of the -+# build is done. -+ifeq ($(install-bootstrap-headers),yes) -+install-headers: $(inst_includedir)/gnu/stubs.h -+else -+install-others = $(inst_includedir)/gnu/stubs.h -+endif -+ - ifeq (yes,$(build-shared)) - headers += gnu/lib-names.h - endif -@@ -151,6 +160,16 @@ - - subdir-stubs := $(foreach dir,$(subdirs),$(common-objpfx)$(dir)/stubs) - -+# gnu/stubs.h depends (via the subdir 'stubs' targets) on all the .o -+# files in EGLIBC. For bootstrapping a GCC/EGLIBC pair, an empty -+# gnu/stubs.h is good enough. -+ifeq ($(install-bootstrap-headers),yes) -+$(inst_includedir)/gnu/stubs.h: include/stubs-bootstrap.h $(+force) -+ $(make-target-directory) -+ $(INSTALL_DATA) $< $@ -+ -+installed-stubs = -+else - ifndef abi-variants - installed-stubs = $(inst_includedir)/gnu/stubs.h - else -@@ -177,6 +196,7 @@ - - install-others-nosubdir: $(installed-stubs) - endif -+endif - - - # Since stubs.h is never needed when building the library, we simplify the -Index: git/include/stubs-bootstrap.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/include/stubs-bootstrap.h 2014-08-27 18:35:19.340070587 +0000 -@@ -0,0 +1,12 @@ -+/* Placeholder stubs.h file for bootstrapping. -+ -+ When bootstrapping a GCC/EGLIBC pair, GCC requires that the EGLIBC -+ headers be installed, but we can't fully build EGLIBC without that -+ GCC. So we run the command: -+ -+ make install-headers install-bootstrap-headers=yes -+ -+ to install the headers GCC needs, but avoid building certain -+ difficult headers. The header depends, via the -+ EGLIBC subdir 'stubs' make targets, on every .o file in EGLIBC, but -+ an empty stubs.h like this will do fine for GCC. */ diff --git a/meta/recipes-core/glibc/glibc/eglibc-install-pic-archives.patch b/meta/recipes-core/glibc/glibc/eglibc-install-pic-archives.patch deleted file mode 100644 index 9a31255b09..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc-install-pic-archives.patch +++ /dev/null @@ -1,109 +0,0 @@ -2008-02-07 Joseph Myers - - * Makerules (install-extras, install-map): New variables. - (installed-libcs): Add libc_pic.a. - (install-lib): Include _pic.a files for versioned shared - libraries. - (install-map-nosubdir, install-extras-nosubdir): Add rules for - installing extra files. - (install-no-libc.a-nosubdir): Depend on install-map-nosubdir and - install-extras-nosubdir. - - -2008-04-01 Maxim Kuvyrkov - - * Makerules (install-lib): Don't install libpthread_pic.a. - (install-map): Don't install libpthread_pic.map. - -Upstream-Status: Pending - -Index: git/Makerules -=================================================================== ---- git.orig/Makerules 2014-08-27 18:49:22.552070587 +0000 -+++ git/Makerules 2014-08-27 18:49:27.308070587 +0000 -@@ -612,6 +631,9 @@ - $(common-objpfx)libc.so: $(common-objpfx)libc.map - endif - common-generated += libc.so libc_pic.os -+ifndef subdir -+install-extras := soinit.o sofini.o -+endif - ifdef libc.so-version - $(common-objpfx)libc.so$(libc.so-version): $(common-objpfx)libc.so - $(make-link) -@@ -834,6 +856,7 @@ - installed-libcs := $(foreach o,$(filter-out .os,$(object-suffixes-for-libc)),\ - $(inst_libdir)/$(patsubst %,$(libtype$o),\ - $(libprefix)$(libc-name))) -+installed-libcs := $(installed-libcs) $(inst_libdir)/libc_pic.a - install: $(installed-libcs) - $(installed-libcs): $(inst_libdir)/lib$(libprefix)%: lib $(+force) - $(make-target-directory) -@@ -862,6 +885,22 @@ - install-lib.so-versioned := $(filter $(versioned), $(install-lib.so)) - install-lib.so-unversioned := $(filter-out $(versioned), $(install-lib.so)) - -+# Install the _pic.a files for versioned libraries, and corresponding -+# .map files. -+# libpthread_pic.a breaks mklibs, so don't install it and its map. -+install-lib := $(install-lib) $(install-lib.so-versioned:%.so=%_pic.a) -+install-lib := $(filter-out libpthread_pic.a,$(install-lib)) -+# Despite having a soname libhurduser and libmachuser do not use symbol -+# versioning, so don't install the corresponding .map files. -+ifeq ($(build-shared),yes) -+install-map := $(patsubst %.so,%.map,\ -+ $(foreach L,$(install-lib.so-versioned),$(notdir $L))) -+install-map := $(filter-out libhurduser.map libmachuser.map libpthread.map,$(install-map)) -+ifndef subdir -+install-map := $(install-map) libc.map -+endif -+endif -+ - # For versioned libraries, we install three files: - # $(inst_libdir)/libfoo.so -- for linking, symlink or ld script - # $(inst_slibdir)/libfoo.so.NN -- for loading by SONAME, symlink -@@ -1103,9 +1142,22 @@ - endif # headers-nonh - endif # headers - -+ifdef install-map -+$(addprefix $(inst_libdir)/,$(patsubst lib%.map,lib%_pic.map,$(install-map))): \ -+ $(inst_libdir)/lib%_pic.map: $(common-objpfx)lib%.map $(+force) -+ $(do-install) -+endif -+ -+ifdef install-extras -+$(addprefix $(inst_libdir)/libc_pic/,$(install-extras)): \ -+ $(inst_libdir)/libc_pic/%.o: $(elfobjdir)/%.os $(+force) -+ $(do-install) -+endif -+ - .PHONY: install-bin-nosubdir install-bin-script-nosubdir \ - install-rootsbin-nosubdir install-sbin-nosubdir install-lib-nosubdir \ -- install-data-nosubdir install-headers-nosubdir -+ install-data-nosubdir install-headers-nosubdir install-map-nosubdir \ -+ install-extras-nosubdir - install-bin-nosubdir: $(addprefix $(inst_bindir)/,$(install-bin)) - install-bin-script-nosubdir: $(addprefix $(inst_bindir)/,$(install-bin-script)) - install-rootsbin-nosubdir: \ -@@ -1118,6 +1170,10 @@ - install-headers-nosubdir: $(addprefix $(inst_includedir)/,$(headers)) - install-others-nosubdir: $(install-others) - install-others-programs-nosubdir: $(install-others-programs) -+install-map-nosubdir: $(addprefix $(inst_libdir)/,\ -+ $(patsubst lib%.map,lib%_pic.map,$(install-map))) -+install-extras-nosubdir: $(addprefix $(inst_libdir)/libc_pic/,\ -+ $(install-extras)) - - # We need all the `-nosubdir' targets so that `install' in the parent - # doesn't depend on several things which each iterate over the subdirs. -@@ -1127,7 +1183,8 @@ - - .PHONY: install install-no-libc.a-nosubdir - install-no-libc.a-nosubdir: install-headers-nosubdir install-data-nosubdir \ -- install-lib-nosubdir install-others-nosubdir -+ install-lib-nosubdir install-others-nosubdir \ -+ install-map-nosubdir install-extras-nosubdir - ifeq ($(build-programs),yes) - install-no-libc.a-nosubdir: install-bin-nosubdir install-bin-script-nosubdir \ - install-rootsbin-nosubdir install-sbin-nosubdir \ diff --git a/meta/recipes-core/glibc/glibc/eglibc-ppc8xx-cache-line-workaround.patch b/meta/recipes-core/glibc/glibc/eglibc-ppc8xx-cache-line-workaround.patch deleted file mode 100644 index bb83d6d36e..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc-ppc8xx-cache-line-workaround.patch +++ /dev/null @@ -1,68 +0,0 @@ -2007-06-13 Nathan Sidwell - Mark Shinwell - - * sysdeps/unix/sysv/linux/powerpc/libc-start.c - (__libc_start_main): Detect 8xx parts and clear - __cache_line_size if detected. - * sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c - (DL_PLATFORM_AUXV): Likewise. - -Upstream-Status: Pending - -Index: git/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c -=================================================================== ---- git.orig/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c 2014-08-27 18:49:23.996070587 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c 2014-08-27 18:49:27.332070587 +0000 -@@ -24,9 +24,21 @@ - /* Scan the Aux Vector for the "Data Cache Block Size" entry. If found - verify that the static extern __cache_line_size is defined by checking - for not NULL. If it is defined then assign the cache block size -- value to __cache_line_size. */ -+ value to __cache_line_size. This is used by memset to -+ optimize setting to zero. We have to detect 8xx processors, which -+ have buggy dcbz implementations that cannot report page faults -+ correctly. That requires reading SPR, which is a privileged -+ operation. Fortunately 2.2.18 and later emulates PowerPC mfspr -+ reads from the PVR register. */ - #define DL_PLATFORM_AUXV \ - case AT_DCACHEBSIZE: \ -+ if (__LINUX_KERNEL_VERSION >= 0x020218) \ -+ { \ -+ unsigned pvr = 0; \ -+ asm ("mfspr %0, 287" : "=r" (pvr)); \ -+ if ((pvr & 0xffff0000) == 0x00500000) \ -+ break; \ -+ } \ - __cache_line_size = av->a_un.a_val; \ - break; - -Index: git/sysdeps/unix/sysv/linux/powerpc/libc-start.c -=================================================================== ---- git.orig/sysdeps/unix/sysv/linux/powerpc/libc-start.c 2014-08-27 18:49:23.996070587 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/libc-start.c 2014-08-27 18:49:27.332070587 +0000 -@@ -68,11 +68,24 @@ - rtld_fini = NULL; - } - -- /* Initialize the __cache_line_size variable from the aux vector. */ -+ /* Initialize the __cache_line_size variable from the aux vector. -+ This is used by memset to optimize setting to zero. We have to -+ detect 8xx processors, which have buggy dcbz implementations that -+ cannot report page faults correctly. That requires reading SPR, -+ which is a privileged operation. Fortunately 2.2.18 and later -+ emulates PowerPC mfspr reads from the PVR register. */ - for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av) - switch (av->a_type) - { - case AT_DCACHEBSIZE: -+ if (__LINUX_KERNEL_VERSION >= 0x020218) -+ { -+ unsigned pvr = 0; -+ -+ asm ("mfspr %0, 287" : "=r" (pvr) :); -+ if ((pvr & 0xffff0000) == 0x00500000) -+ break; -+ } - __cache_line_size = av->a_un.a_val; - break; - } diff --git a/meta/recipes-core/glibc/glibc/eglibc-resolv-dynamic.patch b/meta/recipes-core/glibc/glibc/eglibc-resolv-dynamic.patch deleted file mode 100644 index a73bcebe34..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc-resolv-dynamic.patch +++ /dev/null @@ -1,54 +0,0 @@ -cherry-picked from http://www.eglibc.org/archives/patches/msg00772.html - -It hasnt yet been merged into glibc - -Signed-off-by: Khem Raj - -Upstream-Status: Pending - -Index: git/resolv/res_libc.c -=================================================================== ---- git.orig/resolv/res_libc.c 2014-08-27 18:35:15.492070587 +0000 -+++ git/resolv/res_libc.c 2014-08-27 18:35:19.204070587 +0000 -@@ -22,12 +22,13 @@ - #include - #include - #include -- -+#include - - /* The following bit is copied from res_data.c (where it is #ifdef'ed - out) since res_init() should go into libc.so but the rest of that - file should not. */ - -+__libc_lock_define_initialized (static, lock); - extern unsigned long long int __res_initstamp attribute_hidden; - /* We have atomic increment operations on 64-bit platforms. */ - #if __WORDSIZE == 64 -@@ -35,7 +36,6 @@ - # define atomicincunlock(lock) (void) 0 - # define atomicinc(var) catomic_increment (&(var)) - #else --__libc_lock_define_initialized (static, lock); - # define atomicinclock(lock) __libc_lock_lock (lock) - # define atomicincunlock(lock) __libc_lock_unlock (lock) - # define atomicinc(var) ++var -@@ -94,7 +94,18 @@ - int - __res_maybe_init (res_state resp, int preinit) - { -+ static time_t last_mtime; -+ struct stat statbuf; -+ int ret; -+ - if (resp->options & RES_INIT) { -+ ret = stat (_PATH_RESCONF, &statbuf); -+ __libc_lock_lock (lock); -+ if ((ret == 0) && (last_mtime != statbuf.st_mtime)) { -+ last_mtime = statbuf.st_mtime; -+ atomicinc (__res_initstamp); -+ } -+ __libc_lock_unlock (lock); - if (__res_initstamp != resp->_u._ext.initstamp) { - if (resp->nscount > 0) - __res_iclose (resp, true); diff --git a/meta/recipes-core/glibc/glibc/eglibc-sh4-fpscr_values.patch b/meta/recipes-core/glibc/glibc/eglibc-sh4-fpscr_values.patch deleted file mode 100644 index bfb813eb7c..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc-sh4-fpscr_values.patch +++ /dev/null @@ -1,42 +0,0 @@ -2010-09-29 Nobuhiro Iwamatsu - Andrew Stubbs - - Resolve SH's __fpscr_values to symbol in libc.so. - - * sysdeps/sh/sh4/fpu/fpu_control.h: Add C++ __set_fpscr prototype. - * sysdeps/unix/sysv/linux/sh/Versions (GLIBC_2.2): Add __fpscr_values. - * sysdeps/unix/sysv/linux/sh/sysdep.S (___fpscr_values): New constant. - -Upstream-Status: Pending - -Index: git/sysdeps/unix/sysv/linux/sh/sysdep.S -=================================================================== ---- git.orig/sysdeps/unix/sysv/linux/sh/sysdep.S 2014-08-27 18:49:24.036070587 +0000 -+++ git/sysdeps/unix/sysv/linux/sh/sysdep.S 2014-08-27 18:49:27.332070587 +0000 -@@ -30,3 +30,14 @@ - - #define __syscall_error __syscall_error_1 - #include -+ -+ .data -+ .align 3 -+ .globl ___fpscr_values -+ .type ___fpscr_values, @object -+ .size ___fpscr_values, 8 -+___fpscr_values: -+ .long 0 -+ .long 0x80000 -+weak_alias (___fpscr_values, __fpscr_values) -+ -Index: git/sysdeps/unix/sysv/linux/sh/Versions -=================================================================== ---- git.orig/sysdeps/unix/sysv/linux/sh/Versions 2014-08-27 18:49:24.028070587 +0000 -+++ git/sysdeps/unix/sysv/linux/sh/Versions 2014-08-27 18:49:27.332070587 +0000 -@@ -2,6 +2,7 @@ - GLIBC_2.2 { - # functions used in other libraries - __xstat64; __fxstat64; __lxstat64; -+ __fpscr_values; - - # a* - alphasort64; diff --git a/meta/recipes-core/glibc/glibc/eglibc-use-option-groups.patch b/meta/recipes-core/glibc/glibc/eglibc-use-option-groups.patch deleted file mode 100644 index da92203ca7..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc-use-option-groups.patch +++ /dev/null @@ -1,16725 +0,0 @@ -Forward port eglibc options groups support - -Upstream-Status: Pending - -Index: git/argp/argp-fmtstream.c -=================================================================== ---- git.orig/argp/argp-fmtstream.c -+++ git/argp/argp-fmtstream.c -@@ -42,6 +42,7 @@ - #ifdef _LIBC - # include - # include -+# include - # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) - #endif - -@@ -100,7 +101,11 @@ __argp_fmtstream_free (argp_fmtstream_t - __argp_fmtstream_update (fs); - if (fs->p > fs->buf) - { -+#ifdef _LIBC - __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); -+#else -+ fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); -+#endif - } - free (fs->buf); - free (fs); -@@ -145,9 +150,17 @@ __argp_fmtstream_update (argp_fmtstream_ - size_t i; - for (i = 0; i < pad; i++) - { -+#ifdef _LIBC - if (_IO_fwide (fs->stream, 0) > 0) -- putwc_unlocked (L' ', fs->stream); -+ { -+#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO -+ putwc_unlocked (L' ', fs->stream); -+#else -+ abort (); -+#endif -+ } - else -+#endif - putc_unlocked (' ', fs->stream); - } - } -@@ -308,9 +321,17 @@ __argp_fmtstream_update (argp_fmtstream_ - *nl++ = ' '; - else - for (i = 0; i < fs->wmargin; ++i) -+#ifdef _LIBC - if (_IO_fwide (fs->stream, 0) > 0) -- putwc_unlocked (L' ', fs->stream); -+ { -+#ifdef OPTION_POSIX_WIDE_CHAR_DEVICE_IO -+ putwc_unlocked (L' ', fs->stream); -+#else -+ abort (); -+#endif -+ } - else -+#endif - putc_unlocked (' ', fs->stream); - - /* Copy the tail of the original buffer into the current buffer -Index: git/argp/argp-help.c -=================================================================== ---- git.orig/argp/argp-help.c -+++ git/argp/argp-help.c -@@ -51,6 +51,7 @@ char *alloca (); - #ifdef _LIBC - # include <../libio/libioP.h> - # include -+# include - #endif - - #ifndef _ -@@ -1702,7 +1703,7 @@ char *__argp_basename (char *name) - } - - char * --__argp_short_program_name (void) -+(__argp_short_program_name) (void) - { - # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME - return program_invocation_short_name; -@@ -1873,9 +1874,17 @@ __argp_failure (const struct argp_state - #endif - } - -+#ifdef _LIBC - if (_IO_fwide (stream, 0) > 0) -- putwc_unlocked (L'\n', stream); -+ { -+#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO -+ putwc_unlocked (L'\n', stream); -+#else -+ abort (); -+#endif -+ } - else -+#endif - putc_unlocked ('\n', stream); - - #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) -Index: git/argp/argp-namefrob.h -=================================================================== ---- git.orig/argp/argp-namefrob.h -+++ git/argp/argp-namefrob.h -@@ -76,10 +76,12 @@ - #undef __argp_fmtstream_wmargin - #define __argp_fmtstream_wmargin argp_fmtstream_wmargin - -+#if 0 - #include "mempcpy.h" - #include "strcase.h" - #include "strchrnul.h" - #include "strndup.h" -+#endif - - /* normal libc functions we call */ - #undef __flockfile -Index: git/argp/Makefile -=================================================================== ---- git.orig/argp/Makefile -+++ git/argp/Makefile -@@ -18,6 +18,8 @@ - # - # Makefile for argp. - # -+include ../option-groups.mak -+ - subdir := argp - - include ../Makeconfig -Index: git/catgets/Makefile -=================================================================== ---- git.orig/catgets/Makefile -+++ git/catgets/Makefile -@@ -22,20 +22,23 @@ subdir := catgets - - include ../Makeconfig - -+include ../option-groups.mak -+ - headers = nl_types.h --routines = catgets open_catalog --others = gencat --install-bin = gencat --extra-objs = $(gencat-modules:=.o) -+routines-$(OPTION_EGLIBC_CATGETS) := catgets open_catalog -+others-$(OPTION_EGLIBC_CATGETS) := gencat -+install-bin-$(OPTION_EGLIBC_CATGETS) := gencat -+extra-objs-$(OPTION_EGLIBC_CATGETS) := $(gencat-modules:=.o) - --tests = tst-catgets --test-srcs = test-gencat -+tests-$(OPTION_EGLIBC_CATGETS) := tst-catgets -+test-srcs-$(OPTION_EGLIBC_CATGETS) := test-gencat - -+ifeq (y,$(OPTION_EGLIBC_CATGETS)) - ifeq ($(run-built-tests),yes) - tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \ - $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out - endif -- -+endif - gencat-modules = xmalloc - - # To find xmalloc.c -Index: git/crypt/crypt-entry.c -=================================================================== ---- git.orig/crypt/crypt-entry.c -+++ git/crypt/crypt-entry.c -@@ -27,6 +27,7 @@ - #include - #endif - #include -+#include - #include - #include - -@@ -76,9 +77,11 @@ __crypt_r (key, salt, data) - const char *salt; - struct crypt_data * __restrict data; - { -+#if __OPTION_EGLIBC_CRYPT_UFC - ufc_long res[4]; - char ktab[9]; - ufc_long xx = 25; /* to cope with GCC long long compiler bugs */ -+#endif /*__OPTION_EGLIBC_CRYPT_UFC*/ - - #ifdef _LIBC - /* Try to find out whether we have to use MD5 encryption replacement. */ -@@ -105,6 +108,7 @@ __crypt_r (key, salt, data) - sizeof (struct crypt_data)); - #endif - -+#if __OPTION_EGLIBC_CRYPT_UFC - /* - * Hack DES tables according to salt - */ -@@ -144,6 +148,10 @@ __crypt_r (key, salt, data) - */ - _ufc_output_conversion_r (res[0], res[1], salt, data); - return data->crypt_3_buf; -+#else /* __OPTION_EGLIBC_CRYPT_UFC */ -+ __set_errno (ENOSYS); -+ return NULL; -+#endif /* __OPTION_EGLIBC_CRYPT_UFC */ - } - weak_alias (__crypt_r, crypt_r) - -@@ -168,7 +176,12 @@ crypt (key, salt) - return __sha512_crypt (key, salt); - #endif - -+#if __OPTION_EGLIBC_CRYPT_UFC - return __crypt_r (key, salt, &_ufc_foobar); -+#else /* __OPTION_EGLIBC_CRYPT_UFC */ -+ __set_errno (ENOSYS); -+ return NULL; -+#endif /* __OPTION_EGLIBC_CRYPT_UFC */ - } - - -Index: git/crypt/Makefile -=================================================================== ---- git.orig/crypt/Makefile -+++ git/crypt/Makefile -@@ -18,21 +18,25 @@ - # - # Sub-makefile for crypt() portion of the library. - # -+include ../option-groups.mak -+ - subdir := crypt - - include ../Makeconfig - - headers := crypt.h - --extra-libs := libcrypt --extra-libs-others := $(extra-libs) -+extra-libs-$(OPTION_EGLIBC_CRYPT) := libcrypt -+extra-libs-others-y := $(extra-libs-y) - --libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \ -- crypt_util -+libcrypt-routines :=crypt-entry md5-crypt sha256-crypt sha512-crypt crypt_common -+libcrypt-routines-$(OPTION_EGLIBC_CRYPT_UFC) := crypt crypt_util -+libcrypt-routines += $(libcrypt-routines-y) - --tests := cert md5c-test sha256c-test sha512c-test badsalttest -+tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test badsalttest -+tests-$(OPTION_EGLIBC_CRYPT_UFC) += cert - --ifeq ($(crypt-in-libc),yes) -+ifeq ($(crypt-in-libc)$(OPTION_EGLIBC_CRYPT),yesy) - routines += $(libcrypt-routines) - endif - -@@ -44,7 +48,7 @@ LDLIBS-crypt.so = -lfreebl3 - else - libcrypt-routines += md5 sha256 sha512 - --tests += md5test sha256test sha512test -+tests-$(OPTION_EGLIBC_CRYPT) += md5test sha256test sha512test - - # The test md5test-giant uses up to 400 MB of RSS and runs on a fast - # machine over a minute. -@@ -64,8 +68,10 @@ $(objpfx)sha256test: $(patsubst %, $(obj - $(objpfx)sha512test: $(patsubst %, $(objpfx)%.o,$(sha512-routines)) - endif - -+ifeq ($(OPTION_EGLIBC_CRYPT),y) - ifeq (yes,$(build-shared)) - $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.so - else - $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.a - endif -+endif # eglibc: OPTION_EGLIBC_CRYPT -Index: git/csu/Makefile -=================================================================== ---- git.orig/csu/Makefile -+++ git/csu/Makefile -@@ -22,6 +22,8 @@ - # crtn.o, special "initializer" and "finalizer" files used in the link - # to make the .init and .fini sections work right. - -+include ../option-groups.mak -+ - subdir := csu - - include ../Makeconfig -Index: git/debug/Makefile -=================================================================== ---- git.orig/debug/Makefile -+++ git/debug/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for debug portion of the library. - # -+include ../option-groups.mak -+ - subdir := debug - - include ../Makeconfig -@@ -27,7 +29,7 @@ headers := execinfo.h - # Note that ptsname_r_chk and getlogin_r are not here, but in - # login/Makefile instead. If that subdir is omitted from the - # build, its _FORTIFY_SOURCE support will be too. --routines = backtrace backtracesyms backtracesymsfd noophooks \ -+routines = noophooks \ - memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ - strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ - sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ -@@ -36,20 +38,27 @@ routines = backtrace backtracesyms back - read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ - readlink_chk readlinkat_chk getwd_chk getcwd_chk \ - realpath_chk fread_chk fread_u_chk \ -- wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ -- wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ -- wcpncpy_chk \ -- swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \ -- vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \ - confstr_chk getgroups_chk ttyname_r_chk \ -- gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \ -- wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ -- wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \ -+ gethostname_chk getdomainname_chk \ -+ asprintf_chk vasprintf_chk dprintf_chk \ - vdprintf_chk obprintf_chk \ - longjmp_chk ____longjmp_chk \ - fdelt_chk poll_chk ppoll_chk \ - stack_chk_fail fortify_fail \ - $(static-only-routines) -+routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd -+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ -+ += wprintf_chk fwprintf_chk \ -+ vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ -+ wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ -+ wcpncpy_chk \ -+ swprintf_chk vswprintf_chk \ -+ wcrtomb_chk mbsnrtowcs_chk \ -+ wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ -+ wcstombs_chk -+ - static-only-routines := warning-nop stack_chk_fail_local - - CFLAGS-backtrace.c = -fno-omit-frame-pointer -@@ -131,11 +140,15 @@ LDFLAGS-tst-backtrace4 = -rdynamic - LDFLAGS-tst-backtrace5 = -rdynamic - LDFLAGS-tst-backtrace6 = -rdynamic - --tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ -- tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ -- tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \ -- tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \ -- tst-backtrace5 tst-backtrace6 -+tests = tst-longjmp_chk test-strcpy_chk test-stpcpy_chk tst-longjmp_chk2 -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-chk1 tst-chk2 tst-chk3 tst-lfschk1 tst-lfschk2 tst-lfschk3 -+tests-$(OPTION_EGLIBC_BACKTRACE) \ -+ += backtrace-tst tst-backtrace2 tst-backtrace3 tst-backtrace4 \ -+ tst-backtrace5 tst-backtrace6 -+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_EGLIBC_CXX_TESTS)) -+tests += tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 -+endif - - extra-libs = libSegFault libpcprofile - extra-libs-others = $(extra-libs) -Index: git/debug/segfault.c -=================================================================== ---- git.orig/debug/segfault.c -+++ git/debug/segfault.c -@@ -30,6 +30,7 @@ - #include - #include <_itoa.h> - #include -+#include - - /* This file defines macros to access the content of the sigcontext element - passed up by the signal handler. */ -@@ -68,11 +69,13 @@ write_strsignal (int fd, int signal) - static void - catch_segfault (int signal, SIGCONTEXT ctx) - { -- int fd, cnt, i; -- void **arr; -+ int fd; - struct sigaction sa; -+#if __OPTION_EGLIBC_BACKTRACE -+ int cnt, i; -+ void **arr; - uintptr_t pc; -- -+#endif - /* This is the name of the file we are writing to. If none is given - or we cannot write to this file write to stderr. */ - fd = 2; -@@ -91,6 +94,7 @@ catch_segfault (int signal, SIGCONTEXT c - REGISTER_DUMP; - #endif - -+#if __OPTION_EGLIBC_BACKTRACE - WRITE_STRING ("\nBacktrace:\n"); - - /* Get the backtrace. */ -@@ -113,6 +117,7 @@ catch_segfault (int signal, SIGCONTEXT c - - /* Now generate nicely formatted output. */ - __backtrace_symbols_fd (arr + i, cnt - i, fd); -+#endif - - #ifdef HAVE_PROC_SELF - /* Now the link map. */ -Index: git/debug/tst-chk1.c -=================================================================== ---- git.orig/debug/tst-chk1.c -+++ git/debug/tst-chk1.c -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - - - #define obstack_chunk_alloc malloc -@@ -307,6 +308,7 @@ do_test (void) - snprintf (buf + 8, l0 + 3, "%d", num2); - CHK_FAIL_END - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - CHK_FAIL_START - swprintf (wbuf + 8, 3, L"%d", num1); - CHK_FAIL_END -@@ -314,6 +316,7 @@ do_test (void) - CHK_FAIL_START - swprintf (wbuf + 8, l0 + 3, L"%d", num1); - CHK_FAIL_END -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - # endif - - memcpy (buf, str1 + 2, l0 + 9); -@@ -381,6 +384,7 @@ do_test (void) - CHK_FAIL_END - #endif - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - - /* These ops can be done without runtime checking of object size. */ - wmemcpy (wbuf, L"abcdefghij", 10); -@@ -605,6 +609,7 @@ do_test (void) - CHK_FAIL_END - #endif - -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - - /* Now checks for %n protection. */ - -@@ -1192,6 +1197,7 @@ do_test (void) - # endif - #endif - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL) - { - assert (MB_CUR_MAX <= 10); -@@ -1348,6 +1354,7 @@ do_test (void) - puts ("cannot set locale"); - ret = 1; - } -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - - int fd = posix_openpt (O_RDWR); - if (fd != -1) -Index: git/dlfcn/Makefile -=================================================================== ---- git.orig/dlfcn/Makefile -+++ git/dlfcn/Makefile -@@ -15,6 +15,8 @@ - # License along with the GNU C Library; if not, see - # . - -+include ../option-groups.mak -+ - subdir := dlfcn - - include ../Makeconfig -@@ -36,14 +38,18 @@ endif - ifeq (yes,$(build-shared)) - tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \ - bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ -- bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen -+ tstatexit bug-dl-leaf tst-rec-dlopen -+tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3 - endif - modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \ - defaultmod2 errmsg1mod modatexit modcxaatexit \ - bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ -- bug-atexit2-lib bug-atexit3-lib bug-dl-leaf-lib \ -+ bug-atexit2-lib bug-dl-leaf-lib \ - bug-dl-leaf-lib-cb moddummy1 moddummy2 - -+ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) -+modules-names += bug-atexit3-lib -+endif - failtestmod.so-no-z-defs = yes - glreflib2.so-no-z-defs = yes - errmsg1mod.so-no-z-defs = yes -Index: git/elf/Makefile -=================================================================== ---- git.orig/elf/Makefile -+++ git/elf/Makefile -@@ -17,6 +17,8 @@ - - # Makefile for elf subdirectory of GNU C Library. - -+include ../option-groups.mak -+ - subdir := elf - - include ../Makeconfig -@@ -144,10 +146,11 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ - unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ - tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ - tst-stackguard1 tst-addr1 tst-thrlock \ -- tst-unique1 tst-unique2 tst-unique3 tst-unique4 \ -+ tst-unique1 tst-unique2 \ - tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ - tst-ptrguard1 - # reldep9 -+tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-unique3 tst-unique4 - ifeq ($(build-hardcoded-path-in-tests),yes) - tests += tst-dlopen-aout - endif -@@ -205,8 +208,6 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ - tst-unique1mod1 tst-unique1mod2 \ - tst-unique2mod1 tst-unique2mod2 \ - tst-auditmod9a tst-auditmod9b \ -- tst-unique3lib tst-unique3lib2 \ -- tst-unique4lib \ - tst-initordera1 tst-initorderb1 \ - tst-initordera2 tst-initorderb2 \ - tst-initordera3 tst-initordera4 \ -@@ -214,6 +215,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ - tst-initorder2d \ - tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ - tst-array5dep tst-null-argv-lib -+ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) -+modules-names += tst-unique3lib tst-unique3lib2 tst-unique4lib -+endif - ifeq (yesyes,$(have-fpie)$(build-shared)) - modules-names += tst-piemod1 - tests += tst-pie1 tst-pie2 -Index: git/elf/dl-support.c -=================================================================== ---- git.orig/elf/dl-support.c -+++ git/elf/dl-support.c -@@ -19,6 +19,7 @@ - /* This file defines some things that for the dynamic linker are defined in - rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ - -+#include - #include - #include - #include -@@ -42,7 +43,9 @@ char **_dl_argv = &__progname; /* This i - const char *_dl_platform; - size_t _dl_platformlen; - -+#if __OPTION_EGLIBC_RTLD_DEBUG - int _dl_debug_mask; -+#endif - int _dl_lazy; - ElfW(Addr) _dl_use_load_bias = -2; - int _dl_dynamic_weak; -Index: git/elf/rtld.c -=================================================================== ---- git.orig/elf/rtld.c -+++ git/elf/rtld.c -@@ -16,6 +16,7 @@ - License along with the GNU C Library; if not, see - . */ - -+#include - #include - #include - #include -@@ -2200,6 +2201,7 @@ print_missing_version (int errcode __att - objname, errstring); - } - -+#if __OPTION_EGLIBC_RTLD_DEBUG - /* Nonzero if any of the debugging options is enabled. */ - static int any_debug attribute_relro; - -@@ -2309,6 +2311,7 @@ a filename can be specified using the LD - _exit (0); - } - } -+#endif /* __OPTION_EGLIBC_RTLD_DEBUG */ - - static void - process_dl_audit (char *str) -@@ -2348,8 +2351,9 @@ process_envvars (enum mode *modep) - char **runp = _environ; - char *envline; - enum mode mode = normal; -+#if __OPTION_EGLIBC_RTLD_DEBUG - char *debug_output = NULL; -- -+#endif - /* This is the default place for profiling data file. */ - GLRO(dl_profile_output) - = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0]; -@@ -2376,12 +2380,14 @@ process_envvars (enum mode *modep) - break; - - case 5: -+#if __OPTION_EGLIBC_RTLD_DEBUG - /* Debugging of the dynamic linker? */ - if (memcmp (envline, "DEBUG", 5) == 0) - { - process_dl_debug (&envline[6]); - break; - } -+#endif - if (memcmp (envline, "AUDIT", 5) == 0) - process_dl_audit (&envline[6]); - break; -@@ -2447,13 +2453,14 @@ process_envvars (enum mode *modep) - break; - } - -+#if __OPTION_EGLIBC_RTLD_DEBUG - /* Where to place the profiling data file. */ - if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0) - { - debug_output = &envline[13]; - break; - } -- -+#endif - if (!__libc_enable_secure - && memcmp (envline, "DYNAMIC_WEAK", 12) == 0) - GLRO(dl_dynamic_weak) = 1; -@@ -2490,7 +2497,9 @@ process_envvars (enum mode *modep) - { - mode = trace; - GLRO(dl_verbose) = 1; -+#if __OPTION_EGLIBC_RTLD_DEBUG - GLRO_dl_debug_mask |= DL_DEBUG_PRELINK; -+#endif - GLRO(dl_trace_prelink) = &envline[17]; - } - break; -@@ -2537,12 +2546,15 @@ process_envvars (enum mode *modep) - if (__access ("/etc/suid-debug", F_OK) != 0) - { - unsetenv ("MALLOC_CHECK_"); -+#if __OPTION_EGLIBC_RTLD_DEBUG - GLRO_dl_debug_mask = 0; -+#endif - } - - if (mode != normal) - _exit (5); - } -+#if __OPTION_EGLIBC_RTLD_DEBUG - /* If we have to run the dynamic linker in debugging mode and the - LD_DEBUG_OUTPUT environment variable is given, we write the debug - messages to this file. */ -@@ -2567,6 +2579,7 @@ process_envvars (enum mode *modep) - /* We use standard output if opening the file failed. */ - GLRO(dl_debug_fd) = STDOUT_FILENO; - } -+#endif /* __OPTION_EGLIBC_RTLD_DEBUG */ - } - - -Index: git/extra-lib.mk -=================================================================== ---- git.orig/extra-lib.mk -+++ git/extra-lib.mk -@@ -25,7 +25,9 @@ install-lib := $(install-lib) - extra-objs := $(extra-objs) - - # The modules that go in $(lib). --all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines) -+all-$(lib)-routines := $($(lib)-routines) \ -+ $($(lib)-routines-y) \ -+ $($(lib)-sysdep_routines) - - # Add each flavor of library to the lists of things to build and install. - install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o))) -@@ -101,7 +103,7 @@ endif - endif - - # This will define `libof-ROUTINE := LIB' for each of the routines. --cpp-srcs-left := $($(lib)-routines) $($(lib)-sysdep_routines) -+cpp-srcs-left := $(all-$(lib)-routines) - ifneq (,$(cpp-srcs-left)) - include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left)) - endif -Index: git/grp/Makefile -=================================================================== ---- git.orig/grp/Makefile -+++ git/grp/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for grp portion of the library. - # -+include ../option-groups.mak -+ - subdir := grp - - include ../Makeconfig -@@ -29,6 +31,9 @@ routines := fgetgrent initgroups setgrou - getgrent_r getgrgid_r getgrnam_r fgetgrent_r - - tests := testgrp -+ifneq (y,$(OPTION_EGLIBC_NSSWITCH)) -+LDLIBS-testgrp += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs) -+endif - - ifeq (yes,$(build-shared)) - test-srcs := tst_fgetgrent -Index: git/hesiod/Makefile -=================================================================== ---- git.orig/hesiod/Makefile -+++ git/hesiod/Makefile -@@ -18,12 +18,14 @@ - # - # Sub-makefile for hesiod portion of the library. - # -+include ../option-groups.mak -+ - subdir := hesiod - - include ../Makeconfig - --extra-libs := libnss_hesiod --extra-libs-others = $(extra-libs) -+extra-libs-$(OPTION_EGLIBC_INET) += libnss_hesiod -+extra-libs-others-y += $(extra-libs-y) - - subdir-dirs = nss_hesiod - vpath %.c nss_hesiod -Index: git/iconv/gconv_db.c -=================================================================== ---- git.orig/iconv/gconv_db.c -+++ git/iconv/gconv_db.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -828,9 +829,11 @@ free_modules_db (struct gconv_module *no - /* Free all resources if necessary. */ - libc_freeres_fn (free_mem) - { -+#if __OPTION_EGLIBC_LOCALE_CODE - /* First free locale memory. This needs to be done before freeing derivations, - as ctype cleanup functions dereference steps arrays which we free below. */ - _nl_locale_subfreeres (); -+#endif - - /* finddomain.c has similar problem. */ - extern void _nl_finddomain_subfreeres (void) attribute_hidden; -Index: git/iconv/gconv_trans.c -=================================================================== ---- git.orig/iconv/gconv_trans.c -+++ git/iconv/gconv_trans.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include - #include "gconv_int.h" -@@ -38,15 +39,19 @@ __gconv_transliterate (struct __gconv_st - unsigned char **outbufstart, size_t *irreversible) - { - /* Find out about the locale's transliteration. */ -+#if __OPTION_EGLIBC_LOCALE_CODE - uint_fast32_t size; - const uint32_t *from_idx; - const uint32_t *from_tbl; - const uint32_t *to_idx; - const uint32_t *to_tbl; -+#endif - const uint32_t *winbuf; - const uint32_t *winbufend; -+#if __OPTION_EGLIBC_LOCALE_CODE - uint_fast32_t low; - uint_fast32_t high; -+#endif - - /* The input buffer. There are actually 4-byte values. */ - winbuf = (const uint32_t *) *inbufp; -@@ -58,6 +63,7 @@ __gconv_transliterate (struct __gconv_st - PTR_DEMANGLE (fct); - #endif - -+#if __OPTION_EGLIBC_LOCALE_CODE - /* If there is no transliteration information in the locale don't do - anything and return the error. */ - size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_TAB_SIZE); -@@ -193,6 +199,7 @@ __gconv_transliterate (struct __gconv_st - sorted. */ - break; - } -+#endif - - /* One last chance: use the default replacement. */ - if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN) != 0) -Index: git/iconv/iconv_prog.c -=================================================================== ---- git.orig/iconv/iconv_prog.c -+++ git/iconv/iconv_prog.c -@@ -35,6 +35,7 @@ - #ifdef _POSIX_MAPPED_FILES - # include - #endif -+#include - #include - #include - #include "iconv_prog.h" -@@ -221,10 +222,17 @@ main (int argc, char *argv[]) - bool to_wrong = - (iconv_open (to_code, "UTF-8") == (iconv_t) -1 - && errno == EINVAL); -+#if __OPTION_EGLIBC_LOCALE_CODE - const char *from_pretty = - (from_code[0] ? from_code : nl_langinfo (CODESET)); - const char *to_pretty = - (orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET)); -+#else -+ const char *from_pretty = -+ (from_code[0] ? from_code : "ANSI_X3.4-1968"); -+ const char *to_pretty = -+ (orig_to_code[0] ? orig_to_code : "ANSI_X3.4-1968"); -+#endif - - if (from_wrong) - { -Index: git/iconv/Makefile -=================================================================== ---- git.orig/iconv/Makefile -+++ git/iconv/Makefile -@@ -18,6 +18,8 @@ - # - # Makefile for iconv. - # -+include ../option-groups.mak -+ - subdir := iconv - - include ../Makeconfig -@@ -39,6 +41,11 @@ CFLAGS-iconv_charmap.c = -I../locale/pro - CFLAGS-dummy-repertoire.c = -I../locale/programs - CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \ - -DDEFAULT_CHARMAP=null_pointer -DNEED_NULL_POINTER -+ -+ifneq (y,$(OPTION_EGLIBC_SPAWN)) -+CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS -+endif -+ - CFLAGS-linereader.c = -DNO_TRANSLITERATION - CFLAGS-simple-hash.c = -I../locale - -Index: git/iconvdata/Makefile -=================================================================== ---- git.orig/iconvdata/Makefile -+++ git/iconvdata/Makefile -@@ -18,12 +18,15 @@ - # - # Makefile for iconv data and code. - # -+include ../option-groups.mak -+ - subdir := iconvdata - - include ../Makeconfig - - # Names of all the shared objects which implement the transformations. --modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ -+modules-$(OPTION_EGLIBC_CHARSETS) \ -+ := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ - ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10 \ - ISO8859-11 ISO8859-13 ISO8859-14 ISO8859-15 ISO8859-16 \ - T.61 ISO_6937 SJIS KOI-8 HP-ROMAN8 HP-ROMAN9 EBCDIC-AT-DE \ -@@ -63,11 +66,13 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 - MAC-CENTRALEUROPE KOI8-RU ISO8859-9E \ - CP770 CP771 CP772 CP773 CP774 - --modules.so := $(addsuffix .so, $(modules)) -+modules.so := $(addsuffix .so, $(modules-y)) - - ifeq (yes,$(build-shared)) - tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ -- tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 -+ tst-iconv6 bug-iconv5 bug-iconv8 bug-iconv9 -+tests-$(OPTION_EGLIBC_LOCALE_CODE) += bug-iconv6 tst-iconv7 -+ - ifeq ($(have-thread-library),yes) - tests += bug-iconv3 - endif -@@ -127,13 +132,13 @@ ifeq (yes,$(build-shared)) - # Rule to generate the shared objects. - charmaps = ../localedata/charmaps - -include $(objpfx)iconv-rules --extra-modules-left := $(modules) -+extra-modules-left := $(modules-y) - include extra-module.mk - - - extra-objs += $(modules.so) --install-others = $(addprefix $(inst_gconvdir)/, $(modules.so)) \ -- $(inst_gconvdir)/gconv-modules -+install-others-y += $(addprefix $(inst_gconvdir)/, $(modules.so)) -+install-others-$(OPTION_EGLIBC_CHARSETS) += $(inst_gconvdir)/gconv-modules - - # We can build the conversion tables for numerous charsets automatically. - -@@ -201,7 +206,7 @@ before-compile += $(addprefix $(objpfx), - ifndef avoid-generated - $(objpfx)iconv-rules: Makefile - $(make-target-directory) -- { echo $(filter-out lib%, $(modules)); \ -+ { echo $(filter-out lib%, $(modules-y)); \ - echo 8bit $(gen-8bit-modules); \ - echo 8bit-gap $(gen-8bit-gap-modules); } | \ - LC_ALL=C \ -@@ -245,7 +250,7 @@ $(addprefix $(inst_gconvdir)/, $(modules - $(do-install-program) - $(inst_gconvdir)/gconv-modules: gconv-modules $(+force) - $(do-install) --ifeq (no,$(cross-compiling)) -+# eglibc: ifeq (no,$(cross-compiling)) - # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary - # if this libc has more gconv modules than the previously installed one. - if test -f "$(inst_gconvdir)/gconv-modules.cache"; then \ -@@ -254,9 +259,9 @@ ifeq (no,$(cross-compiling)) - $(common-objpfx)iconv/iconvconfig \ - $(addprefix --prefix=,$(install_root)); \ - fi --else -- @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache' --endif -+# eglibc: else -+# eglibc: @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache' -+# eglibc: endif - - endif # build-shared = yes - -Index: git/include/netdb.h -=================================================================== ---- git.orig/include/netdb.h -+++ git/include/netdb.h -@@ -232,6 +232,10 @@ extern enum nss_status _nss_ ## service - (const char *name, int af, struct hostent *host, \ - char *buffer, size_t buflen, int *errnop, \ - int *h_errnop); \ -+extern enum nss_status _nss_ ## service ## _gethostbyname3_r \ -+ (const char *name, int af, struct hostent *result, \ -+ char *buffer, size_t buflen, int *errnop, \ -+ int *h_errnop, int32_t *ttlp, char **canonp); \ - extern enum nss_status _nss_ ## service ## _gethostbyname_r \ - (const char *name, struct hostent *host, char *buffer, \ - size_t buflen, int *errnop, int *h_errnop); \ -Index: git/inet/Makefile -=================================================================== ---- git.orig/inet/Makefile -+++ git/inet/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for inet portion of the library. - # -+include ../option-groups.mak -+ - subdir := inet - - include ../Makeconfig -@@ -27,7 +29,8 @@ headers := netinet/ether.h netinet/in.h - netinet/tcp.h netinet/ip.h $(wildcard arpa/*.h protocols/*.h) \ - aliases.h ifaddrs.h netinet/ip6.h netinet/icmp6.h bits/in.h - --routines := htonl htons \ -+routines-$(OPTION_EGLIBC_INET) \ -+ += htonl htons \ - inet_lnaof inet_mkadr \ - inet_netof inet_ntoa inet_net herrno herrno-loc \ - gethstbyad gethstbyad_r gethstbynm gethstbynm2 gethstbynm2_r \ -@@ -41,18 +44,23 @@ routines := htonl htons \ - getrpcent_r getrpcbyname_r getrpcbynumber_r \ - ether_aton ether_aton_r ether_hton ether_line \ - ether_ntoa ether_ntoa_r ether_ntoh \ -- rcmd rexec ruserpass \ - getnetgrent_r getnetgrent \ -- getaliasent_r getaliasent getaliasname getaliasname_r \ -- in6_addr getnameinfo if_index ifaddrs inet6_option \ -+ in6_addr getnameinfo if_index ifaddrs \ - getipv4sourcefilter setipv4sourcefilter \ -- getsourcefilter setsourcefilter inet6_opt inet6_rth -+ getsourcefilter setsourcefilter -+routines-$(OPTION_EGLIBC_RCMD) \ -+ += rcmd rexec ruserpass -+routines-$(OPTION_EGLIBC_DB_ALIASES) \ -+ += getaliasent_r getaliasent getaliasname getaliasname_r -+routines-$(OPTION_EGLIBC_ADVANCED_INET6) \ -+ += inet6_option inet6_opt inet6_rth - --aux := check_pf check_native ifreq -+aux-$(OPTION_EGLIBC_INET) += check_pf check_native ifreq - - tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ -- tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ -+ tst-gethnm test-ifaddrs bug-if1 tst-ether_line \ - tst-getni1 tst-getni2 tst-inet6_rth tst-checks -+tests-$(OPTION_EGLIBC_ADVANCED_INET6) += test-inet6_opt - - include ../Rules - -Index: git/intl/dcigettext.c -=================================================================== ---- git.orig/intl/dcigettext.c -+++ git/intl/dcigettext.c -@@ -100,11 +100,15 @@ extern int errno; - # include "libgnuintl.h" - #endif - #include "hash-string.h" -+#ifdef _LIBC -+# include -+#endif - - /* Handle multi-threaded applications. */ - #ifdef _LIBC - # include - # define gl_rwlock_define_initialized __libc_rwlock_define_initialized -+# define gl_rwlock_define __libc_rwlock_define - # define gl_rwlock_rdlock __libc_rwlock_rdlock - # define gl_rwlock_wrlock __libc_rwlock_wrlock - # define gl_rwlock_unlock __libc_rwlock_unlock -@@ -523,8 +527,10 @@ DCIGETTEXT (const char *domainname, cons - saved_errno = errno; - - #ifdef _LIBC -- __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) -- __libc_rwlock_rdlock (__libc_setlocale_lock); -+# if __OPTION_EGLIBC_LOCALE_CODE -+ gl_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) -+ gl_rwlock_rdlock (__libc_setlocale_lock); -+# endif - #endif - - gl_rwlock_rdlock (_nl_state_lock); -@@ -550,7 +556,11 @@ DCIGETTEXT (const char *domainname, cons - #ifdef HAVE_PER_THREAD_LOCALE - # ifndef IN_LIBGLOCALE - # ifdef _LIBC -- localename = strdupa (__current_locale_name (category)); -+# if __OPTION_EGLIBC_LOCALE_CODE -+ localename = strdupa (__current_locale_name (category)); -+# else -+ localename = "C"; -+# endif - # else - categoryname = category_to_name (category); - # define CATEGORYNAME_INITIALIZED -@@ -581,10 +591,12 @@ DCIGETTEXT (const char *domainname, cons - else - retval = (char *) (*foundp)->translation; - -- gl_rwlock_unlock (_nl_state_lock); - # ifdef _LIBC -- __libc_rwlock_unlock (__libc_setlocale_lock); -+# if __OPTION_EGLIBC_LOCALE_CODE -+ gl_rwlock_unlock (__libc_setlocale_lock); -+# endif - # endif -+ gl_rwlock_unlock (_nl_state_lock); - __set_errno (saved_errno); - return retval; - } -@@ -838,10 +850,13 @@ DCIGETTEXT (const char *domainname, cons - if (plural) - retval = plural_lookup (domain, n, retval, retlen); - -- gl_rwlock_unlock (_nl_state_lock); - #ifdef _LIBC -- __libc_rwlock_unlock (__libc_setlocale_lock); -+# if __OPTION_EGLIBC_LOCALE_CODE -+ -+ gl_rwlock_unlock (__libc_setlocale_lock); -+# endif - #endif -+ gl_rwlock_unlock (_nl_state_lock); - return retval; - } - } -@@ -850,10 +865,12 @@ DCIGETTEXT (const char *domainname, cons - return_untranslated: - /* Return the untranslated MSGID. */ - FREE_BLOCKS (block_list); -- gl_rwlock_unlock (_nl_state_lock); - #ifdef _LIBC -- __libc_rwlock_unlock (__libc_setlocale_lock); -+# if __OPTION_EGLIBC_LOCALE_CODE -+ gl_rwlock_unlock (__libc_setlocale_lock); -+# endif - #endif -+ gl_rwlock_unlock (_nl_state_lock); - #ifndef _LIBC - if (!ENABLE_SECURE) - { -@@ -1550,7 +1567,11 @@ guess_category_value (int category, cons - `LC_xxx', and `LANG'. On some systems this can be done by the - `setlocale' function itself. */ - # ifdef _LIBC -+# if __OPTION_EGLIBC_LOCALE_CODE - locale = __current_locale_name (category); -+# else -+ locale = "C"; -+# endif - # else - locale_defaulted = 0; - # if HAVE_USELOCALE -Index: git/intl/Makefile -=================================================================== ---- git.orig/intl/Makefile -+++ git/intl/Makefile -@@ -16,6 +16,7 @@ - # . - - # Makefile for intl subdirectory: message handling code from GNU gettext. -+include ../option-groups.mak - - subdir = intl - -@@ -48,7 +49,7 @@ endif - $(objpfx)plural.o: plural.c - - ifeq ($(run-built-tests),yes) --ifeq (yes,$(build-shared)) -+ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared)) - ifneq ($(strip $(MSGFMT)),:) - tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \ - $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \ -Index: git/io/Makefile -=================================================================== ---- git.orig/io/Makefile -+++ git/io/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for I/O portion of the library. - # -+include ../option-groups.mak -+ - subdir := io - - include ../Makeconfig -@@ -36,7 +38,7 @@ routines := \ - fxstatat fxstatat64 \ - statfs fstatfs statfs64 fstatfs64 \ - statvfs fstatvfs statvfs64 fstatvfs64 \ -- umask chmod fchmod lchmod fchmodat \ -+ umask chmod fchmod fchmodat \ - mkdir mkdirat \ - open open_2 open64 open64_2 openat openat_2 openat64 openat64_2 \ - read write lseek lseek64 access euidaccess faccessat \ -@@ -49,11 +51,13 @@ routines := \ - ttyname ttyname_r isatty \ - link linkat symlink symlinkat readlink readlinkat \ - unlink unlinkat rmdir \ -- ftw ftw64 fts poll ppoll \ -+ poll ppoll \ - posix_fadvise posix_fadvise64 \ - posix_fallocate posix_fallocate64 \ - sendfile sendfile64 \ - utimensat futimens -+routines-$(OPTION_EGLIBC_BSD) += lchmod -+routines-$(OPTION_EGLIBC_FTRAVERSE) += ftw ftw64 fts - - aux := have_o_cloexec - -@@ -64,18 +68,22 @@ static-only-routines = stat fstat lstat - fstatat fstatat64 mknod mknodat - - others := pwd --test-srcs := ftwtest -+test-srcs-$(OPTION_EGLIBC_FTRAVERSE) := ftwtest - tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ -- tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \ -+ tst-fcntl tst-statvfs \ - tst-openat tst-unlinkat tst-fstatat tst-futimesat \ - tst-renameat tst-fchownat tst-fchmodat tst-faccessat \ - tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \ -- tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \ -+ tst-mknodat tst-mkfifoat tst-ttyname_r \ - tst-posix_fallocate -+tests-$(OPTION_EGLIBC_FTRAVERSE) += bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 \ -+ bug-ftw5 - - ifeq ($(run-built-tests),yes) -+ifeq (y,$(OPTION_EGLIBC_FTRAVERSE)) - tests-special += $(objpfx)ftwtest.out - endif -+endif - - include ../Rules - -Index: git/libidn/Makefile -=================================================================== ---- git.orig/libidn/Makefile -+++ git/libidn/Makefile -@@ -16,6 +16,7 @@ - # . - - # Makefile for libidn subdirectory of GNU C Library. -+include ../option-groups.mak - - subdir := libidn - -@@ -23,8 +24,8 @@ include ../Makeconfig - - routines = idn-stub - --extra-libs = libcidn --extra-libs-others = $(extra-libs) -+extra-libs-$(OPTION_EGLIBC_IDN) = libcidn -+extra-libs-others-y = $(extra-libs-y) - - libcidn-routines := punycode toutf8 nfkc stringprep rfc3454 profiles idna \ - iconvme -Index: git/libidn/toutf8.c -=================================================================== ---- git.orig/libidn/toutf8.c -+++ git/libidn/toutf8.c -@@ -33,6 +33,11 @@ - /* Get strlen. */ - #include - -+/* Get __OPTION_EGLIBC_LOCALE_CODE. */ -+#ifdef _LIBC -+# include -+#endif -+ - /* Get iconv_string. */ - #include "iconvme.h" - -@@ -47,7 +52,11 @@ - #endif - - #ifdef _LIBC --# define stringprep_locale_charset() nl_langinfo (CODESET) -+# if __OPTION_EGLIBC_LOCALE_CODE -+# define stringprep_locale_charset() nl_langinfo (CODESET) -+# else -+# define stringprep_locale_charset() "ANSI_X3.4-1968" -+# endif - #else - /** - * stringprep_locale_charset - return charset used in current locale -Index: git/libio/fileops.c -=================================================================== ---- git.orig/libio/fileops.c -+++ git/libio/fileops.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - #include - #if _LIBC - # include "../wcsmbs/wcsmbsload.h" -@@ -172,7 +173,7 @@ _IO_new_file_close_it (_IO_FILE *fp) - - /* Free buffer. */ - #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T -- if (fp->_mode > 0) -+ if (_IO_is_wide (fp)) - { - if (_IO_have_wbackup (fp)) - _IO_free_wbackup_area (fp); -@@ -347,6 +348,7 @@ _IO_new_file_fopen (_IO_FILE *fp, const - cs = strstr (last_recognized + 1, ",ccs="); - if (cs != NULL) - { -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - /* Yep. Load the appropriate conversions and set the orientation - to wide. */ - struct gconv_fcts fcts; -@@ -406,6 +408,12 @@ _IO_new_file_fopen (_IO_FILE *fp, const - - /* Set the mode now. */ - result->_mode = 1; -+#else -+ /* Treat this as if we couldn't find the given character set. */ -+ (void) _IO_file_close_it (fp); -+ __set_errno (EINVAL); -+ return NULL; -+#endif - } - } - -Index: git/libio/__fpurge.c -=================================================================== ---- git.orig/libio/__fpurge.c -+++ git/libio/__fpurge.c -@@ -21,7 +21,7 @@ - void - __fpurge (FILE *fp) - { -- if (fp->_mode > 0) -+ if (_IO_is_wide (fp)) - { - /* Wide-char stream. */ - if (_IO_in_backup (fp)) -Index: git/libio/iofwide.c -=================================================================== ---- git.orig/libio/iofwide.c -+++ git/libio/iofwide.c -@@ -26,6 +26,7 @@ - - #include - #ifdef _LIBC -+# include - # include - # include - #endif -@@ -43,6 +44,8 @@ - #endif - - -+#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR -+ - /* Prototypes of libio's codecvt functions. */ - static enum __codecvt_result do_out (struct _IO_codecvt *codecvt, - __mbstate_t *statep, -@@ -499,3 +502,26 @@ do_max_length (struct _IO_codecvt *codec - return MB_CUR_MAX; - #endif - } -+ -+#else -+/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled. */ -+ -+#undef _IO_fwide -+int -+_IO_fwide (fp, mode) -+ _IO_FILE *fp; -+ int mode; -+{ -+ /* Die helpfully if the user tries to create a wide stream; I -+ disbelieve that most users check the return value from -+ 'fwide (fp, 1)'. */ -+ assert (mode <= 0); -+ -+ /* We can only make streams byte-oriented, which is trivial. */ -+ if (mode < 0) -+ fp->_mode = -1; -+ -+ return fp->_mode; -+} -+ -+#endif -Index: git/libio/ioseekoff.c -=================================================================== ---- git.orig/libio/ioseekoff.c -+++ git/libio/ioseekoff.c -@@ -60,7 +60,7 @@ _IO_seekoff_unlocked (fp, offset, dir, m - else - abort (); - } -- if (_IO_fwide (fp, 0) < 0) -+ if (! _IO_is_wide (fp)) - _IO_free_backup_area (fp); - else - _IO_free_wbackup_area (fp); -Index: git/libio/ioseekpos.c -=================================================================== ---- git.orig/libio/ioseekpos.c -+++ git/libio/ioseekpos.c -@@ -35,7 +35,7 @@ _IO_seekpos_unlocked (fp, pos, mode) - /* If we have a backup buffer, get rid of it, since the __seekoff - callback may not know to do the right thing about it. - This may be over-kill, but it'll do for now. TODO */ -- if (_IO_fwide (fp, 0) <= 0) -+ if (! _IO_is_wide (fp)) - { - if (_IO_have_backup (fp)) - _IO_free_backup_area (fp); -Index: git/libio/iosetbuffer.c -=================================================================== ---- git.orig/libio/iosetbuffer.c -+++ git/libio/iosetbuffer.c -@@ -24,6 +24,8 @@ - This exception applies to code released by its copyright holders - in files containing the exception. */ - -+#include -+ - #include "libioP.h" - - void -@@ -38,9 +40,11 @@ _IO_setbuffer (fp, buf, size) - if (!buf) - size = 0; - (void) _IO_SETBUF (fp, buf, size); -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp)) - /* We also have to set the buffer using the wide char function. */ - (void) _IO_WSETBUF (fp, buf, size); -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - _IO_release_lock (fp); - } - libc_hidden_def (_IO_setbuffer) -Index: git/libio/libioP.h -=================================================================== ---- git.orig/libio/libioP.h -+++ git/libio/libioP.h -@@ -42,6 +42,10 @@ - /*# include */ - #endif - -+#if defined _LIBC -+# include -+#endif -+ - #include - - #include "iolibio.h" -@@ -508,8 +512,20 @@ extern void _IO_old_init (_IO_FILE *fp, - - - #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T -+ -+/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0', -+ except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it -+ expands to a constant, allowing the compiler to realize that it can -+ eliminate code that references wide stream handling functions. -+ This, in turn, allows us to omit them. */ -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR -+# define _IO_is_wide(_f) ((_f)->_mode > 0) -+#else -+# define _IO_is_wide(_f) (0) -+#endif -+ - # define _IO_do_flush(_f) \ -- ((_f)->_mode <= 0 \ -+ (! _IO_is_wide (_f) \ - ? _IO_do_write(_f, (_f)->_IO_write_base, \ - (_f)->_IO_write_ptr-(_f)->_IO_write_base) \ - : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base, \ -Index: git/libio/Makefile -=================================================================== ---- git.orig/libio/Makefile -+++ git/libio/Makefile -@@ -18,6 +18,8 @@ - # - # Specific makefile for libio. - # -+include ../option-groups.mak -+ - subdir := libio - - include ../Makeconfig -@@ -27,16 +29,13 @@ headers := stdio.h libio.h _G_config.h b - - routines := \ - filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ -- iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc \ -+ iofopncook iofputs iofread iofsetpos ioftell \ - iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs \ - ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc \ - iovsprintf iovsscanf \ - iofgetpos64 iofopen64 iofsetpos64 \ -- fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ -- iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u \ -- putwchar putwchar_u putchar putchar_u fwprintf swprintf vwprintf \ -- wprintf wscanf fwscanf vwscanf vswprintf iovswscanf swscanf wgenops \ -- wstrops wfileops iofwide fwide wmemstream \ -+ putchar putchar_u \ -+ iofwide \ - \ - clearerr feof ferror fileno fputc freopen fseek getc getchar \ - memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \ -@@ -48,24 +47,49 @@ routines := \ - \ - libc_fatal fmemopen - --tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ -- tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \ -- tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf \ -- tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof \ -- tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \ -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \ -+ wfiledoalloc \ -+ iowpadn \ -+ swprintf \ -+ vswprintf iovswscanf swscanf wgenops \ -+ wstrops wfileops wmemstream -+routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += \ -+ wdummyfileops -+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += \ -+ fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ -+ iofputws iofputws_u iogetwline ioungetwc putwc putwc_u \ -+ putwchar putwchar_u fwprintf vwprintf \ -+ wprintf wscanf fwscanf vwscanf \ -+ fwide -+ -+tests = test-fmemopen tst-ext tst-ext2 \ -+ tst-mmap-setvbuf tst-atime tst-eof \ -+ tst-freopen bug-ungetc bug-fseek \ - tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \ -- tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \ -- bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \ -+ tst-mmap2-eofsync tst-mmap-offend bug-fopena+ \ -+ bug-ungetc2 bug-ungetc3 bug-ungetc4 \ - tst-memstream1 tst-memstream2 \ -- tst-wmemstream1 tst-wmemstream2 \ -- bug-memstream1 bug-wmemstream1 \ -- tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ -- tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ -- tst-ftell-append tst-fputws -+ bug-memstream1 tst-popen1 tst-fwrite-error \ -+ tst-ftell-active-handler tst-ftell-append -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-swscanf tst-fgetws tst-setvbuf1 \ -+ tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2 \ -+ tst-widetext tst-fputws -+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ -+ += bug-rewind bug-rewind2 bug-ungetwc1 \ -+ bug-wfflush bug-wmemstream1 tst-fopenloc2 \ -+ tst_getwc \ -+ tst_putwc tst_wprintf tst_wprintf2 tst_wscanf \ -+ tst-fgetwc bug-wsetpos tst-fseek tst-ftell-partial-wide -+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += tst_swprintf tst_swscanf \ -+ tst-sscanf \ -+ tst-wmemstream1 tst-wmemstream2 -+ - ifeq (yes,$(build-shared)) - # Add test-fopenloc only if shared library is enabled since it depends on - # shared localedata objects. --tests += tst-fopenloc -+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-fopenloc - endif - test-srcs = test-freopen - -@@ -164,13 +188,17 @@ shared-only-routines = oldiofopen oldiof - oldiofsetpos64 - - ifeq ($(run-built-tests),yes) -+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)) - tests-special += $(objpfx)test-freopen.out -+endif -+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) - ifeq (yes,$(build-shared)) - # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared - # library is enabled since they depend on tst-fopenloc.out. - tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out - endif - endif -+endif - - include ../Rules - -Index: git/libio/wdummyfileops.c -=================================================================== ---- /dev/null -+++ git/libio/wdummyfileops.c -@@ -0,0 +1,161 @@ -+/* Copyright (C) 2007 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. -+ -+ As a special exception, if you link the code in this file with -+ files compiled with a GNU compiler to produce an executable, -+ that does not cause the resulting executable to be covered by -+ the GNU Lesser General Public License. This exception does not -+ however invalidate any other reasons why the executable file -+ might be covered by the GNU Lesser General Public License. -+ This exception applies to code released by its copyright holders -+ in files containing the exception. */ -+ -+#include -+#include -+#include -+#include -+ -+static void __THROW __attribute__ ((__noreturn__)) -+_IO_wfile_wide_char_support_disabled (void) -+{ -+ static const char errstr[] -+ = ("The application tried to use wide character I/O, but libc.so" -+ " was compiled\n" -+ "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n"); -+ __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); -+ abort (); -+} -+ -+static void -+_IO_wfile_disabled_void_int (_IO_FILE *fp, int x) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static int -+_IO_wfile_disabled_int_int (_IO_FILE *fp, int x) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static int -+_IO_wfile_disabled_int_none (_IO_FILE *fp) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_size_t -+_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_size_t -+_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_off64_t -+_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_off64_t -+_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_FILE * -+_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_ssize_t -+_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_ssize_t -+_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static _IO_off64_t -+_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static int -+_IO_wfile_disabled_close (_IO_FILE *fp) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static int -+_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static int -+_IO_wfile_disabled_showmanyc (_IO_FILE *fp) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static void -+_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale) -+{ -+ _IO_wfile_wide_char_support_disabled (); -+} -+ -+static const struct _IO_jump_t _IO_wfile_jumps_disabled = -+{ -+ JUMP_INIT_DUMMY, -+ JUMP_INIT(finish, _IO_wfile_disabled_void_int), -+ JUMP_INIT(overflow, _IO_wfile_disabled_int_int), -+ JUMP_INIT(underflow, _IO_wfile_disabled_int_none), -+ JUMP_INIT(uflow, _IO_wfile_disabled_int_none), -+ JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int), -+ JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn), -+ JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn), -+ JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff), -+ JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos), -+ JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf), -+ JUMP_INIT(sync, _IO_wfile_disabled_int_none), -+ JUMP_INIT(doallocate, _IO_wfile_disabled_int_none), -+ JUMP_INIT(read, _IO_wfile_disabled_read), -+ JUMP_INIT(write, _IO_wfile_disabled_write), -+ JUMP_INIT(seek, _IO_wfile_disabled_seek), -+ JUMP_INIT(close, _IO_wfile_disabled_close), -+ JUMP_INIT(stat, _IO_wfile_disabled_stat), -+ JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc), -+ JUMP_INIT(imbue, _IO_wfile_disabled_imbue) -+}; -+ -+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps) -+libc_hidden_data_def (_IO_wfile_jumps) -+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap) -+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap) -Index: git/locale/catnames.c -=================================================================== ---- /dev/null -+++ git/locale/catnames.c -@@ -0,0 +1,48 @@ -+/* Copyright (C) 2006 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include "localeinfo.h" -+ -+/* Define an array of category names (also the environment variable names). */ -+const union catnamestr_t _nl_category_names attribute_hidden = -+ { -+ { -+#define DEFINE_CATEGORY(category, category_name, items, a) \ -+ category_name, -+#include "categories.def" -+#undef DEFINE_CATEGORY -+ } -+ }; -+ -+const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = -+ { -+#define DEFINE_CATEGORY(category, category_name, items, a) \ -+ [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), -+#include "categories.def" -+#undef DEFINE_CATEGORY -+ }; -+ -+/* An array of their lengths, for convenience. */ -+const uint8_t _nl_category_name_sizes[] attribute_hidden = -+ { -+#define DEFINE_CATEGORY(category, category_name, items, a) \ -+ [category] = sizeof (category_name) - 1, -+#include "categories.def" -+#undef DEFINE_CATEGORY -+ [LC_ALL] = sizeof ("LC_ALL") - 1 -+ }; -Index: git/locale/C-ctype.c -=================================================================== ---- git.orig/locale/C-ctype.c -+++ git/locale/C-ctype.c -@@ -19,8 +19,11 @@ - #include "localeinfo.h" - #include - #include -+#include - -+#if __OPTION_EGLIBC_LOCALE_CODE - #include "C-translit.h" -+#endif - - /* This table's entries are taken from POSIX.2 Table 2-6 - ``LC_CTYPE Category Definition in the POSIX Locale''. -@@ -647,6 +650,7 @@ const struct __locale_data _nl_C_LC_CTYP - { .word = L'7' }, - { .word = L'8' }, - { .word = L'9' }, -+#if __OPTION_EGLIBC_LOCALE_CODE - /* _NL_CTYPE_TRANSLIT_TAB_SIZE */ - { .word = NTRANSLIT }, - /* _NL_CTYPE_TRANSLIT_FROM_IDX */ -@@ -657,6 +661,22 @@ const struct __locale_data _nl_C_LC_CTYP - { .wstr = translit_to_idx }, - /* _NL_CTYPE_TRANSLIT_TO_TBL */ - { .wstr = (uint32_t *) translit_to_tbl }, -+#else -+ /* If the locale code isn't enabled, we don't have the -+ transliteration code in iconv/gconv_trans.c anyway, so there's -+ no need for the transliteration tables here. We'll fall back -+ on the default missing replacement, '?'. */ -+ /* _NL_CTYPE_TRANSLIT_TAB_SIZE */ -+ { .word = 0 }, -+ /* _NL_CTYPE_TRANSLIT_FROM_IDX */ -+ { .wstr = NULL }, -+ /* _NL_CTYPE_TRANSLIT_FROM_TBL */ -+ { .wstr = NULL }, -+ /* _NL_CTYPE_TRANSLIT_TO_IDX */ -+ { .wstr = NULL }, -+ /* _NL_CTYPE_TRANSLIT_TO_TBL */ -+ { .wstr = NULL }, -+#endif - /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN */ - { .word = 1 }, - /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING */ -Index: git/locale/dummy-setlocale.c -=================================================================== ---- /dev/null -+++ git/locale/dummy-setlocale.c -@@ -0,0 +1,33 @@ -+/* Copyright (C) 2006 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+ -+char * -+setlocale (int category, const char *locale) -+{ -+ if (! locale -+ || locale[0] == '\0' -+ || strcmp (locale, "C") == 0 -+ || strcmp (locale, "POSIX") == 0) -+ return (char *) "C"; -+ else -+ return NULL; -+} -+libc_hidden_def (setlocale) -Index: git/locale/localeinfo.h -=================================================================== ---- git.orig/locale/localeinfo.h -+++ git/locale/localeinfo.h -@@ -224,7 +224,7 @@ __libc_tsd_define (extern, __locale_t, L - unused. We can manage this playing some tricks with weak references. - But with thread-local locale settings, it becomes quite ungainly unless - we can use __thread variables. So only in that case do we attempt this. */ --#ifndef SHARED -+#if !defined SHARED && !defined IN_GLIBC_LOCALEDEF - # include - # define NL_CURRENT_INDIRECT 1 - #endif -Index: git/locale/Makefile -=================================================================== ---- git.orig/locale/Makefile -+++ git/locale/Makefile -@@ -18,27 +18,43 @@ - # - # Makefile for locales. - # -+include ../option-groups.mak -+ - subdir := locale - - include ../Makeconfig - - headers = locale.h bits/locale.h langinfo.h xlocale.h --routines = setlocale findlocale loadlocale loadarchive \ -- localeconv nl_langinfo nl_langinfo_l mb_cur_max \ -- newlocale duplocale freelocale uselocale --tests = tst-C-locale tst-locname tst-duplocale -+# catnames is needed by OPTION_EGLIBC_LOCALE_CODE and by the 'intl' code. -+# If we put the latter in an option group, too, we can omit catnames -+# when both option groups are disabled. libstdc++-v3 needs mb_cur_max. -+routines-y := catnames mb_cur_max -+routines-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += setlocale findlocale loadlocale loadarchive \ -+ localeconv nl_langinfo nl_langinfo_l \ -+ newlocale duplocale freelocale uselocale -+ifneq (y,$(OPTION_EGLIBC_LOCALE_CODE)) -+routines-y += dummy-setlocale -+endif -+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-C-locale tst-locname tst-duplocale - categories = ctype messages monetary numeric time paper name \ - address telephone measurement identification collate --aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ -- xlocale localename global-locale coll-lookup --others = localedef locale -+# C-messages belongs in an intl option group. -+aux-y := C-ctype C-time \ -+ SYS_libc C_name xlocale global-locale coll-lookup -+aux-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += $(filter-out $(aux-y), \ -+ $(categories:%=lc-%) $(categories:%=C-%)) \ -+ localename -+others-$(OPTION_EGLIBC_LOCALE_CODE) = localedef locale - #others-static = localedef locale --install-bin = localedef locale --extra-objs = $(localedef-modules:=.o) $(localedef-aux:=.o) \ -+install-bin = $(others-y) -+extra-objs-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ = $(localedef-modules:=.o) $(localedef-aux:=.o) \ - $(locale-modules:=.o) $(lib-modules:=.o) - --extra-libs = libBrokenLocale --extra-libs-others = $(extra-libs) -+extra-libs-$(OPTION_EGLIBC_LOCALE_CODE) = libBrokenLocale -+extra-libs-others = $(extra-libs-y) - - libBrokenLocale-routines = broken_cur_max - -@@ -93,6 +109,9 @@ CPPFLAGS-locale-programs = -DLOCALE_PATH - CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts - CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts - CFLAGS-charmap-dir.c = -Wno-write-strings -+ifneq (y,$(OPTION_EGLIBC_SPAWN)) -+CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS -+endif - - # Set libof-* for each routine. - cpp-srcs-left := $(localedef-modules) $(localedef-aux) $(locale-modules) \ -Index: git/locale/programs/charmap-dir.c -=================================================================== ---- git.orig/locale/programs/charmap-dir.c -+++ git/locale/programs/charmap-dir.c -@@ -19,7 +19,9 @@ - #include - #include - #include -+#ifndef NO_UNCOMPRESS - #include -+#endif - #include - #include - #include -@@ -156,6 +158,7 @@ charmap_closedir (CHARMAP_DIR *cdir) - return closedir (dir); - } - -+#ifndef NO_UNCOMPRESS - /* Creates a subprocess decompressing the given pathname, and returns - a stream reading its output (the decompressed data). */ - static -@@ -204,6 +207,7 @@ fopen_uncompressed (const char *pathname - } - return NULL; - } -+#endif - - /* Opens a charmap for reading, given its name (not an alias name). */ - FILE * -@@ -226,6 +230,7 @@ charmap_open (const char *directory, con - if (stream != NULL) - return stream; - -+#ifndef NO_UNCOMPRESS - memcpy (p, ".gz", 4); - stream = fopen_uncompressed (pathname, "gzip"); - if (stream != NULL) -@@ -235,6 +240,7 @@ charmap_open (const char *directory, con - stream = fopen_uncompressed (pathname, "bzip2"); - if (stream != NULL) - return stream; -+#endif - - return NULL; - } -Index: git/locale/programs/ld-collate.c -=================================================================== ---- git.orig/locale/programs/ld-collate.c -+++ git/locale/programs/ld-collate.c -@@ -350,7 +350,7 @@ new_element (struct locale_collate_t *co - } - if (wcs != NULL) - { -- size_t nwcs = wcslen ((wchar_t *) wcs); -+ size_t nwcs = wcslen_uint32 (wcs); - uint32_t zero = 0; - /* Handle as a single character. */ - if (nwcs == 0) -@@ -1776,8 +1776,7 @@ symbol `%s' has the same encoding as"), - - if ((*eptr)->nwcs == runp->nwcs) - { -- int c = wmemcmp ((wchar_t *) (*eptr)->wcs, -- (wchar_t *) runp->wcs, runp->nwcs); -+ int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs); - - if (c == 0) - { -@@ -2010,9 +2009,9 @@ add_to_tablewc (uint32_t ch, struct elem - one consecutive entry. */ - if (runp->wcnext != NULL - && runp->nwcs == runp->wcnext->nwcs -- && wmemcmp ((wchar_t *) runp->wcs, -- (wchar_t *)runp->wcnext->wcs, -- runp->nwcs - 1) == 0 -+ && wmemcmp_uint32 (runp->wcs, -+ runp->wcnext->wcs, -+ runp->nwcs - 1) == 0 - && (runp->wcs[runp->nwcs - 1] - == runp->wcnext->wcs[runp->nwcs - 1] + 1)) - { -@@ -2036,9 +2035,9 @@ add_to_tablewc (uint32_t ch, struct elem - runp = runp->wcnext; - while (runp->wcnext != NULL - && runp->nwcs == runp->wcnext->nwcs -- && wmemcmp ((wchar_t *) runp->wcs, -- (wchar_t *)runp->wcnext->wcs, -- runp->nwcs - 1) == 0 -+ && wmemcmp_uint32 (runp->wcs, -+ runp->wcnext->wcs, -+ runp->nwcs - 1) == 0 - && (runp->wcs[runp->nwcs - 1] - == runp->wcnext->wcs[runp->nwcs - 1] + 1)); - -Index: git/locale/programs/ld-ctype.c -=================================================================== ---- git.orig/locale/programs/ld-ctype.c -+++ git/locale/programs/ld-ctype.c -@@ -960,7 +960,7 @@ ctype_output (struct localedef_t *locale - allocate_arrays (ctype, charmap, ctype->repertoire); - - default_missing_len = (ctype->default_missing -- ? wcslen ((wchar_t *) ctype->default_missing) -+ ? wcslen_uint32 (ctype->default_missing) - : 0); - - init_locale_data (&file, nelems); -@@ -1971,7 +1971,7 @@ read_translit_entry (struct linereader * - ignore = 1; - else - /* This value is usable. */ -- obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4); -+ obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4); - - first = 0; - } -@@ -2519,8 +2519,8 @@ with character code range values one mus - } - - handle_tok_digit: -- class_bit = _ISwdigit; -- class256_bit = _ISdigit; -+ class_bit = BITw (tok_digit); -+ class256_bit = BIT (tok_digit); - handle_digits = 1; - goto read_charclass; - -@@ -4002,8 +4002,7 @@ allocate_arrays (struct locale_ctype_t * - - while (idx < number) - { -- int res = wcscmp ((const wchar_t *) sorted[idx]->from, -- (const wchar_t *) runp->from); -+ int res = wcscmp_uint32 (sorted[idx]->from, runp->from); - if (res == 0) - { - replace = 1; -@@ -4040,11 +4039,11 @@ allocate_arrays (struct locale_ctype_t * - for (size_t cnt = 0; cnt < number; ++cnt) - { - struct translit_to_t *srunp; -- from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1; -+ from_len += wcslen_uint32 (sorted[cnt]->from) + 1; - srunp = sorted[cnt]->to; - while (srunp != NULL) - { -- to_len += wcslen ((const wchar_t *) srunp->str) + 1; -+ to_len += wcslen_uint32 (srunp->str) + 1; - srunp = srunp->next; - } - /* Plus one for the extra NUL character marking the end of -@@ -4068,18 +4067,18 @@ allocate_arrays (struct locale_ctype_t * - ctype->translit_from_idx[cnt] = from_len; - ctype->translit_to_idx[cnt] = to_len; - -- len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1; -- wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len], -- (const wchar_t *) sorted[cnt]->from, len); -+ len = wcslen_uint32 (sorted[cnt]->from) + 1; -+ wmemcpy_uint32 (&ctype->translit_from_tbl[from_len], -+ sorted[cnt]->from, len); - from_len += len; - - ctype->translit_to_idx[cnt] = to_len; - srunp = sorted[cnt]->to; - while (srunp != NULL) - { -- len = wcslen ((const wchar_t *) srunp->str) + 1; -- wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len], -- (const wchar_t *) srunp->str, len); -+ len = wcslen_uint32 (srunp->str) + 1; -+ wmemcpy_uint32 (&ctype->translit_to_tbl[to_len], -+ srunp->str, len); - to_len += len; - srunp = srunp->next; - } -Index: git/locale/programs/ld-messages.c -=================================================================== ---- git.orig/locale/programs/ld-messages.c -+++ git/locale/programs/ld-messages.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include - -@@ -124,6 +125,7 @@ No definition for %s category found"), " - } - else - { -+#if __OPTION_POSIX_REGEXP - int result; - regex_t re; - -@@ -140,6 +142,7 @@ No definition for %s category found"), " - } - else if (result != 0) - regfree (&re); -+#endif - } - - if (messages->noexpr == NULL) -@@ -158,6 +161,7 @@ No definition for %s category found"), " - } - else - { -+#if __OPTION_POSIX_REGEXP - int result; - regex_t re; - -@@ -174,6 +178,7 @@ No definition for %s category found"), " - } - else if (result != 0) - regfree (&re); -+#endif - } - } - -Index: git/locale/programs/ld-time.c -=================================================================== ---- git.orig/locale/programs/ld-time.c -+++ git/locale/programs/ld-time.c -@@ -215,8 +215,10 @@ No definition for %s category found"), " - } - else - { -+ static const uint32_t wt_fmt_ampm[] -+ = { '%','I',':','%','M',':','%','S',' ','%','p',0 }; - time->t_fmt_ampm = "%I:%M:%S %p"; -- time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p"; -+ time->wt_fmt_ampm = wt_fmt_ampm; - } - } - -@@ -226,7 +228,7 @@ No definition for %s category found"), " - const int days_per_month[12] = { 31, 29, 31, 30, 31, 30, - 31, 31, 30, 31 ,30, 31 }; - size_t idx; -- wchar_t *wstr; -+ uint32_t *wstr; - - time->era_entries = - (struct era_data *) xmalloc (time->num_era -@@ -464,18 +466,18 @@ No definition for %s category found"), " - } - - /* Now generate the wide character name and format. */ -- wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */ -- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end offset */ -- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end start */ -- wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end end */ -+ wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */ -+ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */ -+ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */ -+ wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */ - if (wstr != NULL) - { -- time->era_entries[idx].wname = (uint32_t *) wstr + 1; -- wstr = wcschr (wstr + 1, L':'); /* end name */ -+ time->era_entries[idx].wname = wstr + 1; -+ wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */ - if (wstr != NULL) - { - *wstr = L'\0'; -- time->era_entries[idx].wformat = (uint32_t *) wstr + 1; -+ time->era_entries[idx].wformat = wstr + 1; - } - else - time->era_entries[idx].wname = -@@ -530,7 +532,16 @@ No definition for %s category found"), " - if (time->date_fmt == NULL) - time->date_fmt = "%a %b %e %H:%M:%S %Z %Y"; - if (time->wdate_fmt == NULL) -- time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y"; -+ { -+ static const uint32_t wdate_fmt[] = -+ { '%','a',' ', -+ '%','b',' ', -+ '%','e',' ', -+ '%','H',':','%','M',':','%','S',' ', -+ '%','Z',' ', -+ '%','Y',0 }; -+ time->wdate_fmt = wdate_fmt; -+ } - } - - -Index: git/locale/programs/linereader.c -=================================================================== ---- git.orig/locale/programs/linereader.c -+++ git/locale/programs/linereader.c -@@ -595,7 +595,7 @@ get_string (struct linereader *lr, const - { - int return_widestr = lr->return_widestr; - char *buf; -- wchar_t *buf2 = NULL; -+ uint32_t *buf2 = NULL; - size_t bufact; - size_t bufmax = 56; - -Index: git/locale/programs/localedef.c -=================================================================== ---- git.orig/locale/programs/localedef.c -+++ git/locale/programs/localedef.c -@@ -114,6 +114,7 @@ void (*argp_program_version_hook) (FILE - #define OPT_LIST_ARCHIVE 309 - #define OPT_LITTLE_ENDIAN 400 - #define OPT_BIG_ENDIAN 401 -+#define OPT_UINT32_ALIGN 402 - - /* Definitions of arguments for argp functions. */ - static const struct argp_option options[] = -@@ -150,6 +151,8 @@ static const struct argp_option options[ - N_("Generate little-endian output") }, - { "big-endian", OPT_BIG_ENDIAN, NULL, 0, - N_("Generate big-endian output") }, -+ { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0, -+ N_("Set the target's uint32_t alignment in bytes (default 4)") }, - { NULL, 0, NULL, 0, NULL } - }; - -@@ -239,12 +242,14 @@ main (int argc, char *argv[]) - ctype locale. (P1003.2 4.35.5.2) */ - setlocale (LC_CTYPE, "POSIX"); - -+#ifndef NO_SYSCONF - /* Look whether the system really allows locale definitions. POSIX - defines error code 3 for this situation so I think it must be - a fatal error (see P1003.2 4.35.8). */ - if (sysconf (_SC_2_LOCALEDEF) < 0) - WITH_CUR_LOCALE (error (3, 0, _("\ - FATAL: system does not define `_POSIX2_LOCALEDEF'"))); -+#endif - - /* Process charmap file. */ - charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1); -@@ -338,6 +343,9 @@ parse_opt (int key, char *arg, struct ar - case OPT_BIG_ENDIAN: - set_big_endian (true); - break; -+ case OPT_UINT32_ALIGN: -+ uint32_align_mask = strtol (arg, NULL, 0) - 1; -+ break; - case 'c': - force_output = 1; - break; -Index: git/locale/programs/locfile.c -=================================================================== ---- git.orig/locale/programs/locfile.c -+++ git/locale/programs/locfile.c -@@ -544,6 +544,9 @@ compare_files (const char *filename1, co - machine running localedef. */ - bool swap_endianness_p; - -+/* The target's value of __align__(uint32_t) - 1. */ -+unsigned int uint32_align_mask = 3; -+ - /* When called outside a start_locale_structure/end_locale_structure - or start_locale_prelude/end_locale_prelude block, record that the - next byte in FILE's obstack will be the first byte of a new element. -@@ -621,7 +624,7 @@ add_locale_string (struct locale_file *f - void - add_locale_wstring (struct locale_file *file, const uint32_t *string) - { -- add_locale_uint32_array (file, string, wcslen ((const wchar_t *) string) + 1); -+ add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1); - } - - /* Record that FILE's next element is the 32-bit integer VALUE. */ -Index: git/locale/programs/locfile.h -=================================================================== ---- git.orig/locale/programs/locfile.h -+++ git/locale/programs/locfile.h -@@ -71,6 +71,8 @@ extern void write_all_categories (struct - - extern bool swap_endianness_p; - -+extern unsigned int uint32_align_mask; -+ - /* Change the output to be big-endian if BIG_ENDIAN is true and - little-endian otherwise. */ - static inline void -@@ -89,7 +91,8 @@ maybe_swap_uint32 (uint32_t value) - } - - /* Likewise, but munge an array of N uint32_ts starting at ARRAY. */ --static inline void -+static void -+__attribute__ ((unused)) - maybe_swap_uint32_array (uint32_t *array, size_t n) - { - if (swap_endianness_p) -@@ -99,7 +102,8 @@ maybe_swap_uint32_array (uint32_t *array - - /* Like maybe_swap_uint32_array, but the array of N elements is at - the end of OBSTACK's current object. */ --static inline void -+static void -+__attribute__ ((unused)) - maybe_swap_uint32_obstack (struct obstack *obstack, size_t n) - { - maybe_swap_uint32_array ((uint32_t *) obstack_next_free (obstack) - n, n); -@@ -276,4 +280,55 @@ extern void identification_output (struc - const struct charmap_t *charmap, - const char *output_path); - -+static size_t wcslen_uint32 (const uint32_t *str) __attribute__ ((unused)); -+static uint32_t * wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused)); -+static uint32_t * wcschr_uint32 (const uint32_t *s, uint32_t ch) __attribute__ ((unused)); -+static int wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) __attribute__ ((unused)); -+static int wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused)); -+ -+static size_t -+wcslen_uint32 (const uint32_t *str) -+{ -+ size_t len = 0; -+ while (str[len] != 0) -+ len++; -+ return len; -+} -+ -+static int -+wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) -+{ -+ while (n-- != 0) -+ { -+ int diff = *s1++ - *s2++; -+ if (diff != 0) -+ return diff; -+ } -+ return 0; -+} -+ -+static int -+wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) -+{ -+ while (*s1 != 0 && *s1 == *s2) -+ s1++, s2++; -+ return *s1 - *s2; -+} -+ -+static uint32_t * -+wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) -+{ -+ return memcpy (s1, s2, n * sizeof (uint32_t)); -+} -+ -+static uint32_t * -+wcschr_uint32 (const uint32_t *s, uint32_t ch) -+{ -+ do -+ if (*s == ch) -+ return (uint32_t *) s; -+ while (*s++ != 0); -+ return 0; -+} -+ - #endif /* locfile.h */ -Index: git/locale/setlocale.c -=================================================================== ---- git.orig/locale/setlocale.c -+++ git/locale/setlocale.c -@@ -64,36 +64,6 @@ static char *const _nl_current_used[] = - #endif - - --/* Define an array of category names (also the environment variable names). */ --const union catnamestr_t _nl_category_names attribute_hidden = -- { -- { --#define DEFINE_CATEGORY(category, category_name, items, a) \ -- category_name, --#include "categories.def" --#undef DEFINE_CATEGORY -- } -- }; -- --const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = -- { --#define DEFINE_CATEGORY(category, category_name, items, a) \ -- [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), --#include "categories.def" --#undef DEFINE_CATEGORY -- }; -- --/* An array of their lengths, for convenience. */ --const uint8_t _nl_category_name_sizes[] attribute_hidden = -- { --#define DEFINE_CATEGORY(category, category_name, items, a) \ -- [category] = sizeof (category_name) - 1, --#include "categories.def" --#undef DEFINE_CATEGORY -- [LC_ALL] = sizeof ("LC_ALL") - 1 -- }; -- -- - #ifdef NL_CURRENT_INDIRECT - # define WEAK_POSTLOAD(postload) weak_extern (postload) - #else -Index: git/locale/xlocale.c -=================================================================== ---- git.orig/locale/xlocale.c -+++ git/locale/xlocale.c -@@ -18,6 +18,7 @@ - . */ - - #include -+#include - #include "localeinfo.h" - - #define DEFINE_CATEGORY(category, category_name, items, a) \ -@@ -25,6 +26,19 @@ extern struct __locale_data _nl_C_##cate - #include "categories.def" - #undef DEFINE_CATEGORY - -+/* If the locale support code isn't enabled, don't generate strong -+ reference to the C locale_data structures here; let the Makefile -+ decide which ones to include. (In the static linking case, the -+ strong reference to the 'class', 'toupper', and 'tolower' tables -+ will cause C-ctype.o to be brought in, as it should be, even when -+ the reference to _nl_C_LC_CTYPE will be weak.) */ -+#if ! __OPTION_EGLIBC_LOCALE_CODE -+# define DEFINE_CATEGORY(category, category_name, items, a) \ -+ weak_extern (_nl_C_##category) -+# include "categories.def" -+# undef DEFINE_CATEGORY -+#endif -+ - /* Defined in locale/C-ctype.c. */ - extern const char _nl_C_LC_CTYPE_class[] attribute_hidden; - extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden; -@@ -52,3 +66,26 @@ const struct __locale_struct _nl_C_locob - .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128, - .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128 - }; -+ -+ -+#if ! __OPTION_EGLIBC_LOCALE_CODE -+/* When locale code is enabled, these are each defined in the -+ appropriate lc-CATEGORY.c file, so that static links (when __thread -+ is supported) bring in only those lc-CATEGORY.o files for -+ categories the program actually uses; look for NL_CURRENT_INDIRECT -+ in localeinfo.h. -+ -+ When locale code is disabled, the _nl_C_CATEGORY objects are the -+ only possible referents. At the moment, there isn't a way to get -+ __OPTION_EGLIBC_LOCALE_CODE defined in every compilation unit that -+ #includes localeinfo.h, so we can't just turn off -+ NL_CURRENT_INDIRECT. So we'll define the _nl_current_CATEGORY -+ pointers here. */ -+#if defined (NL_CURRENT_INDIRECT) -+#define DEFINE_CATEGORY(category, category_name, items, a) \ -+ __thread struct __locale_data * const *_nl_current_##category \ -+ attribute_hidden = &_nl_C_locobj.__locales[category]; -+#include "categories.def" -+#undef DEFINE_CATEGORY -+#endif -+#endif /* __OPTION_EGLIBC_LOCALE_CODE */ -Index: git/localedata/Makefile -=================================================================== ---- git.orig/localedata/Makefile -+++ git/localedata/Makefile -@@ -21,12 +21,22 @@ subdir := localedata - - include ../Makeconfig - --# List with all available character set descriptions. --charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*) -+include ../option-groups.mak - - # List with all available character set descriptions. --locales := $(wildcard locales/*) -+all-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*) -+ -+all-locales := $(wildcard locales/*) - -+# If the EGLIBC_LOCALES option group is not enabled, trim the -+# list of charmap and locale source files. -+ifeq ($(OPTION_EGLIBC_LOCALES),y) -+charmaps := $(all-charmaps) -+locales := $(all-locales) -+else -+charmaps := -+locales := locales/POSIX -+endif - - subdir-dirs = tests-mbwc - vpath %.c tests-mbwc -@@ -71,14 +81,20 @@ locale_test_suite := tst_iswalnum tst_is - tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \ - tst_wctype tst_wcwidth - --tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \ -+# Since these tests build their own locale files, they're not -+# dependent on the OPTION_EGLIBC_LOCALES option group. But they do -+# need the locale functions to be present. -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \ - tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \ - tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \ - tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \ - tst-wctype -+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) - tests-static = bug-setlocale1-static - tests += $(tests-static) --ifeq (yes,$(build-shared)) -+endif -+ifeq (yesy,$(build-shared)$(OPTION_EGLIBC_LOCALE_CODE)) - ifneq (no,$(PERL)) - tests-special += $(objpfx)mtrace-tst-leaks.out - endif -@@ -95,6 +111,7 @@ tests: $(objdir)/iconvdata/gconv-modules - tests-static += tst-langinfo-static - - ifeq ($(run-built-tests),yes) -+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) - tests-special += $(objpfx)sort-test.out $(objpfx)tst-fmon.out \ - $(objpfx)tst-locale.out $(objpfx)tst-rpmatch.out \ - $(objpfx)tst-trans.out $(objpfx)tst-ctype.out \ -@@ -113,6 +130,7 @@ CHARMAPS := $(shell echo "$(LOCALES)" | - CTYPE_FILES = $(addsuffix /LC_CTYPE,$(LOCALES)) - tests-special += $(addprefix $(objpfx),$(CTYPE_FILES)) - endif -+endif - - include ../Rules - -@@ -205,6 +223,11 @@ endif - - include SUPPORTED - -+# Only install locale data if OPTION_EGLIBC_LOCALES is selected. -+ifneq ($(OPTION_EGLIBC_LOCALES),y) -+SUPPORTED-LOCALES := -+endif -+ - INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES)) - - # Sometimes the whole collection of locale files should be installed. -Index: git/login/Makefile -=================================================================== ---- git.orig/login/Makefile -+++ git/login/Makefile -@@ -18,6 +18,7 @@ - # - # Sub-makefile for login portion of the library. - # -+include ../option-groups.mak - - subdir := login - -@@ -25,14 +26,16 @@ include ../Makeconfig - - headers := utmp.h bits/utmp.h lastlog.h pty.h - --routines := getlogin getlogin_r setlogin getlogin_r_chk \ -- getutent getutent_r getutid getutline getutid_r getutline_r \ -- utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \ -- ptsname_r_chk -+routines := getpt grantpt unlockpt ptsname ptsname_r_chk -+routines-$(OPTION_EGLIBC_UTMP) \ -+ += getutent getutent_r getutid getutline getutid_r getutline_r \ -+ utmp_file utmpname updwtmp -+routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin getlogin_r getlogin_r_chk -+routines-$(OPTION_EGLIBC_BSD) += setlogin - - CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"' - --others = utmpdump -+others-$(OPTION_EGLIBC_UTMP) += utmpdump - - ifeq (yes,$(build-pt-chown)) - others += pt_chown -@@ -46,8 +49,8 @@ vpath %.c programs - tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname - - # Build the -lutil library with these extra functions. --extra-libs := libutil --extra-libs-others := $(extra-libs) -+extra-libs-$(OPTION_EGLIBC_UTMP) := libutil -+extra-libs-others := $(extra-libs-y) - - libutil-routines:= login login_tty logout logwtmp openpty forkpty - -Index: git/Makeconfig -=================================================================== ---- git.orig/Makeconfig -+++ git/Makeconfig -@@ -582,7 +582,7 @@ elf-objpfx = $(common-objpfx)elf/ - # and run on the build system, causes that program with those - # arguments to be run on the host for which the library is built. - ifndef test-wrapper --test-wrapper = -+test-wrapper = $(cross-test-wrapper) - endif - # Likewise, but the name of the program is preceded by - # = assignments for environment variables. -@@ -1055,6 +1055,24 @@ else - libm = $(common-objpfx)math/libm.a - endif - -+# Generate a header file that #defines preprocessor symbols indicating -+# which option groups are enabled. Note that the option-groups.config file -+# may not exist at all. -+before-compile += $(common-objpfx)gnu/option-groups.h -+common-generated += gnu/option-groups.h gnu/option-groups.stmp -+headers += gnu/option-groups.h -+$(common-objpfx)gnu/option-groups.h: $(common-objpfx)gnu/option-groups.stmp; @: -+$(common-objpfx)gnu/option-groups.stmp: \ -+ $(..)scripts/option-groups.awk \ -+ $(..)option-groups.defaults \ -+ $(wildcard $(common-objpfx)option-groups.config) -+ $(make-target-directory) -+ @rm -f ${@:stmp=T} $@ -+ LC_ALL=C $(AWK) -f $^ > ${@:stmp=T} -+ $(move-if-change) ${@:stmp=T} ${@:stmp=h} -+ touch $@ -+ -+ - # These are the subdirectories containing the library source. The order - # is more or less arbitrary. The sorting step will take care of the - # dependencies. -Index: git/Makerules -=================================================================== ---- git.orig/Makerules -+++ git/Makerules -@@ -446,6 +446,25 @@ define sed-remove-objpfx - endef - endif - -+# Include targets in the selected option groups. -+aux += $(aux-y) -+extra-libs += $(extra-libs-y) -+extra-libs-others += $(extra-libs-others-y) -+extra-objs += $(extra-objs-y) -+install-bin += $(install-bin-y) -+install-others += $(install-others-y) -+install-sbin += $(install-sbin-y) -+modules += $(modules-y) -+others += $(others-y) -+others-pie += $(others-pie-y) -+routines += $(routines-y) -+static-only-routines += $(static-only-routines-y) -+sysdep_routines += $(sysdep_routines-y) -+test-srcs += $(test-srcs-y) -+tests += $(tests-y) -+xtests += $(xtests-y) -+ -+ - # Modify the list of routines we build for different targets - - ifeq (yes,$(build-shared)) -Index: git/malloc/Makefile -=================================================================== ---- git.orig/malloc/Makefile -+++ git/malloc/Makefile -@@ -18,6 +18,8 @@ - # - # Makefile for malloc routines - # -+include ../option-groups.mak -+ - subdir := malloc - - include ../Makeconfig -@@ -36,9 +38,15 @@ install-lib := libmcheck.a - non-lib.a := libmcheck.a - - # Additional library. -+ifeq ($(OPTION_EGLIBC_MEMUSAGE),y) - extra-libs = libmemusage - extra-libs-others = $(extra-libs) - -+ifdef OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE -+CPPFLAGS-memusage += -D__OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE=$(OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE) -+endif -+endif -+ - libmemusage-routines = memusage - libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) - -@@ -65,7 +73,7 @@ endif - # Unless we get a test for the availability of libgd which also works - # for cross-compiling we disable the memusagestat generation in this - # situation. --ifneq ($(cross-compiling),yes) -+ifeq ($(cross-compiling)$(OPTION_EGLIBC_MEMUSAGE),noy) - # If the gd library is available we build the `memusagestat' program. - ifneq ($(LIBGD),no) - others: $(objpfx)memusage -Index: git/malloc/memusage.c -=================================================================== ---- git.orig/malloc/memusage.c -+++ git/malloc/memusage.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - - #include - -@@ -93,7 +94,11 @@ static __thread uintptr_t start_sp; - #define peak_stack peak_use[1] - #define peak_total peak_use[2] - --#define DEFAULT_BUFFER_SIZE 32768 -+#ifndef __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE -+# define DEFAULT_BUFFER_SIZE 32768 -+#else -+# define DEFAULT_BUFFER_SIZE __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE -+#endif - static size_t buffer_size; - - static int fd = -1; -Index: git/malloc/memusage.sh -=================================================================== ---- git.orig/malloc/memusage.sh -+++ git/malloc/memusage.sh -@@ -35,7 +35,7 @@ do_missing_arg() { - - # Print help message - do_help() { -- echo $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]... -+ printf $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]... - Profile memory usage of PROGRAM. - - -n,--progname=NAME Name of the program file to profile -Index: git/math/Makefile -=================================================================== ---- git.orig/math/Makefile -+++ git/math/Makefile -@@ -21,6 +21,8 @@ subdir := math - - include ../Makeconfig - -+include ../option-groups.mak -+ - # Installed header files. - headers := math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \ - bits/huge_valf.h bits/huge_vall.h bits/inf.h bits/nan.h \ -@@ -33,8 +35,8 @@ aux := setfpucw fpu_control - - # Build the -lm library. - --extra-libs := libm --extra-libs-others = $(extra-libs) -+extra-libs-$(OPTION_EGLIBC_LIBM) := libm -+extra-libs-others-$(OPTION_EGLIBC_LIBM) = $(extra-libs-$(OPTION_EGLIBC_LIBM)) - - libm-support = s_lib_version s_matherr s_signgam \ - fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg \ -Index: git/misc/err.c -=================================================================== ---- git.orig/misc/err.c -+++ git/misc/err.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #define flockfile(s) _IO_flockfile (s) -@@ -37,6 +38,7 @@ extern char *__progname; - va_end (ap); \ - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - static void - convert_and_print (const char *format, __gnuc_va_list ap) - { -@@ -81,6 +83,7 @@ convert_and_print (const char *format, _ - - __vfwprintf (stderr, wformat, ap); - } -+#endif - - void - vwarnx (const char *format, __gnuc_va_list ap) -@@ -88,9 +91,13 @@ vwarnx (const char *format, __gnuc_va_li - flockfile (stderr); - if (_IO_fwide (stderr, 0) > 0) - { -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - __fwprintf (stderr, L"%s: ", __progname); - convert_and_print (format, ap); - putwc_unlocked (L'\n', stderr); -+#else -+ abort (); -+#endif - } - else - { -@@ -111,6 +118,7 @@ vwarn (const char *format, __gnuc_va_lis - flockfile (stderr); - if (_IO_fwide (stderr, 0) > 0) - { -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - __fwprintf (stderr, L"%s: ", __progname); - if (format) - { -@@ -119,6 +127,9 @@ vwarn (const char *format, __gnuc_va_lis - } - __set_errno (error); - __fwprintf (stderr, L"%m\n"); -+#else -+ abort (); -+#endif - } - else - { -Index: git/misc/error.c -=================================================================== ---- git.orig/misc/error.c -+++ git/misc/error.c -@@ -35,6 +35,7 @@ - #endif - - #ifdef _LIBC -+# include - # include - # include - # include -@@ -205,6 +206,7 @@ error_tail (int status, int errnum, cons - #if _LIBC - if (_IO_fwide (stderr, 0) > 0) - { -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - size_t len = strlen (message) + 1; - wchar_t *wmessage = NULL; - mbstate_t st; -@@ -265,6 +267,9 @@ error_tail (int status, int errnum, cons - - if (use_malloc) - free (wmessage); -+#else -+ abort (); -+#endif - } - else - #endif -Index: git/misc/Makefile -=================================================================== ---- git.orig/misc/Makefile -+++ git/misc/Makefile -@@ -19,6 +19,10 @@ - # Sub-makefile for misc portion of the library. - # - -+# Some system-dependent implementations of these functions use option -+# groups (see sysdeps/unix/sysv/linux/Makefile, for example). -+include ../option-groups.mak -+ - subdir := misc - - include ../Makeconfig -@@ -46,40 +50,47 @@ routines := brk sbrk sstk ioctl \ - select pselect \ - acct chroot fsync sync fdatasync syncfs reboot \ - gethostid sethostid \ -- revoke vhangup \ -+ vhangup \ - swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \ - mkostemp mkostemp64 mkstemps mkstemps64 mkostemps mkostemps64 \ - ualarm usleep \ - gtty stty \ - ptrace \ -- fstab mntent mntent_r \ -+ mntent mntent_r \ - utimes lutimes futimes futimesat \ - truncate ftruncate truncate64 ftruncate64 \ -- chflags fchflags \ - insremque getttyent getusershell getpass ttyslot \ - syslog syscall daemon \ - mmap mmap64 munmap mprotect msync madvise mincore remap_file_pages\ - mlock munlock mlockall munlockall \ -- efgcvt efgcvt_r qefgcvt qefgcvt_r \ - hsearch hsearch_r tsearch lsearch \ - err error ustat \ -- getsysstats dirname regexp \ -+ getsysstats dirname \ - getloadavg getclktck \ - fgetxattr flistxattr fremovexattr fsetxattr getxattr \ - listxattr lgetxattr llistxattr lremovexattr lsetxattr \ - removexattr setxattr getauxval ifunc-impl-list - -+routines-$(OPTION_POSIX_REGEXP) += regexp -+routines-$(OPTION_EGLIBC_FSTAB) += fstab -+routines-$(OPTION_EGLIBC_BSD) += chflags fchflags revoke -+routines-$(OPTION_EGLIBC_FCVT) += efgcvt efgcvt_r qefgcvt qefgcvt_r -+ - generated += tst-error1.mtrace tst-error1-mem.out - - aux := init-misc - install-lib := libg.a - gpl2lgpl := error.c error.h - --tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ -- tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 -+tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \ -+ tst-pselect tst-insremque tst-mntent2 bug-hsearch1 -+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += tst-error1 -+tests-$(OPTION_EGLIBC_FCVT) += tst-efgcvt - ifeq ($(run-built-tests),yes) -+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)) - tests-special += $(objpfx)tst-error1-mem.out - endif -+endif - - CFLAGS-select.c = -fexceptions -fasynchronous-unwind-tables - CFLAGS-tsearch.c = $(uses-callbacks) -Index: git/misc/tst-efgcvt.c -=================================================================== ---- git.orig/misc/tst-efgcvt.c -+++ git/misc/tst-efgcvt.c -@@ -59,7 +59,7 @@ static testcase ecvt_tests[] = - { 123.01, -4, 3, "" }, - { 126.71, -4, 3, "" }, - { 0.0, 4, 1, "0000" }, --#if DBL_MANT_DIG == 53 -+#if DBL_MANT_DIG == 53 && !(defined __powerpc__ && defined __NO_FPRS__ && !defined _SOFT_FLOAT && !defined _SOFT_DOUBLE) - { 0x1p-1074, 3, -323, "494" }, - { -0x1p-1074, 3, -323, "494" }, - #endif -Index: git/nis/Makefile -=================================================================== ---- git.orig/nis/Makefile -+++ git/nis/Makefile -@@ -18,6 +18,8 @@ - # - # Makefile for NIS/NIS+ part. - # -+include ../option-groups.mak -+ - subdir := nis - - include ../Makeconfig -@@ -30,19 +32,26 @@ endif - - # These are the databases available for the nis (and perhaps later nisplus) - # service. This must be a superset of the services in nss. --databases = proto service hosts network grp pwd rpc ethers \ -- spwd netgrp alias publickey -+databases-y := proto service hosts network grp pwd rpc ethers \ -+ spwd netgrp publickey -+databases-$(OPTION_EGLIBC_DB_ALIASES) += alias - - # Specify rules for the nss_* modules. --services := nis nisplus compat -+# The 'compat' module includes nis support, and the 'nss' directory -+# includes a bare-bones "files" library, so we'll include 'compat' in -+# OPTION_EGLIBC_NIS. -+services-y := -+services-$(OPTION_EGLIBC_NIS) += nis nisplus compat -+ -+extra-libs-$(OPTION_EGLIBC_NIS) += libnsl -+extra-libs-y += $(services-y:%=libnss_%) - --extra-libs = libnsl $(services:%=libnss_%) - # These libraries will be built in the `others' pass rather than - # the `lib' pass, because they depend on libc.so being built already. --extra-libs-others = $(extra-libs) -+extra-libs-others-y += $(extra-libs-y) - - # The sources are found in the appropriate subdir. --subdir-dirs = $(services:%=nss_%) -+subdir-dirs = $(services-y:%=nss_%) - vpath %.c $(subdir-dirs) - - libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ -@@ -60,11 +69,11 @@ libnsl-routines = yp_xdr ypclnt ypupdate - libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) - libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) - --libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \ -+libnss_nis-routines := $(addprefix nis-,$(databases-y)) nis-initgroups \ - nss-nis - libnss_nis-inhibit-o = $(filter-out .os,$(object-suffixes)) - --libnss_nisplus-routines := $(addprefix nisplus-,$(databases)) nisplus-parser \ -+libnss_nisplus-routines := $(addprefix nisplus-,$(databases-y)) nisplus-parser \ - nss-nisplus nisplus-initgroups - libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes)) - -@@ -80,12 +89,12 @@ libnsl-libc = $(common-objpfx)linkobj/li - # Target-specific variable setting to link objects using deprecated - # RPC interfaces with the version of libc.so that makes them available - # for new links: --$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \ -+$(services-y:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \ - libc-for-link = $(libnsl-libc) - - - ifeq ($(build-shared),yes) --$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) -+$(others-y:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) - else --$(others:%=$(objpfx)%): $(objpfx)libnsl.a -+$(others-y:%=$(objpfx)%): $(objpfx)libnsl.a - endif -Index: git/nptl/Makefile -=================================================================== ---- git.orig/nptl/Makefile -+++ git/nptl/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for NPTL portion of the library. - # -+include ../option-groups.mak -+ - subdir := nptl - - include ../Makeconfig -@@ -117,7 +119,7 @@ libpthread-routines = nptl-init vars eve - pt-raise pt-system \ - flockfile ftrylockfile funlockfile \ - sigaction \ -- herrno res pt-allocrtsig \ -+ pt-allocrtsig \ - pthread_kill_other_threads \ - pthread_getaffinity pthread_setaffinity \ - pthread_attr_getaffinity pthread_attr_setaffinity \ -@@ -137,6 +139,8 @@ libpthread-routines = nptl-init vars eve - # pthread_setgid pthread_setegid pthread_setregid \ - # pthread_setresgid - -+libpthread-routines-$(OPTION_EGLIBC_INET) := herrno res -+ - libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind - libpthread-static-only-routines = pthread_atfork - -@@ -211,7 +215,7 @@ tests = tst-typesizes \ - tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ - tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \ - tst-mutexpi9 \ -- tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ -+ tst-spin1 tst-spin2 tst-spin3 \ - tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ - tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ - tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ -@@ -245,14 +249,14 @@ tests = tst-typesizes \ - tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \ - tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \ - tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \ -- tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \ -+ tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \ - tst-cancel-self tst-cancel-self-cancelstate \ - tst-cancel-self-canceltype tst-cancel-self-testcancel \ - tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ - tst-flock1 tst-flock2 \ - tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ - tst-signal6 tst-signal7 \ -- tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ -+ tst-exec2 tst-exec3 tst-exec4 \ - tst-exit1 tst-exit2 tst-exit3 \ - tst-stdio1 tst-stdio2 \ - tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \ -@@ -260,13 +264,12 @@ tests = tst-typesizes \ - tst-unload \ - tst-dlsym1 \ - tst-sysconf \ -- tst-locale1 tst-locale2 \ -+ tst-locale2 \ - tst-umask1 \ - tst-popen1 \ - tst-clock1 \ - tst-context1 \ - tst-sched1 \ -- tst-backtrace1 \ - tst-abstime \ - tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ - tst-getpid1 tst-getpid2 tst-getpid3 \ -@@ -277,6 +280,17 @@ xtests = tst-setuid1 tst-setuid1-static - tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 - test-srcs = tst-oddstacklimit - -+# This test uses the posix_spawn functions. -+tests-$(OPTION_EGLIBC_SPAWN) += tst-exec1 -+ -+# This test uses the 'backtrace' functions. -+tests-$(OPTION_EGLIBC_BACKTRACE) += tst-backtrace1 -+ -+# This test is written in C++. -+tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24 -+ -+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1 -+ - # Files which must not be linked with libpthread. - tests-nolibpthread = tst-unload - -@@ -363,12 +377,18 @@ - $(common-objpfx)libc.a - - tests-static += tst-locale1 tst-locale2 tst-stackguard1-static \ -- tst-cancel21-static tst-cancel24-static tst-cond8-static \ -+ tst-cancel21-static tst-cond8-static \ - tst-mutex8-static tst-mutexpi8-static tst-sem11-static \ - tst-sem12-static --tests += tst-stackguard1-static tst-cancel21-static tst-cancel24-static \ -+ -+ifeq (y,$(OPTION_EGLIBC_CXX_TESTS)) -+tests-static += tst-cancel24-static -+endif -+ -+tests += tst-stackguard1-static tst-cancel21-static \ - tst-cond8-static tst-mutex8-static tst-mutexpi8-static \ - tst-sem11-static tst-sem12-static -+tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24-static - xtests-static += tst-setuid1-static - - # These tests are linked with libc before libpthread -Index: git/nptl/pthread_create.c -=================================================================== ---- git.orig/nptl/pthread_create.c -+++ git/nptl/pthread_create.c -@@ -32,6 +32,7 @@ - #include - #include - -+#include - #include - - #include -@@ -261,8 +262,10 @@ START_THREAD_DEFN - THREAD_SETMEM (pd, cpuclock_offset, now); - #endif - -+#if __OPTION_EGLIBC_INET - /* Initialize resolver state pointer. */ - __resp = &pd->res; -+#endif - - /* Initialize pointers to locale data. */ - __ctype_init (); -@@ -345,8 +348,10 @@ START_THREAD_DEFN - /* Run the destructor for the thread-local data. */ - __nptl_deallocate_tsd (); - -+#if __OPTION_EGLIBC_INET - /* Clean up any state libc stored in thread-local variables. */ - __libc_thread_freeres (); -+#endif - - /* If this is the last thread we terminate the process now. We - do not notify the debugger, it might just irritate it if there -Index: git/nscd/Makefile -=================================================================== ---- git.orig/nscd/Makefile -+++ git/nscd/Makefile -@@ -18,14 +18,17 @@ - # - # Sub-makefile for nscd portion of the library. - # -+include ../option-groups.mak -+ - subdir := nscd - - include ../Makeconfig - - ifneq ($(use-nscd),no) --routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ -+routines-$(OPTION_EGLIBC_INET) += \ -+ nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ - nscd_initgroups nscd_getserv_r nscd_netgroup --aux := nscd_helper -+aux-$(OPTION_EGLIBC_INET) += nscd_helper - endif - - # To find xmalloc.c -@@ -37,14 +40,18 @@ nscd-modules := nscd connections pwdcach - dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ - xmalloc xstrdup aicache initgrcache gai res_hconf \ - netgroupcache -- -+ifneq (y,$(OPTION_EGLIBC_NIS)) -+# If we haven't build libnsl.so, then we'll need to include our -+# own copy of nis_hash. -+nscd-modules += nis_hash -+endif - ifeq ($(build-nscd)$(have-thread-library),yesyes) - --others += nscd --others-pie += nscd --install-sbin := nscd -+others-$(OPTION_EGLIBC_INET) += nscd -+others-pie-$(OPTION_EGLIBC_INET) += nscd -+install-sbin-$(OPTION_EGLIBC_INET) += nscd - --extra-objs = $(nscd-modules:=.o) -+extra-objs-$(OPTION_EGLIBC_INET) += $(nscd-modules:=.o) - - endif - -@@ -100,7 +107,15 @@ include $(patsubst %,$(..)cppflags-itera - $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o) - - ifeq ($(build-shared),yes) --$(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so -+$(objpfx)nscd: $(shared-thread-library) -+else -+$(objpfx)nscd: $(static-thread-library) -+endif -+ -+ifeq (y,$(OPTION_EGLIBC_NIS)) -+ifeq ($(build-shared),yes) -+$(objpfx)nscd: $(common-objpfx)nis/libnsl.so - else --$(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a -+$(objpfx)nscd: $(common-objpfx)nis/libnsl.a -+endif - endif -Index: git/nscd/nis_hash.c -=================================================================== ---- /dev/null -+++ git/nscd/nis_hash.c -@@ -0,0 +1,3 @@ -+/* If OPTION_EGLIBC_NIS is disabled, nscd can't get this from libnsl.so; -+ we need our own copy. */ -+#include "../nis/nis_hash.c" -Index: git/nss/fixed-nsswitch.conf -=================================================================== ---- /dev/null -+++ git/nss/fixed-nsswitch.conf -@@ -0,0 +1,22 @@ -+# /etc/nsswitch.conf -+# -+# Example configuration for fixed name service. -+# See the description of OPTION_EGLIBC_NSSWITCH in option-groups.def -+# for details. -+# -+ -+aliases: files -+ -+passwd: files -+group: files -+shadow: files -+ -+hosts: files dns -+networks: files dns -+ -+protocols: files -+services: files -+ethers: files -+rpc: files -+ -+netgroup: files -Index: git/nss/fixed-nsswitch.functions -=================================================================== ---- /dev/null -+++ git/nss/fixed-nsswitch.functions -@@ -0,0 +1,121 @@ -+/* List of functions defined for fixed NSS in GNU C Library. -+ Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+/* When OPTION_EGLIBC_NSSWITCH is disabled (see option-groups.def), -+ EGLIBC does not use the 'dlopen' and 'dlsym' functions to look for -+ database query functions in the individual name service libraries. -+ Instead, it uses a set of functions chosen at compile time, as -+ directed by the OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS file. This -+ file is a sample of what you might use there. -+ -+ This file is C source code; it should only contain invocations of -+ the following macros: -+ -+ - DEFINE_ENT (DATABASE, SERVICE, X) -+ -+ Declare the 'setXent', 'getXent_r', and 'endXent' functions that -+ query DATABASE using the service library 'libnss_SERVICE.so.2'. -+ DATABASE should be the full name of the database as it appears in -+ 'nsswitch.conf', like 'passwd' or 'aliases'. -+ -+ (The non-reentrant 'getXent' functions are implemented in terms -+ of the reentrant 'getXent_r' functions, so there is no need to -+ refer to them explicitly here.) -+ -+ - DEFINE_GETBY (DATABASE, SERVICE, X, KEY) -+ -+ Declare the 'getXbyKEY_r' functions that query DATABASE using -+ SERVICE. DATABASE and SERVICE are as described above. -+ -+ (The non-reentrant 'getXbyKEY' functions are implemented in terms -+ of the reentrant 'getXbyKEY_r' functions, so there is no need to -+ refer to them explicitly here.) -+ -+ Use the special key 'name3' for the service library function that -+ implements the 'getaddrinfo' function. -+ -+ - DEFINE_GET (DATABASE, SERVICE, QUERY) -+ -+ Declare the 'getQUERY_r' functions that query DATABASE using -+ SERVICE. This is used for functions like 'getpwnam'. -+ -+ (The non-reentrant 'getQUERY' functions are implemented in terms -+ of the reentrant 'getQUERY_r' functions, so there is no need to -+ refer to them explicitly here.) -+ -+ This sample file only includes functions that consult the files in -+ '/etc', and the Domain Name System (DNS). */ -+ -+/* aliases */ -+DEFINE_ENT (aliases, files, alias) -+DEFINE_GETBY (aliases, files, alias, name) -+ -+/* ethers */ -+DEFINE_ENT (ethers, files, ether) -+ -+/* group */ -+DEFINE_ENT (group, files, gr) -+DEFINE_GET (group, files, grgid) -+DEFINE_GET (group, files, grnam) -+ -+/* hosts */ -+DEFINE_ENT (hosts, files, host) -+DEFINE_GETBY (hosts, files, host, addr) -+DEFINE_GETBY (hosts, files, host, name) -+DEFINE_GETBY (hosts, files, host, name2) -+DEFINE_GET (hosts, files, hostton) -+DEFINE_GET (hosts, files, ntohost) -+DEFINE_GETBY (hosts, dns, host, addr) -+DEFINE_GETBY (hosts, dns, host, name) -+DEFINE_GETBY (hosts, dns, host, name2) -+DEFINE_GETBY (hosts, dns, host, name3) -+ -+/* netgroup */ -+DEFINE_ENT (netgroup, files, netgr) -+ -+/* networks */ -+DEFINE_ENT (networks, files, net) -+DEFINE_GETBY (networks, files, net, name) -+DEFINE_GETBY (networks, files, net, addr) -+DEFINE_GETBY (networks, dns, net, name) -+DEFINE_GETBY (networks, dns, net, addr) -+ -+/* protocols */ -+DEFINE_ENT (protocols, files, proto) -+DEFINE_GETBY (protocols, files, proto, name) -+DEFINE_GETBY (protocols, files, proto, number) -+ -+/* passwd */ -+DEFINE_ENT (passwd, files, pw) -+DEFINE_GET (passwd, files, pwnam) -+DEFINE_GET (passwd, files, pwuid) -+ -+/* rpc */ -+DEFINE_ENT (rpc, files, rpc) -+DEFINE_GETBY (rpc, files, rpc, name) -+DEFINE_GETBY (rpc, files, rpc, number) -+ -+/* services */ -+DEFINE_ENT (services, files, serv) -+DEFINE_GETBY (services, files, serv, name) -+DEFINE_GETBY (services, files, serv, port) -+ -+/* shadow */ -+DEFINE_ENT (shadow, files, sp) -+DEFINE_GET (shadow, files, spnam) -Index: git/nss/gen-fixed-nsswitch.c -=================================================================== ---- /dev/null -+++ git/nss/gen-fixed-nsswitch.c -@@ -0,0 +1,803 @@ -+/* gen-fixed-nsswitch.c --- generate fixed name service data structures -+ Copyright (C) 1996-1999, 2001-2006, 2007 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "gnu/lib-names.h" -+#include "nss.h" -+ -+/* Provide a fallback definition to allow this file to be compiled outside -+ libc. */ -+#ifndef internal_function -+# define internal_function -+#endif -+ -+ -+/* Simple utilities. */ -+ -+void __attribute__ ((noreturn)) -+error (const char *message) -+{ -+ fprintf (stderr, "%s\n", message); -+ exit (1); -+} -+ -+ -+void * -+check_alloc (void *p) -+{ -+ if (p) -+ return p; -+ else -+ error ("out of memory"); -+} -+ -+void * -+xmalloc (size_t size) -+{ -+ return check_alloc (malloc (size)); -+} -+ -+ -+/* Format ARGS according to FORMAT, and return the result as a -+ malloc'ed string. */ -+char * -+saprintf (const char *format, ...) -+{ -+ va_list args; -+ size_t len; -+ char *buf; -+ -+ va_start (args, format); -+ len = vsnprintf (NULL, 0, format, args); -+ va_end (args); -+ -+ buf = xmalloc (len + 1); -+ va_start (args, format); -+ assert (len == vsnprintf (buf, len + 1, format, args)); -+ va_end (args); -+ -+ return buf; -+} -+ -+ -+ -+/* Data structures representing the configuration file in memory. */ -+ -+/* These are copied from nsswitch.h. -+ -+ We could simply #include that file, but this program runs on the -+ build machine and links against the build machine's libraries, -+ whereas that header is meant for use by target code; it uses -+ 'libc_hidden_proto', 'internal_function', and related hair. Since -+ we've copied the parsing code, we might as well copy the data -+ structure definitions as well. */ -+ -+/* Actions performed after lookup finished. */ -+typedef enum -+{ -+ NSS_ACTION_CONTINUE, -+ NSS_ACTION_RETURN -+} lookup_actions; -+ -+ -+typedef struct service_library -+{ -+ /* Name of service (`files', `dns', `nis', ...). */ -+ const char *name; -+ /* Pointer to the loaded shared library. */ -+ void *lib_handle; -+ /* And the link to the next entry. */ -+ struct service_library *next; -+} service_library; -+ -+ -+/* For mapping a function name to a function pointer. It is known in -+ nsswitch.c:nss_lookup_function that a string pointer for the lookup key -+ is the first member. */ -+typedef struct -+{ -+ const char *fct_name; -+ void *fct_ptr; -+} known_function; -+ -+ -+typedef struct service_user -+{ -+ /* And the link to the next entry. */ -+ struct service_user *next; -+ /* Action according to result. */ -+ lookup_actions actions[5]; -+ /* Link to the underlying library object. */ -+ service_library *library; -+ /* Collection of known functions. -+ -+ With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a -+ 'tsearch'-style tree. -+ -+ With OPTION_EGLIBC_NSSWITCH disabled, this is an array of -+ pointers to known_function structures, NULL-terminated. */ -+ union -+ { -+ void *tree; -+ const known_function **array; -+ } known; -+ /* Name of the service (`files', `dns', `nis', ...). */ -+ const char *name; -+} service_user; -+ -+/* To access the action based on the status value use this macro. */ -+#define nss_next_action(ni, status) ((ni)->actions[2 + status]) -+ -+ -+typedef struct name_database_entry -+{ -+ /* And the link to the next entry. */ -+ struct name_database_entry *next; -+ /* List of service to be used. */ -+ service_user *service; -+ /* Name of the database. */ -+ const char *name; -+} name_database_entry; -+ -+ -+typedef struct name_database -+{ -+ /* List of all known databases. */ -+ name_database_entry *entry; -+ /* List of libraries with service implementation. */ -+ service_library *library; -+} name_database; -+ -+ -+ -+/* Gathering the contents of the FIXED_FUNCTIONS file. */ -+ -+/* It should be possible to generate this list automatically by -+ looking at the services and databases used in the nsswitch.conf -+ file, and having a hard-coded set of queries supported on each -+ database. */ -+ -+/* We #include the FIXED_FUNCTIONS file several times to build an -+ array of function structures holding its data. */ -+enum function_kind { -+ fk_end = 0, /* Last entry. */ -+ fk_setent, /* Like setpwent. */ -+ fk_getent, /* Like getpwent. */ -+ fk_endent, /* Like endpwent. */ -+ fk_getby, /* Like gethostbyname. */ -+ fk_get /* Like getpwnam. */ -+}; -+ -+ -+struct function { -+ /* What kind of function this is. */ -+ enum function_kind kind; -+ -+ /* The database and service of the function being hardwired in. */ -+ char *database, *service; -+ -+ /* The kind of entry being queried, for 'fk_setent', 'fk_getent', -+ 'fk_endent', and 'fk_getby' functions. */ -+ char *entry; -+ -+ /* The key, for 'fk_getby' entries. */ -+ char *key; -+ -+ /* The value and key, for 'fk_get' entries. */ -+ char *value_and_key; -+}; -+ -+ -+const struct function functions[] = -+ { -+ -+#define DEFINE_ENT(database, service, entry) \ -+ { fk_setent, #database, #service, #entry }, \ -+ { fk_getent, #database, #service, #entry }, \ -+ { fk_endent, #database, #service, #entry }, -+#define DEFINE_GETBY(database, service, entry, key) \ -+ { fk_getby, #database, #service, #entry, #key }, -+#define DEFINE_GET(database, service, value_and_key) \ -+ { fk_get, #database, #service, NULL, NULL, #value_and_key }, -+ -+#include FIXED_FUNCTIONS -+ -+#undef DEFINE_ENT -+#undef DEFINE_GETBY -+#undef DEFINE_GET -+ -+ { fk_end } -+ }; -+ -+ -+/* Parsing the config file. Functions copied from nsswitch.c. */ -+ -+#define __strchrnul strchrnul -+#define __getline getline -+#define __strncasecmp strncasecmp -+ -+/* Prototypes for the local functions. */ -+static name_database *nss_parse_file (const char *fname) internal_function; -+static name_database_entry *nss_getline (char *line) internal_function; -+static service_user *nss_parse_service_list (const char *line) -+ internal_function; -+ -+static name_database * -+internal_function -+nss_parse_file (const char *fname) -+{ -+ FILE *fp; -+ name_database *result; -+ name_database_entry *last; -+ char *line; -+ size_t len; -+ -+ /* Open the configuration file. */ -+ fp = fopen (fname, "rc"); -+ if (fp == NULL) -+ return NULL; -+ -+ // /* No threads use this stream. */ -+ // __fsetlocking (fp, FSETLOCKING_BYCALLER); -+ -+ result = (name_database *) xmalloc (sizeof (name_database)); -+ -+ result->entry = NULL; -+ result->library = NULL; -+ last = NULL; -+ line = NULL; -+ len = 0; -+ do -+ { -+ name_database_entry *this; -+ ssize_t n; -+ -+ n = __getline (&line, &len, fp); -+ if (n < 0) -+ break; -+ if (line[n - 1] == '\n') -+ line[n - 1] = '\0'; -+ -+ /* Because the file format does not know any form of quoting we -+ can search forward for the next '#' character and if found -+ make it terminating the line. */ -+ *__strchrnul (line, '#') = '\0'; -+ -+ /* If the line is blank it is ignored. */ -+ if (line[0] == '\0') -+ continue; -+ -+ /* Each line completely specifies the actions for a database. */ -+ this = nss_getline (line); -+ if (this != NULL) -+ { -+ if (last != NULL) -+ last->next = this; -+ else -+ result->entry = this; -+ -+ last = this; -+ } -+ } -+ while (!feof_unlocked (fp)); -+ -+ /* Free the buffer. */ -+ free (line); -+ /* Close configuration file. */ -+ fclose (fp); -+ -+ return result; -+} -+ -+ -+/* Read the source names: -+ `( ( "[" "!"? ( "=" )+ "]" )? )*' -+ */ -+static service_user * -+internal_function -+nss_parse_service_list (const char *line) -+{ -+ service_user *result = NULL, **nextp = &result; -+ -+ while (1) -+ { -+ service_user *new_service; -+ const char *name; -+ -+ while (isspace (line[0])) -+ ++line; -+ if (line[0] == '\0') -+ /* No source specified. */ -+ return result; -+ -+ /* Read identifier. */ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') -+ ++line; -+ if (name == line) -+ return result; -+ -+ -+ new_service = (service_user *) xmalloc (sizeof (*new_service)); -+ new_service->name = (char *) xmalloc (line - name + 1); -+ -+ *((char *) __mempcpy ((char *) new_service->name, name, line - name)) -+ = '\0'; -+ -+ /* Set default actions. */ -+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; -+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; -+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; -+ new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; -+ new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; -+ new_service->library = NULL; -+ new_service->known.tree = NULL; -+ new_service->next = NULL; -+ -+ while (isspace (line[0])) -+ ++line; -+ -+ if (line[0] == '[') -+ { -+ /* Read criterions. */ -+ do -+ ++line; -+ while (line[0] != '\0' && isspace (line[0])); -+ -+ do -+ { -+ int not; -+ enum nss_status status; -+ lookup_actions action; -+ -+ /* Grok ! before name to mean all statii but that one. */ -+ not = line[0] == '!'; -+ if (not) -+ ++line; -+ -+ /* Read status name. */ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' -+ && line[0] != ']') -+ ++line; -+ -+ /* Compare with known statii. */ -+ if (line - name == 7) -+ { -+ if (__strncasecmp (name, "SUCCESS", 7) == 0) -+ status = NSS_STATUS_SUCCESS; -+ else if (__strncasecmp (name, "UNAVAIL", 7) == 0) -+ status = NSS_STATUS_UNAVAIL; -+ else -+ return result; -+ } -+ else if (line - name == 8) -+ { -+ if (__strncasecmp (name, "NOTFOUND", 8) == 0) -+ status = NSS_STATUS_NOTFOUND; -+ else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) -+ status = NSS_STATUS_TRYAGAIN; -+ else -+ return result; -+ } -+ else -+ return result; -+ -+ while (isspace (line[0])) -+ ++line; -+ if (line[0] != '=') -+ return result; -+ do -+ ++line; -+ while (isspace (line[0])); -+ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' -+ && line[0] != ']') -+ ++line; -+ -+ if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) -+ action = NSS_ACTION_RETURN; -+ else if (line - name == 8 -+ && __strncasecmp (name, "CONTINUE", 8) == 0) -+ action = NSS_ACTION_CONTINUE; -+ else -+ return result; -+ -+ if (not) -+ { -+ /* Save the current action setting for this status, -+ set them all to the given action, and reset this one. */ -+ const lookup_actions save = new_service->actions[2 + status]; -+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; -+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; -+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; -+ new_service->actions[2 + NSS_STATUS_SUCCESS] = action; -+ new_service->actions[2 + status] = save; -+ } -+ else -+ new_service->actions[2 + status] = action; -+ -+ /* Skip white spaces. */ -+ while (isspace (line[0])) -+ ++line; -+ } -+ while (line[0] != ']'); -+ -+ /* Skip the ']'. */ -+ ++line; -+ } -+ -+ *nextp = new_service; -+ nextp = &new_service->next; -+ } -+} -+ -+static name_database_entry * -+internal_function -+nss_getline (char *line) -+{ -+ const char *name; -+ name_database_entry *result; -+ size_t len; -+ -+ /* Ignore leading white spaces. ATTENTION: this is different from -+ what is implemented in Solaris. The Solaris man page says a line -+ beginning with a white space character is ignored. We regard -+ this as just another misfeature in Solaris. */ -+ while (isspace (line[0])) -+ ++line; -+ -+ /* Recognize ` ":"'. */ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') -+ ++line; -+ if (line[0] == '\0' || name == line) -+ /* Syntax error. */ -+ return NULL; -+ *line++ = '\0'; -+ -+ len = strlen (name) + 1; -+ -+ result = (name_database_entry *) xmalloc (sizeof (*result)); -+ result->name = (char *) xmalloc (len); -+ -+ /* Save the database name. */ -+ memcpy ((char *) result->name, name, len); -+ -+ /* Parse the list of services. */ -+ result->service = nss_parse_service_list (line); -+ -+ result->next = NULL; -+ return result; -+} -+ -+ -+ -+/* Generating code for statically initialized nsswitch structures. */ -+ -+ -+/* Return the service-neutral suffix of the name of the service -+ library function referred to by the function F. The result is -+ allocated with malloc. */ -+char * -+known_function_suffix (const struct function *f) -+{ -+ switch (f->kind) -+ { -+ case fk_setent: -+ return saprintf ("set%sent", f->entry); -+ -+ case fk_getent: -+ return saprintf ("get%sent_r", f->entry); -+ -+ case fk_endent: -+ return saprintf ("end%sent", f->entry); -+ -+ case fk_getby: -+ return saprintf ("get%sby%s_r", f->entry, f->key); -+ -+ case fk_get: -+ return saprintf ("get%s_r", f->value_and_key); -+ -+ default: -+ abort (); -+ } -+} -+ -+ -+/* Return the name of the service library function referred to by the -+ function F. The result is allocated with malloc. */ -+char * -+known_function_name (const struct function *f) -+{ -+ return saprintf ("_nss_%s_%s", f->service, known_function_suffix (f)); -+} -+ -+ -+/* Write initialized known_function structures to OUT for -+ all the functions we'll use. */ -+void -+generate_known_functions (FILE *out) -+{ -+ int i; -+ -+ /* First, generate weak references to the functions. The service -+ libraries depend on libc, and if these references weren't weak, -+ we'd be making libc depend circularly on the service -+ libraries. */ -+ for (i = 0; functions[i].kind; i++) -+ { -+ char *name = known_function_name (&functions[i]); -+ fprintf (out, "typeof (%s) %s __attribute__ ((weak));\n", -+ name, name); -+ } -+ fputs ("\n", out); -+ -+ /* Then, a table mapping names to functions. */ -+ fputs ("static const known_function fixed_known_functions[] = {\n", -+ out); -+ for (i = 0; functions[i].kind; i++) -+ { -+ const struct function *f = &functions[i]; -+ char *suffix = known_function_suffix (f); -+ -+ fprintf (out, " /* %2d */ { \"%s\", _nss_%s_%s },\n", -+ i, suffix, f->service, suffix); -+ } -+ fputs ("};\n", out); -+ fputs ("\n", out); -+} -+ -+ -+/* Print code to OUT for an initialized array of pointers to the -+ 'known_function' structures needed for USER, which is for -+ DATABASE. Return its name, allocated with malloc. */ -+char * -+generate_known_function_list (FILE *out, -+ const name_database_entry *database, -+ const service_user *user) -+{ -+ char *list_name = saprintf ("fixed_%s_%s_known_funcs", -+ database->name, user->name); -+ fprintf (out, "static const known_function *%s[] = {\n", -+ list_name); -+ int i; -+ for (i = 0; functions[i].kind; i++) -+ if (strcmp (functions[i].database, database->name) == 0 -+ && strcmp (functions[i].service, user->name) == 0) -+ fprintf (out, " &fixed_known_functions[%d], /* %s */\n", -+ i, known_function_name (&functions[i])); -+ fputs (" NULL\n", out); -+ fputs ("};\n", out); -+ fputs ("\n", out); -+ -+ return list_name; -+} -+ -+ -+/* Return the name of the status value STATUS, as a statically -+ allocated string. */ -+const char * -+lookup_status_name (enum nss_status status) -+{ -+ switch (status) -+ { -+ case NSS_STATUS_TRYAGAIN: return "NSS_STATUS_TRYAGAIN"; -+ case NSS_STATUS_UNAVAIL: return "NSS_STATUS_UNAVAIL"; -+ case NSS_STATUS_NOTFOUND: return "NSS_STATUS_NOTFOUND"; -+ case NSS_STATUS_SUCCESS: return "NSS_STATUS_SUCCESS"; -+ case NSS_STATUS_RETURN: return "NSS_STATUS_RETURN"; -+ default: abort (); -+ }; -+} -+ -+ -+/* Return the name of ACTION as a statically allocated string. */ -+const char * -+lookup_action_name (lookup_actions action) -+{ -+ switch (action) -+ { -+ case NSS_ACTION_CONTINUE: return "NSS_ACTION_CONTINUE"; -+ case NSS_ACTION_RETURN: return "NSS_ACTION_RETURN"; -+ default: abort (); -+ } -+} -+ -+ -+/* Print code to OUT for the list of service_user structures starting -+ with USER, which are all for DATABASE. Return the name of the -+ first structure in that list, or zero if USER is NULL. */ -+char * -+generate_service_user_list (FILE *out, -+ name_database_entry *database, -+ service_user *user) -+{ -+ if (user) -+ { -+ /* Generate the tail of the list. */ -+ char *next_name = generate_service_user_list (out, database, user->next); -+ /* Generate our known function list. */ -+ char *known_function_list_name = -+ generate_known_function_list (out, database, user); -+ -+ char *name = saprintf ("fixed_%s_%s_user", database->name, user->name); -+ -+ fprintf (out, "static const service_user %s = {\n", name); -+ if (next_name) -+ fprintf (out, " (service_user *) &%s,\n", next_name); -+ else -+ fprintf (out, " NULL, /* no next entry */\n"); -+ fputs (" {\n", out); -+ int i; -+ for (i = 0; i < sizeof (user->actions) / sizeof (user->actions[0]); i++) -+ fprintf (out, " %s, /* %s */\n", -+ lookup_action_name (user->actions[i]), -+ lookup_status_name (i - 2)); -+ fputs (" },\n", out); -+ fprintf (out, " NULL, /* we never need the service library */\n"); -+ fprintf (out, " { .array = %s },\n", known_function_list_name); -+ fprintf (out, " \"%s\"\n", user->name); -+ fputs ("};\n", out); -+ fputs ("\n", out); -+ -+ return name; -+ } -+ else -+ return NULL; -+} -+ -+ -+/* Print code to OUT for the list of name_database_entry structures -+ starting with DATABASE. Return the name of the first structure -+ in that list, or zero if DATABASE is NULL. */ -+char * -+generate_name_database_entries (FILE *out, name_database_entry *database) -+{ -+ if (database) -+ { -+ char *next_name = generate_name_database_entries (out, database->next); -+ char *service_user_name -+ = generate_service_user_list (out, database, database->service); -+ char *name = saprintf ("fixed_%s_name_database", database->name); -+ -+ fprintf (out, "static const name_database_entry %s = {\n", name); -+ -+ if (next_name) -+ fprintf (out, " (name_database_entry *) &%s,\n", next_name); -+ else -+ fprintf (out, " NULL,\n"); -+ -+ if (service_user_name) -+ fprintf (out, " (service_user *) &%s,\n", service_user_name); -+ else -+ fprintf (out, " NULL,\n"); -+ -+ fprintf (out, " \"%s\"\n", database->name); -+ fprintf (out, "};\n"); -+ fputs ("\n", out); -+ -+ return name; -+ } -+ else -+ return NULL; -+} -+ -+ -+void -+generate_name_database (FILE *out, name_database *service_table) -+{ -+ /* Produce a linked list of the known name_database_entry -+ structures. */ -+ char *entries = generate_name_database_entries (out, service_table->entry); -+ -+ /* Now produce the main structure that points to them all. */ -+ fprintf (out, "static const name_database fixed_name_database = {\n"); -+ if (entries) -+ fprintf (out, " (name_database_entry *) &%s,\n", entries); -+ else -+ fprintf (out, " NULL,\n"); -+ fputs (" NULL /* we don't need the libraries */\n" -+ "};\n", -+ out); -+} -+ -+ -+ -+/* Generating the list of service libraries we generate references to. */ -+ -+/* String with revision number of the shared object files. */ -+static const char *const nss_shlib_revision = LIBNSS_FILES_SO + 15; -+ -+void -+generate_service_lib_list (FILE *out, name_database *service_table) -+{ -+ int i, j; -+ int printed_any = 0; -+ -+ for (i = 0; functions[i].kind; i++) -+ { -+ /* Mention each service library only once. */ -+ for (j = 0; j < i; j++) -+ if (strcmp (functions[i].service, functions[j].service) == 0) -+ break; -+ -+ if (j >= i) -+ { -+ if (printed_any) -+ putc (' ', out); -+ fprintf (out, "-lnss_%s", -+ functions[i].service, -+ nss_shlib_revision); -+ printed_any = 1; -+ } -+ } -+} -+ -+ -+/* Main. */ -+ -+int -+main (int argc, char **argv) -+{ -+ if (argc != 4) -+ { -+ fprintf (stderr, "usage: gen-fixed-nsswitch HEADER SERVLIBS CONFIG\n"); -+ exit (1); -+ } -+ -+ name_database *service_table = nss_parse_file (argv[3]); -+ -+ FILE *header = fopen (argv[1], "w"); -+ if (! header) -+ { -+ fprintf (stderr, -+ "gen-fixed-nsswitch: couldn't open output file %s: %s\n", -+ argv[1], strerror (errno)); -+ exit (1); -+ } -+ fputs ("/* Generated by nss/gen-fixed-nsswitch.c. */\n", header); -+ fputs ("\n", header); -+ generate_known_functions (header); -+ generate_name_database (header, service_table); -+ fclose (header); -+ -+ FILE *service_lib_list = fopen (argv[2], "w"); -+ if (! service_lib_list) -+ { -+ fprintf (stderr, -+ "gen-fixed-nsswitch: couldn't open output file %s: %s\n", -+ argv[2], strerror (errno)); -+ exit (1); -+ } -+ generate_service_lib_list (service_lib_list, service_table); -+ fclose (service_lib_list); -+ -+ return 0; -+} -Index: git/nss/getent.c -=================================================================== ---- git.orig/nss/getent.c -+++ git/nss/getent.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - - /* Get libc version number. */ - #include -@@ -91,6 +92,7 @@ warranty; not even for MERCHANTABILITY o - fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk"); - } - -+#if __OPTION_EGLIBC_DB_ALIASES - /* This is for aliases */ - static void - print_aliases (struct aliasent *alias) -@@ -135,7 +137,9 @@ aliases_keys (int number, char *key[]) - - return result; - } -+#endif /* __OPTION_EGLIBC_DB_ALIASES */ - -+#if __OPTION_EGLIBC_INET - /* This is for ethers */ - static int - ethers_keys (int number, char *key[]) -@@ -179,6 +183,7 @@ ethers_keys (int number, char *key[]) - - return result; - } -+#endif /* __OPTION_EGLIBC_INET */ - - /* This is for group */ - static void -@@ -301,6 +306,7 @@ gshadow_keys (int number, char *key[]) - return result; - } - -+#if __OPTION_EGLIBC_INET - /* This is for hosts */ - static void - print_hosts (struct hostent *host) -@@ -598,6 +604,7 @@ networks_keys (int number, char *key[]) - - return result; - } -+#endif /* __OPTION_EGLIBC_INET */ - - /* Now is all for passwd */ - static void -@@ -650,6 +657,7 @@ passwd_keys (int number, char *key[]) - return result; - } - -+#if __OPTION_EGLIBC_INET - /* This is for protocols */ - static void - print_protocols (struct protoent *proto) -@@ -805,6 +813,7 @@ services_keys (int number, char *key[]) - - return result; - } -+#endif /* __OPTION_EGLIBC_INET */ - - /* This is for shadow */ - static void -@@ -871,21 +880,34 @@ struct - } databases[] = - { - #define D(name) { #name, name ## _keys }, --D(ahosts) --D(ahostsv4) --D(ahostsv6) --D(aliases) --D(ethers) -+ -+#if __OPTION_EGLIBC_INET -+#define DN(name) D(name) -+#else -+#define DN(name) -+#endif -+ -+#if __OPTION_EGLIBC_DB_ALIASES -+#define DA(name) D(name) -+#else -+#define DA(name) -+#endif -+ -+DN(ahosts) -+DN(ahostsv4) -+DN(ahostsv6) -+DA(aliases) -+DN(ethers) - D(group) - D(gshadow) --D(hosts) --D(initgroups) --D(netgroup) --D(networks) -+DN(hosts) -+DN(initgroups) -+DN(netgroup) -+DN(networks) - D(passwd) --D(protocols) --D(rpc) --D(services) -+DN(protocols) -+DN(rpc) -+DN(services) - D(shadow) - #undef D - { NULL, NULL } -Index: git/nss/getnssent_r.c -=================================================================== ---- git.orig/nss/getnssent_r.c -+++ git/nss/getnssent_r.c -@@ -16,6 +16,7 @@ - . */ - - #include -+#include - #include - #include "nsswitch.h" - -@@ -59,11 +60,13 @@ __nss_setent (const char *func_name, db_ - } fct; - int no_more; - -+#if __OPTION_EGLIBC_INET - if (res && __res_maybe_init (&_res, 0) == -1) - { - __set_h_errno (NETDB_INTERNAL); - return; - } -+#endif /* __OPTION_EGLIBC_INET */ - - /* Cycle through the services and run their `setXXent' functions until - we find an available service. */ -@@ -101,11 +104,13 @@ __nss_endent (const char *func_name, db_ - } fct; - int no_more; - -+#if __OPTION_EGLIBC_INET - if (res && __res_maybe_init (&_res, 0) == -1) - { - __set_h_errno (NETDB_INTERNAL); - return; - } -+#endif /* __OPTION_EGLIBC_INET */ - - /* Cycle through all the services and run their endXXent functions. */ - no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1); -@@ -141,12 +146,14 @@ __nss_getent_r (const char *getent_func_ - int no_more; - enum nss_status status; - -+#if __OPTION_EGLIBC_INET - if (res && __res_maybe_init (&_res, 0) == -1) - { - *h_errnop = NETDB_INTERNAL; - *result = NULL; - return errno; - } -+#endif /* __OPTION_EGLIBC_INET */ - - /* Initialize status to return if no more functions are found. */ - status = NSS_STATUS_NOTFOUND; -@@ -161,7 +168,7 @@ __nss_getent_r (const char *getent_func_ - int is_last_nip = *nip == *last_nip; - - status = DL_CALL_FCT (fct.f, -- (resbuf, buffer, buflen, &errno, &h_errno)); -+ (resbuf, buffer, buflen, &errno, h_errnop)); - - /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the - provided buffer is too small. In this case we should give -Index: git/nss/Makefile -=================================================================== ---- git.orig/nss/Makefile -+++ git/nss/Makefile -@@ -18,29 +18,36 @@ - # - # Makefile for name service switch. - # -+include ../option-groups.mak -+ - subdir := nss - - include ../Makeconfig - - headers := nss.h - --# This is the trivial part which goes into libc itself. --routines = nsswitch getnssent getnssent_r digits_dots \ -- $(addsuffix -lookup,$(databases)) -- - # These are the databases that go through nss dispatch. - # Caution: if you add a database here, you must add its real name - # in databases.def, too. --databases = proto service hosts network grp pwd rpc ethers \ -- spwd netgrp key alias sgrp -+databases-y = grp pwd spwd sgrp -+databases-$(OPTION_EGLIBC_INET) \ -+ += proto service hosts network rpc ethers \ -+ netgrp key -+databases-$(OPTION_EGLIBC_DB_ALIASES) += alias -+ -+# This is the trivial part which goes into libc itself. -+routines-y += nsswitch getnssent getnssent_r \ -+ $(addsuffix -lookup,$(databases-y)) -+routines-$(OPTION_EGLIBC_INET) += digits_dots - - others := getent makedb - install-bin := getent makedb - makedb-modules = xmalloc hash-string - extra-objs += $(makedb-modules:=.o) - --tests = test-netdb tst-nss-test1 test-digits-dots --xtests = bug-erange -+tests = tst-nss-test1 -+tests-$(OPTION_EGLIBC_INET) += test-netdb test-digits-dots -+xtests-$(OPTION_EGLIBC_INET) += bug-erange - - # Specify rules for the nss_* modules. We have some services. - services := files db -@@ -55,7 +62,7 @@ subdir-dirs = $(services:%=nss_%) - vpath %.c $(subdir-dirs) ../locale/programs ../intl - - --libnss_files-routines := $(addprefix files-,$(databases)) \ -+libnss_files-routines := $(addprefix files-,$(databases-y)) \ - files-initgroups files-have_o_cloexec files-init - - libnss_db-dbs := $(addprefix db-,\ -@@ -78,6 +85,45 @@ tests-static = tst-nss-static - tests += $(tests-static) - endif - -+ifneq ($(OPTION_EGLIBC_NSSWITCH),y) -+ -+ifndef OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG -+$(error OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG variable left unset) -+endif -+ -+ifndef OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS -+$(error OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS variable left unset) -+endif -+ -+ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG))) -+$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed config file) -+$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)) -+endif -+ -+ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS))) -+$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed functions file) -+$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)) -+endif -+ -+before-compile := $(objpfx)fixed-nsswitch.h -+generated := fixed-nsswitch.h -+$(objpfx)fixed-nsswitch.h $(objfpx)fixed-nsswitch-libs: \ -+ $(objpfx)gen-fixed-nsswitch \ -+ $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG) -+ $< $(objpfx)fixed-nsswitch.h \ -+ $(objpfx)fixed-nsswitch-libs \ -+ $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG) -+ -+$(objpfx)gen-fixed-nsswitch: gen-fixed-nsswitch.c \ -+ $(common-objpfx)option-groups.config \ -+ $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS) -+ $(native-compile) -+gen-fixed-nsswitch-CFLAGS = \ -+ -g3 -O -Wall \ -+ -I $(objpfx) \ -+ -DFIXED_FUNCTIONS='"$(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)"' -+endif -+ - include ../Rules - - ifeq (yes,$(have-selinux)) -Index: git/nss/nsswitch.c -=================================================================== ---- git.orig/nss/nsswitch.c -+++ git/nss/nsswitch.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -41,6 +42,15 @@ - #include "../nscd/nscd_proto.h" - #include - -+/* When OPTION_EGLIBC_NSSWITCH is disabled, we use fixed tables of -+ databases and services, generated at library build time. Thus: -+ - We can't reconfigure individual databases, so we don't need a -+ name-to-database map. -+ - We never add databases or service libraries, or look up functions -+ at runtime, so there's no need for a lock to protect our tables. -+ See ../option-groups.def for the details. */ -+#if __OPTION_EGLIBC_NSSWITCH -+ - /* Prototypes for the local functions. */ - static name_database *nss_parse_file (const char *fname) internal_function; - static name_database_entry *nss_getline (char *line) internal_function; -@@ -79,6 +89,9 @@ bool __nss_database_custom[NSS_DBSIDX_ma - - __libc_lock_define_initialized (static, lock) - -+#define lock_nsswitch __libc_lock_lock (lock) -+#define unlock_nsswitch __libc_lock_unlock (lock) -+ - #if !defined DO_STATIC_NSS || defined SHARED - /* String with revision number of the shared object files. */ - static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15; -@@ -93,6 +106,20 @@ static name_database *service_table; - __libc_freeres. */ - static name_database_entry *defconfig_entries; - -+#else /* __OPTION_EGLIBC_NSSWITCH */ -+ -+/* Bring in the statically initialized service table we generated at -+ build time. */ -+#include "fixed-nsswitch.h" -+ -+const static name_database *service_table = &fixed_name_database; -+ -+/* Nothing ever changes, so there's no need to lock anything. */ -+#define lock_nsswitch (0) -+#define unlock_nsswitch (0) -+ -+#endif /* __OPTION_EGLIBC_NSSWITCH */ -+ - - #ifdef USE_NSCD - /* Nonzero if this is the nscd process. */ -@@ -109,20 +136,22 @@ __nss_database_lookup (const char *datab - const char *defconfig, service_user **ni) - { - /* Prevent multiple threads to change the service table. */ -- __libc_lock_lock (lock); -+ lock_nsswitch; - - /* Reconsider database variable in case some other thread called - `__nss_configure_lookup' while we waited for the lock. */ - if (*ni != NULL) - { -- __libc_lock_unlock (lock); -+ unlock_nsswitch; - return 0; - } - -+#if __OPTION_EGLIBC_NSSWITCH - /* Are we initialized yet? */ - if (service_table == NULL) - /* Read config file. */ - service_table = nss_parse_file (_PATH_NSSWITCH_CONF); -+#endif - - /* Test whether configuration data is available. */ - if (service_table != NULL) -@@ -144,6 +173,7 @@ __nss_database_lookup (const char *datab - *ni = entry->service; - } - -+#if __OPTION_EGLIBC_NSSWITCH - /* No configuration data is available, either because nsswitch.conf - doesn't exist or because it doesn't have a line for this database. - -@@ -166,13 +196,23 @@ __nss_database_lookup (const char *datab - { - entry->next = defconfig_entries; - entry->service = *ni; -- entry->name[0] = '\0'; -+ entry->name = ""; - defconfig_entries = entry; - } - } - } -+#else -+ /* Without the dynamic behavior, we can't process defconfig. The -+ databases the user specified at library build time are all you -+ get. */ -+ if (*ni == NULL) -+ { -+ unlock_nsswitch; -+ return -1; -+ } -+#endif - -- __libc_lock_unlock (lock); -+ unlock_nsswitch; - - return *ni != NULL ? 0 : -1; - } -@@ -252,6 +292,7 @@ __nss_next2 (service_user **ni, const ch - libc_hidden_def (__nss_next2) - - -+#if __OPTION_EGLIBC_NSSWITCH - int - attribute_compat_text_section - __nss_next (service_user **ni, const char *fct_name, void **fctp, int status, -@@ -300,13 +341,13 @@ __nss_configure_lookup (const char *dbna - } - - /* Prevent multiple threads to change the service table. */ -- __libc_lock_lock (lock); -+ lock_nsswitch; - - /* Install new rules. */ - *databases[cnt].dbp = new_db; - __nss_database_custom[cnt] = true; - -- __libc_lock_unlock (lock); -+ unlock_nsswitch; - - return 0; - } -@@ -402,7 +443,7 @@ __nss_lookup_function (service_user *ni, - void **found, *result; - - /* We now modify global data. Protect it. */ -- __libc_lock_lock (lock); -+ lock_nsswitch; - - /* Search the tree of functions previously requested. Data in the - tree are `known_function' structures, whose first member is a -@@ -413,7 +454,7 @@ __nss_lookup_function (service_user *ni, - enough to a pointer to our structure to use as a lookup key that - will be passed to `known_compare' (above). */ - -- found = __tsearch (&fct_name, &ni->known, &known_compare); -+ found = __tsearch (&fct_name, &ni->known.tree, &known_compare); - if (found == NULL) - /* This means out-of-memory. */ - result = NULL; -@@ -440,7 +481,7 @@ __nss_lookup_function (service_user *ni, - #endif - /* Oops. We can't instantiate this node properly. - Remove it from the tree. */ -- __tdelete (&fct_name, &ni->known, &known_compare); -+ __tdelete (&fct_name, &ni->known.tree, &known_compare); - free (known); - result = NULL; - } -@@ -520,13 +561,43 @@ __nss_lookup_function (service_user *ni, - } - - /* Remove the lock. */ -- __libc_lock_unlock (lock); -+ unlock_nsswitch; - - return result; - } - libc_hidden_def (__nss_lookup_function) - - -+#else /* below if ! __OPTION_EGLIBC_NSSWITCH */ -+ -+ -+int -+__nss_configure_lookup (const char *dbname, const char *service_line) -+{ -+ /* We can't dynamically configure lookup without -+ OPTION_EGLIBC_NSSWITCH. */ -+ __set_errno (EINVAL); -+ return -1; -+} -+ -+ -+void * -+__nss_lookup_function (service_user *ni, const char *fct_name) -+{ -+ int i; -+ const known_function **known = ni->known.array; -+ -+ for (i = 0; known[i]; i++) -+ if (strcmp (fct_name, known[i]->fct_name) == 0) -+ return known[i]->fct_ptr; -+ -+ return NULL; -+} -+libc_hidden_def (__nss_lookup_function) -+#endif -+ -+ -+#if __OPTION_EGLIBC_NSSWITCH - static name_database * - internal_function - nss_parse_file (const char *fname) -@@ -632,8 +703,10 @@ nss_parse_service_list (const char *line - + (line - name + 1)); - if (new_service == NULL) - return result; -+ new_service->name = (char *) (new_service + 1); - -- *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; -+ *((char *) __mempcpy ((char *) new_service->name, name, line - name)) -+ = '\0'; - - /* Set default actions. */ - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; -@@ -642,7 +715,7 @@ nss_parse_service_list (const char *line - new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; - new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; - new_service->library = NULL; -- new_service->known = NULL; -+ new_service->known.tree = NULL; - new_service->next = NULL; - - while (isspace (line[0])) -@@ -778,9 +851,10 @@ nss_getline (char *line) - result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); - if (result == NULL) - return NULL; -+ result->name = (char *) (result + 1); - - /* Save the database name. */ -- memcpy (result->name, name, len); -+ memcpy ((char *) result->name, name, len); - - /* Parse the list of services. */ - result->service = nss_parse_service_list (line); -@@ -816,6 +890,7 @@ nss_new_service (name_database *database - return *currentp; - } - #endif -+#endif /* __OPTION_EGLIBC_NSSWITCH */ - - - #if defined SHARED && defined USE_NSCD -@@ -834,6 +909,7 @@ nss_load_all_libraries (const char *serv - } - - -+#if __OPTION_EGLIBC_INET - /* Called by nscd and nscd alone. */ - void - __nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) -@@ -857,8 +933,10 @@ __nss_disable_nscd (void (*cb) (size_t, - __nss_not_use_nscd_services = -1; - __nss_not_use_nscd_netgroup = -1; - } -+#endif /* __OPTION_EGLIBC_INET */ - #endif - -+#if __OPTION_EGLIBC_NSSWITCH - static void - free_database_entries (name_database_entry *entry) - { -@@ -871,8 +949,8 @@ free_database_entries (name_database_ent - { - service_user *olds = service; - -- if (service->known != NULL) -- __tdestroy (service->known, free); -+ if (service->known.tree != NULL) -+ __tdestroy (service->known.tree, free); - - service = service->next; - free (olds); -@@ -926,3 +1004,4 @@ libc_freeres_fn (free_mem) - - free (top); - } -+#endif /* __OPTION_EGLIBC_NSSWITCH */ -Index: git/nss/nsswitch.h -=================================================================== ---- git.orig/nss/nsswitch.h -+++ git/nss/nsswitch.h -@@ -65,10 +65,20 @@ typedef struct service_user - lookup_actions actions[5]; - /* Link to the underlying library object. */ - service_library *library; -- /* Collection of known functions. */ -- void *known; -+ /* Collection of known functions. -+ -+ With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a -+ 'tsearch'-style tree. -+ -+ With OPTION_EGLIBC_NSSWITCH disabled, this is an array of -+ pointers to known_function structures, NULL-terminated. */ -+ union -+ { -+ void *tree; -+ const known_function **array; -+ } known; - /* Name of the service (`files', `dns', `nis', ...). */ -- char name[0]; -+ const char *name; - } service_user; - - /* To access the action based on the status value use this macro. */ -@@ -82,7 +92,7 @@ typedef struct name_database_entry - /* List of service to be used. */ - service_user *service; - /* Name of the database. */ -- char name[0]; -+ const char *name; - } name_database_entry; - - -Index: git/posix/bug-regex1.c -=================================================================== ---- git.orig/posix/bug-regex1.c -+++ git/posix/bug-regex1.c -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - int - main (void) -@@ -17,7 +18,9 @@ main (void) - memset (®ex, '\0', sizeof (regex)); - - setlocale (LC_ALL, "de_DE.ISO-8859-1"); -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - fwide (stdout, -1); -+#endif - - re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_DEBUG); - -Index: git/posix/bug-regex6.c -=================================================================== ---- git.orig/posix/bug-regex6.c -+++ git/posix/bug-regex6.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - - int -@@ -30,7 +31,12 @@ main (int argc, char *argv[]) - regex_t re; - regmatch_t mat[10]; - int i, j, ret = 0; -- const char *locales[] = { "C", "de_DE.UTF-8" }; -+ const char *locales[] = { -+ "C", -+#if __OPTION_EGLIBC_LOCALE_CODE -+ "de_DE.UTF-8" -+#endif -+ }; - const char *string = "http://www.regex.com/pattern/matching.html#intro"; - regmatch_t expect[10] = { - { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 }, -Index: git/posix/fnmatch.c -=================================================================== ---- git.orig/posix/fnmatch.c -+++ git/posix/fnmatch.c -@@ -30,6 +30,10 @@ - #include - #include - -+#if defined _LIBC -+# include -+#endif -+ - #if defined STDC_HEADERS || defined _LIBC - # include - #endif -@@ -131,7 +135,7 @@ extern int fnmatch (const char *pattern, - # define ISWCTYPE(WC, WT) iswctype (WC, WT) - # endif - --# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC -+# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS && _LIBC && __OPTION_EGLIBC_LOCALE_CODE) - /* In this case we are implementing the multibyte character handling. */ - # define HANDLE_MULTIBYTE 1 - # endif -Index: git/posix/fnmatch_loop.c -=================================================================== ---- git.orig/posix/fnmatch_loop.c -+++ git/posix/fnmatch_loop.c -@@ -15,6 +15,8 @@ - License along with the GNU C Library; if not, see - . */ - -+#include -+ - #include - - struct STRUCT -@@ -54,10 +56,15 @@ FCT (pattern, string, string_end, no_lea - const char *collseq = (const char *) - _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); - # else -+# if __OPTION_EGLIBC_LOCALE_CODE - const UCHAR *collseq = (const UCHAR *) - _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); --# endif --#endif -+# define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)]) -+# else -+# define COLLSEQ_BYTE_LOOKUP(ix) (ix) -+# endif /* __OPTION_EGLIBC_LOCALE_CODE */ -+# endif /* WIDE_CHAR_VERSION */ -+#endif /* _LIBC */ - - while ((c = *p++) != L('\0')) - { -@@ -277,7 +284,7 @@ FCT (pattern, string, string_end, no_lea - /* Leave room for the null. */ - CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; - size_t c1 = 0; --#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) -+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) - wctype_t wt; - #endif - const CHAR *startp = p; -@@ -307,7 +314,7 @@ FCT (pattern, string, string_end, no_lea - } - str[c1] = L('\0'); - --#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) -+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) - wt = IS_CHAR_CLASS (str); - if (wt == 0) - /* Invalid character class name. */ -@@ -680,8 +687,10 @@ FCT (pattern, string, string_end, no_lea - else - lcollseq = __collseq_table_lookup (collseq, cold); - # else -- fcollseq = collseq[fn]; -- lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; -+ fcollseq = COLLSEQ_BYTE_LOOKUP (fn); -+ lcollseq = (is_seqval -+ ? cold -+ : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold)); - # endif - - is_seqval = 0; -@@ -857,7 +866,7 @@ FCT (pattern, string, string_end, no_lea - goto matched; - } - # else -- hcollseq = collseq[cend]; -+ hcollseq = COLLSEQ_BYTE_LOOKUP (cend); - # endif - } - -Index: git/posix/glob.c -=================================================================== ---- git.orig/posix/glob.c -+++ git/posix/glob.c -@@ -25,6 +25,9 @@ - #include - #include - #include -+#ifdef _LIBC -+# include -+#endif - - /* Outcomment the following line for production quality code. */ - /* #define NDEBUG 1 */ -@@ -607,6 +610,7 @@ glob (pattern, flags, errfunc, pglob) - if (home_dir == NULL || home_dir[0] == '\0') - home_dir = "c:/users/default"; /* poor default */ - # else -+# if ! _LIBC || __OPTION_EGLIBC_GETLOGIN - if (home_dir == NULL || home_dir[0] == '\0') - { - int success; -@@ -623,19 +627,19 @@ glob (pattern, flags, errfunc, pglob) - if (success) - { - struct passwd *p; --# if defined HAVE_GETPWNAM_R || defined _LIBC -+# if defined HAVE_GETPWNAM_R || defined _LIBC - long int pwbuflen = GETPW_R_SIZE_MAX (); - char *pwtmpbuf; - struct passwd pwbuf; - int malloc_pwtmpbuf = 0; - int save = errno; - --# ifndef _LIBC -+# ifndef _LIBC - if (pwbuflen == -1) - /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. - Try a moderate value. */ - pwbuflen = 1024; --# endif -+# endif - if (__libc_use_alloca (alloca_used + pwbuflen)) - pwtmpbuf = alloca_account (pwbuflen, alloca_used); - else -@@ -682,9 +686,9 @@ glob (pattern, flags, errfunc, pglob) - } - __set_errno (save); - } --# else -+# else - p = getpwnam (name); --# endif -+# endif - if (p != NULL) - { - if (!malloc_pwtmpbuf) -@@ -713,6 +717,7 @@ glob (pattern, flags, errfunc, pglob) - } - } - } -+# endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */ - if (home_dir == NULL || home_dir[0] == '\0') - { - if (flags & GLOB_TILDE_CHECK) -Index: git/posix/Makefile -=================================================================== ---- git.orig/posix/Makefile -+++ git/posix/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for POSIX portion of the library. - # -+include ../option-groups.mak -+ - subdir := posix - - include ../Makeconfig -@@ -43,13 +45,24 @@ routines := \ - getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \ - getresuid getresgid setresuid setresgid \ - pathconf sysconf fpathconf \ -- glob glob64 fnmatch regex \ -+ glob glob64 fnmatch \ - confstr \ - getopt getopt1 getopt_init \ - sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \ - sched_primin sched_rr_gi sched_getaffinity sched_setaffinity \ -- getaddrinfo gai_strerror wordexp \ - pread pwrite pread64 pwrite64 \ -+ posix_madvise \ -+ get_child_max sched_cpucount sched_cpualloc sched_cpufree -+ -+routines-$(OPTION_EGLIBC_INET) += getaddrinfo gai_strerror -+ -+ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC)) -+routines-$(OPTION_POSIX_REGEXP) += regex -+else -+routines-$(OPTION_POSIX_REGEXP) += xregex -+endif -+ -+routines-$(OPTION_EGLIBC_SPAWN) += \ - spawn_faction_init spawn_faction_destroy spawn_faction_addclose \ - spawn_faction_addopen spawn_faction_adddup2 \ - spawnattr_init spawnattr_destroy \ -@@ -61,37 +74,53 @@ routines := \ - posix_madvise \ - get_child_max sched_cpucount sched_cpualloc sched_cpufree - -+routines-$(OPTION_EGLIBC_WORDEXP) += wordexp -+ - aux := init-posix environ --tests := tstgetopt testfnm runtests runptests \ -+tests := tstgetopt testfnm runtests \ - tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \ -- tst-getlogin tst-mmap tst-getaddrinfo tst-truncate \ -- tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \ -- tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \ -- tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \ -- bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \ -- bug-regex13 bug-regex14 bug-regex15 bug-regex16 \ -- bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ -- bug-regex21 bug-regex22 bug-regex23 bug-regex24 \ -- bug-regex25 bug-regex26 bug-regex27 bug-regex28 \ -- bug-regex29 bug-regex30 bug-regex31 bug-regex32 \ -- bug-regex33 tst-nice tst-nanosleep tst-regex2 \ -- transbug tst-rxspencer tst-pcre tst-boost \ -- bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \ -- tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \ -+ tst-getlogin tst-mmap tst-truncate \ -+ tst-truncate64 tst-fork tst-dir \ -+ tst-chmod bug-regex2 bug-regex3 bug-regex4 \ -+ tst-gnuglob bug-regex6 bug-regex7 \ -+ bug-regex8 bug-regex9 bug-regex10 bug-regex12 \ -+ bug-regex14 bug-regex15 \ -+ bug-regex21 bug-regex24 \ -+ bug-regex27 bug-regex28 \ -+ bug-regex29 bug-regex30 bug-regex31 \ -+ tst-nice tst-nanosleep \ -+ transbug \ -+ tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \ -+ bug-glob1 bug-glob2 bug-glob3 tst-sysconf \ - tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \ - tst-execv1 tst-execv2 tst-execl1 tst-execl2 \ - tst-execve1 tst-execve2 tst-execle1 tst-execle2 \ -- tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \ -- tst-rfc3484-3 \ -- tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \ -+ tst-execvp3 tst-execvp4 \ -+ tst-fnmatch2 tst-cpucount tst-cpuset \ - bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ - bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ - tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ - tst-fnmatch3 bug-regex36 tst-getaddrinfo5 --xtests := bug-ga2 -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \ -+ bug-regex23 bug-regex25 bug-regex32 bug-regex33 -+tests-$(OPTION_EGLIBC_INET) \ -+ += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \ -+ tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 tst-getaddrinfo3 -+tests-$(OPTION_POSIX_REGEXP_GLIBC) \ -+ += runptests bug-regex11 bug-regex13 bug-regex16 \ -+ tst-regex2 tst-rxspencer tst-pcre tst-boost -+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP_GLIBC)) -+tests += tst-regex bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ -+ bug-regex22 bug-regex26 -+endif -+xtests-$(OPTION_EGLIBC_INET) += bug-ga2 -+ - ifeq (yes,$(build-shared)) - test-srcs := globtest --tests += wordexp-test tst-exec tst-spawn -+tests += tst-exec -+tests-$(OPTION_EGLIBC_SPAWN) += tst-spawn -+tests-$(OPTION_EGLIBC_WORDEXP) += wordexp-test - endif - tests-static = tst-exec-static tst-spawn-static - tests += $(tests-static) -@@ -117,7 +146,10 @@ generated += $(addprefix wordexp-test-re - - ifeq ($(run-built-tests),yes) - ifeq (yes,$(build-shared)) --tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out -+tests-special += $(objpfx)globtest.out -+ifeq (y,$(OPTION_EGLIBC_WORDEXP)) -+tests-special += $(objpfx)wordexp-tst.out -+endif - endif - endif - -@@ -125,12 +157,16 @@ endif - # XXX Please note that for now we ignore the result of this test. - tests-special += $(objpfx)annexc.out - ifeq ($(run-built-tests),yes) --tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \ -+tests-special += $(objpfx)bug-regex2-mem.out \ - $(objpfx)bug-regex21-mem.out $(objpfx)bug-regex31-mem.out \ -- $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \ -- $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \ -+ $(objpfx)tst-getconf.out \ - $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \ - $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out -+ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC)) -+tests-special += $(objpfx)bug-regex14-mem.out $(objpfx)tst-rxspencer-no-utf8-mem.out \ -+ $(objpfx)tst-pcre-mem.out $(objpfx)tst-boost-mem.out -+endif -+ - xtests-special += $(objpfx)bug-ga2-mem.out - endif - -@@ -143,6 +179,8 @@ $(objpfx)globtest.out: globtest.sh $(obj - $(SHELL) $< $(common-objpfx) '$(test-via-rtld-prefix)' \ - '$(test-program-prefix)' '$(test-wrapper-env)'; \ - $(evaluate-test) -+LDLIBS-globtest += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs) -+ - $(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test - $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \ - '$(run-program-env)' '$(test-program-prefix-after-env)'; \ -@@ -205,7 +243,10 @@ tst-dir-ARGS = `pwd` `cd $(common-objdir - tst-chmod-ARGS = $(objdir) - tst-vfork3-ARGS = --test-dir=$(objpfx) - --tst-rxspencer-ARGS = --utf8 rxspencer/tests -+tst-rxspencer-ARGS = rxspencer/tests -+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) -+tst-rxspencer-ARGS += --utf8 -+endif - tst-rxspencer-no-utf8-ARGS = rxspencer/tests - tst-pcre-ARGS = PCRE.tests - tst-boost-ARGS = BOOST.tests -Index: git/posix/regcomp.c -=================================================================== ---- git.orig/posix/regcomp.c -+++ git/posix/regcomp.c -@@ -18,6 +18,7 @@ - . */ - - #include -+#include - - #ifdef _LIBC - # include -@@ -309,7 +310,7 @@ re_compile_fastmap_iter (regex_t *bufp, - { - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - int node_cnt; -- int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); -+ int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE)); - for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) - { - int node = init_state->nodes.elems[node_cnt]; -@@ -319,9 +320,9 @@ re_compile_fastmap_iter (regex_t *bufp, - { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); - #ifdef RE_ENABLE_I18N -- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) -+ if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1) - { -- unsigned char *buf = alloca (dfa->mb_cur_max), *p; -+ unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p; - wchar_t wc; - mbstate_t state; - -@@ -352,7 +353,11 @@ re_compile_fastmap_iter (regex_t *bufp, - re_set_fastmap (fastmap, icase, ch); - } - } --#ifdef RE_ENABLE_I18N -+ -+ /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current -+ locale is always C, which has no rules and no multi-byte -+ characters. */ -+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE - else if (type == COMPLEX_BRACKET) - { - re_charset_t *cset = dfa->nodes[node].opr.mbcset; -@@ -380,7 +385,7 @@ re_compile_fastmap_iter (regex_t *bufp, - i.e. where we would not find an invalid sequence. This only - applies to multibyte character sets; for single byte character - sets, the SIMPLE_BRACKET again suffices. */ -- if (dfa->mb_cur_max > 1 -+ if (dfa_mb_cur_max (dfa) > 1 - && (cset->nchar_classes || cset->non_match || cset->nranges - # ifdef _LIBC - || cset->nequiv_classes -@@ -408,7 +413,7 @@ re_compile_fastmap_iter (regex_t *bufp, - memset (&state, '\0', sizeof (state)); - if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); -- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) -+ if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1) - { - if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) - != (size_t) -1) -@@ -417,7 +422,7 @@ re_compile_fastmap_iter (regex_t *bufp, - } - } - } --#endif /* RE_ENABLE_I18N */ -+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ - else if (type == OP_PERIOD - #ifdef RE_ENABLE_I18N - || type == OP_UTF8_PERIOD -@@ -860,11 +865,15 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) - - dfa->mb_cur_max = MB_CUR_MAX; - #ifdef _LIBC -- if (dfa->mb_cur_max == 6 -+ if (dfa_mb_cur_max (dfa) == 6 - && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) - dfa->is_utf8 = 1; -+# if __OPTION_EGLIBC_LOCALE_CODE - dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) - != 0); -+# else -+ dfa->map_notascii = 0; -+# endif - #else - # ifdef HAVE_LANGINFO_CODESET - codeset_name = nl_langinfo (CODESET); -@@ -890,7 +899,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) - #endif - - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - { - if (dfa->is_utf8) - dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; -@@ -1788,7 +1797,7 @@ peek_token (re_token_t *token, re_string - token->word_char = 0; - #ifdef RE_ENABLE_I18N - token->mb_partial = 0; -- if (input->mb_cur_max > 1 && -+ if (string_mb_cur_max (input) > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; -@@ -1809,7 +1818,7 @@ peek_token (re_token_t *token, re_string - token->opr.c = c2; - token->type = CHARACTER; - #ifdef RE_ENABLE_I18N -- if (input->mb_cur_max > 1) -+ if (string_mb_cur_max (input) > 1) - { - wint_t wc = re_string_wchar_at (input, - re_string_cur_idx (input) + 1); -@@ -1923,7 +1932,7 @@ peek_token (re_token_t *token, re_string - - token->type = CHARACTER; - #ifdef RE_ENABLE_I18N -- if (input->mb_cur_max > 1) -+ if (string_mb_cur_max (input) > 1) - { - wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; -@@ -2023,7 +2032,7 @@ peek_token_bracket (re_token_t *token, r - token->opr.c = c; - - #ifdef RE_ENABLE_I18N -- if (input->mb_cur_max > 1 && -+ if (string_mb_cur_max (input) > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; -@@ -2246,7 +2255,7 @@ parse_expression (re_string_t *regexp, r - return NULL; - } - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - { - while (!re_string_eoi (regexp) - && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) -@@ -2384,7 +2393,7 @@ parse_expression (re_string_t *regexp, r - *err = REG_ESPACE; - return NULL; - } -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - dfa->has_mb_node = 1; - break; - case OP_WORD: -@@ -2690,7 +2699,7 @@ build_range_exp (bitset_t sbcset, bracke - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes -- no MBCSET if dfa->mb_cur_max == 1. */ -+ no MBCSET if dfa_mb_cur_max (dfa) == 1. */ - if (mbcset) - { - /* Check the space of the arrays. */ -@@ -2786,7 +2795,13 @@ parse_bracket_exp (re_string_t *regexp, - reg_syntax_t syntax, reg_errcode_t *err) - { - #ifdef _LIBC -+#if __OPTION_EGLIBC_LOCALE_CODE - const unsigned char *collseqmb; -+# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)]) -+#else -+# define COLLSEQMB_LOOKUP(ix) (ix) -+#endif -+ - const char *collseqwc; - uint32_t nrules; - int32_t table_size; -@@ -2834,18 +2849,20 @@ parse_bracket_exp (re_string_t *regexp, - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) -- return collseqmb[br_elem->opr.ch]; -+ return COLLSEQMB_LOOKUP (br_elem->opr.ch); - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } -+#if __OPTION_EGLIBC_LOCALE_CODE - else if (br_elem->type == MB_CHAR) - { - if (nrules != 0) - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); - } -+#endif - else if (br_elem->type == COLL_SYM) - { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); -@@ -2876,11 +2893,11 @@ parse_bracket_exp (re_string_t *regexp, - { - /* No valid character. Match it as a single byte - character. */ -- return collseqmb[br_elem->opr.name[0]]; -+ return COLLSEQMB_LOOKUP (br_elem->opr.name[0]); - } - } - else if (sym_name_len == 1) -- return collseqmb[br_elem->opr.name[0]]; -+ return COLLSEQMB_LOOKUP (br_elem->opr.name[0]); - } - return UINT_MAX; - } -@@ -2920,7 +2937,7 @@ parse_bracket_exp (re_string_t *regexp, - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ -- if (nrules > 0 || dfa->mb_cur_max > 1) -+ if (nrules > 0 || dfa_mb_cur_max (dfa) > 1) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) -@@ -2957,7 +2974,7 @@ parse_bracket_exp (re_string_t *regexp, - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) -- ch_collseq = collseqmb[ch]; -+ ch_collseq = COLLSEQMB_LOOKUP (ch); - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) -@@ -3035,7 +3052,10 @@ parse_bracket_exp (re_string_t *regexp, - re_bitset_ptr_t sbcset; - #ifdef RE_ENABLE_I18N - re_charset_t *mbcset; -- int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; -+ int coll_sym_alloc = 0, range_alloc = 0; -+#if __OPTION_EGLIBC_LOCALE_CODE -+ int mbchar_alloc = 0; -+#endif - int equiv_class_alloc = 0, char_class_alloc = 0; - #endif /* not RE_ENABLE_I18N */ - int non_match = 0; -@@ -3043,9 +3063,15 @@ parse_bracket_exp (re_string_t *regexp, - int token_len; - int first_round = 1; - #ifdef _LIBC -+#if __OPTION_EGLIBC_LOCALE_CODE - collseqmb = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); -+#else -+ /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the -+ compiler can't figure that out. */ -+ nrules = 0; -+#endif - if (nrules) - { - /* -@@ -3175,7 +3201,7 @@ parse_bracket_exp (re_string_t *regexp, - #else - # ifdef RE_ENABLE_I18N - *err = build_range_exp (sbcset, -- dfa->mb_cur_max > 1 ? mbcset : NULL, -+ dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL, - &range_alloc, &start_elem, &end_elem); - # else - *err = build_range_exp (sbcset, &start_elem, &end_elem); -@@ -3191,7 +3217,7 @@ parse_bracket_exp (re_string_t *regexp, - case SB_CHAR: - bitset_set (sbcset, start_elem.opr.ch); - break; --#ifdef RE_ENABLE_I18N -+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE - case MB_CHAR: - /* Check whether the array has enough space. */ - if (BE (mbchar_alloc == mbcset->nmbchars, 0)) -@@ -3209,7 +3235,7 @@ parse_bracket_exp (re_string_t *regexp, - } - mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; - break; --#endif /* RE_ENABLE_I18N */ -+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ - case EQUIV_CLASS: - *err = build_equiv_class (sbcset, - #ifdef RE_ENABLE_I18N -@@ -3259,11 +3285,11 @@ parse_bracket_exp (re_string_t *regexp, - - #ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - bitset_mask (sbcset, dfa->sb_char); - - if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes -- || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes -+ || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes - || mbcset->non_match))) - { - bin_tree_t *mbc_tree; -@@ -3332,7 +3358,7 @@ parse_bracket_element (bracket_elem_t *e - re_token_t *token, int token_len, re_dfa_t *dfa, - reg_syntax_t syntax, int accept_hyphen) - { --#ifdef RE_ENABLE_I18N -+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE - int cur_char_size; - cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); - if (cur_char_size > 1) -@@ -3342,7 +3368,7 @@ parse_bracket_element (bracket_elem_t *e - re_string_skip_bytes (regexp, cur_char_size); - return REG_NOERROR; - } --#endif /* RE_ENABLE_I18N */ -+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS - || token->type == OP_OPEN_EQUIV_CLASS) -@@ -3422,7 +3448,9 @@ build_equiv_class (bitset_t sbcset, re_c - build_equiv_class (bitset_t sbcset, const unsigned char *name) - #endif /* not RE_ENABLE_I18N */ - { --#ifdef _LIBC -+ /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale -+ is supported; it has no collation rules. */ -+#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { -@@ -3492,7 +3520,7 @@ build_equiv_class (bitset_t sbcset, cons - mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; - } - else --#endif /* _LIBC */ -+#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ - { - if (BE (strlen ((const char *) name) != 1, 0)) - return REG_ECOLLATE; -@@ -3526,7 +3554,7 @@ build_charclass (RE_TRANSLATE_TYPE trans - && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) - name = "alpha"; - --#ifdef RE_ENABLE_I18N -+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE - /* Check the space of the arrays. */ - if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) - { -@@ -3542,7 +3570,7 @@ build_charclass (RE_TRANSLATE_TYPE trans - *char_class_alloc = new_char_class_alloc; - } - mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); --#endif /* RE_ENABLE_I18N */ -+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ - - #define BUILD_CHARCLASS_LOOP(ctype_func) \ - do { \ -@@ -3653,7 +3681,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TR - - #ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - bitset_mask (sbcset, dfa->sb_char); - #endif - -@@ -3665,7 +3693,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TR - goto build_word_op_espace; - - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - { - bin_tree_t *mbc_tree; - /* Build a tree for complex bracket. */ -Index: git/posix/regexec.c -=================================================================== ---- git.orig/posix/regexec.c -+++ git/posix/regexec.c -@@ -18,6 +18,7 @@ - . */ - - #include -+#include - - static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, - int n) internal_function; -@@ -186,11 +187,11 @@ static int build_trtable (const re_dfa_t - static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, - const re_string_t *input, int idx) - internal_function; --# ifdef _LIBC -+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE - static unsigned int find_collation_sequence_value (const unsigned char *mbs, - size_t name_len) - internal_function; --# endif /* _LIBC */ -+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ - #endif /* RE_ENABLE_I18N */ - static int group_nodes_into_DFAstates (const re_dfa_t *dfa, - const re_dfastate_t *state, -@@ -255,25 +256,9 @@ regexec (preg, string, nmatch, pmatch, e - return err != REG_NOERROR; - } - --#ifdef _LIBC --# include --versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); -- --# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) --__typeof__ (__regexec) __compat_regexec; -- --int --attribute_compat_text_section --__compat_regexec (const regex_t *__restrict preg, -- const char *__restrict string, size_t nmatch, -- regmatch_t pmatch[], int eflags) --{ -- return regexec (preg, string, nmatch, pmatch, -- eflags & (REG_NOTBOL | REG_NOTEOL)); --} --compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); --# endif --#endif -+/* EGLIBC: The code that used to be here was move to a separate file -+ so that it can be shared with xregex.c. */ -+#include "regexec-compat.c" - - /* Entry points for GNU code. */ - -@@ -728,7 +713,7 @@ re_search_internal (preg, string, length - incr = (range < 0) ? -1 : 1; - left_lim = (range < 0) ? start + range : start; - right_lim = (range < 0) ? start : start + range; -- sb = dfa->mb_cur_max == 1; -+ sb = dfa_mb_cur_max (dfa) == 1; - match_kind = - (fastmap - ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) -@@ -3448,7 +3433,7 @@ out_free: - if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - -- if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) -+ if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1) - need_word_trtable = 1; - - dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, -@@ -3590,7 +3575,7 @@ group_nodes_into_DFAstates (const re_dfa - else if (type == OP_PERIOD) - { - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - bitset_merge (accepts, dfa->sb_char); - else - #endif -@@ -3641,7 +3626,7 @@ group_nodes_into_DFAstates (const re_dfa - continue; - } - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); - else -@@ -3660,7 +3645,7 @@ group_nodes_into_DFAstates (const re_dfa - continue; - } - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); - else -@@ -3836,12 +3821,6 @@ check_node_accept_bytes (const re_dfa_t - if (node->type == COMPLEX_BRACKET) - { - const re_charset_t *cset = node->opr.mbcset; --# ifdef _LIBC -- const unsigned char *pin -- = ((const unsigned char *) re_string_get_buffer (input) + str_idx); -- int j; -- uint32_t nrules; --# endif /* _LIBC */ - int match_len = 0; - wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) - ? re_string_wchar_at (input, str_idx) : 0); -@@ -3853,6 +3832,7 @@ check_node_accept_bytes (const re_dfa_t - match_len = char_len; - goto check_node_accept_bytes_match; - } -+#if __OPTION_EGLIBC_LOCALE_CODE - /* match with character_class? */ - for (i = 0; i < cset->nchar_classes; ++i) - { -@@ -3863,14 +3843,22 @@ check_node_accept_bytes (const re_dfa_t - goto check_node_accept_bytes_match; - } - } -+#endif -+ -+ /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C -+ locale is supported; it has no collation rules. */ -+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE -+ const unsigned char *pin -+ = ((const unsigned char *) re_string_get_buffer (input) + str_idx); -+ int j; -+ uint32_t nrules; - --# ifdef _LIBC - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - unsigned int in_collseq = 0; - const int32_t *table, *indirect; -- const unsigned char *weights, *extra; -+ const unsigned char *weights, *extra = NULL; - const char *collseqwc; - - /* match with collating_symbol? */ -@@ -3955,8 +3943,12 @@ check_node_accept_bytes (const re_dfa_t - } - } - else --# endif /* _LIBC */ -+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ - { -+ /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is -+ disabled, there can be no multibyte range endpoints, and -+ cset->nranges is always zero. */ -+#if __OPTION_EGLIBC_LOCALE_CODE - /* match with range expression? */ - #if __GNUC__ >= 2 - wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; -@@ -3975,6 +3967,7 @@ check_node_accept_bytes (const re_dfa_t - goto check_node_accept_bytes_match; - } - } -+#endif /* __OPTION_EGLIBC_LOCALE_CODE */ - } - check_node_accept_bytes_match: - if (!cset->non_match) -@@ -3990,7 +3983,7 @@ check_node_accept_bytes (const re_dfa_t - return 0; - } - --# ifdef _LIBC -+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE - static unsigned int - internal_function - find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) -@@ -4048,7 +4041,7 @@ find_collation_sequence_value (const uns - return UINT_MAX; - } - } --# endif /* _LIBC */ -+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ - #endif /* RE_ENABLE_I18N */ - - /* Check whether the node accepts the byte which is IDX-th -@@ -4139,7 +4132,7 @@ extend_buffers (re_match_context_t *mctx - if (pstr->icase) - { - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) -@@ -4152,7 +4145,7 @@ extend_buffers (re_match_context_t *mctx - else - { - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - build_wcs_buffer (pstr); - else - #endif /* RE_ENABLE_I18N */ -Index: git/posix/regexec-compat.c -=================================================================== ---- /dev/null -+++ git/posix/regexec-compat.c -@@ -0,0 +1,39 @@ -+/* Extended regular expression matching and search library. -+ Copyright (C) 2008 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Isamu Hasegawa . -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#ifdef _LIBC -+# include -+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); -+ -+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -+__typeof__ (__regexec) __compat_regexec; -+ -+int -+attribute_compat_text_section -+__compat_regexec (const regex_t *__restrict preg, -+ const char *__restrict string, size_t nmatch, -+ regmatch_t pmatch[], int eflags) -+{ -+ return regexec (preg, string, nmatch, pmatch, -+ eflags & (REG_NOTBOL | REG_NOTEOL)); -+} -+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); -+# endif -+#endif -Index: git/posix/regex.h -=================================================================== ---- git.orig/posix/regex.h -+++ git/posix/regex.h -@@ -21,6 +21,7 @@ - #define _REGEX_H 1 - - #include -+#include - - /* Allow the use in C++ code. */ - #ifdef __cplusplus -@@ -156,6 +157,8 @@ typedef unsigned long int reg_syntax_t; - treated as 'a\{1'. */ - # define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) - -+/* EGLIBC: Old regex implementation does not support these. */ -+# if __OPTION_POSIX_REGEXP_GLIBC - /* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ - # define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) -@@ -172,6 +175,7 @@ typedef unsigned long int reg_syntax_t; - /* If this bit is set, then no_sub will be set to 1 during - re_compile_pattern. */ - # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) -+# endif /* __OPTION_POSIX_REGEXP_GLIBC */ - #endif - - /* This global variable defines the particular regexp syntax to use (for -@@ -231,8 +235,13 @@ extern reg_syntax_t re_syntax_options; - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -+#if __OPTION_POSIX_REGEXP_GLIBC - #define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) -+#else -+#define RE_SYNTAX_POSIX_BASIC \ -+ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) -+#endif - - /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this -@@ -298,9 +307,11 @@ extern reg_syntax_t re_syntax_options; - /* Like REG_NOTBOL, except for the end-of-line. */ - #define REG_NOTEOL (1 << 1) - -+#if __OPTION_POSIX_REGEXP_GLIBC - /* Use PMATCH[0] to delimit the start and end of the search in the - buffer. */ - #define REG_STARTEND (1 << 2) -+#endif - - - /* If any error codes are removed, changed, or added, update the -Index: git/posix/regex_internal.c -=================================================================== ---- git.orig/posix/regex_internal.c -+++ git/posix/regex_internal.c -@@ -43,8 +43,8 @@ re_string_allocate (re_string_t *pstr, c - int init_buf_len; - - /* Ensure at least one character fits into the buffers. */ -- if (init_len < dfa->mb_cur_max) -- init_len = dfa->mb_cur_max; -+ if (init_len < dfa_mb_cur_max (dfa)) -+ init_len = dfa_mb_cur_max (dfa); - init_buf_len = (len + 1 < init_len) ? len + 1: init_len; - re_string_construct_common (str, len, pstr, trans, icase, dfa); - -@@ -55,7 +55,7 @@ re_string_allocate (re_string_t *pstr, c - pstr->word_char = dfa->word_char; - pstr->word_ops_used = dfa->word_ops_used; - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; -- pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; -+ pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len; - pstr->valid_raw_len = pstr->valid_len; - return REG_NOERROR; - } -@@ -82,7 +82,7 @@ re_string_construct (re_string_t *pstr, - if (icase) - { - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - { - while (1) - { -@@ -91,7 +91,7 @@ re_string_construct (re_string_t *pstr, - return ret; - if (pstr->valid_raw_len >= len) - break; -- if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) -+ if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa)) - break; - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) -@@ -105,7 +105,7 @@ re_string_construct (re_string_t *pstr, - else - { - #ifdef RE_ENABLE_I18N -- if (dfa->mb_cur_max > 1) -+ if (dfa_mb_cur_max (dfa) > 1) - build_wcs_buffer (pstr); - else - #endif /* RE_ENABLE_I18N */ -@@ -130,7 +130,7 @@ internal_function __attribute_warn_unuse - re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) - { - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - { - wint_t *new_wcs; - -@@ -177,7 +177,7 @@ re_string_construct_common (const char * - pstr->trans = trans; - pstr->icase = icase ? 1 : 0; - pstr->mbs_allocated = (trans != NULL || icase); -- pstr->mb_cur_max = dfa->mb_cur_max; -+ pstr->mb_cur_max = dfa_mb_cur_max (dfa); - pstr->is_utf8 = dfa->is_utf8; - pstr->map_notascii = dfa->map_notascii; - pstr->stop = pstr->len; -@@ -203,7 +203,7 @@ build_wcs_buffer (re_string_t *pstr) - { - #ifdef _LIBC - unsigned char buf[MB_LEN_MAX]; -- assert (MB_LEN_MAX >= pstr->mb_cur_max); -+ assert (MB_LEN_MAX >= string_mb_cur_max (pstr)); - #else - unsigned char buf[64]; - #endif -@@ -226,7 +226,7 @@ build_wcs_buffer (re_string_t *pstr) - { - int i, ch; - -- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) -+ for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; - buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; -@@ -275,7 +275,7 @@ build_wcs_upper_buffer (re_string_t *pst - size_t mbclen; - #ifdef _LIBC - char buf[MB_LEN_MAX]; -- assert (MB_LEN_MAX >= pstr->mb_cur_max); -+ assert (MB_LEN_MAX >= string_mb_cur_max (pstr)); - #else - char buf[64]; - #endif -@@ -369,7 +369,7 @@ build_wcs_upper_buffer (re_string_t *pst - { - int i, ch; - -- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) -+ for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; - buf[i] = pstr->trans[ch]; -@@ -567,8 +567,9 @@ re_string_translate_buffer (re_string_t - } - - /* This function re-construct the buffers. -- Concretely, convert to wide character in case of pstr->mb_cur_max > 1, -- convert to upper case in case of REG_ICASE, apply translation. */ -+ Concretely, convert to wide character in case of -+ string_mb_cur_max (pstr) > 1, convert to upper case in case of -+ REG_ICASE, apply translation. */ - - static reg_errcode_t - internal_function __attribute_warn_unused_result__ -@@ -579,7 +580,7 @@ re_string_reconstruct (re_string_t *pstr - { - /* Reset buffer. */ - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - #endif /* RE_ENABLE_I18N */ - pstr->len = pstr->raw_len; -@@ -670,7 +671,7 @@ re_string_reconstruct (re_string_t *pstr - pstr->tip_context = re_string_context_at (pstr, offset - 1, - eflags); - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - #endif /* RE_ENABLE_I18N */ -@@ -699,7 +700,7 @@ re_string_reconstruct (re_string_t *pstr - #endif - pstr->valid_len = 0; - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - { - int wcs_idx; - wint_t wc = WEOF; -@@ -711,7 +712,7 @@ re_string_reconstruct (re_string_t *pstr - /* Special case UTF-8. Multi-byte chars start with any - byte other than 0x80 - 0xbf. */ - raw = pstr->raw_mbs + pstr->raw_mbs_idx; -- end = raw + (offset - pstr->mb_cur_max); -+ end = raw + (offset - string_mb_cur_max (pstr)); - if (end < pstr->raw_mbs) - end = pstr->raw_mbs; - p = raw + offset - 1; -@@ -803,7 +804,7 @@ re_string_reconstruct (re_string_t *pstr - - /* Then build the buffers. */ - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1) -+ if (string_mb_cur_max (pstr) > 1) - { - if (pstr->icase) - { -@@ -841,7 +842,7 @@ re_string_peek_byte_case (const re_strin - return re_string_peek_byte (pstr, idx); - - #ifdef RE_ENABLE_I18N -- if (pstr->mb_cur_max > 1 -+ if (string_mb_cur_max (pstr) > 1 - && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) - return re_string_peek_byte (pstr, idx); - #endif -@@ -930,7 +931,7 @@ re_string_context_at (const re_string_t - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); - #ifdef RE_ENABLE_I18N -- if (input->mb_cur_max > 1) -+ if (string_mb_cur_max (input) > 1) - { - wint_t wc; - int wc_idx = idx; -@@ -1444,7 +1445,7 @@ re_dfa_add_node (re_dfa_t *dfa, re_token - dfa->nodes[dfa->nodes_len].constraint = 0; - #ifdef RE_ENABLE_I18N - dfa->nodes[dfa->nodes_len].accept_mb = -- (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; -+ (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET; - #endif - dfa->nexts[dfa->nodes_len] = -1; - re_node_set_init_empty (dfa->edests + dfa->nodes_len); -Index: git/posix/regex_internal.h -=================================================================== ---- git.orig/posix/regex_internal.h -+++ git/posix/regex_internal.h -@@ -26,6 +26,10 @@ - #include - #include - -+#if defined _LIBC -+# include -+#endif -+ - #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC - # include - #endif -@@ -369,6 +373,13 @@ struct re_string_t - }; - typedef struct re_string_t re_string_t; - -+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1; -+ help the compiler make use of that fact. */ -+#if __OPTION_EGLIBC_LOCALE_CODE -+# define string_mb_cur_max(str) ((str)->mb_cur_max + 0) -+#else -+# define string_mb_cur_max(str) (1) -+#endif - - struct re_dfa_t; - typedef struct re_dfa_t re_dfa_t; -@@ -654,6 +665,14 @@ struct re_dfa_t - __libc_lock_define (, lock) - }; - -+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1; -+ help the compiler make use of that fact. */ -+#if __OPTION_EGLIBC_LOCALE_CODE -+# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0) -+#else -+# define dfa_mb_cur_max(dfa) (1) -+#endif -+ - #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) - #define re_node_set_remove(set,id) \ - (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) -@@ -714,7 +733,7 @@ internal_function __attribute__ ((pure, - re_string_char_size_at (const re_string_t *pstr, int idx) - { - int byte_idx; -- if (pstr->mb_cur_max == 1) -+ if (string_mb_cur_max (pstr) == 1) - return 1; - for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) - if (pstr->wcs[idx + byte_idx] != WEOF) -@@ -726,7 +745,7 @@ static wint_t - internal_function __attribute__ ((pure, unused)) - re_string_wchar_at (const re_string_t *pstr, int idx) - { -- if (pstr->mb_cur_max == 1) -+ if (string_mb_cur_max (pstr) == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; - } -Index: git/posix/xregex.c -=================================================================== ---- /dev/null -+++ git/posix/xregex.c -@@ -0,0 +1,8215 @@ -+/* Extended regular expression matching and search library, -+ version 0.12. -+ (Implements POSIX draft P1003.2/D11.2, except for some of the -+ internationalization features.) -+ -+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -+ 2002, 2005 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ 02110-1301 USA. */ -+ -+/* AIX requires this to be the first thing in the file. */ -+#if defined _AIX && !defined __GNUC__ && !defined REGEX_MALLOC -+ #pragma alloca -+#endif -+ -+#undef _GNU_SOURCE -+#define _GNU_SOURCE -+ -+#ifndef INSIDE_RECURSION -+# ifdef HAVE_CONFIG_H -+# include -+# endif -+#endif -+ -+/*#include */ -+ -+ -+#ifndef INSIDE_RECURSION -+ -+# if defined STDC_HEADERS && !defined emacs -+# include -+# else -+/* We need this for `regex.h', and perhaps for the Emacs include files. */ -+# include -+# endif -+ -+# if (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_BTOWC) -+# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) -+# else -+# define WIDE_CHAR_SUPPORT 0 -+# endif -+/* For platform which support the ISO C amendement 1 functionality we -+ support user defined character classes. */ -+# if WIDE_CHAR_SUPPORT -+/* Solaris 2.5 has a bug: must be included before . */ -+# include -+# include -+# endif -+ -+# ifdef _LIBC -+/* We have to keep the namespace clean. */ -+# define regfree(preg) __regfree (preg) -+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -+# define regerror(errcode, preg, errbuf, errbuf_size) \ -+ __regerror(errcode, preg, errbuf, errbuf_size) -+# define re_set_registers(bu, re, nu, st, en) \ -+ __re_set_registers (bu, re, nu, st, en) -+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ -+ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -+# define re_match(bufp, string, size, pos, regs) \ -+ __re_match (bufp, string, size, pos, regs) -+# define re_search(bufp, string, size, startpos, range, regs) \ -+ __re_search (bufp, string, size, startpos, range, regs) -+# define re_compile_pattern(pattern, length, bufp) \ -+ __re_compile_pattern (pattern, length, bufp) -+# define re_set_syntax(syntax) __re_set_syntax (syntax) -+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ -+ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) -+ -+# define btowc __btowc -+ -+/* We are also using some library internals. */ -+# include -+# include -+# include -+# include -+# endif -+ -+/* This is for other GNU distributions with internationalized messages. */ -+# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -+# include -+# ifdef _LIBC -+# undef gettext -+# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) -+# endif -+# else -+# define gettext(msgid) (msgid) -+# endif -+ -+# ifndef gettext_noop -+/* This define is so xgettext can find the internationalizable -+ strings. */ -+# define gettext_noop(String) String -+# endif -+ -+/* The `emacs' switch turns on certain matching commands -+ that make sense only in Emacs. */ -+# ifdef emacs -+ -+# include "lisp.h" -+# include "buffer.h" -+# include "syntax.h" -+ -+# else /* not emacs */ -+ -+/* If we are not linking with Emacs proper, -+ we can't use the relocating allocator -+ even if config.h says that we can. */ -+# undef REL_ALLOC -+ -+# if defined STDC_HEADERS || defined _LIBC -+# include -+# else -+char *malloc (); -+char *realloc (); -+# endif -+ -+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. -+ If nothing else has been done, use the method below. */ -+# ifdef INHIBIT_STRING_HEADER -+# if !(defined HAVE_BZERO && defined HAVE_BCOPY) -+# if !defined bzero && !defined bcopy -+# undef INHIBIT_STRING_HEADER -+# endif -+# endif -+# endif -+ -+/* This is the normal way of making sure we have a bcopy and a bzero. -+ This is used in most programs--a few other programs avoid this -+ by defining INHIBIT_STRING_HEADER. */ -+# ifndef INHIBIT_STRING_HEADER -+# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC -+# include -+# ifndef bzero -+# ifndef _LIBC -+# define bzero(s, n) (memset (s, '\0', n), (s)) -+# else -+# define bzero(s, n) __bzero (s, n) -+# endif -+# endif -+# else -+# include -+# ifndef memcmp -+# define memcmp(s1, s2, n) bcmp (s1, s2, n) -+# endif -+# ifndef memcpy -+# define memcpy(d, s, n) (bcopy (s, d, n), (d)) -+# endif -+# endif -+# endif -+ -+/* Define the syntax stuff for \<, \>, etc. */ -+ -+/* This must be nonzero for the wordchar and notwordchar pattern -+ commands in re_match_2. */ -+# ifndef Sword -+# define Sword 1 -+# endif -+ -+# ifdef SWITCH_ENUM_BUG -+# define SWITCH_ENUM_CAST(x) ((int)(x)) -+# else -+# define SWITCH_ENUM_CAST(x) (x) -+# endif -+ -+# endif /* not emacs */ -+ -+# if defined _LIBC || HAVE_LIMITS_H -+# include -+# endif -+ -+# ifndef MB_LEN_MAX -+# define MB_LEN_MAX 1 -+# endif -+ -+/* Get the interface, including the syntax bits. */ -+# include "regex.h" -+ -+/* isalpha etc. are used for the character classes. */ -+# include -+ -+/* Jim Meyering writes: -+ -+ "... Some ctype macros are valid only for character codes that -+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when -+ using /bin/cc or gcc but without giving an ansi option). So, all -+ ctype uses should be through macros like ISPRINT... If -+ STDC_HEADERS is defined, then autoconf has verified that the ctype -+ macros don't need to be guarded with references to isascii. ... -+ Defining isascii to 1 should let any compiler worth its salt -+ eliminate the && through constant folding." -+ Solaris defines some of these symbols so we must undefine them first. */ -+ -+# undef ISASCII -+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) -+# define ISASCII(c) 1 -+# else -+# define ISASCII(c) isascii(c) -+# endif -+ -+# ifdef isblank -+# define ISBLANK(c) (ISASCII (c) && isblank (c)) -+# else -+# define ISBLANK(c) ((c) == ' ' || (c) == '\t') -+# endif -+# ifdef isgraph -+# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) -+# else -+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) -+# endif -+ -+# undef ISPRINT -+# define ISPRINT(c) (ISASCII (c) && isprint (c)) -+# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) -+# define ISALNUM(c) (ISASCII (c) && isalnum (c)) -+# define ISALPHA(c) (ISASCII (c) && isalpha (c)) -+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) -+# define ISLOWER(c) (ISASCII (c) && islower (c)) -+# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) -+# define ISSPACE(c) (ISASCII (c) && isspace (c)) -+# define ISUPPER(c) (ISASCII (c) && isupper (c)) -+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) -+ -+# ifdef _tolower -+# define TOLOWER(c) _tolower(c) -+# else -+# define TOLOWER(c) tolower(c) -+# endif -+ -+# ifndef NULL -+# define NULL (void *)0 -+# endif -+ -+/* We remove any previous definition of `SIGN_EXTEND_CHAR', -+ since ours (we hope) works properly with all combinations of -+ machines, compilers, `char' and `unsigned char' argument types. -+ (Per Bothner suggested the basic approach.) */ -+# undef SIGN_EXTEND_CHAR -+# if __STDC__ -+# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) -+# else /* not __STDC__ */ -+/* As in Harbison and Steele. */ -+# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) -+# endif -+ -+# ifndef emacs -+/* How many characters in the character set. */ -+# define CHAR_SET_SIZE 256 -+ -+# ifdef SYNTAX_TABLE -+ -+extern char *re_syntax_table; -+ -+# else /* not SYNTAX_TABLE */ -+ -+static char re_syntax_table[CHAR_SET_SIZE]; -+ -+static void init_syntax_once (void); -+ -+static void -+init_syntax_once (void) -+{ -+ register int c; -+ static int done = 0; -+ -+ if (done) -+ return; -+ bzero (re_syntax_table, sizeof re_syntax_table); -+ -+ for (c = 0; c < CHAR_SET_SIZE; ++c) -+ if (ISALNUM (c)) -+ re_syntax_table[c] = Sword; -+ -+ re_syntax_table['_'] = Sword; -+ -+ done = 1; -+} -+ -+# endif /* not SYNTAX_TABLE */ -+ -+# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] -+ -+# endif /* emacs */ -+ -+/* Integer type for pointers. */ -+# if !defined _LIBC && !defined HAVE_UINTPTR_T -+typedef unsigned long int uintptr_t; -+# endif -+ -+/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we -+ use `alloca' instead of `malloc'. This is because using malloc in -+ re_search* or re_match* could cause memory leaks when C-g is used in -+ Emacs; also, malloc is slower and causes storage fragmentation. On -+ the other hand, malloc is more portable, and easier to debug. -+ -+ Because we sometimes use alloca, some routines have to be macros, -+ not functions -- `alloca'-allocated space disappears at the end of the -+ function it is called in. */ -+ -+# ifdef REGEX_MALLOC -+ -+# define REGEX_ALLOCATE malloc -+# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) -+# define REGEX_FREE free -+ -+# else /* not REGEX_MALLOC */ -+ -+/* Emacs already defines alloca, sometimes. */ -+# ifndef alloca -+ -+/* Make alloca work the best possible way. */ -+# ifdef __GNUC__ -+# define alloca __builtin_alloca -+# else /* not __GNUC__ */ -+# if HAVE_ALLOCA_H -+# include -+# endif /* HAVE_ALLOCA_H */ -+# endif /* not __GNUC__ */ -+ -+# endif /* not alloca */ -+ -+# define REGEX_ALLOCATE alloca -+ -+/* Assumes a `char *destination' variable. */ -+# define REGEX_REALLOCATE(source, osize, nsize) \ -+ (destination = (char *) alloca (nsize), \ -+ memcpy (destination, source, osize)) -+ -+/* No need to do anything to free, after alloca. */ -+# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ -+ -+# endif /* not REGEX_MALLOC */ -+ -+/* Define how to allocate the failure stack. */ -+ -+# if defined REL_ALLOC && defined REGEX_MALLOC -+ -+# define REGEX_ALLOCATE_STACK(size) \ -+ r_alloc (&failure_stack_ptr, (size)) -+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ -+ r_re_alloc (&failure_stack_ptr, (nsize)) -+# define REGEX_FREE_STACK(ptr) \ -+ r_alloc_free (&failure_stack_ptr) -+ -+# else /* not using relocating allocator */ -+ -+# ifdef REGEX_MALLOC -+ -+# define REGEX_ALLOCATE_STACK malloc -+# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) -+# define REGEX_FREE_STACK free -+ -+# else /* not REGEX_MALLOC */ -+ -+# define REGEX_ALLOCATE_STACK alloca -+ -+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ -+ REGEX_REALLOCATE (source, osize, nsize) -+/* No need to explicitly free anything. */ -+# define REGEX_FREE_STACK(arg) -+ -+# endif /* not REGEX_MALLOC */ -+# endif /* not using relocating allocator */ -+ -+ -+/* True if `size1' is non-NULL and PTR is pointing anywhere inside -+ `string1' or just past its end. This works if PTR is NULL, which is -+ a good thing. */ -+# define FIRST_STRING_P(ptr) \ -+ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) -+ -+/* (Re)Allocate N items of type T using malloc, or fail. */ -+# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) -+# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) -+# define RETALLOC_IF(addr, n, t) \ -+ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) -+# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) -+ -+# define BYTEWIDTH 8 /* In bits. */ -+ -+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) -+ -+# undef MAX -+# undef MIN -+# define MAX(a, b) ((a) > (b) ? (a) : (b)) -+# define MIN(a, b) ((a) < (b) ? (a) : (b)) -+ -+typedef char boolean; -+# define false 0 -+# define true 1 -+ -+static reg_errcode_t byte_regex_compile (const char *pattern, size_t size, -+ reg_syntax_t syntax, -+ struct re_pattern_buffer *bufp); -+ -+static int byte_re_match_2_internal (struct re_pattern_buffer *bufp, -+ const char *string1, int size1, -+ const char *string2, int size2, -+ int pos, -+ struct re_registers *regs, -+ int stop); -+static int byte_re_search_2 (struct re_pattern_buffer *bufp, -+ const char *string1, int size1, -+ const char *string2, int size2, -+ int startpos, int range, -+ struct re_registers *regs, int stop); -+static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp); -+ -+#ifdef MBS_SUPPORT -+static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size, -+ reg_syntax_t syntax, -+ struct re_pattern_buffer *bufp); -+ -+ -+static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp, -+ const char *cstring1, int csize1, -+ const char *cstring2, int csize2, -+ int pos, -+ struct re_registers *regs, -+ int stop, -+ wchar_t *string1, int size1, -+ wchar_t *string2, int size2, -+ int *mbs_offset1, int *mbs_offset2); -+static int wcs_re_search_2 (struct re_pattern_buffer *bufp, -+ const char *string1, int size1, -+ const char *string2, int size2, -+ int startpos, int range, -+ struct re_registers *regs, int stop); -+static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp); -+#endif -+ -+/* These are the command codes that appear in compiled regular -+ expressions. Some opcodes are followed by argument bytes. A -+ command code can specify any interpretation whatsoever for its -+ arguments. Zero bytes may appear in the compiled regular expression. */ -+ -+typedef enum -+{ -+ no_op = 0, -+ -+ /* Succeed right away--no more backtracking. */ -+ succeed, -+ -+ /* Followed by one byte giving n, then by n literal bytes. */ -+ exactn, -+ -+# ifdef MBS_SUPPORT -+ /* Same as exactn, but contains binary data. */ -+ exactn_bin, -+# endif -+ -+ /* Matches any (more or less) character. */ -+ anychar, -+ -+ /* Matches any one char belonging to specified set. First -+ following byte is number of bitmap bytes. Then come bytes -+ for a bitmap saying which chars are in. Bits in each byte -+ are ordered low-bit-first. A character is in the set if its -+ bit is 1. A character too large to have a bit in the map is -+ automatically not in the set. */ -+ /* ifdef MBS_SUPPORT, following element is length of character -+ classes, length of collating symbols, length of equivalence -+ classes, length of character ranges, and length of characters. -+ Next, character class element, collating symbols elements, -+ equivalence class elements, range elements, and character -+ elements follow. -+ See regex_compile function. */ -+ charset, -+ -+ /* Same parameters as charset, but match any character that is -+ not one of those specified. */ -+ charset_not, -+ -+ /* Start remembering the text that is matched, for storing in a -+ register. Followed by one byte with the register number, in -+ the range 0 to one less than the pattern buffer's re_nsub -+ field. Then followed by one byte with the number of groups -+ inner to this one. (This last has to be part of the -+ start_memory only because we need it in the on_failure_jump -+ of re_match_2.) */ -+ start_memory, -+ -+ /* Stop remembering the text that is matched and store it in a -+ memory register. Followed by one byte with the register -+ number, in the range 0 to one less than `re_nsub' in the -+ pattern buffer, and one byte with the number of inner groups, -+ just like `start_memory'. (We need the number of inner -+ groups here because we don't have any easy way of finding the -+ corresponding start_memory when we're at a stop_memory.) */ -+ stop_memory, -+ -+ /* Match a duplicate of something remembered. Followed by one -+ byte containing the register number. */ -+ duplicate, -+ -+ /* Fail unless at beginning of line. */ -+ begline, -+ -+ /* Fail unless at end of line. */ -+ endline, -+ -+ /* Succeeds if at beginning of buffer (if emacs) or at beginning -+ of string to be matched (if not). */ -+ begbuf, -+ -+ /* Analogously, for end of buffer/string. */ -+ endbuf, -+ -+ /* Followed by two byte relative address to which to jump. */ -+ jump, -+ -+ /* Same as jump, but marks the end of an alternative. */ -+ jump_past_alt, -+ -+ /* Followed by two-byte relative address of place to resume at -+ in case of failure. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ on_failure_jump, -+ -+ /* Like on_failure_jump, but pushes a placeholder instead of the -+ current string position when executed. */ -+ on_failure_keep_string_jump, -+ -+ /* Throw away latest failure point and then jump to following -+ two-byte relative address. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ pop_failure_jump, -+ -+ /* Change to pop_failure_jump if know won't have to backtrack to -+ match; otherwise change to jump. This is used to jump -+ back to the beginning of a repeat. If what follows this jump -+ clearly won't match what the repeat does, such that we can be -+ sure that there is no use backtracking out of repetitions -+ already matched, then we change it to a pop_failure_jump. -+ Followed by two-byte address. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ maybe_pop_jump, -+ -+ /* Jump to following two-byte address, and push a dummy failure -+ point. This failure point will be thrown away if an attempt -+ is made to use it for a failure. A `+' construct makes this -+ before the first repeat. Also used as an intermediary kind -+ of jump when compiling an alternative. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ dummy_failure_jump, -+ -+ /* Push a dummy failure point and continue. Used at the end of -+ alternatives. */ -+ push_dummy_failure, -+ -+ /* Followed by two-byte relative address and two-byte number n. -+ After matching N times, jump to the address upon failure. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ succeed_n, -+ -+ /* Followed by two-byte relative address, and two-byte number n. -+ Jump to the address N times, then fail. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ jump_n, -+ -+ /* Set the following two-byte relative address to the -+ subsequent two-byte number. The address *includes* the two -+ bytes of number. */ -+ /* ifdef MBS_SUPPORT, the size of address is 1. */ -+ set_number_at, -+ -+ wordchar, /* Matches any word-constituent character. */ -+ notwordchar, /* Matches any char that is not a word-constituent. */ -+ -+ wordbeg, /* Succeeds if at word beginning. */ -+ wordend, /* Succeeds if at word end. */ -+ -+ wordbound, /* Succeeds if at a word boundary. */ -+ notwordbound /* Succeeds if not at a word boundary. */ -+ -+# ifdef emacs -+ ,before_dot, /* Succeeds if before point. */ -+ at_dot, /* Succeeds if at point. */ -+ after_dot, /* Succeeds if after point. */ -+ -+ /* Matches any character whose syntax is specified. Followed by -+ a byte which contains a syntax code, e.g., Sword. */ -+ syntaxspec, -+ -+ /* Matches any character whose syntax is not that specified. */ -+ notsyntaxspec -+# endif /* emacs */ -+} re_opcode_t; -+#endif /* not INSIDE_RECURSION */ -+ -+ -+#ifdef BYTE -+# define CHAR_T char -+# define UCHAR_T unsigned char -+# define COMPILED_BUFFER_VAR bufp->buffer -+# define OFFSET_ADDRESS_SIZE 2 -+# define PREFIX(name) byte_##name -+# define ARG_PREFIX(name) name -+# define PUT_CHAR(c) putchar (c) -+# include -+# define FINDIDX findidx -+#else -+# ifdef WCHAR -+# define CHAR_T wchar_t -+# define UCHAR_T wchar_t -+# define COMPILED_BUFFER_VAR wc_buffer -+# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ -+# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) -+# define PREFIX(name) wcs_##name -+# define ARG_PREFIX(name) c##name -+/* Should we use wide stream?? */ -+# define PUT_CHAR(c) printf ("%C", c); -+# define TRUE 1 -+# define FALSE 0 -+# define findidx findidxwc -+# include -+# undef findidx -+# define FINDIDX findidxwc -+# else -+# ifdef MBS_SUPPORT -+# define WCHAR -+# define INSIDE_RECURSION -+# include "xregex.c" -+# undef INSIDE_RECURSION -+# endif -+# define BYTE -+# define INSIDE_RECURSION -+# include "xregex.c" -+# undef INSIDE_RECURSION -+# endif -+#endif -+ -+#ifdef INSIDE_RECURSION -+/* Common operations on the compiled pattern. */ -+ -+/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ -+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -+ -+# ifdef WCHAR -+# define STORE_NUMBER(destination, number) \ -+ do { \ -+ *(destination) = (UCHAR_T)(number); \ -+ } while (0) -+# else /* BYTE */ -+# define STORE_NUMBER(destination, number) \ -+ do { \ -+ (destination)[0] = (number) & 0377; \ -+ (destination)[1] = (number) >> 8; \ -+ } while (0) -+# endif /* WCHAR */ -+ -+/* Same as STORE_NUMBER, except increment DESTINATION to -+ the byte after where the number is stored. Therefore, DESTINATION -+ must be an lvalue. */ -+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -+ -+# define STORE_NUMBER_AND_INCR(destination, number) \ -+ do { \ -+ STORE_NUMBER (destination, number); \ -+ (destination) += OFFSET_ADDRESS_SIZE; \ -+ } while (0) -+ -+/* Put into DESTINATION a number stored in two contiguous bytes starting -+ at SOURCE. */ -+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -+ -+# ifdef WCHAR -+# define EXTRACT_NUMBER(destination, source) \ -+ do { \ -+ (destination) = *(source); \ -+ } while (0) -+# else /* BYTE */ -+# define EXTRACT_NUMBER(destination, source) \ -+ do { \ -+ (destination) = *(source) & 0377; \ -+ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ -+ } while (0) -+# endif -+ -+# ifdef DEBUG -+static void PREFIX(extract_number) (int *dest, UCHAR_T *source); -+static void -+PREFIX(extract_number) (int *dest, UCHAR_T *source) -+{ -+# ifdef WCHAR -+ *dest = *source; -+# else /* BYTE */ -+ int temp = SIGN_EXTEND_CHAR (*(source + 1)); -+ *dest = *source & 0377; -+ *dest += temp << 8; -+# endif -+} -+ -+# ifndef EXTRACT_MACROS /* To debug the macros. */ -+# undef EXTRACT_NUMBER -+# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) -+# endif /* not EXTRACT_MACROS */ -+ -+# endif /* DEBUG */ -+ -+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. -+ SOURCE must be an lvalue. */ -+ -+# define EXTRACT_NUMBER_AND_INCR(destination, source) \ -+ do { \ -+ EXTRACT_NUMBER (destination, source); \ -+ (source) += OFFSET_ADDRESS_SIZE; \ -+ } while (0) -+ -+# ifdef DEBUG -+static void PREFIX(extract_number_and_incr) (int *destination, -+ UCHAR_T **source); -+static void -+PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source) -+{ -+ PREFIX(extract_number) (destination, *source); -+ *source += OFFSET_ADDRESS_SIZE; -+} -+ -+# ifndef EXTRACT_MACROS -+# undef EXTRACT_NUMBER_AND_INCR -+# define EXTRACT_NUMBER_AND_INCR(dest, src) \ -+ PREFIX(extract_number_and_incr) (&dest, &src) -+# endif /* not EXTRACT_MACROS */ -+ -+# endif /* DEBUG */ -+ -+ -+ -+/* If DEBUG is defined, Regex prints many voluminous messages about what -+ it is doing (if the variable `debug' is nonzero). If linked with the -+ main program in `iregex.c', you can enter patterns and strings -+ interactively. And if linked with the main program in `main.c' and -+ the other test files, you can run the already-written tests. */ -+ -+# ifdef DEBUG -+ -+# ifndef DEFINED_ONCE -+ -+/* We use standard I/O for debugging. */ -+# include -+ -+/* It is useful to test things that ``must'' be true when debugging. */ -+# include -+ -+static int debug; -+ -+# define DEBUG_STATEMENT(e) e -+# define DEBUG_PRINT1(x) if (debug) printf (x) -+# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) -+# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) -+# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) -+# endif /* not DEFINED_ONCE */ -+ -+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ -+ if (debug) PREFIX(print_partial_compiled_pattern) (s, e) -+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ -+ if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) -+ -+ -+/* Print the fastmap in human-readable form. */ -+ -+# ifndef DEFINED_ONCE -+void -+print_fastmap (char *fastmap) -+{ -+ unsigned was_a_range = 0; -+ unsigned i = 0; -+ -+ while (i < (1 << BYTEWIDTH)) -+ { -+ if (fastmap[i++]) -+ { -+ was_a_range = 0; -+ putchar (i - 1); -+ while (i < (1 << BYTEWIDTH) && fastmap[i]) -+ { -+ was_a_range = 1; -+ i++; -+ } -+ if (was_a_range) -+ { -+ printf ("-"); -+ putchar (i - 1); -+ } -+ } -+ } -+ putchar ('\n'); -+} -+# endif /* not DEFINED_ONCE */ -+ -+ -+/* Print a compiled pattern string in human-readable form, starting at -+ the START pointer into it and ending just before the pointer END. */ -+ -+void -+PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end) -+{ -+ int mcnt, mcnt2; -+ UCHAR_T *p1; -+ UCHAR_T *p = start; -+ UCHAR_T *pend = end; -+ -+ if (start == NULL) -+ { -+ printf ("(null)\n"); -+ return; -+ } -+ -+ /* Loop over pattern commands. */ -+ while (p < pend) -+ { -+# ifdef _LIBC -+ printf ("%td:\t", p - start); -+# else -+ printf ("%ld:\t", (long int) (p - start)); -+# endif -+ -+ switch ((re_opcode_t) *p++) -+ { -+ case no_op: -+ printf ("/no_op"); -+ break; -+ -+ case exactn: -+ mcnt = *p++; -+ printf ("/exactn/%d", mcnt); -+ do -+ { -+ putchar ('/'); -+ PUT_CHAR (*p++); -+ } -+ while (--mcnt); -+ break; -+ -+# ifdef MBS_SUPPORT -+ case exactn_bin: -+ mcnt = *p++; -+ printf ("/exactn_bin/%d", mcnt); -+ do -+ { -+ printf("/%lx", (long int) *p++); -+ } -+ while (--mcnt); -+ break; -+# endif /* MBS_SUPPORT */ -+ -+ case start_memory: -+ mcnt = *p++; -+ printf ("/start_memory/%d/%ld", mcnt, (long int) *p++); -+ break; -+ -+ case stop_memory: -+ mcnt = *p++; -+ printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++); -+ break; -+ -+ case duplicate: -+ printf ("/duplicate/%ld", (long int) *p++); -+ break; -+ -+ case anychar: -+ printf ("/anychar"); -+ break; -+ -+ case charset: -+ case charset_not: -+ { -+# ifdef WCHAR -+ int i, length; -+ wchar_t *workp = p; -+ printf ("/charset [%s", -+ (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); -+ p += 5; -+ length = *workp++; /* the length of char_classes */ -+ for (i=0 ; ibuffer; -+ -+ PREFIX(print_partial_compiled_pattern) (buffer, buffer -+ + bufp->used / sizeof(UCHAR_T)); -+ printf ("%ld bytes used/%ld bytes allocated.\n", -+ bufp->used, bufp->allocated); -+ -+ if (bufp->fastmap_accurate && bufp->fastmap) -+ { -+ printf ("fastmap: "); -+ print_fastmap (bufp->fastmap); -+ } -+ -+# ifdef _LIBC -+ printf ("re_nsub: %Zd\t", bufp->re_nsub); -+# else -+ printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); -+# endif -+ printf ("regs_alloc: %d\t", bufp->regs_allocated); -+ printf ("can_be_null: %d\t", bufp->can_be_null); -+ printf ("newline_anchor: %d\n", bufp->newline_anchor); -+ printf ("no_sub: %d\t", bufp->no_sub); -+ printf ("not_bol: %d\t", bufp->not_bol); -+ printf ("not_eol: %d\t", bufp->not_eol); -+ printf ("syntax: %lx\n", bufp->syntax); -+ /* Perhaps we should print the translate table? */ -+} -+ -+ -+void -+PREFIX(print_double_string) (const CHAR_T *where, const CHAR_T *string1, -+ int size1, const CHAR_T *string2, int size2) -+{ -+ int this_char; -+ -+ if (where == NULL) -+ printf ("(null)"); -+ else -+ { -+ int cnt; -+ -+ if (FIRST_STRING_P (where)) -+ { -+ for (this_char = where - string1; this_char < size1; this_char++) -+ PUT_CHAR (string1[this_char]); -+ -+ where = string2; -+ } -+ -+ cnt = 0; -+ for (this_char = where - string2; this_char < size2; this_char++) -+ { -+ PUT_CHAR (string2[this_char]); -+ if (++cnt > 100) -+ { -+ fputs ("...", stdout); -+ break; -+ } -+ } -+ } -+} -+ -+# ifndef DEFINED_ONCE -+void -+printchar (int c) -+{ -+ putc (c, stderr); -+} -+# endif -+ -+# else /* not DEBUG */ -+ -+# ifndef DEFINED_ONCE -+# undef assert -+# define assert(e) -+ -+# define DEBUG_STATEMENT(e) -+# define DEBUG_PRINT1(x) -+# define DEBUG_PRINT2(x1, x2) -+# define DEBUG_PRINT3(x1, x2, x3) -+# define DEBUG_PRINT4(x1, x2, x3, x4) -+# endif /* not DEFINED_ONCE */ -+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) -+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) -+ -+# endif /* not DEBUG */ -+ -+ -+ -+# ifdef WCHAR -+/* This convert a multibyte string to a wide character string. -+ And write their correspondances to offset_buffer(see below) -+ and write whether each wchar_t is binary data to is_binary. -+ This assume invalid multibyte sequences as binary data. -+ We assume offset_buffer and is_binary is already allocated -+ enough space. */ -+ -+static size_t convert_mbs_to_wcs (CHAR_T *dest, const unsigned char* src, -+ size_t len, int *offset_buffer, -+ char *is_binary); -+static size_t -+convert_mbs_to_wcs (CHAR_T *dest, const unsigned char*src, size_t len, -+ int *offset_buffer, char *is_binary) -+ /* It hold correspondances between src(char string) and -+ dest(wchar_t string) for optimization. -+ e.g. src = "xxxyzz" -+ dest = {'X', 'Y', 'Z'} -+ (each "xxx", "y" and "zz" represent one multibyte character -+ corresponding to 'X', 'Y' and 'Z'.) -+ offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} -+ = {0, 3, 4, 6} -+ */ -+{ -+ wchar_t *pdest = dest; -+ const unsigned char *psrc = src; -+ size_t wc_count = 0; -+ -+ mbstate_t mbs; -+ int i, consumed; -+ size_t mb_remain = len; -+ size_t mb_count = 0; -+ -+ /* Initialize the conversion state. */ -+ memset (&mbs, 0, sizeof (mbstate_t)); -+ -+ offset_buffer[0] = 0; -+ for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, -+ psrc += consumed) -+ { -+#ifdef _LIBC -+ consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs); -+#else -+ consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); -+#endif -+ -+ if (consumed <= 0) -+ /* failed to convert. maybe src contains binary data. -+ So we consume 1 byte manualy. */ -+ { -+ *pdest = *psrc; -+ consumed = 1; -+ is_binary[wc_count] = TRUE; -+ } -+ else -+ is_binary[wc_count] = FALSE; -+ /* In sjis encoding, we use yen sign as escape character in -+ place of reverse solidus. So we convert 0x5c(yen sign in -+ sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse -+ solidus in UCS2). */ -+ if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) -+ *pdest = (wchar_t) *psrc; -+ -+ offset_buffer[wc_count + 1] = mb_count += consumed; -+ } -+ -+ /* Fill remain of the buffer with sentinel. */ -+ for (i = wc_count + 1 ; i <= len ; i++) -+ offset_buffer[i] = mb_count + 1; -+ -+ return wc_count; -+} -+ -+# endif /* WCHAR */ -+ -+#else /* not INSIDE_RECURSION */ -+ -+/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can -+ also be assigned to arbitrarily: each pattern buffer stores its own -+ syntax, so it can be changed between regex compilations. */ -+/* This has no initializer because initialized variables in Emacs -+ become read-only after dumping. */ -+reg_syntax_t re_syntax_options; -+ -+ -+/* Specify the precise syntax of regexps for compilation. This provides -+ for compatibility for various utilities which historically have -+ different, incompatible syntaxes. -+ -+ The argument SYNTAX is a bit mask comprised of the various bits -+ defined in regex.h. We return the old syntax. */ -+ -+reg_syntax_t -+re_set_syntax (reg_syntax_t syntax) -+{ -+ reg_syntax_t ret = re_syntax_options; -+ -+ re_syntax_options = syntax; -+# ifdef DEBUG -+ if (syntax & RE_DEBUG) -+ debug = 1; -+ else if (debug) /* was on but now is not */ -+ debug = 0; -+# endif /* DEBUG */ -+ return ret; -+} -+# ifdef _LIBC -+weak_alias (__re_set_syntax, re_set_syntax) -+# endif -+ -+/* This table gives an error message for each of the error codes listed -+ in regex.h. Obviously the order here has to be same as there. -+ POSIX doesn't require that we do anything for REG_NOERROR, -+ but why not be nice? */ -+ -+static const char *re_error_msgid[] = -+ { -+ gettext_noop ("Success"), /* REG_NOERROR */ -+ gettext_noop ("No match"), /* REG_NOMATCH */ -+ gettext_noop ("Invalid regular expression"), /* REG_BADPAT */ -+ gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */ -+ gettext_noop ("Invalid character class name"), /* REG_ECTYPE */ -+ gettext_noop ("Trailing backslash"), /* REG_EESCAPE */ -+ gettext_noop ("Invalid back reference"), /* REG_ESUBREG */ -+ gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */ -+ gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */ -+ gettext_noop ("Unmatched \\{"), /* REG_EBRACE */ -+ gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */ -+ gettext_noop ("Invalid range end"), /* REG_ERANGE */ -+ gettext_noop ("Memory exhausted"), /* REG_ESPACE */ -+ gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */ -+ gettext_noop ("Premature end of regular expression"), /* REG_EEND */ -+ gettext_noop ("Regular expression too big"), /* REG_ESIZE */ -+ gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ -+ }; -+ -+#endif /* INSIDE_RECURSION */ -+ -+#ifndef DEFINED_ONCE -+/* Avoiding alloca during matching, to placate r_alloc. */ -+ -+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the -+ searching and matching functions should not call alloca. On some -+ systems, alloca is implemented in terms of malloc, and if we're -+ using the relocating allocator routines, then malloc could cause a -+ relocation, which might (if the strings being searched are in the -+ ralloc heap) shift the data out from underneath the regexp -+ routines. -+ -+ Here's another reason to avoid allocation: Emacs -+ processes input from X in a signal handler; processing X input may -+ call malloc; if input arrives while a matching routine is calling -+ malloc, then we're scrod. But Emacs can't just block input while -+ calling matching routines; then we don't notice interrupts when -+ they come in. So, Emacs blocks input around all regexp calls -+ except the matching calls, which it leaves unprotected, in the -+ faith that they will not malloc. */ -+ -+/* Normally, this is fine. */ -+# define MATCH_MAY_ALLOCATE -+ -+/* When using GNU C, we are not REALLY using the C alloca, no matter -+ what config.h may say. So don't take precautions for it. */ -+# ifdef __GNUC__ -+# undef C_ALLOCA -+# endif -+ -+/* The match routines may not allocate if (1) they would do it with malloc -+ and (2) it's not safe for them to use malloc. -+ Note that if REL_ALLOC is defined, matching would not use malloc for the -+ failure stack, but we would still use it for the register vectors; -+ so REL_ALLOC should not affect this. */ -+# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs -+# undef MATCH_MAY_ALLOCATE -+# endif -+#endif /* not DEFINED_ONCE */ -+ -+#ifdef INSIDE_RECURSION -+/* Failure stack declarations and macros; both re_compile_fastmap and -+ re_match_2 use a failure stack. These have to be macros because of -+ REGEX_ALLOCATE_STACK. */ -+ -+ -+/* Number of failure points for which to initially allocate space -+ when matching. If this number is exceeded, we allocate more -+ space, so it is not a hard limit. */ -+# ifndef INIT_FAILURE_ALLOC -+# define INIT_FAILURE_ALLOC 5 -+# endif -+ -+/* Roughly the maximum number of failure points on the stack. Would be -+ exactly that if always used MAX_FAILURE_ITEMS items each time we failed. -+ This is a variable only so users of regex can assign to it; we never -+ change it ourselves. */ -+ -+ -+# ifndef DEFINED_ONCE -+ -+# ifdef INT_IS_16BIT -+# define RE_M_F_TYPE long int -+# else -+# define RE_M_F_TYPE int -+# endif /* INT_IS_16BIT */ -+ -+# ifdef MATCH_MAY_ALLOCATE -+/* 4400 was enough to cause a crash on Alpha OSF/1, -+ whose default stack limit is 2mb. */ -+# define RE_M_F_DEFAULT 4000 -+# else -+# define RE_M_F_DEFAULT 2000 -+# endif /* MATCH_MAY_ALLOCATE */ -+ -+# include -+ -+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) -+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") -+RE_M_F_TYPE re_max_failures = RE_M_F_DEFAULT; -+# else -+RE_M_F_TYPE re_max_failures attribute_hidden = RE_M_F_DEFAULT; -+# endif /* SHLIB_COMPAT */ -+ -+# undef RE_M_F_TYPE -+# undef RE_M_F_DEFAULT -+ -+# endif /* DEFINED_ONCE */ -+ -+# ifdef INT_IS_16BIT -+ -+union PREFIX(fail_stack_elt) -+{ -+ UCHAR_T *pointer; -+ long int integer; -+}; -+ -+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); -+ -+typedef struct -+{ -+ PREFIX(fail_stack_elt_t) *stack; -+ unsigned long int size; -+ unsigned long int avail; /* Offset of next open position. */ -+} PREFIX(fail_stack_type); -+ -+# else /* not INT_IS_16BIT */ -+ -+union PREFIX(fail_stack_elt) -+{ -+ UCHAR_T *pointer; -+ int integer; -+}; -+ -+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); -+ -+typedef struct -+{ -+ PREFIX(fail_stack_elt_t) *stack; -+ unsigned size; -+ unsigned avail; /* Offset of next open position. */ -+} PREFIX(fail_stack_type); -+ -+# endif /* INT_IS_16BIT */ -+ -+# ifndef DEFINED_ONCE -+# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) -+# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) -+# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) -+# endif -+ -+ -+/* Define macros to initialize and free the failure stack. -+ Do `return -2' if the alloc fails. */ -+ -+# ifdef MATCH_MAY_ALLOCATE -+# define INIT_FAIL_STACK() \ -+ do { \ -+ fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ -+ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ -+ \ -+ if (fail_stack.stack == NULL) \ -+ return -2; \ -+ \ -+ fail_stack.size = INIT_FAILURE_ALLOC; \ -+ fail_stack.avail = 0; \ -+ } while (0) -+ -+# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) -+# else -+# define INIT_FAIL_STACK() \ -+ do { \ -+ fail_stack.avail = 0; \ -+ } while (0) -+ -+# define RESET_FAIL_STACK() -+# endif -+ -+ -+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. -+ -+ Return 1 if succeeds, and 0 if either ran out of memory -+ allocating space for it or it was already too large. -+ -+ REGEX_REALLOCATE_STACK requires `destination' be declared. */ -+ -+# define DOUBLE_FAIL_STACK(fail_stack) \ -+ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ -+ ? 0 \ -+ : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ -+ REGEX_REALLOCATE_STACK ((fail_stack).stack, \ -+ (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ -+ ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ -+ \ -+ (fail_stack).stack == NULL \ -+ ? 0 \ -+ : ((fail_stack).size <<= 1, \ -+ 1))) -+ -+ -+/* Push pointer POINTER on FAIL_STACK. -+ Return 1 if was able to do so and 0 if ran out of memory allocating -+ space to do so. */ -+# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ -+ ((FAIL_STACK_FULL () \ -+ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ -+ ? 0 \ -+ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ -+ 1)) -+ -+/* Push a pointer value onto the failure stack. -+ Assumes the variable `fail_stack'. Probably should only -+ be called from within `PUSH_FAILURE_POINT'. */ -+# define PUSH_FAILURE_POINTER(item) \ -+ fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) -+ -+/* This pushes an integer-valued item onto the failure stack. -+ Assumes the variable `fail_stack'. Probably should only -+ be called from within `PUSH_FAILURE_POINT'. */ -+# define PUSH_FAILURE_INT(item) \ -+ fail_stack.stack[fail_stack.avail++].integer = (item) -+ -+/* Push a fail_stack_elt_t value onto the failure stack. -+ Assumes the variable `fail_stack'. Probably should only -+ be called from within `PUSH_FAILURE_POINT'. */ -+# define PUSH_FAILURE_ELT(item) \ -+ fail_stack.stack[fail_stack.avail++] = (item) -+ -+/* These three POP... operations complement the three PUSH... operations. -+ All assume that `fail_stack' is nonempty. */ -+# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer -+# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer -+# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] -+ -+/* Used to omit pushing failure point id's when we're not debugging. */ -+# ifdef DEBUG -+# define DEBUG_PUSH PUSH_FAILURE_INT -+# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () -+# else -+# define DEBUG_PUSH(item) -+# define DEBUG_POP(item_addr) -+# endif -+ -+ -+/* Push the information about the state we will need -+ if we ever fail back to it. -+ -+ Requires variables fail_stack, regstart, regend, reg_info, and -+ num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' -+ be declared. -+ -+ Does `return FAILURE_CODE' if runs out of memory. */ -+ -+# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ -+ do { \ -+ char *destination; \ -+ /* Must be int, so when we don't save any registers, the arithmetic \ -+ of 0 + -1 isn't done as unsigned. */ \ -+ /* Can't be int, since there is not a shred of a guarantee that int \ -+ is wide enough to hold a value of something to which pointer can \ -+ be assigned */ \ -+ active_reg_t this_reg; \ -+ \ -+ DEBUG_STATEMENT (failure_id++); \ -+ DEBUG_STATEMENT (nfailure_points_pushed++); \ -+ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ -+ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ -+ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ -+ \ -+ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ -+ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ -+ \ -+ /* Ensure we have enough space allocated for what we will push. */ \ -+ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ -+ { \ -+ if (!DOUBLE_FAIL_STACK (fail_stack)) \ -+ return failure_code; \ -+ \ -+ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ -+ (fail_stack).size); \ -+ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ -+ } \ -+ \ -+ /* Push the info, starting with the registers. */ \ -+ DEBUG_PRINT1 ("\n"); \ -+ \ -+ if (1) \ -+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ -+ this_reg++) \ -+ { \ -+ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ -+ DEBUG_STATEMENT (num_regs_pushed++); \ -+ \ -+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ -+ PUSH_FAILURE_POINTER (regstart[this_reg]); \ -+ \ -+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ -+ PUSH_FAILURE_POINTER (regend[this_reg]); \ -+ \ -+ DEBUG_PRINT2 (" info: %p\n ", \ -+ reg_info[this_reg].word.pointer); \ -+ DEBUG_PRINT2 (" match_null=%d", \ -+ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ -+ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ -+ DEBUG_PRINT2 (" matched_something=%d", \ -+ MATCHED_SOMETHING (reg_info[this_reg])); \ -+ DEBUG_PRINT2 (" ever_matched=%d", \ -+ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ -+ DEBUG_PRINT1 ("\n"); \ -+ PUSH_FAILURE_ELT (reg_info[this_reg].word); \ -+ } \ -+ \ -+ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ -+ PUSH_FAILURE_INT (lowest_active_reg); \ -+ \ -+ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ -+ PUSH_FAILURE_INT (highest_active_reg); \ -+ \ -+ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ -+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ -+ PUSH_FAILURE_POINTER (pattern_place); \ -+ \ -+ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ -+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ -+ size2); \ -+ DEBUG_PRINT1 ("'\n"); \ -+ PUSH_FAILURE_POINTER (string_place); \ -+ \ -+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ -+ DEBUG_PUSH (failure_id); \ -+ } while (0) -+ -+# ifndef DEFINED_ONCE -+/* This is the number of items that are pushed and popped on the stack -+ for each register. */ -+# define NUM_REG_ITEMS 3 -+ -+/* Individual items aside from the registers. */ -+# ifdef DEBUG -+# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ -+# else -+# define NUM_NONREG_ITEMS 4 -+# endif -+ -+/* We push at most this many items on the stack. */ -+/* We used to use (num_regs - 1), which is the number of registers -+ this regexp will save; but that was changed to 5 -+ to avoid stack overflow for a regexp with lots of parens. */ -+# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) -+ -+/* We actually push this many items. */ -+# define NUM_FAILURE_ITEMS \ -+ (((0 \ -+ ? 0 : highest_active_reg - lowest_active_reg + 1) \ -+ * NUM_REG_ITEMS) \ -+ + NUM_NONREG_ITEMS) -+ -+/* How many items can still be added to the stack without overflowing it. */ -+# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) -+# endif /* not DEFINED_ONCE */ -+ -+ -+/* Pops what PUSH_FAIL_STACK pushes. -+ -+ We restore into the parameters, all of which should be lvalues: -+ STR -- the saved data position. -+ PAT -- the saved pattern position. -+ LOW_REG, HIGH_REG -- the highest and lowest active registers. -+ REGSTART, REGEND -- arrays of string positions. -+ REG_INFO -- array of information about each subexpression. -+ -+ Also assumes the variables `fail_stack' and (if debugging), `bufp', -+ `pend', `string1', `size1', `string2', and `size2'. */ -+# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ -+{ \ -+ DEBUG_STATEMENT (unsigned failure_id;) \ -+ active_reg_t this_reg; \ -+ const UCHAR_T *string_temp; \ -+ \ -+ assert (!FAIL_STACK_EMPTY ()); \ -+ \ -+ /* Remove failure points and point to how many regs pushed. */ \ -+ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ -+ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ -+ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ -+ \ -+ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ -+ \ -+ DEBUG_POP (&failure_id); \ -+ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ -+ \ -+ /* If the saved string location is NULL, it came from an \ -+ on_failure_keep_string_jump opcode, and we want to throw away the \ -+ saved NULL, thus retaining our current position in the string. */ \ -+ string_temp = POP_FAILURE_POINTER (); \ -+ if (string_temp != NULL) \ -+ str = (const CHAR_T *) string_temp; \ -+ \ -+ DEBUG_PRINT2 (" Popping string %p: `", str); \ -+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ -+ DEBUG_PRINT1 ("'\n"); \ -+ \ -+ pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ -+ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ -+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ -+ \ -+ /* Restore register info. */ \ -+ high_reg = (active_reg_t) POP_FAILURE_INT (); \ -+ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ -+ \ -+ low_reg = (active_reg_t) POP_FAILURE_INT (); \ -+ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ -+ \ -+ if (1) \ -+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ -+ { \ -+ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ -+ \ -+ reg_info[this_reg].word = POP_FAILURE_ELT (); \ -+ DEBUG_PRINT2 (" info: %p\n", \ -+ reg_info[this_reg].word.pointer); \ -+ \ -+ regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ -+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ -+ \ -+ regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ -+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ -+ } \ -+ else \ -+ { \ -+ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ -+ { \ -+ reg_info[this_reg].word.integer = 0; \ -+ regend[this_reg] = 0; \ -+ regstart[this_reg] = 0; \ -+ } \ -+ highest_active_reg = high_reg; \ -+ } \ -+ \ -+ set_regs_matched_done = 0; \ -+ DEBUG_STATEMENT (nfailure_points_popped++); \ -+} /* POP_FAILURE_POINT */ -+ -+/* Structure for per-register (a.k.a. per-group) information. -+ Other register information, such as the -+ starting and ending positions (which are addresses), and the list of -+ inner groups (which is a bits list) are maintained in separate -+ variables. -+ -+ We are making a (strictly speaking) nonportable assumption here: that -+ the compiler will pack our bit fields into something that fits into -+ the type of `word', i.e., is something that fits into one item on the -+ failure stack. */ -+ -+ -+/* Declarations and macros for re_match_2. */ -+ -+typedef union -+{ -+ PREFIX(fail_stack_elt_t) word; -+ struct -+ { -+ /* This field is one if this group can match the empty string, -+ zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ -+# define MATCH_NULL_UNSET_VALUE 3 -+ unsigned match_null_string_p : 2; -+ unsigned is_active : 1; -+ unsigned matched_something : 1; -+ unsigned ever_matched_something : 1; -+ } bits; -+} PREFIX(register_info_type); -+ -+# ifndef DEFINED_ONCE -+# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) -+# define IS_ACTIVE(R) ((R).bits.is_active) -+# define MATCHED_SOMETHING(R) ((R).bits.matched_something) -+# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) -+ -+ -+/* Call this when have matched a real character; it sets `matched' flags -+ for the subexpressions which we are currently inside. Also records -+ that those subexprs have matched. */ -+# define SET_REGS_MATCHED() \ -+ do \ -+ { \ -+ if (!set_regs_matched_done) \ -+ { \ -+ active_reg_t r; \ -+ set_regs_matched_done = 1; \ -+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \ -+ { \ -+ MATCHED_SOMETHING (reg_info[r]) \ -+ = EVER_MATCHED_SOMETHING (reg_info[r]) \ -+ = 1; \ -+ } \ -+ } \ -+ } \ -+ while (0) -+# endif /* not DEFINED_ONCE */ -+ -+/* Registers are set to a sentinel when they haven't yet matched. */ -+static CHAR_T PREFIX(reg_unset_dummy); -+# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) -+# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) -+ -+/* Subroutine declarations and macros for regex_compile. */ -+static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg); -+static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, -+ int arg1, int arg2); -+static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, -+ int arg, UCHAR_T *end); -+static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, -+ int arg1, int arg2, UCHAR_T *end); -+static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern, -+ const CHAR_T *p, -+ reg_syntax_t syntax); -+static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p, -+ const CHAR_T *pend, -+ reg_syntax_t syntax); -+# ifdef WCHAR -+static reg_errcode_t wcs_compile_range (CHAR_T range_start, -+ const CHAR_T **p_ptr, -+ const CHAR_T *pend, -+ char *translate, -+ reg_syntax_t syntax, -+ UCHAR_T *b, -+ CHAR_T *char_set); -+static void insert_space (int num, CHAR_T *loc, CHAR_T *end); -+# else /* BYTE */ -+static reg_errcode_t byte_compile_range (unsigned int range_start, -+ const char **p_ptr, -+ const char *pend, -+ RE_TRANSLATE_TYPE translate, -+ reg_syntax_t syntax, -+ unsigned char *b); -+# endif /* WCHAR */ -+ -+/* Fetch the next character in the uncompiled pattern---translating it -+ if necessary. Also cast from a signed character in the constant -+ string passed to us by the user to an unsigned char that we can use -+ as an array index (in, e.g., `translate'). */ -+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, -+ because it is impossible to allocate 4GB array for some encodings -+ which have 4 byte character_set like UCS4. */ -+# ifndef PATFETCH -+# ifdef WCHAR -+# define PATFETCH(c) \ -+ do {if (p == pend) return REG_EEND; \ -+ c = (UCHAR_T) *p++; \ -+ if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ -+ } while (0) -+# else /* BYTE */ -+# define PATFETCH(c) \ -+ do {if (p == pend) return REG_EEND; \ -+ c = (unsigned char) *p++; \ -+ if (translate) c = (unsigned char) translate[c]; \ -+ } while (0) -+# endif /* WCHAR */ -+# endif -+ -+/* Fetch the next character in the uncompiled pattern, with no -+ translation. */ -+# define PATFETCH_RAW(c) \ -+ do {if (p == pend) return REG_EEND; \ -+ c = (UCHAR_T) *p++; \ -+ } while (0) -+ -+/* Go backwards one character in the pattern. */ -+# define PATUNFETCH p-- -+ -+ -+/* If `translate' is non-null, return translate[D], else just D. We -+ cast the subscript to translate because some data is declared as -+ `char *', to avoid warnings when a string constant is passed. But -+ when we use a character as a subscript we must make it unsigned. */ -+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, -+ because it is impossible to allocate 4GB array for some encodings -+ which have 4 byte character_set like UCS4. */ -+ -+# ifndef TRANSLATE -+# ifdef WCHAR -+# define TRANSLATE(d) \ -+ ((translate && ((UCHAR_T) (d)) <= 0xff) \ -+ ? (char) translate[(unsigned char) (d)] : (d)) -+# else /* BYTE */ -+# define TRANSLATE(d) \ -+ (translate ? (char) translate[(unsigned char) (d)] : (char) (d)) -+# endif /* WCHAR */ -+# endif -+ -+ -+/* Macros for outputting the compiled pattern into `buffer'. */ -+ -+/* If the buffer isn't allocated when it comes in, use this. */ -+# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) -+ -+/* Make sure we have at least N more bytes of space in buffer. */ -+# ifdef WCHAR -+# define GET_BUFFER_SPACE(n) \ -+ while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ -+ + (n)*sizeof(CHAR_T)) > bufp->allocated) \ -+ EXTEND_BUFFER () -+# else /* BYTE */ -+# define GET_BUFFER_SPACE(n) \ -+ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ -+ EXTEND_BUFFER () -+# endif /* WCHAR */ -+ -+/* Make sure we have one more byte of buffer space and then add C to it. */ -+# define BUF_PUSH(c) \ -+ do { \ -+ GET_BUFFER_SPACE (1); \ -+ *b++ = (UCHAR_T) (c); \ -+ } while (0) -+ -+ -+/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ -+# define BUF_PUSH_2(c1, c2) \ -+ do { \ -+ GET_BUFFER_SPACE (2); \ -+ *b++ = (UCHAR_T) (c1); \ -+ *b++ = (UCHAR_T) (c2); \ -+ } while (0) -+ -+ -+/* As with BUF_PUSH_2, except for three bytes. */ -+# define BUF_PUSH_3(c1, c2, c3) \ -+ do { \ -+ GET_BUFFER_SPACE (3); \ -+ *b++ = (UCHAR_T) (c1); \ -+ *b++ = (UCHAR_T) (c2); \ -+ *b++ = (UCHAR_T) (c3); \ -+ } while (0) -+ -+/* Store a jump with opcode OP at LOC to location TO. We store a -+ relative address offset by the three bytes the jump itself occupies. */ -+# define STORE_JUMP(op, loc, to) \ -+ PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) -+ -+/* Likewise, for a two-argument jump. */ -+# define STORE_JUMP2(op, loc, to, arg) \ -+ PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) -+ -+/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ -+# define INSERT_JUMP(op, loc, to) \ -+ PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) -+ -+/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ -+# define INSERT_JUMP2(op, loc, to, arg) \ -+ PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ -+ arg, b) -+ -+/* This is not an arbitrary limit: the arguments which represent offsets -+ into the pattern are two bytes long. So if 2^16 bytes turns out to -+ be too small, many things would have to change. */ -+/* Any other compiler which, like MSC, has allocation limit below 2^16 -+ bytes will have to use approach similar to what was done below for -+ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up -+ reallocating to 0 bytes. Such thing is not going to work too well. -+ You have been warned!! */ -+# ifndef DEFINED_ONCE -+# if defined _MSC_VER && !defined WIN32 -+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. -+ The REALLOC define eliminates a flurry of conversion warnings, -+ but is not required. */ -+# define MAX_BUF_SIZE 65500L -+# define REALLOC(p,s) realloc ((p), (size_t) (s)) -+# else -+# define MAX_BUF_SIZE (1L << 16) -+# define REALLOC(p,s) realloc ((p), (s)) -+# endif -+ -+/* Extend the buffer by twice its current size via realloc and -+ reset the pointers that pointed into the old block to point to the -+ correct places in the new one. If extending the buffer results in it -+ being larger than MAX_BUF_SIZE, then flag memory exhausted. */ -+# ifndef __BOUNDED_POINTERS__ -+# define __BOUNDED_POINTERS__ 0 -+# endif -+# if __BOUNDED_POINTERS__ -+# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) -+# define MOVE_BUFFER_POINTER(P) \ -+ (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) -+# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ -+ else \ -+ { \ -+ SET_HIGH_BOUND (b); \ -+ SET_HIGH_BOUND (begalt); \ -+ if (fixup_alt_jump) \ -+ SET_HIGH_BOUND (fixup_alt_jump); \ -+ if (laststart) \ -+ SET_HIGH_BOUND (laststart); \ -+ if (pending_exact) \ -+ SET_HIGH_BOUND (pending_exact); \ -+ } -+# else -+# define MOVE_BUFFER_POINTER(P) (P) += incr -+# define ELSE_EXTEND_BUFFER_HIGH_BOUND -+# endif -+# endif /* not DEFINED_ONCE */ -+ -+# ifdef WCHAR -+# define EXTEND_BUFFER() \ -+ do { \ -+ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ -+ int wchar_count; \ -+ if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ -+ return REG_ESIZE; \ -+ bufp->allocated <<= 1; \ -+ if (bufp->allocated > MAX_BUF_SIZE) \ -+ bufp->allocated = MAX_BUF_SIZE; \ -+ /* How many characters the new buffer can have? */ \ -+ wchar_count = bufp->allocated / sizeof(UCHAR_T); \ -+ if (wchar_count == 0) wchar_count = 1; \ -+ /* Truncate the buffer to CHAR_T align. */ \ -+ bufp->allocated = wchar_count * sizeof(UCHAR_T); \ -+ RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ -+ bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ -+ if (COMPILED_BUFFER_VAR == NULL) \ -+ return REG_ESPACE; \ -+ /* If the buffer moved, move all the pointers into it. */ \ -+ if (old_buffer != COMPILED_BUFFER_VAR) \ -+ { \ -+ int incr = COMPILED_BUFFER_VAR - old_buffer; \ -+ MOVE_BUFFER_POINTER (b); \ -+ MOVE_BUFFER_POINTER (begalt); \ -+ if (fixup_alt_jump) \ -+ MOVE_BUFFER_POINTER (fixup_alt_jump); \ -+ if (laststart) \ -+ MOVE_BUFFER_POINTER (laststart); \ -+ if (pending_exact) \ -+ MOVE_BUFFER_POINTER (pending_exact); \ -+ } \ -+ ELSE_EXTEND_BUFFER_HIGH_BOUND \ -+ } while (0) -+# else /* BYTE */ -+# define EXTEND_BUFFER() \ -+ do { \ -+ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ -+ if (bufp->allocated == MAX_BUF_SIZE) \ -+ return REG_ESIZE; \ -+ bufp->allocated <<= 1; \ -+ if (bufp->allocated > MAX_BUF_SIZE) \ -+ bufp->allocated = MAX_BUF_SIZE; \ -+ bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \ -+ bufp->allocated); \ -+ if (COMPILED_BUFFER_VAR == NULL) \ -+ return REG_ESPACE; \ -+ /* If the buffer moved, move all the pointers into it. */ \ -+ if (old_buffer != COMPILED_BUFFER_VAR) \ -+ { \ -+ int incr = COMPILED_BUFFER_VAR - old_buffer; \ -+ MOVE_BUFFER_POINTER (b); \ -+ MOVE_BUFFER_POINTER (begalt); \ -+ if (fixup_alt_jump) \ -+ MOVE_BUFFER_POINTER (fixup_alt_jump); \ -+ if (laststart) \ -+ MOVE_BUFFER_POINTER (laststart); \ -+ if (pending_exact) \ -+ MOVE_BUFFER_POINTER (pending_exact); \ -+ } \ -+ ELSE_EXTEND_BUFFER_HIGH_BOUND \ -+ } while (0) -+# endif /* WCHAR */ -+ -+# ifndef DEFINED_ONCE -+/* Since we have one byte reserved for the register number argument to -+ {start,stop}_memory, the maximum number of groups we can report -+ things about is what fits in that byte. */ -+# define MAX_REGNUM 255 -+ -+/* But patterns can have more than `MAX_REGNUM' registers. We just -+ ignore the excess. */ -+typedef unsigned regnum_t; -+ -+ -+/* Macros for the compile stack. */ -+ -+/* Since offsets can go either forwards or backwards, this type needs to -+ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ -+/* int may be not enough when sizeof(int) == 2. */ -+typedef long pattern_offset_t; -+ -+typedef struct -+{ -+ pattern_offset_t begalt_offset; -+ pattern_offset_t fixup_alt_jump; -+ pattern_offset_t inner_group_offset; -+ pattern_offset_t laststart_offset; -+ regnum_t regnum; -+} compile_stack_elt_t; -+ -+ -+typedef struct -+{ -+ compile_stack_elt_t *stack; -+ unsigned size; -+ unsigned avail; /* Offset of next open position. */ -+} compile_stack_type; -+ -+ -+# define INIT_COMPILE_STACK_SIZE 32 -+ -+# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) -+# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) -+ -+/* The next available element. */ -+# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) -+ -+# endif /* not DEFINED_ONCE */ -+ -+/* Set the bit for character C in a list. */ -+# ifndef DEFINED_ONCE -+# define SET_LIST_BIT(c) \ -+ (b[((unsigned char) (c)) / BYTEWIDTH] \ -+ |= 1 << (((unsigned char) c) % BYTEWIDTH)) -+# endif /* DEFINED_ONCE */ -+ -+/* Get the next unsigned number in the uncompiled pattern. */ -+# define GET_UNSIGNED_NUMBER(num) \ -+ { \ -+ while (p != pend) \ -+ { \ -+ PATFETCH (c); \ -+ if (c < '0' || c > '9') \ -+ break; \ -+ if (num <= RE_DUP_MAX) \ -+ { \ -+ if (num < 0) \ -+ num = 0; \ -+ num = num * 10 + c - '0'; \ -+ } \ -+ } \ -+ } -+ -+# ifndef DEFINED_ONCE -+# if WIDE_CHAR_SUPPORT -+/* The GNU C library provides support for user-defined character classes -+ and the functions from ISO C amendement 1. */ -+# ifdef CHARCLASS_NAME_MAX -+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX -+# else -+/* This shouldn't happen but some implementation might still have this -+ problem. Use a reasonable default value. */ -+# define CHAR_CLASS_MAX_LENGTH 256 -+# endif -+ -+# ifdef _LIBC -+# define IS_CHAR_CLASS(string) __wctype (string) -+# else -+# define IS_CHAR_CLASS(string) wctype (string) -+# endif -+# else -+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ -+ -+# define IS_CHAR_CLASS(string) \ -+ (STREQ (string, "alpha") || STREQ (string, "upper") \ -+ || STREQ (string, "lower") || STREQ (string, "digit") \ -+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ -+ || STREQ (string, "space") || STREQ (string, "print") \ -+ || STREQ (string, "punct") || STREQ (string, "graph") \ -+ || STREQ (string, "cntrl") || STREQ (string, "blank")) -+# endif -+# endif /* DEFINED_ONCE */ -+ -+# ifndef MATCH_MAY_ALLOCATE -+ -+/* If we cannot allocate large objects within re_match_2_internal, -+ we make the fail stack and register vectors global. -+ The fail stack, we grow to the maximum size when a regexp -+ is compiled. -+ The register vectors, we adjust in size each time we -+ compile a regexp, according to the number of registers it needs. */ -+ -+static PREFIX(fail_stack_type) fail_stack; -+ -+/* Size with which the following vectors are currently allocated. -+ That is so we can make them bigger as needed, -+ but never make them smaller. */ -+# ifdef DEFINED_ONCE -+static int regs_allocated_size; -+ -+static const char ** regstart, ** regend; -+static const char ** old_regstart, ** old_regend; -+static const char **best_regstart, **best_regend; -+static const char **reg_dummy; -+# endif /* DEFINED_ONCE */ -+ -+static PREFIX(register_info_type) *PREFIX(reg_info); -+static PREFIX(register_info_type) *PREFIX(reg_info_dummy); -+ -+/* Make the register vectors big enough for NUM_REGS registers, -+ but don't make them smaller. */ -+ -+static void -+PREFIX(regex_grow_registers) (int num_regs) -+{ -+ if (num_regs > regs_allocated_size) -+ { -+ RETALLOC_IF (regstart, num_regs, const char *); -+ RETALLOC_IF (regend, num_regs, const char *); -+ RETALLOC_IF (old_regstart, num_regs, const char *); -+ RETALLOC_IF (old_regend, num_regs, const char *); -+ RETALLOC_IF (best_regstart, num_regs, const char *); -+ RETALLOC_IF (best_regend, num_regs, const char *); -+ RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); -+ RETALLOC_IF (reg_dummy, num_regs, const char *); -+ RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); -+ -+ regs_allocated_size = num_regs; -+ } -+} -+ -+# endif /* not MATCH_MAY_ALLOCATE */ -+ -+# ifndef DEFINED_ONCE -+static boolean group_in_compile_stack (compile_stack_type compile_stack, -+ regnum_t regnum); -+# endif /* not DEFINED_ONCE */ -+ -+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. -+ Returns one of error codes defined in `regex.h', or zero for success. -+ -+ Assumes the `allocated' (and perhaps `buffer') and `translate' -+ fields are set in BUFP on entry. -+ -+ If it succeeds, results are put in BUFP (if it returns an error, the -+ contents of BUFP are undefined): -+ `buffer' is the compiled pattern; -+ `syntax' is set to SYNTAX; -+ `used' is set to the length of the compiled pattern; -+ `fastmap_accurate' is zero; -+ `re_nsub' is the number of subexpressions in PATTERN; -+ `not_bol' and `not_eol' are zero; -+ -+ The `fastmap' and `newline_anchor' fields are neither -+ examined nor set. */ -+ -+/* Return, freeing storage we allocated. */ -+# ifdef WCHAR -+# define FREE_STACK_RETURN(value) \ -+ return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) -+# else -+# define FREE_STACK_RETURN(value) \ -+ return (free (compile_stack.stack), value) -+# endif /* WCHAR */ -+ -+static reg_errcode_t -+PREFIX(regex_compile) (const char *ARG_PREFIX(pattern), -+ size_t ARG_PREFIX(size), reg_syntax_t syntax, -+ struct re_pattern_buffer *bufp) -+{ -+ /* We fetch characters from PATTERN here. Even though PATTERN is -+ `char *' (i.e., signed), we declare these variables as unsigned, so -+ they can be reliably used as array indices. */ -+ register UCHAR_T c, c1; -+ -+#ifdef WCHAR -+ /* A temporary space to keep wchar_t pattern and compiled pattern. */ -+ CHAR_T *pattern, *COMPILED_BUFFER_VAR; -+ size_t size; -+ /* offset buffer for optimization. See convert_mbs_to_wc. */ -+ int *mbs_offset = NULL; -+ /* It hold whether each wchar_t is binary data or not. */ -+ char *is_binary = NULL; -+ /* A flag whether exactn is handling binary data or not. */ -+ char is_exactn_bin = FALSE; -+#endif /* WCHAR */ -+ -+ /* A random temporary spot in PATTERN. */ -+ const CHAR_T *p1; -+ -+ /* Points to the end of the buffer, where we should append. */ -+ register UCHAR_T *b; -+ -+ /* Keeps track of unclosed groups. */ -+ compile_stack_type compile_stack; -+ -+ /* Points to the current (ending) position in the pattern. */ -+#ifdef WCHAR -+ const CHAR_T *p; -+ const CHAR_T *pend; -+#else /* BYTE */ -+ const CHAR_T *p = pattern; -+ const CHAR_T *pend = pattern + size; -+#endif /* WCHAR */ -+ -+ /* How to translate the characters in the pattern. */ -+ RE_TRANSLATE_TYPE translate = bufp->translate; -+ -+ /* Address of the count-byte of the most recently inserted `exactn' -+ command. This makes it possible to tell if a new exact-match -+ character can be added to that command or if the character requires -+ a new `exactn' command. */ -+ UCHAR_T *pending_exact = 0; -+ -+ /* Address of start of the most recently finished expression. -+ This tells, e.g., postfix * where to find the start of its -+ operand. Reset at the beginning of groups and alternatives. */ -+ UCHAR_T *laststart = 0; -+ -+ /* Address of beginning of regexp, or inside of last group. */ -+ UCHAR_T *begalt; -+ -+ /* Address of the place where a forward jump should go to the end of -+ the containing expression. Each alternative of an `or' -- except the -+ last -- ends with a forward jump of this sort. */ -+ UCHAR_T *fixup_alt_jump = 0; -+ -+ /* Counts open-groups as they are encountered. Remembered for the -+ matching close-group on the compile stack, so the same register -+ number is put in the stop_memory as the start_memory. */ -+ regnum_t regnum = 0; -+ -+#ifdef WCHAR -+ /* Initialize the wchar_t PATTERN and offset_buffer. */ -+ p = pend = pattern = TALLOC(csize + 1, CHAR_T); -+ mbs_offset = TALLOC(csize + 1, int); -+ is_binary = TALLOC(csize + 1, char); -+ if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) -+ { -+ free(pattern); -+ free(mbs_offset); -+ free(is_binary); -+ return REG_ESPACE; -+ } -+ pattern[csize] = L'\0'; /* sentinel */ -+ size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); -+ pend = p + size; -+ if (size < 0) -+ { -+ free(pattern); -+ free(mbs_offset); -+ free(is_binary); -+ return REG_BADPAT; -+ } -+#endif -+ -+#ifdef DEBUG -+ DEBUG_PRINT1 ("\nCompiling pattern: "); -+ if (debug) -+ { -+ unsigned debug_count; -+ -+ for (debug_count = 0; debug_count < size; debug_count++) -+ PUT_CHAR (pattern[debug_count]); -+ putchar ('\n'); -+ } -+#endif /* DEBUG */ -+ -+ /* Initialize the compile stack. */ -+ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); -+ if (compile_stack.stack == NULL) -+ { -+#ifdef WCHAR -+ free(pattern); -+ free(mbs_offset); -+ free(is_binary); -+#endif -+ return REG_ESPACE; -+ } -+ -+ compile_stack.size = INIT_COMPILE_STACK_SIZE; -+ compile_stack.avail = 0; -+ -+ /* Initialize the pattern buffer. */ -+ bufp->syntax = syntax; -+ bufp->fastmap_accurate = 0; -+ bufp->not_bol = bufp->not_eol = 0; -+ -+ /* Set `used' to zero, so that if we return an error, the pattern -+ printer (for debugging) will think there's no pattern. We reset it -+ at the end. */ -+ bufp->used = 0; -+ -+ /* Always count groups, whether or not bufp->no_sub is set. */ -+ bufp->re_nsub = 0; -+ -+#if !defined emacs && !defined SYNTAX_TABLE -+ /* Initialize the syntax table. */ -+ init_syntax_once (); -+#endif -+ -+ if (bufp->allocated == 0) -+ { -+ if (bufp->buffer) -+ { /* If zero allocated, but buffer is non-null, try to realloc -+ enough space. This loses if buffer's address is bogus, but -+ that is the user's responsibility. */ -+#ifdef WCHAR -+ /* Free bufp->buffer and allocate an array for wchar_t pattern -+ buffer. */ -+ free(bufp->buffer); -+ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), -+ UCHAR_T); -+#else -+ RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); -+#endif /* WCHAR */ -+ } -+ else -+ { /* Caller did not allocate a buffer. Do it for them. */ -+ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), -+ UCHAR_T); -+ } -+ -+ if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); -+#ifdef WCHAR -+ bufp->buffer = (char*)COMPILED_BUFFER_VAR; -+#endif /* WCHAR */ -+ bufp->allocated = INIT_BUF_SIZE; -+ } -+#ifdef WCHAR -+ else -+ COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; -+#endif -+ -+ begalt = b = COMPILED_BUFFER_VAR; -+ -+ /* Loop through the uncompiled pattern until we're at the end. */ -+ while (p != pend) -+ { -+ PATFETCH (c); -+ -+ switch (c) -+ { -+ case '^': -+ { -+ if ( /* If at start of pattern, it's an operator. */ -+ p == pattern + 1 -+ /* If context independent, it's an operator. */ -+ || syntax & RE_CONTEXT_INDEP_ANCHORS -+ /* Otherwise, depends on what's come before. */ -+ || PREFIX(at_begline_loc_p) (pattern, p, syntax)) -+ BUF_PUSH (begline); -+ else -+ goto normal_char; -+ } -+ break; -+ -+ -+ case '$': -+ { -+ if ( /* If at end of pattern, it's an operator. */ -+ p == pend -+ /* If context independent, it's an operator. */ -+ || syntax & RE_CONTEXT_INDEP_ANCHORS -+ /* Otherwise, depends on what's next. */ -+ || PREFIX(at_endline_loc_p) (p, pend, syntax)) -+ BUF_PUSH (endline); -+ else -+ goto normal_char; -+ } -+ break; -+ -+ -+ case '+': -+ case '?': -+ if ((syntax & RE_BK_PLUS_QM) -+ || (syntax & RE_LIMITED_OPS)) -+ goto normal_char; -+ handle_plus: -+ case '*': -+ /* If there is no previous pattern... */ -+ if (!laststart) -+ { -+ if (syntax & RE_CONTEXT_INVALID_OPS) -+ FREE_STACK_RETURN (REG_BADRPT); -+ else if (!(syntax & RE_CONTEXT_INDEP_OPS)) -+ goto normal_char; -+ } -+ -+ { -+ /* Are we optimizing this jump? */ -+ boolean keep_string_p = false; -+ -+ /* 1 means zero (many) matches is allowed. */ -+ char zero_times_ok = 0, many_times_ok = 0; -+ -+ /* If there is a sequence of repetition chars, collapse it -+ down to just one (the right one). We can't combine -+ interval operators with these because of, e.g., `a{2}*', -+ which should only match an even number of `a's. */ -+ -+ for (;;) -+ { -+ zero_times_ok |= c != '+'; -+ many_times_ok |= c != '?'; -+ -+ if (p == pend) -+ break; -+ -+ PATFETCH (c); -+ -+ if (c == '*' -+ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) -+ ; -+ -+ else if (syntax & RE_BK_PLUS_QM && c == '\\') -+ { -+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); -+ -+ PATFETCH (c1); -+ if (!(c1 == '+' || c1 == '?')) -+ { -+ PATUNFETCH; -+ PATUNFETCH; -+ break; -+ } -+ -+ c = c1; -+ } -+ else -+ { -+ PATUNFETCH; -+ break; -+ } -+ -+ /* If we get here, we found another repeat character. */ -+ } -+ -+ /* Star, etc. applied to an empty pattern is equivalent -+ to an empty pattern. */ -+ if (!laststart) -+ break; -+ -+ /* Now we know whether or not zero matches is allowed -+ and also whether or not two or more matches is allowed. */ -+ if (many_times_ok) -+ { /* More than one repetition is allowed, so put in at the -+ end a backward relative jump from `b' to before the next -+ jump we're going to put in below (which jumps from -+ laststart to after this jump). -+ -+ But if we are at the `*' in the exact sequence `.*\n', -+ insert an unconditional jump backwards to the ., -+ instead of the beginning of the loop. This way we only -+ push a failure point once, instead of every time -+ through the loop. */ -+ assert (p - 1 > pattern); -+ -+ /* Allocate the space for the jump. */ -+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); -+ -+ /* We know we are not at the first character of the pattern, -+ because laststart was nonzero. And we've already -+ incremented `p', by the way, to be the character after -+ the `*'. Do we have to do something analogous here -+ for null bytes, because of RE_DOT_NOT_NULL? */ -+ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') -+ && zero_times_ok -+ && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') -+ && !(syntax & RE_DOT_NEWLINE)) -+ { /* We have .*\n. */ -+ STORE_JUMP (jump, b, laststart); -+ keep_string_p = true; -+ } -+ else -+ /* Anything else. */ -+ STORE_JUMP (maybe_pop_jump, b, laststart - -+ (1 + OFFSET_ADDRESS_SIZE)); -+ -+ /* We've added more stuff to the buffer. */ -+ b += 1 + OFFSET_ADDRESS_SIZE; -+ } -+ -+ /* On failure, jump from laststart to b + 3, which will be the -+ end of the buffer after this jump is inserted. */ -+ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of -+ 'b + 3'. */ -+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); -+ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump -+ : on_failure_jump, -+ laststart, b + 1 + OFFSET_ADDRESS_SIZE); -+ pending_exact = 0; -+ b += 1 + OFFSET_ADDRESS_SIZE; -+ -+ if (!zero_times_ok) -+ { -+ /* At least one repetition is required, so insert a -+ `dummy_failure_jump' before the initial -+ `on_failure_jump' instruction of the loop. This -+ effects a skip over that instruction the first time -+ we hit that loop. */ -+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); -+ INSERT_JUMP (dummy_failure_jump, laststart, laststart + -+ 2 + 2 * OFFSET_ADDRESS_SIZE); -+ b += 1 + OFFSET_ADDRESS_SIZE; -+ } -+ } -+ break; -+ -+ -+ case '.': -+ laststart = b; -+ BUF_PUSH (anychar); -+ break; -+ -+ -+ case '[': -+ { -+ boolean had_char_class = false; -+#ifdef WCHAR -+ CHAR_T range_start = 0xffffffff; -+#else -+ unsigned int range_start = 0xffffffff; -+#endif -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+#ifdef WCHAR -+ /* We assume a charset(_not) structure as a wchar_t array. -+ charset[0] = (re_opcode_t) charset(_not) -+ charset[1] = l (= length of char_classes) -+ charset[2] = m (= length of collating_symbols) -+ charset[3] = n (= length of equivalence_classes) -+ charset[4] = o (= length of char_ranges) -+ charset[5] = p (= length of chars) -+ -+ charset[6] = char_class (wctype_t) -+ charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t) -+ ... -+ charset[l+5] = char_class (wctype_t) -+ -+ charset[l+6] = collating_symbol (wchar_t) -+ ... -+ charset[l+m+5] = collating_symbol (wchar_t) -+ ifdef _LIBC we use the index if -+ _NL_COLLATE_SYMB_EXTRAMB instead of -+ wchar_t string. -+ -+ charset[l+m+6] = equivalence_classes (wchar_t) -+ ... -+ charset[l+m+n+5] = equivalence_classes (wchar_t) -+ ifdef _LIBC we use the index in -+ _NL_COLLATE_WEIGHT instead of -+ wchar_t string. -+ -+ charset[l+m+n+6] = range_start -+ charset[l+m+n+7] = range_end -+ ... -+ charset[l+m+n+2o+4] = range_start -+ charset[l+m+n+2o+5] = range_end -+ ifdef _LIBC we use the value looked up -+ in _NL_COLLATE_COLLSEQ instead of -+ wchar_t character. -+ -+ charset[l+m+n+2o+6] = char -+ ... -+ charset[l+m+n+2o+p+5] = char -+ -+ */ -+ -+ /* We need at least 6 spaces: the opcode, the length of -+ char_classes, the length of collating_symbols, the length of -+ equivalence_classes, the length of char_ranges, the length of -+ chars. */ -+ GET_BUFFER_SPACE (6); -+ -+ /* Save b as laststart. And We use laststart as the pointer -+ to the first element of the charset here. -+ In other words, laststart[i] indicates charset[i]. */ -+ laststart = b; -+ -+ /* We test `*p == '^' twice, instead of using an if -+ statement, so we only need one BUF_PUSH. */ -+ BUF_PUSH (*p == '^' ? charset_not : charset); -+ if (*p == '^') -+ p++; -+ -+ /* Push the length of char_classes, the length of -+ collating_symbols, the length of equivalence_classes, the -+ length of char_ranges and the length of chars. */ -+ BUF_PUSH_3 (0, 0, 0); -+ BUF_PUSH_2 (0, 0); -+ -+ /* Remember the first position in the bracket expression. */ -+ p1 = p; -+ -+ /* charset_not matches newline according to a syntax bit. */ -+ if ((re_opcode_t) b[-6] == charset_not -+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) -+ { -+ BUF_PUSH('\n'); -+ laststart[5]++; /* Update the length of characters */ -+ } -+ -+ /* Read in characters and ranges, setting map bits. */ -+ for (;;) -+ { -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ PATFETCH (c); -+ -+ /* \ might escape characters inside [...] and [^...]. */ -+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') -+ { -+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); -+ -+ PATFETCH (c1); -+ BUF_PUSH(c1); -+ laststart[5]++; /* Update the length of chars */ -+ range_start = c1; -+ continue; -+ } -+ -+ /* Could be the end of the bracket expression. If it's -+ not (i.e., when the bracket expression is `[]' so -+ far), the ']' character bit gets set way below. */ -+ if (c == ']' && p != p1 + 1) -+ break; -+ -+ /* Look ahead to see if it's a range when the last thing -+ was a character class. */ -+ if (had_char_class && c == '-' && *p != ']') -+ FREE_STACK_RETURN (REG_ERANGE); -+ -+ /* Look ahead to see if it's a range when the last thing -+ was a character: if this is a hyphen not at the -+ beginning or the end of a list, then it's the range -+ operator. */ -+ if (c == '-' -+ && !(p - 2 >= pattern && p[-2] == '[') -+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') -+ && *p != ']') -+ { -+ reg_errcode_t ret; -+ /* Allocate the space for range_start and range_end. */ -+ GET_BUFFER_SPACE (2); -+ /* Update the pointer to indicate end of buffer. */ -+ b += 2; -+ ret = wcs_compile_range (range_start, &p, pend, translate, -+ syntax, b, laststart); -+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); -+ range_start = 0xffffffff; -+ } -+ else if (p[0] == '-' && p[1] != ']') -+ { /* This handles ranges made up of characters only. */ -+ reg_errcode_t ret; -+ -+ /* Move past the `-'. */ -+ PATFETCH (c1); -+ /* Allocate the space for range_start and range_end. */ -+ GET_BUFFER_SPACE (2); -+ /* Update the pointer to indicate end of buffer. */ -+ b += 2; -+ ret = wcs_compile_range (c, &p, pend, translate, syntax, b, -+ laststart); -+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); -+ range_start = 0xffffffff; -+ } -+ -+ /* See if we're at the beginning of a possible character -+ class. */ -+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') -+ { /* Leave room for the null. */ -+ char str[CHAR_CLASS_MAX_LENGTH + 1]; -+ -+ PATFETCH (c); -+ c1 = 0; -+ -+ /* If pattern is `[[:'. */ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (;;) -+ { -+ PATFETCH (c); -+ if ((c == ':' && *p == ']') || p == pend) -+ break; -+ if (c1 < CHAR_CLASS_MAX_LENGTH) -+ str[c1++] = c; -+ else -+ /* This is in any case an invalid class name. */ -+ str[0] = '\0'; -+ } -+ str[c1] = '\0'; -+ -+ /* If isn't a word bracketed by `[:' and `:]': -+ undo the ending character, the letters, and leave -+ the leading `:' and `[' (but store them as character). */ -+ if (c == ':' && *p == ']') -+ { -+ wctype_t wt; -+ uintptr_t alignedp; -+ -+ /* Query the character class as wctype_t. */ -+ wt = IS_CHAR_CLASS (str); -+ if (wt == 0) -+ FREE_STACK_RETURN (REG_ECTYPE); -+ -+ /* Throw away the ] at the end of the character -+ class. */ -+ PATFETCH (c); -+ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ /* Allocate the space for character class. */ -+ GET_BUFFER_SPACE(CHAR_CLASS_SIZE); -+ /* Update the pointer to indicate end of buffer. */ -+ b += CHAR_CLASS_SIZE; -+ /* Move data which follow character classes -+ not to violate the data. */ -+ insert_space(CHAR_CLASS_SIZE, -+ laststart + 6 + laststart[1], -+ b - 1); -+ alignedp = ((uintptr_t)(laststart + 6 + laststart[1]) -+ + __alignof__(wctype_t) - 1) -+ & ~(uintptr_t)(__alignof__(wctype_t) - 1); -+ /* Store the character class. */ -+ *((wctype_t*)alignedp) = wt; -+ /* Update length of char_classes */ -+ laststart[1] += CHAR_CLASS_SIZE; -+ -+ had_char_class = true; -+ } -+ else -+ { -+ c1++; -+ while (c1--) -+ PATUNFETCH; -+ BUF_PUSH ('['); -+ BUF_PUSH (':'); -+ laststart[5] += 2; /* Update the length of characters */ -+ range_start = ':'; -+ had_char_class = false; -+ } -+ } -+ else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' -+ || *p == '.')) -+ { -+ CHAR_T str[128]; /* Should be large enough. */ -+ CHAR_T delim = *p; /* '=' or '.' */ -+# ifdef _LIBC -+ uint32_t nrules = -+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); -+# endif -+ PATFETCH (c); -+ c1 = 0; -+ -+ /* If pattern is `[[=' or '[[.'. */ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (;;) -+ { -+ PATFETCH (c); -+ if ((c == delim && *p == ']') || p == pend) -+ break; -+ if (c1 < sizeof (str) - 1) -+ str[c1++] = c; -+ else -+ /* This is in any case an invalid class name. */ -+ str[0] = '\0'; -+ } -+ str[c1] = '\0'; -+ -+ if (c == delim && *p == ']' && str[0] != '\0') -+ { -+ unsigned int i, offset; -+ /* If we have no collation data we use the default -+ collation in which each character is in a class -+ by itself. It also means that ASCII is the -+ character set and therefore we cannot have character -+ with more than one byte in the multibyte -+ representation. */ -+ -+ /* If not defined _LIBC, we push the name and -+ `\0' for the sake of matching performance. */ -+ int datasize = c1 + 1; -+ -+# ifdef _LIBC -+ int32_t idx = 0; -+ if (nrules == 0) -+# endif -+ { -+ if (c1 != 1) -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ } -+# ifdef _LIBC -+ else -+ { -+ const int32_t *table; -+ const int32_t *weights; -+ const int32_t *extra; -+ const int32_t *indirect; -+ wint_t *cp; -+ -+ if(delim == '=') -+ { -+ /* We push the index for equivalence class. */ -+ cp = (wint_t*)str; -+ -+ table = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_TABLEWC); -+ weights = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_WEIGHTWC); -+ extra = (const wint_t *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_EXTRAWC); -+ indirect = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_INDIRECTWC); -+ -+ idx = FINDIDX (table, indirect, extra, &cp, 1); -+ if (idx == 0 || cp < (wint_t*) str + c1) -+ /* This is no valid character. */ -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ -+ str[0] = (wchar_t)idx; -+ } -+ else /* delim == '.' */ -+ { -+ /* We push collation sequence value -+ for collating symbol. */ -+ int32_t table_size; -+ const int32_t *symb_table; -+ const unsigned char *extra; -+ int32_t idx; -+ int32_t elem; -+ int32_t second; -+ int32_t hash; -+ char char_str[c1]; -+ -+ /* We have to convert the name to a single-byte -+ string. This is possible since the names -+ consist of ASCII characters and the internal -+ representation is UCS4. */ -+ for (i = 0; i < c1; ++i) -+ char_str[i] = str[i]; -+ -+ table_size = -+ _NL_CURRENT_WORD (LC_COLLATE, -+ _NL_COLLATE_SYMB_HASH_SIZEMB); -+ symb_table = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_SYMB_TABLEMB); -+ extra = (const unsigned char *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_SYMB_EXTRAMB); -+ -+ /* Locate the character in the hashing table. */ -+ hash = elem_hash (char_str, c1); -+ -+ idx = 0; -+ elem = hash % table_size; -+ second = hash % (table_size - 2); -+ while (symb_table[2 * elem] != 0) -+ { -+ /* First compare the hashing value. */ -+ if (symb_table[2 * elem] == hash -+ && c1 == extra[symb_table[2 * elem + 1]] -+ && memcmp (char_str, -+ &extra[symb_table[2 * elem + 1] -+ + 1], c1) == 0) -+ { -+ /* Yep, this is the entry. */ -+ idx = symb_table[2 * elem + 1]; -+ idx += 1 + extra[idx]; -+ break; -+ } -+ -+ /* Next entry. */ -+ elem += second; -+ } -+ -+ if (symb_table[2 * elem] != 0) -+ { -+ /* Compute the index of the byte sequence -+ in the table. */ -+ idx += 1 + extra[idx]; -+ /* Adjust for the alignment. */ -+ idx = (idx + 3) & ~3; -+ -+ str[0] = (wchar_t) idx + 4; -+ } -+ else if (symb_table[2 * elem] == 0 && c1 == 1) -+ { -+ /* No valid character. Match it as a -+ single byte character. */ -+ had_char_class = false; -+ BUF_PUSH(str[0]); -+ /* Update the length of characters */ -+ laststart[5]++; -+ range_start = str[0]; -+ -+ /* Throw away the ] at the end of the -+ collating symbol. */ -+ PATFETCH (c); -+ /* exit from the switch block. */ -+ continue; -+ } -+ else -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ } -+ datasize = 1; -+ } -+# endif -+ /* Throw away the ] at the end of the equivalence -+ class (or collating symbol). */ -+ PATFETCH (c); -+ -+ /* Allocate the space for the equivalence class -+ (or collating symbol) (and '\0' if needed). */ -+ GET_BUFFER_SPACE(datasize); -+ /* Update the pointer to indicate end of buffer. */ -+ b += datasize; -+ -+ if (delim == '=') -+ { /* equivalence class */ -+ /* Calculate the offset of char_ranges, -+ which is next to equivalence_classes. */ -+ offset = laststart[1] + laststart[2] -+ + laststart[3] +6; -+ /* Insert space. */ -+ insert_space(datasize, laststart + offset, b - 1); -+ -+ /* Write the equivalence_class and \0. */ -+ for (i = 0 ; i < datasize ; i++) -+ laststart[offset + i] = str[i]; -+ -+ /* Update the length of equivalence_classes. */ -+ laststart[3] += datasize; -+ had_char_class = true; -+ } -+ else /* delim == '.' */ -+ { /* collating symbol */ -+ /* Calculate the offset of the equivalence_classes, -+ which is next to collating_symbols. */ -+ offset = laststart[1] + laststart[2] + 6; -+ /* Insert space and write the collationg_symbol -+ and \0. */ -+ insert_space(datasize, laststart + offset, b-1); -+ for (i = 0 ; i < datasize ; i++) -+ laststart[offset + i] = str[i]; -+ -+ /* In re_match_2_internal if range_start < -1, we -+ assume -range_start is the offset of the -+ collating symbol which is specified as -+ the character of the range start. So we assign -+ -(laststart[1] + laststart[2] + 6) to -+ range_start. */ -+ range_start = -(laststart[1] + laststart[2] + 6); -+ /* Update the length of collating_symbol. */ -+ laststart[2] += datasize; -+ had_char_class = false; -+ } -+ } -+ else -+ { -+ c1++; -+ while (c1--) -+ PATUNFETCH; -+ BUF_PUSH ('['); -+ BUF_PUSH (delim); -+ laststart[5] += 2; /* Update the length of characters */ -+ range_start = delim; -+ had_char_class = false; -+ } -+ } -+ else -+ { -+ had_char_class = false; -+ BUF_PUSH(c); -+ laststart[5]++; /* Update the length of characters */ -+ range_start = c; -+ } -+ } -+ -+#else /* BYTE */ -+ /* Ensure that we have enough space to push a charset: the -+ opcode, the length count, and the bitset; 34 bytes in all. */ -+ GET_BUFFER_SPACE (34); -+ -+ laststart = b; -+ -+ /* We test `*p == '^' twice, instead of using an if -+ statement, so we only need one BUF_PUSH. */ -+ BUF_PUSH (*p == '^' ? charset_not : charset); -+ if (*p == '^') -+ p++; -+ -+ /* Remember the first position in the bracket expression. */ -+ p1 = p; -+ -+ /* Push the number of bytes in the bitmap. */ -+ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); -+ -+ /* Clear the whole map. */ -+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); -+ -+ /* charset_not matches newline according to a syntax bit. */ -+ if ((re_opcode_t) b[-2] == charset_not -+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) -+ SET_LIST_BIT ('\n'); -+ -+ /* Read in characters and ranges, setting map bits. */ -+ for (;;) -+ { -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ PATFETCH (c); -+ -+ /* \ might escape characters inside [...] and [^...]. */ -+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') -+ { -+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); -+ -+ PATFETCH (c1); -+ SET_LIST_BIT (c1); -+ range_start = c1; -+ continue; -+ } -+ -+ /* Could be the end of the bracket expression. If it's -+ not (i.e., when the bracket expression is `[]' so -+ far), the ']' character bit gets set way below. */ -+ if (c == ']' && p != p1 + 1) -+ break; -+ -+ /* Look ahead to see if it's a range when the last thing -+ was a character class. */ -+ if (had_char_class && c == '-' && *p != ']') -+ FREE_STACK_RETURN (REG_ERANGE); -+ -+ /* Look ahead to see if it's a range when the last thing -+ was a character: if this is a hyphen not at the -+ beginning or the end of a list, then it's the range -+ operator. */ -+ if (c == '-' -+ && !(p - 2 >= pattern && p[-2] == '[') -+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') -+ && *p != ']') -+ { -+ reg_errcode_t ret -+ = byte_compile_range (range_start, &p, pend, translate, -+ syntax, b); -+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); -+ range_start = 0xffffffff; -+ } -+ -+ else if (p[0] == '-' && p[1] != ']') -+ { /* This handles ranges made up of characters only. */ -+ reg_errcode_t ret; -+ -+ /* Move past the `-'. */ -+ PATFETCH (c1); -+ -+ ret = byte_compile_range (c, &p, pend, translate, syntax, b); -+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); -+ range_start = 0xffffffff; -+ } -+ -+ /* See if we're at the beginning of a possible character -+ class. */ -+ -+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') -+ { /* Leave room for the null. */ -+ char str[CHAR_CLASS_MAX_LENGTH + 1]; -+ -+ PATFETCH (c); -+ c1 = 0; -+ -+ /* If pattern is `[[:'. */ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (;;) -+ { -+ PATFETCH (c); -+ if ((c == ':' && *p == ']') || p == pend) -+ break; -+ if (((int) c1) < CHAR_CLASS_MAX_LENGTH) -+ str[c1++] = c; -+ else -+ /* This is in any case an invalid class name. */ -+ str[0] = '\0'; -+ } -+ str[c1] = '\0'; -+ -+ /* If isn't a word bracketed by `[:' and `:]': -+ undo the ending character, the letters, and leave -+ the leading `:' and `[' (but set bits for them). */ -+ if (c == ':' && *p == ']') -+ { -+# if WIDE_CHAR_SUPPORT -+ boolean is_lower = STREQ (str, "lower"); -+ boolean is_upper = STREQ (str, "upper"); -+ wctype_t wt; -+ int ch; -+ -+ wt = IS_CHAR_CLASS (str); -+ if (wt == 0) -+ FREE_STACK_RETURN (REG_ECTYPE); -+ -+ /* Throw away the ] at the end of the character -+ class. */ -+ PATFETCH (c); -+ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) -+ { -+# ifdef _LIBC -+ if (__iswctype (__btowc (ch), wt)) -+ SET_LIST_BIT (ch); -+# else -+ if (iswctype (btowc (ch), wt)) -+ SET_LIST_BIT (ch); -+# endif -+ -+ if (translate && (is_upper || is_lower) -+ && (ISUPPER (ch) || ISLOWER (ch))) -+ SET_LIST_BIT (ch); -+ } -+ -+ had_char_class = true; -+# else -+ int ch; -+ boolean is_alnum = STREQ (str, "alnum"); -+ boolean is_alpha = STREQ (str, "alpha"); -+ boolean is_blank = STREQ (str, "blank"); -+ boolean is_cntrl = STREQ (str, "cntrl"); -+ boolean is_digit = STREQ (str, "digit"); -+ boolean is_graph = STREQ (str, "graph"); -+ boolean is_lower = STREQ (str, "lower"); -+ boolean is_print = STREQ (str, "print"); -+ boolean is_punct = STREQ (str, "punct"); -+ boolean is_space = STREQ (str, "space"); -+ boolean is_upper = STREQ (str, "upper"); -+ boolean is_xdigit = STREQ (str, "xdigit"); -+ -+ if (!IS_CHAR_CLASS (str)) -+ FREE_STACK_RETURN (REG_ECTYPE); -+ -+ /* Throw away the ] at the end of the character -+ class. */ -+ PATFETCH (c); -+ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++) -+ { -+ /* This was split into 3 if's to -+ avoid an arbitrary limit in some compiler. */ -+ if ( (is_alnum && ISALNUM (ch)) -+ || (is_alpha && ISALPHA (ch)) -+ || (is_blank && ISBLANK (ch)) -+ || (is_cntrl && ISCNTRL (ch))) -+ SET_LIST_BIT (ch); -+ if ( (is_digit && ISDIGIT (ch)) -+ || (is_graph && ISGRAPH (ch)) -+ || (is_lower && ISLOWER (ch)) -+ || (is_print && ISPRINT (ch))) -+ SET_LIST_BIT (ch); -+ if ( (is_punct && ISPUNCT (ch)) -+ || (is_space && ISSPACE (ch)) -+ || (is_upper && ISUPPER (ch)) -+ || (is_xdigit && ISXDIGIT (ch))) -+ SET_LIST_BIT (ch); -+ if ( translate && (is_upper || is_lower) -+ && (ISUPPER (ch) || ISLOWER (ch))) -+ SET_LIST_BIT (ch); -+ } -+ had_char_class = true; -+# endif /* libc || wctype.h */ -+ } -+ else -+ { -+ c1++; -+ while (c1--) -+ PATUNFETCH; -+ SET_LIST_BIT ('['); -+ SET_LIST_BIT (':'); -+ range_start = ':'; -+ had_char_class = false; -+ } -+ } -+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=') -+ { -+ unsigned char str[MB_LEN_MAX + 1]; -+# ifdef _LIBC -+ uint32_t nrules = -+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); -+# endif -+ -+ PATFETCH (c); -+ c1 = 0; -+ -+ /* If pattern is `[[='. */ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (;;) -+ { -+ PATFETCH (c); -+ if ((c == '=' && *p == ']') || p == pend) -+ break; -+ if (c1 < MB_LEN_MAX) -+ str[c1++] = c; -+ else -+ /* This is in any case an invalid class name. */ -+ str[0] = '\0'; -+ } -+ str[c1] = '\0'; -+ -+ if (c == '=' && *p == ']' && str[0] != '\0') -+ { -+ /* If we have no collation data we use the default -+ collation in which each character is in a class -+ by itself. It also means that ASCII is the -+ character set and therefore we cannot have character -+ with more than one byte in the multibyte -+ representation. */ -+# ifdef _LIBC -+ if (nrules == 0) -+# endif -+ { -+ if (c1 != 1) -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ -+ /* Throw away the ] at the end of the equivalence -+ class. */ -+ PATFETCH (c); -+ -+ /* Set the bit for the character. */ -+ SET_LIST_BIT (str[0]); -+ } -+# ifdef _LIBC -+ else -+ { -+ /* Try to match the byte sequence in `str' against -+ those known to the collate implementation. -+ First find out whether the bytes in `str' are -+ actually from exactly one character. */ -+ const int32_t *table; -+ const unsigned char *weights; -+ const unsigned char *extra; -+ const int32_t *indirect; -+ int32_t idx; -+ const unsigned char *cp = str; -+ int ch; -+ -+ table = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); -+ weights = (const unsigned char *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); -+ extra = (const unsigned char *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); -+ indirect = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); -+ idx = FINDIDX (table, indirect, extra, &cp, 1); -+ if (idx == 0 || cp < str + c1) -+ /* This is no valid character. */ -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ -+ /* Throw away the ] at the end of the equivalence -+ class. */ -+ PATFETCH (c); -+ -+ /* Now we have to go throught the whole table -+ and find all characters which have the same -+ first level weight. -+ -+ XXX Note that this is not entirely correct. -+ we would have to match multibyte sequences -+ but this is not possible with the current -+ implementation. */ -+ for (ch = 1; ch < 256; ++ch) -+ /* XXX This test would have to be changed if we -+ would allow matching multibyte sequences. */ -+ if (table[ch] > 0) -+ { -+ int32_t idx2 = table[ch]; -+ size_t len = weights[idx2]; -+ -+ /* Test whether the lenghts match. */ -+ if (weights[idx] == len) -+ { -+ /* They do. New compare the bytes of -+ the weight. */ -+ size_t cnt = 0; -+ -+ while (cnt < len -+ && (weights[idx + 1 + cnt] -+ == weights[idx2 + 1 + cnt])) -+ ++cnt; -+ -+ if (cnt == len) -+ /* They match. Mark the character as -+ acceptable. */ -+ SET_LIST_BIT (ch); -+ } -+ } -+ } -+# endif -+ had_char_class = true; -+ } -+ else -+ { -+ c1++; -+ while (c1--) -+ PATUNFETCH; -+ SET_LIST_BIT ('['); -+ SET_LIST_BIT ('='); -+ range_start = '='; -+ had_char_class = false; -+ } -+ } -+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.') -+ { -+ unsigned char str[128]; /* Should be large enough. */ -+# ifdef _LIBC -+ uint32_t nrules = -+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); -+# endif -+ -+ PATFETCH (c); -+ c1 = 0; -+ -+ /* If pattern is `[[.'. */ -+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -+ -+ for (;;) -+ { -+ PATFETCH (c); -+ if ((c == '.' && *p == ']') || p == pend) -+ break; -+ if (c1 < sizeof (str)) -+ str[c1++] = c; -+ else -+ /* This is in any case an invalid class name. */ -+ str[0] = '\0'; -+ } -+ str[c1] = '\0'; -+ -+ if (c == '.' && *p == ']' && str[0] != '\0') -+ { -+ /* If we have no collation data we use the default -+ collation in which each character is the name -+ for its own class which contains only the one -+ character. It also means that ASCII is the -+ character set and therefore we cannot have character -+ with more than one byte in the multibyte -+ representation. */ -+# ifdef _LIBC -+ if (nrules == 0) -+# endif -+ { -+ if (c1 != 1) -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ -+ /* Throw away the ] at the end of the equivalence -+ class. */ -+ PATFETCH (c); -+ -+ /* Set the bit for the character. */ -+ SET_LIST_BIT (str[0]); -+ range_start = ((const unsigned char *) str)[0]; -+ } -+# ifdef _LIBC -+ else -+ { -+ /* Try to match the byte sequence in `str' against -+ those known to the collate implementation. -+ First find out whether the bytes in `str' are -+ actually from exactly one character. */ -+ int32_t table_size; -+ const int32_t *symb_table; -+ const unsigned char *extra; -+ int32_t idx; -+ int32_t elem; -+ int32_t second; -+ int32_t hash; -+ -+ table_size = -+ _NL_CURRENT_WORD (LC_COLLATE, -+ _NL_COLLATE_SYMB_HASH_SIZEMB); -+ symb_table = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_SYMB_TABLEMB); -+ extra = (const unsigned char *) -+ _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_SYMB_EXTRAMB); -+ -+ /* Locate the character in the hashing table. */ -+ hash = elem_hash ((const char *) str, c1); -+ -+ idx = 0; -+ elem = hash % table_size; -+ second = hash % (table_size - 2); -+ while (symb_table[2 * elem] != 0) -+ { -+ /* First compare the hashing value. */ -+ if (symb_table[2 * elem] == hash -+ && c1 == extra[symb_table[2 * elem + 1]] -+ && memcmp (str, -+ &extra[symb_table[2 * elem + 1] -+ + 1], -+ c1) == 0) -+ { -+ /* Yep, this is the entry. */ -+ idx = symb_table[2 * elem + 1]; -+ idx += 1 + extra[idx]; -+ break; -+ } -+ -+ /* Next entry. */ -+ elem += second; -+ } -+ -+ if (symb_table[2 * elem] == 0) -+ /* This is no valid character. */ -+ FREE_STACK_RETURN (REG_ECOLLATE); -+ -+ /* Throw away the ] at the end of the equivalence -+ class. */ -+ PATFETCH (c); -+ -+ /* Now add the multibyte character(s) we found -+ to the accept list. -+ -+ XXX Note that this is not entirely correct. -+ we would have to match multibyte sequences -+ but this is not possible with the current -+ implementation. Also, we have to match -+ collating symbols, which expand to more than -+ one file, as a whole and not allow the -+ individual bytes. */ -+ c1 = extra[idx++]; -+ if (c1 == 1) -+ range_start = extra[idx]; -+ while (c1-- > 0) -+ { -+ SET_LIST_BIT (extra[idx]); -+ ++idx; -+ } -+ } -+# endif -+ had_char_class = false; -+ } -+ else -+ { -+ c1++; -+ while (c1--) -+ PATUNFETCH; -+ SET_LIST_BIT ('['); -+ SET_LIST_BIT ('.'); -+ range_start = '.'; -+ had_char_class = false; -+ } -+ } -+ else -+ { -+ had_char_class = false; -+ SET_LIST_BIT (c); -+ range_start = c; -+ } -+ } -+ -+ /* Discard any (non)matching list bytes that are all 0 at the -+ end of the map. Decrease the map-length byte too. */ -+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) -+ b[-1]--; -+ b += b[-1]; -+#endif /* WCHAR */ -+ } -+ break; -+ -+ -+ case '(': -+ if (syntax & RE_NO_BK_PARENS) -+ goto handle_open; -+ else -+ goto normal_char; -+ -+ -+ case ')': -+ if (syntax & RE_NO_BK_PARENS) -+ goto handle_close; -+ else -+ goto normal_char; -+ -+ -+ case '\n': -+ if (syntax & RE_NEWLINE_ALT) -+ goto handle_alt; -+ else -+ goto normal_char; -+ -+ -+ case '|': -+ if (syntax & RE_NO_BK_VBAR) -+ goto handle_alt; -+ else -+ goto normal_char; -+ -+ -+ case '{': -+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) -+ goto handle_interval; -+ else -+ goto normal_char; -+ -+ -+ case '\\': -+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); -+ -+ /* Do not translate the character after the \, so that we can -+ distinguish, e.g., \B from \b, even if we normally would -+ translate, e.g., B to b. */ -+ PATFETCH_RAW (c); -+ -+ switch (c) -+ { -+ case '(': -+ if (syntax & RE_NO_BK_PARENS) -+ goto normal_backslash; -+ -+ handle_open: -+ bufp->re_nsub++; -+ regnum++; -+ -+ if (COMPILE_STACK_FULL) -+ { -+ RETALLOC (compile_stack.stack, compile_stack.size << 1, -+ compile_stack_elt_t); -+ if (compile_stack.stack == NULL) return REG_ESPACE; -+ -+ compile_stack.size <<= 1; -+ } -+ -+ /* These are the values to restore when we hit end of this -+ group. They are all relative offsets, so that if the -+ whole pattern moves because of realloc, they will still -+ be valid. */ -+ COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR; -+ COMPILE_STACK_TOP.fixup_alt_jump -+ = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0; -+ COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR; -+ COMPILE_STACK_TOP.regnum = regnum; -+ -+ /* We will eventually replace the 0 with the number of -+ groups inner to this one. But do not push a -+ start_memory for groups beyond the last one we can -+ represent in the compiled pattern. */ -+ if (regnum <= MAX_REGNUM) -+ { -+ COMPILE_STACK_TOP.inner_group_offset = b -+ - COMPILED_BUFFER_VAR + 2; -+ BUF_PUSH_3 (start_memory, regnum, 0); -+ } -+ -+ compile_stack.avail++; -+ -+ fixup_alt_jump = 0; -+ laststart = 0; -+ begalt = b; -+ /* If we've reached MAX_REGNUM groups, then this open -+ won't actually generate any code, so we'll have to -+ clear pending_exact explicitly. */ -+ pending_exact = 0; -+ break; -+ -+ -+ case ')': -+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash; -+ -+ if (COMPILE_STACK_EMPTY) -+ { -+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) -+ goto normal_backslash; -+ else -+ FREE_STACK_RETURN (REG_ERPAREN); -+ } -+ -+ handle_close: -+ if (fixup_alt_jump) -+ { /* Push a dummy failure point at the end of the -+ alternative for a possible future -+ `pop_failure_jump' to pop. See comments at -+ `push_dummy_failure' in `re_match_2'. */ -+ BUF_PUSH (push_dummy_failure); -+ -+ /* We allocated space for this jump when we assigned -+ to `fixup_alt_jump', in the `handle_alt' case below. */ -+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); -+ } -+ -+ /* See similar code for backslashed left paren above. */ -+ if (COMPILE_STACK_EMPTY) -+ { -+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) -+ goto normal_char; -+ else -+ FREE_STACK_RETURN (REG_ERPAREN); -+ } -+ -+ /* Since we just checked for an empty stack above, this -+ ``can't happen''. */ -+ assert (compile_stack.avail != 0); -+ { -+ /* We don't just want to restore into `regnum', because -+ later groups should continue to be numbered higher, -+ as in `(ab)c(de)' -- the second group is #2. */ -+ regnum_t this_group_regnum; -+ -+ compile_stack.avail--; -+ begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset; -+ fixup_alt_jump -+ = COMPILE_STACK_TOP.fixup_alt_jump -+ ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1 -+ : 0; -+ laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset; -+ this_group_regnum = COMPILE_STACK_TOP.regnum; -+ /* If we've reached MAX_REGNUM groups, then this open -+ won't actually generate any code, so we'll have to -+ clear pending_exact explicitly. */ -+ pending_exact = 0; -+ -+ /* We're at the end of the group, so now we know how many -+ groups were inside this one. */ -+ if (this_group_regnum <= MAX_REGNUM) -+ { -+ UCHAR_T *inner_group_loc -+ = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; -+ -+ *inner_group_loc = regnum - this_group_regnum; -+ BUF_PUSH_3 (stop_memory, this_group_regnum, -+ regnum - this_group_regnum); -+ } -+ } -+ break; -+ -+ -+ case '|': /* `\|'. */ -+ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) -+ goto normal_backslash; -+ handle_alt: -+ if (syntax & RE_LIMITED_OPS) -+ goto normal_char; -+ -+ /* Insert before the previous alternative a jump which -+ jumps to this alternative if the former fails. */ -+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); -+ INSERT_JUMP (on_failure_jump, begalt, -+ b + 2 + 2 * OFFSET_ADDRESS_SIZE); -+ pending_exact = 0; -+ b += 1 + OFFSET_ADDRESS_SIZE; -+ -+ /* The alternative before this one has a jump after it -+ which gets executed if it gets matched. Adjust that -+ jump so it will jump to this alternative's analogous -+ jump (put in below, which in turn will jump to the next -+ (if any) alternative's such jump, etc.). The last such -+ jump jumps to the correct final destination. A picture: -+ _____ _____ -+ | | | | -+ | v | v -+ a | b | c -+ -+ If we are at `b', then fixup_alt_jump right now points to a -+ three-byte space after `a'. We'll put in the jump, set -+ fixup_alt_jump to right after `b', and leave behind three -+ bytes which we'll fill in when we get to after `c'. */ -+ -+ if (fixup_alt_jump) -+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b); -+ -+ /* Mark and leave space for a jump after this alternative, -+ to be filled in later either by next alternative or -+ when know we're at the end of a series of alternatives. */ -+ fixup_alt_jump = b; -+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); -+ b += 1 + OFFSET_ADDRESS_SIZE; -+ -+ laststart = 0; -+ begalt = b; -+ break; -+ -+ -+ case '{': -+ /* If \{ is a literal. */ -+ if (!(syntax & RE_INTERVALS) -+ /* If we're at `\{' and it's not the open-interval -+ operator. */ -+ || (syntax & RE_NO_BK_BRACES)) -+ goto normal_backslash; -+ -+ handle_interval: -+ { -+ /* If got here, then the syntax allows intervals. */ -+ -+ /* At least (most) this many matches must be made. */ -+ int lower_bound = -1, upper_bound = -1; -+ -+ /* Place in the uncompiled pattern (i.e., just after -+ the '{') to go back to if the interval is invalid. */ -+ const CHAR_T *beg_interval = p; -+ -+ if (p == pend) -+ goto invalid_interval; -+ -+ GET_UNSIGNED_NUMBER (lower_bound); -+ -+ if (c == ',') -+ { -+ GET_UNSIGNED_NUMBER (upper_bound); -+ if (upper_bound < 0) -+ upper_bound = RE_DUP_MAX; -+ } -+ else -+ /* Interval such as `{1}' => match exactly once. */ -+ upper_bound = lower_bound; -+ -+ if (! (0 <= lower_bound && lower_bound <= upper_bound)) -+ goto invalid_interval; -+ -+ if (!(syntax & RE_NO_BK_BRACES)) -+ { -+ if (c != '\\' || p == pend) -+ goto invalid_interval; -+ PATFETCH (c); -+ } -+ -+ if (c != '}') -+ goto invalid_interval; -+ -+ /* If it's invalid to have no preceding re. */ -+ if (!laststart) -+ { -+ if (syntax & RE_CONTEXT_INVALID_OPS -+ && !(syntax & RE_INVALID_INTERVAL_ORD)) -+ FREE_STACK_RETURN (REG_BADRPT); -+ else if (syntax & RE_CONTEXT_INDEP_OPS) -+ laststart = b; -+ else -+ goto unfetch_interval; -+ } -+ -+ /* We just parsed a valid interval. */ -+ -+ if (RE_DUP_MAX < upper_bound) -+ FREE_STACK_RETURN (REG_BADBR); -+ -+ /* If the upper bound is zero, don't want to succeed at -+ all; jump from `laststart' to `b + 3', which will be -+ the end of the buffer after we insert the jump. */ -+ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' -+ instead of 'b + 3'. */ -+ if (upper_bound == 0) -+ { -+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); -+ INSERT_JUMP (jump, laststart, b + 1 -+ + OFFSET_ADDRESS_SIZE); -+ b += 1 + OFFSET_ADDRESS_SIZE; -+ } -+ -+ /* Otherwise, we have a nontrivial interval. When -+ we're all done, the pattern will look like: -+ set_number_at -+ set_number_at -+ succeed_n -+ -+ jump_n -+ (The upper bound and `jump_n' are omitted if -+ `upper_bound' is 1, though.) */ -+ else -+ { /* If the upper bound is > 1, we need to insert -+ more at the end of the loop. */ -+ unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE + -+ (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE); -+ -+ GET_BUFFER_SPACE (nbytes); -+ -+ /* Initialize lower bound of the `succeed_n', even -+ though it will be set during matching by its -+ attendant `set_number_at' (inserted next), -+ because `re_compile_fastmap' needs to know. -+ Jump to the `jump_n' we might insert below. */ -+ INSERT_JUMP2 (succeed_n, laststart, -+ b + 1 + 2 * OFFSET_ADDRESS_SIZE -+ + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE) -+ , lower_bound); -+ b += 1 + 2 * OFFSET_ADDRESS_SIZE; -+ -+ /* Code to initialize the lower bound. Insert -+ before the `succeed_n'. The `5' is the last two -+ bytes of this `set_number_at', plus 3 bytes of -+ the following `succeed_n'. */ -+ /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' -+ is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' -+ of the following `succeed_n'. */ -+ PREFIX(insert_op2) (set_number_at, laststart, 1 -+ + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); -+ b += 1 + 2 * OFFSET_ADDRESS_SIZE; -+ -+ if (upper_bound > 1) -+ { /* More than one repetition is allowed, so -+ append a backward jump to the `succeed_n' -+ that starts this interval. -+ -+ When we've reached this during matching, -+ we'll have matched the interval once, so -+ jump back only `upper_bound - 1' times. */ -+ STORE_JUMP2 (jump_n, b, laststart -+ + 2 * OFFSET_ADDRESS_SIZE + 1, -+ upper_bound - 1); -+ b += 1 + 2 * OFFSET_ADDRESS_SIZE; -+ -+ /* The location we want to set is the second -+ parameter of the `jump_n'; that is `b-2' as -+ an absolute address. `laststart' will be -+ the `set_number_at' we're about to insert; -+ `laststart+3' the number to set, the source -+ for the relative address. But we are -+ inserting into the middle of the pattern -- -+ so everything is getting moved up by 5. -+ Conclusion: (b - 2) - (laststart + 3) + 5, -+ i.e., b - laststart. -+ -+ We insert this at the beginning of the loop -+ so that if we fail during matching, we'll -+ reinitialize the bounds. */ -+ PREFIX(insert_op2) (set_number_at, laststart, -+ b - laststart, -+ upper_bound - 1, b); -+ b += 1 + 2 * OFFSET_ADDRESS_SIZE; -+ } -+ } -+ pending_exact = 0; -+ break; -+ -+ invalid_interval: -+ if (!(syntax & RE_INVALID_INTERVAL_ORD)) -+ FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR); -+ unfetch_interval: -+ /* Match the characters as literals. */ -+ p = beg_interval; -+ c = '{'; -+ if (syntax & RE_NO_BK_BRACES) -+ goto normal_char; -+ else -+ goto normal_backslash; -+ } -+ -+#ifdef emacs -+ /* There is no way to specify the before_dot and after_dot -+ operators. rms says this is ok. --karl */ -+ case '=': -+ BUF_PUSH (at_dot); -+ break; -+ -+ case 's': -+ laststart = b; -+ PATFETCH (c); -+ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); -+ break; -+ -+ case 'S': -+ laststart = b; -+ PATFETCH (c); -+ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); -+ break; -+#endif /* emacs */ -+ -+ -+ case 'w': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ laststart = b; -+ BUF_PUSH (wordchar); -+ break; -+ -+ -+ case 'W': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ laststart = b; -+ BUF_PUSH (notwordchar); -+ break; -+ -+ -+ case '<': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ BUF_PUSH (wordbeg); -+ break; -+ -+ case '>': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ BUF_PUSH (wordend); -+ break; -+ -+ case 'b': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ BUF_PUSH (wordbound); -+ break; -+ -+ case 'B': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ BUF_PUSH (notwordbound); -+ break; -+ -+ case '`': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ BUF_PUSH (begbuf); -+ break; -+ -+ case '\'': -+ if (syntax & RE_NO_GNU_OPS) -+ goto normal_char; -+ BUF_PUSH (endbuf); -+ break; -+ -+ case '1': case '2': case '3': case '4': case '5': -+ case '6': case '7': case '8': case '9': -+ if (syntax & RE_NO_BK_REFS) -+ goto normal_char; -+ -+ c1 = c - '0'; -+ -+ if (c1 > regnum) -+ FREE_STACK_RETURN (REG_ESUBREG); -+ -+ /* Can't back reference to a subexpression if inside of it. */ -+ if (group_in_compile_stack (compile_stack, (regnum_t) c1)) -+ goto normal_char; -+ -+ laststart = b; -+ BUF_PUSH_2 (duplicate, c1); -+ break; -+ -+ -+ case '+': -+ case '?': -+ if (syntax & RE_BK_PLUS_QM) -+ goto handle_plus; -+ else -+ goto normal_backslash; -+ -+ default: -+ normal_backslash: -+ /* You might think it would be useful for \ to mean -+ not to translate; but if we don't translate it -+ it will never match anything. */ -+ c = TRANSLATE (c); -+ goto normal_char; -+ } -+ break; -+ -+ -+ default: -+ /* Expects the character in `c'. */ -+ normal_char: -+ /* If no exactn currently being built. */ -+ if (!pending_exact -+#ifdef WCHAR -+ /* If last exactn handle binary(or character) and -+ new exactn handle character(or binary). */ -+ || is_exactn_bin != is_binary[p - 1 - pattern] -+#endif /* WCHAR */ -+ -+ /* If last exactn not at current position. */ -+ || pending_exact + *pending_exact + 1 != b -+ -+ /* We have only one byte following the exactn for the count. */ -+ || *pending_exact == (1 << BYTEWIDTH) - 1 -+ -+ /* If followed by a repetition operator. */ -+ || *p == '*' || *p == '^' -+ || ((syntax & RE_BK_PLUS_QM) -+ ? *p == '\\' && (p[1] == '+' || p[1] == '?') -+ : (*p == '+' || *p == '?')) -+ || ((syntax & RE_INTERVALS) -+ && ((syntax & RE_NO_BK_BRACES) -+ ? *p == '{' -+ : (p[0] == '\\' && p[1] == '{')))) -+ { -+ /* Start building a new exactn. */ -+ -+ laststart = b; -+ -+#ifdef WCHAR -+ /* Is this exactn binary data or character? */ -+ is_exactn_bin = is_binary[p - 1 - pattern]; -+ if (is_exactn_bin) -+ BUF_PUSH_2 (exactn_bin, 0); -+ else -+ BUF_PUSH_2 (exactn, 0); -+#else -+ BUF_PUSH_2 (exactn, 0); -+#endif /* WCHAR */ -+ pending_exact = b - 1; -+ } -+ -+ BUF_PUSH (c); -+ (*pending_exact)++; -+ break; -+ } /* switch (c) */ -+ } /* while p != pend */ -+ -+ -+ /* Through the pattern now. */ -+ -+ if (fixup_alt_jump) -+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b); -+ -+ if (!COMPILE_STACK_EMPTY) -+ FREE_STACK_RETURN (REG_EPAREN); -+ -+ /* If we don't want backtracking, force success -+ the first time we reach the end of the compiled pattern. */ -+ if (syntax & RE_NO_POSIX_BACKTRACKING) -+ BUF_PUSH (succeed); -+ -+#ifdef WCHAR -+ free (pattern); -+ free (mbs_offset); -+ free (is_binary); -+#endif -+ free (compile_stack.stack); -+ -+ /* We have succeeded; set the length of the buffer. */ -+#ifdef WCHAR -+ bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; -+#else -+ bufp->used = b - bufp->buffer; -+#endif -+ -+#ifdef DEBUG -+ if (debug) -+ { -+ DEBUG_PRINT1 ("\nCompiled pattern: \n"); -+ PREFIX(print_compiled_pattern) (bufp); -+ } -+#endif /* DEBUG */ -+ -+#ifndef MATCH_MAY_ALLOCATE -+ /* Initialize the failure stack to the largest possible stack. This -+ isn't necessary unless we're trying to avoid calling alloca in -+ the search and match routines. */ -+ { -+ int num_regs = bufp->re_nsub + 1; -+ -+ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size -+ is strictly greater than re_max_failures, the largest possible stack -+ is 2 * re_max_failures failure points. */ -+ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) -+ { -+ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); -+ -+# ifdef emacs -+ if (! fail_stack.stack) -+ fail_stack.stack -+ = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size -+ * sizeof (PREFIX(fail_stack_elt_t))); -+ else -+ fail_stack.stack -+ = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, -+ (fail_stack.size -+ * sizeof (PREFIX(fail_stack_elt_t)))); -+# else /* not emacs */ -+ if (! fail_stack.stack) -+ fail_stack.stack -+ = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size -+ * sizeof (PREFIX(fail_stack_elt_t))); -+ else -+ fail_stack.stack -+ = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack, -+ (fail_stack.size -+ * sizeof (PREFIX(fail_stack_elt_t)))); -+# endif /* not emacs */ -+ } -+ -+ PREFIX(regex_grow_registers) (num_regs); -+ } -+#endif /* not MATCH_MAY_ALLOCATE */ -+ -+ return REG_NOERROR; -+} /* regex_compile */ -+ -+/* Subroutines for `regex_compile'. */ -+ -+/* Store OP at LOC followed by two-byte integer parameter ARG. */ -+/* ifdef WCHAR, integer parameter is 1 wchar_t. */ -+ -+static void -+PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg) -+{ -+ *loc = (UCHAR_T) op; -+ STORE_NUMBER (loc + 1, arg); -+} -+ -+ -+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ -+/* ifdef WCHAR, integer parameter is 1 wchar_t. */ -+ -+static void -+PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2) -+{ -+ *loc = (UCHAR_T) op; -+ STORE_NUMBER (loc + 1, arg1); -+ STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); -+} -+ -+ -+/* Copy the bytes from LOC to END to open up three bytes of space at LOC -+ for OP followed by two-byte integer parameter ARG. */ -+/* ifdef WCHAR, integer parameter is 1 wchar_t. */ -+ -+static void -+PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end) -+{ -+ register UCHAR_T *pfrom = end; -+ register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; -+ -+ while (pfrom != loc) -+ *--pto = *--pfrom; -+ -+ PREFIX(store_op1) (op, loc, arg); -+} -+ -+ -+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ -+/* ifdef WCHAR, integer parameter is 1 wchar_t. */ -+ -+static void -+PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, -+ int arg2, UCHAR_T *end) -+{ -+ register UCHAR_T *pfrom = end; -+ register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; -+ -+ while (pfrom != loc) -+ *--pto = *--pfrom; -+ -+ PREFIX(store_op2) (op, loc, arg1, arg2); -+} -+ -+ -+/* P points to just after a ^ in PATTERN. Return true if that ^ comes -+ after an alternative or a begin-subexpression. We assume there is at -+ least one character before the ^. */ -+ -+static boolean -+PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p, -+ reg_syntax_t syntax) -+{ -+ const CHAR_T *prev = p - 2; -+ boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; -+ -+ return -+ /* After a subexpression? */ -+ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) -+ /* After an alternative? */ -+ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); -+} -+ -+ -+/* The dual of at_begline_loc_p. This one is for $. We assume there is -+ at least one character after the $, i.e., `P < PEND'. */ -+ -+static boolean -+PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend, -+ reg_syntax_t syntax) -+{ -+ const CHAR_T *next = p; -+ boolean next_backslash = *next == '\\'; -+ const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; -+ -+ return -+ /* Before a subexpression? */ -+ (syntax & RE_NO_BK_PARENS ? *next == ')' -+ : next_backslash && next_next && *next_next == ')') -+ /* Before an alternative? */ -+ || (syntax & RE_NO_BK_VBAR ? *next == '|' -+ : next_backslash && next_next && *next_next == '|'); -+} -+ -+#else /* not INSIDE_RECURSION */ -+ -+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and -+ false if it's not. */ -+ -+static boolean -+group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum) -+{ -+ int this_element; -+ -+ for (this_element = compile_stack.avail - 1; -+ this_element >= 0; -+ this_element--) -+ if (compile_stack.stack[this_element].regnum == regnum) -+ return true; -+ -+ return false; -+} -+#endif /* not INSIDE_RECURSION */ -+ -+#ifdef INSIDE_RECURSION -+ -+#ifdef WCHAR -+/* This insert space, which size is "num", into the pattern at "loc". -+ "end" must point the end of the allocated buffer. */ -+static void -+insert_space (int num, CHAR_T *loc, CHAR_T *end) -+{ -+ register CHAR_T *pto = end; -+ register CHAR_T *pfrom = end - num; -+ -+ while (pfrom >= loc) -+ *pto-- = *pfrom--; -+} -+#endif /* WCHAR */ -+ -+#ifdef WCHAR -+static reg_errcode_t -+wcs_compile_range (CHAR_T range_start_char, const CHAR_T **p_ptr, -+ const CHAR_T *pend, RE_TRANSLATE_TYPE translate, -+ reg_syntax_t syntax, CHAR_T *b, CHAR_T *char_set) -+{ -+ const CHAR_T *p = *p_ptr; -+ CHAR_T range_start, range_end; -+ reg_errcode_t ret; -+# ifdef _LIBC -+ uint32_t nrules; -+ uint32_t start_val, end_val; -+# endif -+ if (p == pend) -+ return REG_ERANGE; -+ -+# ifdef _LIBC -+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); -+ if (nrules != 0) -+ { -+ const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, -+ _NL_COLLATE_COLLSEQWC); -+ const unsigned char *extra = (const unsigned char *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); -+ -+ if (range_start_char < -1) -+ { -+ /* range_start is a collating symbol. */ -+ int32_t *wextra; -+ /* Retreive the index and get collation sequence value. */ -+ wextra = (int32_t*)(extra + char_set[-range_start_char]); -+ start_val = wextra[1 + *wextra]; -+ } -+ else -+ start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char)); -+ -+ end_val = collseq_table_lookup (collseq, TRANSLATE (p[0])); -+ -+ /* Report an error if the range is empty and the syntax prohibits -+ this. */ -+ ret = ((syntax & RE_NO_EMPTY_RANGES) -+ && (start_val > end_val))? REG_ERANGE : REG_NOERROR; -+ -+ /* Insert space to the end of the char_ranges. */ -+ insert_space(2, b - char_set[5] - 2, b - 1); -+ *(b - char_set[5] - 2) = (wchar_t)start_val; -+ *(b - char_set[5] - 1) = (wchar_t)end_val; -+ char_set[4]++; /* ranges_index */ -+ } -+ else -+# endif -+ { -+ range_start = (range_start_char >= 0)? TRANSLATE (range_start_char): -+ range_start_char; -+ range_end = TRANSLATE (p[0]); -+ /* Report an error if the range is empty and the syntax prohibits -+ this. */ -+ ret = ((syntax & RE_NO_EMPTY_RANGES) -+ && (range_start > range_end))? REG_ERANGE : REG_NOERROR; -+ -+ /* Insert space to the end of the char_ranges. */ -+ insert_space(2, b - char_set[5] - 2, b - 1); -+ *(b - char_set[5] - 2) = range_start; -+ *(b - char_set[5] - 1) = range_end; -+ char_set[4]++; /* ranges_index */ -+ } -+ /* Have to increment the pointer into the pattern string, so the -+ caller isn't still at the ending character. */ -+ (*p_ptr)++; -+ -+ return ret; -+} -+#else /* BYTE */ -+/* Read the ending character of a range (in a bracket expression) from the -+ uncompiled pattern *P_PTR (which ends at PEND). We assume the -+ starting character is in `P[-2]'. (`P[-1]' is the character `-'.) -+ Then we set the translation of all bits between the starting and -+ ending characters (inclusive) in the compiled pattern B. -+ -+ Return an error code. -+ -+ We use these short variable names so we can use the same macros as -+ `regex_compile' itself. */ -+ -+static reg_errcode_t -+byte_compile_range (unsigned int range_start_char, const char **p_ptr, -+ const char *pend, RE_TRANSLATE_TYPE translate, -+ reg_syntax_t syntax, unsigned char *b) -+{ -+ unsigned this_char; -+ const char *p = *p_ptr; -+ reg_errcode_t ret; -+# if _LIBC -+ const unsigned char *collseq; -+ unsigned int start_colseq; -+ unsigned int end_colseq; -+# else -+ unsigned end_char; -+# endif -+ -+ if (p == pend) -+ return REG_ERANGE; -+ -+ /* Have to increment the pointer into the pattern string, so the -+ caller isn't still at the ending character. */ -+ (*p_ptr)++; -+ -+ /* Report an error if the range is empty and the syntax prohibits this. */ -+ ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; -+ -+# if _LIBC -+ collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, -+ _NL_COLLATE_COLLSEQMB); -+ -+ start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)]; -+ end_colseq = collseq[(unsigned char) TRANSLATE (p[0])]; -+ for (this_char = 0; this_char <= (unsigned char) -1; ++this_char) -+ { -+ unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)]; -+ -+ if (start_colseq <= this_colseq && this_colseq <= end_colseq) -+ { -+ SET_LIST_BIT (TRANSLATE (this_char)); -+ ret = REG_NOERROR; -+ } -+ } -+# else -+ /* Here we see why `this_char' has to be larger than an `unsigned -+ char' -- we would otherwise go into an infinite loop, since all -+ characters <= 0xff. */ -+ range_start_char = TRANSLATE (range_start_char); -+ /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE, -+ and some compilers cast it to int implicitly, so following for_loop -+ may fall to (almost) infinite loop. -+ e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff. -+ To avoid this, we cast p[0] to unsigned int and truncate it. */ -+ end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1)); -+ -+ for (this_char = range_start_char; this_char <= end_char; ++this_char) -+ { -+ SET_LIST_BIT (TRANSLATE (this_char)); -+ ret = REG_NOERROR; -+ } -+# endif -+ -+ return ret; -+} -+#endif /* WCHAR */ -+ -+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in -+ BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible -+ characters can start a string that matches the pattern. This fastmap -+ is used by re_search to skip quickly over impossible starting points. -+ -+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data -+ area as BUFP->fastmap. -+ -+ We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in -+ the pattern buffer. -+ -+ Returns 0 if we succeed, -2 if an internal error. */ -+ -+#ifdef WCHAR -+/* local function for re_compile_fastmap. -+ truncate wchar_t character to char. */ -+static unsigned char truncate_wchar (CHAR_T c); -+ -+static unsigned char -+truncate_wchar (CHAR_T c) -+{ -+ unsigned char buf[MB_CUR_MAX]; -+ mbstate_t state; -+ int retval; -+ memset (&state, '\0', sizeof (state)); -+# ifdef _LIBC -+ retval = __wcrtomb (buf, c, &state); -+# else -+ retval = wcrtomb (buf, c, &state); -+# endif -+ return retval > 0 ? buf[0] : (unsigned char) c; -+} -+#endif /* WCHAR */ -+ -+static int -+PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp) -+{ -+ int j, k; -+#ifdef MATCH_MAY_ALLOCATE -+ PREFIX(fail_stack_type) fail_stack; -+#endif -+#ifndef REGEX_MALLOC -+ char *destination; -+#endif -+ -+ register char *fastmap = bufp->fastmap; -+ -+#ifdef WCHAR -+ /* We need to cast pattern to (wchar_t*), because we casted this compiled -+ pattern to (char*) in regex_compile. */ -+ UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; -+ register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); -+#else /* BYTE */ -+ UCHAR_T *pattern = bufp->buffer; -+ register UCHAR_T *pend = pattern + bufp->used; -+#endif /* WCHAR */ -+ UCHAR_T *p = pattern; -+ -+#ifdef REL_ALLOC -+ /* This holds the pointer to the failure stack, when -+ it is allocated relocatably. */ -+ fail_stack_elt_t *failure_stack_ptr; -+#endif -+ -+ /* Assume that each path through the pattern can be null until -+ proven otherwise. We set this false at the bottom of switch -+ statement, to which we get only if a particular path doesn't -+ match the empty string. */ -+ boolean path_can_be_null = true; -+ -+ /* We aren't doing a `succeed_n' to begin with. */ -+ boolean succeed_n_p = false; -+ -+ assert (fastmap != NULL && p != NULL); -+ -+ INIT_FAIL_STACK (); -+ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ -+ bufp->fastmap_accurate = 1; /* It will be when we're done. */ -+ bufp->can_be_null = 0; -+ -+ while (1) -+ { -+ if (p == pend || *p == (UCHAR_T) succeed) -+ { -+ /* We have reached the (effective) end of pattern. */ -+ if (!FAIL_STACK_EMPTY ()) -+ { -+ bufp->can_be_null |= path_can_be_null; -+ -+ /* Reset for next path. */ -+ path_can_be_null = true; -+ -+ p = fail_stack.stack[--fail_stack.avail].pointer; -+ -+ continue; -+ } -+ else -+ break; -+ } -+ -+ /* We should never be about to go beyond the end of the pattern. */ -+ assert (p < pend); -+ -+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) -+ { -+ -+ /* I guess the idea here is to simply not bother with a fastmap -+ if a backreference is used, since it's too hard to figure out -+ the fastmap for the corresponding group. Setting -+ `can_be_null' stops `re_search_2' from using the fastmap, so -+ that is all we do. */ -+ case duplicate: -+ bufp->can_be_null = 1; -+ goto done; -+ -+ -+ /* Following are the cases which match a character. These end -+ with `break'. */ -+ -+#ifdef WCHAR -+ case exactn: -+ fastmap[truncate_wchar(p[1])] = 1; -+ break; -+#else /* BYTE */ -+ case exactn: -+ fastmap[p[1]] = 1; -+ break; -+#endif /* WCHAR */ -+#ifdef MBS_SUPPORT -+ case exactn_bin: -+ fastmap[p[1]] = 1; -+ break; -+#endif -+ -+#ifdef WCHAR -+ /* It is hard to distinguish fastmap from (multi byte) characters -+ which depends on current locale. */ -+ case charset: -+ case charset_not: -+ case wordchar: -+ case notwordchar: -+ bufp->can_be_null = 1; -+ goto done; -+#else /* BYTE */ -+ case charset: -+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) -+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) -+ fastmap[j] = 1; -+ break; -+ -+ -+ case charset_not: -+ /* Chars beyond end of map must be allowed. */ -+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) -+ fastmap[j] = 1; -+ -+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) -+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) -+ fastmap[j] = 1; -+ break; -+ -+ -+ case wordchar: -+ for (j = 0; j < (1 << BYTEWIDTH); j++) -+ if (SYNTAX (j) == Sword) -+ fastmap[j] = 1; -+ break; -+ -+ -+ case notwordchar: -+ for (j = 0; j < (1 << BYTEWIDTH); j++) -+ if (SYNTAX (j) != Sword) -+ fastmap[j] = 1; -+ break; -+#endif /* WCHAR */ -+ -+ case anychar: -+ { -+ int fastmap_newline = fastmap['\n']; -+ -+ /* `.' matches anything ... */ -+ for (j = 0; j < (1 << BYTEWIDTH); j++) -+ fastmap[j] = 1; -+ -+ /* ... except perhaps newline. */ -+ if (!(bufp->syntax & RE_DOT_NEWLINE)) -+ fastmap['\n'] = fastmap_newline; -+ -+ /* Return if we have already set `can_be_null'; if we have, -+ then the fastmap is irrelevant. Something's wrong here. */ -+ else if (bufp->can_be_null) -+ goto done; -+ -+ /* Otherwise, have to check alternative paths. */ -+ break; -+ } -+ -+#ifdef emacs -+ case syntaxspec: -+ k = *p++; -+ for (j = 0; j < (1 << BYTEWIDTH); j++) -+ if (SYNTAX (j) == (enum syntaxcode) k) -+ fastmap[j] = 1; -+ break; -+ -+ -+ case notsyntaxspec: -+ k = *p++; -+ for (j = 0; j < (1 << BYTEWIDTH); j++) -+ if (SYNTAX (j) != (enum syntaxcode) k) -+ fastmap[j] = 1; -+ break; -+ -+ -+ /* All cases after this match the empty string. These end with -+ `continue'. */ -+ -+ -+ case before_dot: -+ case at_dot: -+ case after_dot: -+ continue; -+#endif /* emacs */ -+ -+ -+ case no_op: -+ case begline: -+ case endline: -+ case begbuf: -+ case endbuf: -+ case wordbound: -+ case notwordbound: -+ case wordbeg: -+ case wordend: -+ case push_dummy_failure: -+ continue; -+ -+ -+ case jump_n: -+ case pop_failure_jump: -+ case maybe_pop_jump: -+ case jump: -+ case jump_past_alt: -+ case dummy_failure_jump: -+ EXTRACT_NUMBER_AND_INCR (j, p); -+ p += j; -+ if (j > 0) -+ continue; -+ -+ /* Jump backward implies we just went through the body of a -+ loop and matched nothing. Opcode jumped to should be -+ `on_failure_jump' or `succeed_n'. Just treat it like an -+ ordinary jump. For a * loop, it has pushed its failure -+ point already; if so, discard that as redundant. */ -+ if ((re_opcode_t) *p != on_failure_jump -+ && (re_opcode_t) *p != succeed_n) -+ continue; -+ -+ p++; -+ EXTRACT_NUMBER_AND_INCR (j, p); -+ p += j; -+ -+ /* If what's on the stack is where we are now, pop it. */ -+ if (!FAIL_STACK_EMPTY () -+ && fail_stack.stack[fail_stack.avail - 1].pointer == p) -+ fail_stack.avail--; -+ -+ continue; -+ -+ -+ case on_failure_jump: -+ case on_failure_keep_string_jump: -+ handle_on_failure_jump: -+ EXTRACT_NUMBER_AND_INCR (j, p); -+ -+ /* For some patterns, e.g., `(a?)?', `p+j' here points to the -+ end of the pattern. We don't want to push such a point, -+ since when we restore it above, entering the switch will -+ increment `p' past the end of the pattern. We don't need -+ to push such a point since we obviously won't find any more -+ fastmap entries beyond `pend'. Such a pattern can match -+ the null string, though. */ -+ if (p + j < pend) -+ { -+ if (!PUSH_PATTERN_OP (p + j, fail_stack)) -+ { -+ RESET_FAIL_STACK (); -+ return -2; -+ } -+ } -+ else -+ bufp->can_be_null = 1; -+ -+ if (succeed_n_p) -+ { -+ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ -+ succeed_n_p = false; -+ } -+ -+ continue; -+ -+ -+ case succeed_n: -+ /* Get to the number of times to succeed. */ -+ p += OFFSET_ADDRESS_SIZE; -+ -+ /* Increment p past the n for when k != 0. */ -+ EXTRACT_NUMBER_AND_INCR (k, p); -+ if (k == 0) -+ { -+ p -= 2 * OFFSET_ADDRESS_SIZE; -+ succeed_n_p = true; /* Spaghetti code alert. */ -+ goto handle_on_failure_jump; -+ } -+ continue; -+ -+ -+ case set_number_at: -+ p += 2 * OFFSET_ADDRESS_SIZE; -+ continue; -+ -+ -+ case start_memory: -+ case stop_memory: -+ p += 2; -+ continue; -+ -+ -+ default: -+ abort (); /* We have listed all the cases. */ -+ } /* switch *p++ */ -+ -+ /* Getting here means we have found the possible starting -+ characters for one path of the pattern -- and that the empty -+ string does not match. We need not follow this path further. -+ Instead, look at the next alternative (remembered on the -+ stack), or quit if no more. The test at the top of the loop -+ does these things. */ -+ path_can_be_null = false; -+ p = pend; -+ } /* while p */ -+ -+ /* Set `can_be_null' for the last path (also the first path, if the -+ pattern is empty). */ -+ bufp->can_be_null |= path_can_be_null; -+ -+ done: -+ RESET_FAIL_STACK (); -+ return 0; -+} -+ -+#else /* not INSIDE_RECURSION */ -+ -+int -+re_compile_fastmap (struct re_pattern_buffer *bufp) -+{ -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ return wcs_re_compile_fastmap(bufp); -+ else -+# endif -+ return byte_re_compile_fastmap(bufp); -+} /* re_compile_fastmap */ -+#ifdef _LIBC -+weak_alias (__re_compile_fastmap, re_compile_fastmap) -+#endif -+ -+ -+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and -+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use -+ this memory for recording register information. STARTS and ENDS -+ must be allocated using the malloc library routine, and must each -+ be at least NUM_REGS * sizeof (regoff_t) bytes long. -+ -+ If NUM_REGS == 0, then subsequent matches should allocate their own -+ register data. -+ -+ Unless this function is called, the first search or match using -+ PATTERN_BUFFER will allocate its own register data, without -+ freeing the old data. */ -+ -+void -+re_set_registers (struct re_pattern_buffer *bufp, -+ struct re_registers *regs, unsigned num_regs, -+ regoff_t *starts, regoff_t *ends) -+{ -+ if (num_regs) -+ { -+ bufp->regs_allocated = REGS_REALLOCATE; -+ regs->num_regs = num_regs; -+ regs->start = starts; -+ regs->end = ends; -+ } -+ else -+ { -+ bufp->regs_allocated = REGS_UNALLOCATED; -+ regs->num_regs = 0; -+ regs->start = regs->end = (regoff_t *) 0; -+ } -+} -+#ifdef _LIBC -+weak_alias (__re_set_registers, re_set_registers) -+#endif -+ -+/* Searching routines. */ -+ -+/* Like re_search_2, below, but only one string is specified, and -+ doesn't let you say where to stop matching. */ -+ -+int -+re_search (struct re_pattern_buffer *bufp, const char *string, int size, -+ int startpos, int range, struct re_registers *regs) -+{ -+ return re_search_2 (bufp, NULL, 0, string, size, startpos, range, -+ regs, size); -+} -+#ifdef _LIBC -+weak_alias (__re_search, re_search) -+#endif -+ -+ -+/* Using the compiled pattern in BUFP->buffer, first tries to match the -+ virtual concatenation of STRING1 and STRING2, starting first at index -+ STARTPOS, then at STARTPOS + 1, and so on. -+ -+ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. -+ -+ RANGE is how far to scan while trying to match. RANGE = 0 means try -+ only at STARTPOS; in general, the last start tried is STARTPOS + -+ RANGE. -+ -+ In REGS, return the indices of the virtual concatenation of STRING1 -+ and STRING2 that matched the entire BUFP->buffer and its contained -+ subexpressions. -+ -+ Do not consider matching one past the index STOP in the virtual -+ concatenation of STRING1 and STRING2. -+ -+ We return either the position in the strings at which the match was -+ found, -1 if no match, or -2 if error (such as failure -+ stack overflow). */ -+ -+int -+re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, -+ const char *string2, int size2, int startpos, int range, -+ struct re_registers *regs, int stop) -+{ -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, -+ range, regs, stop); -+ else -+# endif -+ return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, -+ range, regs, stop); -+} /* re_search_2 */ -+#ifdef _LIBC -+weak_alias (__re_search_2, re_search_2) -+#endif -+ -+#endif /* not INSIDE_RECURSION */ -+ -+#ifdef INSIDE_RECURSION -+ -+#ifdef MATCH_MAY_ALLOCATE -+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL -+#else -+# define FREE_VAR(var) if (var) free (var); var = NULL -+#endif -+ -+#ifdef WCHAR -+# define MAX_ALLOCA_SIZE 2000 -+ -+# define FREE_WCS_BUFFERS() \ -+ do { \ -+ if (size1 > MAX_ALLOCA_SIZE) \ -+ { \ -+ free (wcs_string1); \ -+ free (mbs_offset1); \ -+ } \ -+ else \ -+ { \ -+ FREE_VAR (wcs_string1); \ -+ FREE_VAR (mbs_offset1); \ -+ } \ -+ if (size2 > MAX_ALLOCA_SIZE) \ -+ { \ -+ free (wcs_string2); \ -+ free (mbs_offset2); \ -+ } \ -+ else \ -+ { \ -+ FREE_VAR (wcs_string2); \ -+ FREE_VAR (mbs_offset2); \ -+ } \ -+ } while (0) -+ -+#endif -+ -+ -+static int -+PREFIX(re_search_2) (struct re_pattern_buffer *bufp, const char *string1, -+ int size1, const char *string2, int size2, -+ int startpos, int range, -+ struct re_registers *regs, int stop) -+{ -+ int val; -+ register char *fastmap = bufp->fastmap; -+ register RE_TRANSLATE_TYPE translate = bufp->translate; -+ int total_size = size1 + size2; -+ int endpos = startpos + range; -+#ifdef WCHAR -+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */ -+ wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; -+ /* We need the size of wchar_t buffers correspond to csize1, csize2. */ -+ int wcs_size1 = 0, wcs_size2 = 0; -+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ -+ int *mbs_offset1 = NULL, *mbs_offset2 = NULL; -+ /* They hold whether each wchar_t is binary data or not. */ -+ char *is_binary = NULL; -+#endif /* WCHAR */ -+ -+ /* Check for out-of-range STARTPOS. */ -+ if (startpos < 0 || startpos > total_size) -+ return -1; -+ -+ /* Fix up RANGE if it might eventually take us outside -+ the virtual concatenation of STRING1 and STRING2. -+ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ -+ if (endpos < 0) -+ range = 0 - startpos; -+ else if (endpos > total_size) -+ range = total_size - startpos; -+ -+ /* If the search isn't to be a backwards one, don't waste time in a -+ search for a pattern that must be anchored. */ -+ if (bufp->used > 0 && range > 0 -+ && ((re_opcode_t) bufp->buffer[0] == begbuf -+ /* `begline' is like `begbuf' if it cannot match at newlines. */ -+ || ((re_opcode_t) bufp->buffer[0] == begline -+ && !bufp->newline_anchor))) -+ { -+ if (startpos > 0) -+ return -1; -+ else -+ range = 1; -+ } -+ -+#ifdef emacs -+ /* In a forward search for something that starts with \=. -+ don't keep searching past point. */ -+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) -+ { -+ range = PT - startpos; -+ if (range <= 0) -+ return -1; -+ } -+#endif /* emacs */ -+ -+ /* Update the fastmap now if not correct already. */ -+ if (fastmap && !bufp->fastmap_accurate) -+ if (re_compile_fastmap (bufp) == -2) -+ return -2; -+ -+#ifdef WCHAR -+ /* Allocate wchar_t array for wcs_string1 and wcs_string2 and -+ fill them with converted string. */ -+ if (size1 != 0) -+ { -+ if (size1 > MAX_ALLOCA_SIZE) -+ { -+ wcs_string1 = TALLOC (size1 + 1, CHAR_T); -+ mbs_offset1 = TALLOC (size1 + 1, int); -+ is_binary = TALLOC (size1 + 1, char); -+ } -+ else -+ { -+ wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); -+ mbs_offset1 = REGEX_TALLOC (size1 + 1, int); -+ is_binary = REGEX_TALLOC (size1 + 1, char); -+ } -+ if (!wcs_string1 || !mbs_offset1 || !is_binary) -+ { -+ if (size1 > MAX_ALLOCA_SIZE) -+ { -+ free (wcs_string1); -+ free (mbs_offset1); -+ free (is_binary); -+ } -+ else -+ { -+ FREE_VAR (wcs_string1); -+ FREE_VAR (mbs_offset1); -+ FREE_VAR (is_binary); -+ } -+ return -2; -+ } -+ wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, -+ mbs_offset1, is_binary); -+ wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ -+ if (size1 > MAX_ALLOCA_SIZE) -+ free (is_binary); -+ else -+ FREE_VAR (is_binary); -+ } -+ if (size2 != 0) -+ { -+ if (size2 > MAX_ALLOCA_SIZE) -+ { -+ wcs_string2 = TALLOC (size2 + 1, CHAR_T); -+ mbs_offset2 = TALLOC (size2 + 1, int); -+ is_binary = TALLOC (size2 + 1, char); -+ } -+ else -+ { -+ wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); -+ mbs_offset2 = REGEX_TALLOC (size2 + 1, int); -+ is_binary = REGEX_TALLOC (size2 + 1, char); -+ } -+ if (!wcs_string2 || !mbs_offset2 || !is_binary) -+ { -+ FREE_WCS_BUFFERS (); -+ if (size2 > MAX_ALLOCA_SIZE) -+ free (is_binary); -+ else -+ FREE_VAR (is_binary); -+ return -2; -+ } -+ wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, -+ mbs_offset2, is_binary); -+ wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ -+ if (size2 > MAX_ALLOCA_SIZE) -+ free (is_binary); -+ else -+ FREE_VAR (is_binary); -+ } -+#endif /* WCHAR */ -+ -+ -+ /* Loop through the string, looking for a place to start matching. */ -+ for (;;) -+ { -+ /* If a fastmap is supplied, skip quickly over characters that -+ cannot be the start of a match. If the pattern can match the -+ null string, however, we don't need to skip characters; we want -+ the first null string. */ -+ if (fastmap && startpos < total_size && !bufp->can_be_null) -+ { -+ if (range > 0) /* Searching forwards. */ -+ { -+ register const char *d; -+ register int lim = 0; -+ int irange = range; -+ -+ if (startpos < size1 && startpos + range >= size1) -+ lim = range - (size1 - startpos); -+ -+ d = (startpos >= size1 ? string2 - size1 : string1) + startpos; -+ -+ /* Written out as an if-else to avoid testing `translate' -+ inside the loop. */ -+ if (translate) -+ while (range > lim -+ && !fastmap[(unsigned char) -+ translate[(unsigned char) *d++]]) -+ range--; -+ else -+ while (range > lim && !fastmap[(unsigned char) *d++]) -+ range--; -+ -+ startpos += irange - range; -+ } -+ else /* Searching backwards. */ -+ { -+ register CHAR_T c = (size1 == 0 || startpos >= size1 -+ ? string2[startpos - size1] -+ : string1[startpos]); -+ -+ if (!fastmap[(unsigned char) TRANSLATE (c)]) -+ goto advance; -+ } -+ } -+ -+ /* If can't match the null string, and that's all we have left, fail. */ -+ if (range >= 0 && startpos == total_size && fastmap -+ && !bufp->can_be_null) -+ { -+#ifdef WCHAR -+ FREE_WCS_BUFFERS (); -+#endif -+ return -1; -+ } -+ -+#ifdef WCHAR -+ val = wcs_re_match_2_internal (bufp, string1, size1, string2, -+ size2, startpos, regs, stop, -+ wcs_string1, wcs_size1, -+ wcs_string2, wcs_size2, -+ mbs_offset1, mbs_offset2); -+#else /* BYTE */ -+ val = byte_re_match_2_internal (bufp, string1, size1, string2, -+ size2, startpos, regs, stop); -+#endif /* BYTE */ -+ -+#ifndef REGEX_MALLOC -+# ifdef C_ALLOCA -+ alloca (0); -+# endif -+#endif -+ -+ if (val >= 0) -+ { -+#ifdef WCHAR -+ FREE_WCS_BUFFERS (); -+#endif -+ return startpos; -+ } -+ -+ if (val == -2) -+ { -+#ifdef WCHAR -+ FREE_WCS_BUFFERS (); -+#endif -+ return -2; -+ } -+ -+ advance: -+ if (!range) -+ break; -+ else if (range > 0) -+ { -+ range--; -+ startpos++; -+ } -+ else -+ { -+ range++; -+ startpos--; -+ } -+ } -+#ifdef WCHAR -+ FREE_WCS_BUFFERS (); -+#endif -+ return -1; -+} -+ -+#ifdef WCHAR -+/* This converts PTR, a pointer into one of the search wchar_t strings -+ `string1' and `string2' into an multibyte string offset from the -+ beginning of that string. We use mbs_offset to optimize. -+ See convert_mbs_to_wcs. */ -+# define POINTER_TO_OFFSET(ptr) \ -+ (FIRST_STRING_P (ptr) \ -+ ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ -+ : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ -+ + csize1))) -+#else /* BYTE */ -+/* This converts PTR, a pointer into one of the search strings `string1' -+ and `string2' into an offset from the beginning of that string. */ -+# define POINTER_TO_OFFSET(ptr) \ -+ (FIRST_STRING_P (ptr) \ -+ ? ((regoff_t) ((ptr) - string1)) \ -+ : ((regoff_t) ((ptr) - string2 + size1))) -+#endif /* WCHAR */ -+ -+/* Macros for dealing with the split strings in re_match_2. */ -+ -+#define MATCHING_IN_FIRST_STRING (dend == end_match_1) -+ -+/* Call before fetching a character with *d. This switches over to -+ string2 if necessary. */ -+#define PREFETCH() \ -+ while (d == dend) \ -+ { \ -+ /* End of string2 => fail. */ \ -+ if (dend == end_match_2) \ -+ goto fail; \ -+ /* End of string1 => advance to string2. */ \ -+ d = string2; \ -+ dend = end_match_2; \ -+ } -+ -+/* Test if at very beginning or at very end of the virtual concatenation -+ of `string1' and `string2'. If only one string, it's `string2'. */ -+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) -+#define AT_STRINGS_END(d) ((d) == end2) -+ -+ -+/* Test if D points to a character which is word-constituent. We have -+ two special cases to check for: if past the end of string1, look at -+ the first character in string2; and if before the beginning of -+ string2, look at the last character in string1. */ -+#ifdef WCHAR -+/* Use internationalized API instead of SYNTAX. */ -+# define WORDCHAR_P(d) \ -+ (iswalnum ((wint_t)((d) == end1 ? *string2 \ -+ : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ -+ || ((d) == end1 ? *string2 \ -+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') -+#else /* BYTE */ -+# define WORDCHAR_P(d) \ -+ (SYNTAX ((d) == end1 ? *string2 \ -+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ -+ == Sword) -+#endif /* WCHAR */ -+ -+/* Disabled due to a compiler bug -- see comment at case wordbound */ -+#if 0 -+/* Test if the character before D and the one at D differ with respect -+ to being word-constituent. */ -+#define AT_WORD_BOUNDARY(d) \ -+ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ -+ || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) -+#endif -+ -+/* Free everything we malloc. */ -+#ifdef MATCH_MAY_ALLOCATE -+# ifdef WCHAR -+# define FREE_VARIABLES() \ -+ do { \ -+ REGEX_FREE_STACK (fail_stack.stack); \ -+ FREE_VAR (regstart); \ -+ FREE_VAR (regend); \ -+ FREE_VAR (old_regstart); \ -+ FREE_VAR (old_regend); \ -+ FREE_VAR (best_regstart); \ -+ FREE_VAR (best_regend); \ -+ FREE_VAR (reg_info); \ -+ FREE_VAR (reg_dummy); \ -+ FREE_VAR (reg_info_dummy); \ -+ if (!cant_free_wcs_buf) \ -+ { \ -+ FREE_VAR (string1); \ -+ FREE_VAR (string2); \ -+ FREE_VAR (mbs_offset1); \ -+ FREE_VAR (mbs_offset2); \ -+ } \ -+ } while (0) -+# else /* BYTE */ -+# define FREE_VARIABLES() \ -+ do { \ -+ REGEX_FREE_STACK (fail_stack.stack); \ -+ FREE_VAR (regstart); \ -+ FREE_VAR (regend); \ -+ FREE_VAR (old_regstart); \ -+ FREE_VAR (old_regend); \ -+ FREE_VAR (best_regstart); \ -+ FREE_VAR (best_regend); \ -+ FREE_VAR (reg_info); \ -+ FREE_VAR (reg_dummy); \ -+ FREE_VAR (reg_info_dummy); \ -+ } while (0) -+# endif /* WCHAR */ -+#else -+# ifdef WCHAR -+# define FREE_VARIABLES() \ -+ do { \ -+ if (!cant_free_wcs_buf) \ -+ { \ -+ FREE_VAR (string1); \ -+ FREE_VAR (string2); \ -+ FREE_VAR (mbs_offset1); \ -+ FREE_VAR (mbs_offset2); \ -+ } \ -+ } while (0) -+# else /* BYTE */ -+# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ -+# endif /* WCHAR */ -+#endif /* not MATCH_MAY_ALLOCATE */ -+ -+/* These values must meet several constraints. They must not be valid -+ register values; since we have a limit of 255 registers (because -+ we use only one byte in the pattern for the register number), we can -+ use numbers larger than 255. They must differ by 1, because of -+ NUM_FAILURE_ITEMS above. And the value for the lowest register must -+ be larger than the value for the highest register, so we do not try -+ to actually save any registers when none are active. */ -+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) -+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) -+ -+#else /* not INSIDE_RECURSION */ -+/* Matching routines. */ -+ -+#ifndef emacs /* Emacs never uses this. */ -+/* re_match is like re_match_2 except it takes only a single string. */ -+ -+int -+re_match (struct re_pattern_buffer *bufp, const char *string, -+ int size, int pos, struct re_registers *regs) -+{ -+ int result; -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, -+ pos, regs, size, -+ NULL, 0, NULL, 0, NULL, NULL); -+ else -+# endif -+ result = byte_re_match_2_internal (bufp, NULL, 0, string, size, -+ pos, regs, size); -+# ifndef REGEX_MALLOC -+# ifdef C_ALLOCA -+ alloca (0); -+# endif -+# endif -+ return result; -+} -+# ifdef _LIBC -+weak_alias (__re_match, re_match) -+# endif -+#endif /* not emacs */ -+ -+#endif /* not INSIDE_RECURSION */ -+ -+#ifdef INSIDE_RECURSION -+static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p, -+ UCHAR_T *end, -+ PREFIX(register_info_type) *reg_info); -+static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p, -+ UCHAR_T *end, -+ PREFIX(register_info_type) *reg_info); -+static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p, -+ UCHAR_T *end, -+ PREFIX(register_info_type) *reg_info); -+static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, -+ register int len, -+ RE_TRANSLATE_TYPE translate); -+#else /* not INSIDE_RECURSION */ -+ -+/* re_match_2 matches the compiled pattern in BUFP against the -+ the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 -+ and SIZE2, respectively). We start matching at POS, and stop -+ matching at STOP. -+ -+ If REGS is non-null and the `no_sub' field of BUFP is nonzero, we -+ store offsets for the substring each group matched in REGS. See the -+ documentation for exactly how many groups we fill. -+ -+ We return -1 if no match, -2 if an internal error (such as the -+ failure stack overflowing). Otherwise, we return the length of the -+ matched substring. */ -+ -+int -+re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, -+ const char *string2, int size2, int pos, -+ struct re_registers *regs, int stop) -+{ -+ int result; -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, -+ pos, regs, stop, -+ NULL, 0, NULL, 0, NULL, NULL); -+ else -+# endif -+ result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, -+ pos, regs, stop); -+ -+#ifndef REGEX_MALLOC -+# ifdef C_ALLOCA -+ alloca (0); -+# endif -+#endif -+ return result; -+} -+#ifdef _LIBC -+weak_alias (__re_match_2, re_match_2) -+#endif -+ -+#endif /* not INSIDE_RECURSION */ -+ -+#ifdef INSIDE_RECURSION -+ -+#ifdef WCHAR -+static int count_mbs_length (int *, int); -+ -+/* This check the substring (from 0, to length) of the multibyte string, -+ to which offset_buffer correspond. And count how many wchar_t_characters -+ the substring occupy. We use offset_buffer to optimization. -+ See convert_mbs_to_wcs. */ -+ -+static int -+count_mbs_length(int *offset_buffer, int length) -+{ -+ int upper, lower; -+ -+ /* Check whether the size is valid. */ -+ if (length < 0) -+ return -1; -+ -+ if (offset_buffer == NULL) -+ return 0; -+ -+ /* If there are no multibyte character, offset_buffer[i] == i. -+ Optmize for this case. */ -+ if (offset_buffer[length] == length) -+ return length; -+ -+ /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ -+ upper = length; -+ lower = 0; -+ -+ while (true) -+ { -+ int middle = (lower + upper) / 2; -+ if (middle == lower || middle == upper) -+ break; -+ if (offset_buffer[middle] > length) -+ upper = middle; -+ else if (offset_buffer[middle] < length) -+ lower = middle; -+ else -+ return middle; -+ } -+ -+ return -1; -+} -+#endif /* WCHAR */ -+ -+/* This is a separate function so that we can force an alloca cleanup -+ afterwards. */ -+#ifdef WCHAR -+static int -+wcs_re_match_2_internal (struct re_pattern_buffer *bufp, -+ const char *cstring1, int csize1, -+ const char *cstring2, int csize2, -+ int pos, -+ struct re_registers *regs, -+ int stop, -+ /* string1 == string2 == NULL means string1/2, size1/2 and -+ mbs_offset1/2 need seting up in this function. */ -+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */ -+ wchar_t *string1, int size1, -+ wchar_t *string2, int size2, -+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ -+ int *mbs_offset1, int *mbs_offset2) -+#else /* BYTE */ -+static int -+byte_re_match_2_internal (struct re_pattern_buffer *bufp, -+ const char *string1, int size1, -+ const char *string2, int size2, -+ int pos, -+ struct re_registers *regs, int stop) -+#endif /* BYTE */ -+{ -+ /* General temporaries. */ -+ int mcnt; -+ UCHAR_T *p1; -+#ifdef WCHAR -+ /* They hold whether each wchar_t is binary data or not. */ -+ char *is_binary = NULL; -+ /* If true, we can't free string1/2, mbs_offset1/2. */ -+ int cant_free_wcs_buf = 1; -+#endif /* WCHAR */ -+ -+ /* Just past the end of the corresponding string. */ -+ const CHAR_T *end1, *end2; -+ -+ /* Pointers into string1 and string2, just past the last characters in -+ each to consider matching. */ -+ const CHAR_T *end_match_1, *end_match_2; -+ -+ /* Where we are in the data, and the end of the current string. */ -+ const CHAR_T *d, *dend; -+ -+ /* Where we are in the pattern, and the end of the pattern. */ -+#ifdef WCHAR -+ UCHAR_T *pattern, *p; -+ register UCHAR_T *pend; -+#else /* BYTE */ -+ UCHAR_T *p = bufp->buffer; -+ register UCHAR_T *pend = p + bufp->used; -+#endif /* WCHAR */ -+ -+ /* Mark the opcode just after a start_memory, so we can test for an -+ empty subpattern when we get to the stop_memory. */ -+ UCHAR_T *just_past_start_mem = 0; -+ -+ /* We use this to map every character in the string. */ -+ RE_TRANSLATE_TYPE translate = bufp->translate; -+ -+ /* Failure point stack. Each place that can handle a failure further -+ down the line pushes a failure point on this stack. It consists of -+ restart, regend, and reg_info for all registers corresponding to -+ the subexpressions we're currently inside, plus the number of such -+ registers, and, finally, two char *'s. The first char * is where -+ to resume scanning the pattern; the second one is where to resume -+ scanning the strings. If the latter is zero, the failure point is -+ a ``dummy''; if a failure happens and the failure point is a dummy, -+ it gets discarded and the next next one is tried. */ -+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ -+ PREFIX(fail_stack_type) fail_stack; -+#endif -+#ifdef DEBUG -+ static unsigned failure_id; -+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; -+#endif -+ -+#ifdef REL_ALLOC -+ /* This holds the pointer to the failure stack, when -+ it is allocated relocatably. */ -+ fail_stack_elt_t *failure_stack_ptr; -+#endif -+ -+ /* We fill all the registers internally, independent of what we -+ return, for use in backreferences. The number here includes -+ an element for register zero. */ -+ size_t num_regs = bufp->re_nsub + 1; -+ -+ /* The currently active registers. */ -+ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; -+ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; -+ -+ /* Information on the contents of registers. These are pointers into -+ the input strings; they record just what was matched (on this -+ attempt) by a subexpression part of the pattern, that is, the -+ regnum-th regstart pointer points to where in the pattern we began -+ matching and the regnum-th regend points to right after where we -+ stopped matching the regnum-th subexpression. (The zeroth register -+ keeps track of what the whole pattern matches.) */ -+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ -+ const CHAR_T **regstart, **regend; -+#endif -+ -+ /* If a group that's operated upon by a repetition operator fails to -+ match anything, then the register for its start will need to be -+ restored because it will have been set to wherever in the string we -+ are when we last see its open-group operator. Similarly for a -+ register's end. */ -+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ -+ const CHAR_T **old_regstart, **old_regend; -+#endif -+ -+ /* The is_active field of reg_info helps us keep track of which (possibly -+ nested) subexpressions we are currently in. The matched_something -+ field of reg_info[reg_num] helps us tell whether or not we have -+ matched any of the pattern so far this time through the reg_num-th -+ subexpression. These two fields get reset each time through any -+ loop their register is in. */ -+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ -+ PREFIX(register_info_type) *reg_info; -+#endif -+ -+ /* The following record the register info as found in the above -+ variables when we find a match better than any we've seen before. -+ This happens as we backtrack through the failure points, which in -+ turn happens only if we have not yet matched the entire string. */ -+ unsigned best_regs_set = false; -+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ -+ const CHAR_T **best_regstart, **best_regend; -+#endif -+ -+ /* Logically, this is `best_regend[0]'. But we don't want to have to -+ allocate space for that if we're not allocating space for anything -+ else (see below). Also, we never need info about register 0 for -+ any of the other register vectors, and it seems rather a kludge to -+ treat `best_regend' differently than the rest. So we keep track of -+ the end of the best match so far in a separate variable. We -+ initialize this to NULL so that when we backtrack the first time -+ and need to test it, it's not garbage. */ -+ const CHAR_T *match_end = NULL; -+ -+ /* This helps SET_REGS_MATCHED avoid doing redundant work. */ -+ int set_regs_matched_done = 0; -+ -+ /* Used when we pop values we don't care about. */ -+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ -+ const CHAR_T **reg_dummy; -+ PREFIX(register_info_type) *reg_info_dummy; -+#endif -+ -+#ifdef DEBUG -+ /* Counts the total number of registers pushed. */ -+ unsigned num_regs_pushed = 0; -+#endif -+ -+ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); -+ -+ INIT_FAIL_STACK (); -+ -+#ifdef MATCH_MAY_ALLOCATE -+ /* Do not bother to initialize all the register variables if there are -+ no groups in the pattern, as it takes a fair amount of time. If -+ there are groups, we include space for register 0 (the whole -+ pattern), even though we never use it, since it simplifies the -+ array indexing. We should fix this. */ -+ if (bufp->re_nsub) -+ { -+ regstart = REGEX_TALLOC (num_regs, const CHAR_T *); -+ regend = REGEX_TALLOC (num_regs, const CHAR_T *); -+ old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); -+ old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); -+ best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); -+ best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); -+ reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); -+ reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); -+ reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); -+ -+ if (!(regstart && regend && old_regstart && old_regend && reg_info -+ && best_regstart && best_regend && reg_dummy && reg_info_dummy)) -+ { -+ FREE_VARIABLES (); -+ return -2; -+ } -+ } -+ else -+ { -+ /* We must initialize all our variables to NULL, so that -+ `FREE_VARIABLES' doesn't try to free them. */ -+ regstart = regend = old_regstart = old_regend = best_regstart -+ = best_regend = reg_dummy = NULL; -+ reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; -+ } -+#endif /* MATCH_MAY_ALLOCATE */ -+ -+ /* The starting position is bogus. */ -+#ifdef WCHAR -+ if (pos < 0 || pos > csize1 + csize2) -+#else /* BYTE */ -+ if (pos < 0 || pos > size1 + size2) -+#endif -+ { -+ FREE_VARIABLES (); -+ return -1; -+ } -+ -+#ifdef WCHAR -+ /* Allocate wchar_t array for string1 and string2 and -+ fill them with converted string. */ -+ if (string1 == NULL && string2 == NULL) -+ { -+ /* We need seting up buffers here. */ -+ -+ /* We must free wcs buffers in this function. */ -+ cant_free_wcs_buf = 0; -+ -+ if (csize1 != 0) -+ { -+ string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); -+ mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); -+ is_binary = REGEX_TALLOC (csize1 + 1, char); -+ if (!string1 || !mbs_offset1 || !is_binary) -+ { -+ FREE_VAR (string1); -+ FREE_VAR (mbs_offset1); -+ FREE_VAR (is_binary); -+ return -2; -+ } -+ } -+ if (csize2 != 0) -+ { -+ string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); -+ mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); -+ is_binary = REGEX_TALLOC (csize2 + 1, char); -+ if (!string2 || !mbs_offset2 || !is_binary) -+ { -+ FREE_VAR (string1); -+ FREE_VAR (mbs_offset1); -+ FREE_VAR (string2); -+ FREE_VAR (mbs_offset2); -+ FREE_VAR (is_binary); -+ return -2; -+ } -+ size2 = convert_mbs_to_wcs(string2, cstring2, csize2, -+ mbs_offset2, is_binary); -+ string2[size2] = L'\0'; /* for a sentinel */ -+ FREE_VAR (is_binary); -+ } -+ } -+ -+ /* We need to cast pattern to (wchar_t*), because we casted this compiled -+ pattern to (char*) in regex_compile. */ -+ p = pattern = (CHAR_T*)bufp->buffer; -+ pend = (CHAR_T*)(bufp->buffer + bufp->used); -+ -+#endif /* WCHAR */ -+ -+ /* Initialize subexpression text positions to -1 to mark ones that no -+ start_memory/stop_memory has been seen for. Also initialize the -+ register information struct. */ -+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) -+ { -+ regstart[mcnt] = regend[mcnt] -+ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; -+ -+ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; -+ IS_ACTIVE (reg_info[mcnt]) = 0; -+ MATCHED_SOMETHING (reg_info[mcnt]) = 0; -+ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; -+ } -+ -+ /* We move `string1' into `string2' if the latter's empty -- but not if -+ `string1' is null. */ -+ if (size2 == 0 && string1 != NULL) -+ { -+ string2 = string1; -+ size2 = size1; -+ string1 = 0; -+ size1 = 0; -+#ifdef WCHAR -+ mbs_offset2 = mbs_offset1; -+ csize2 = csize1; -+ mbs_offset1 = NULL; -+ csize1 = 0; -+#endif -+ } -+ end1 = string1 + size1; -+ end2 = string2 + size2; -+ -+ /* Compute where to stop matching, within the two strings. */ -+#ifdef WCHAR -+ if (stop <= csize1) -+ { -+ mcnt = count_mbs_length(mbs_offset1, stop); -+ end_match_1 = string1 + mcnt; -+ end_match_2 = string2; -+ } -+ else -+ { -+ if (stop > csize1 + csize2) -+ stop = csize1 + csize2; -+ end_match_1 = end1; -+ mcnt = count_mbs_length(mbs_offset2, stop-csize1); -+ end_match_2 = string2 + mcnt; -+ } -+ if (mcnt < 0) -+ { /* count_mbs_length return error. */ -+ FREE_VARIABLES (); -+ return -1; -+ } -+#else -+ if (stop <= size1) -+ { -+ end_match_1 = string1 + stop; -+ end_match_2 = string2; -+ } -+ else -+ { -+ end_match_1 = end1; -+ end_match_2 = string2 + stop - size1; -+ } -+#endif /* WCHAR */ -+ -+ /* `p' scans through the pattern as `d' scans through the data. -+ `dend' is the end of the input string that `d' points within. `d' -+ is advanced into the following input string whenever necessary, but -+ this happens before fetching; therefore, at the beginning of the -+ loop, `d' can be pointing at the end of a string, but it cannot -+ equal `string2'. */ -+#ifdef WCHAR -+ if (size1 > 0 && pos <= csize1) -+ { -+ mcnt = count_mbs_length(mbs_offset1, pos); -+ d = string1 + mcnt; -+ dend = end_match_1; -+ } -+ else -+ { -+ mcnt = count_mbs_length(mbs_offset2, pos-csize1); -+ d = string2 + mcnt; -+ dend = end_match_2; -+ } -+ -+ if (mcnt < 0) -+ { /* count_mbs_length return error. */ -+ FREE_VARIABLES (); -+ return -1; -+ } -+#else -+ if (size1 > 0 && pos <= size1) -+ { -+ d = string1 + pos; -+ dend = end_match_1; -+ } -+ else -+ { -+ d = string2 + pos - size1; -+ dend = end_match_2; -+ } -+#endif /* WCHAR */ -+ -+ DEBUG_PRINT1 ("The compiled pattern is:\n"); -+ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); -+ DEBUG_PRINT1 ("The string to match is: `"); -+ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); -+ DEBUG_PRINT1 ("'\n"); -+ -+ /* This loops over pattern commands. It exits by returning from the -+ function if the match is complete, or it drops through if the match -+ fails at this starting point in the input data. */ -+ for (;;) -+ { -+#ifdef _LIBC -+ DEBUG_PRINT2 ("\n%p: ", p); -+#else -+ DEBUG_PRINT2 ("\n0x%x: ", p); -+#endif -+ -+ if (p == pend) -+ { /* End of pattern means we might have succeeded. */ -+ DEBUG_PRINT1 ("end of pattern ... "); -+ -+ /* If we haven't matched the entire string, and we want the -+ longest match, try backtracking. */ -+ if (d != end_match_2) -+ { -+ /* 1 if this match ends in the same string (string1 or string2) -+ as the best previous match. */ -+ boolean same_str_p = (FIRST_STRING_P (match_end) -+ == MATCHING_IN_FIRST_STRING); -+ /* 1 if this match is the best seen so far. */ -+ boolean best_match_p; -+ -+ /* AIX compiler got confused when this was combined -+ with the previous declaration. */ -+ if (same_str_p) -+ best_match_p = d > match_end; -+ else -+ best_match_p = !MATCHING_IN_FIRST_STRING; -+ -+ DEBUG_PRINT1 ("backtracking.\n"); -+ -+ if (!FAIL_STACK_EMPTY ()) -+ { /* More failure points to try. */ -+ -+ /* If exceeds best match so far, save it. */ -+ if (!best_regs_set || best_match_p) -+ { -+ best_regs_set = true; -+ match_end = d; -+ -+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); -+ -+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) -+ { -+ best_regstart[mcnt] = regstart[mcnt]; -+ best_regend[mcnt] = regend[mcnt]; -+ } -+ } -+ goto fail; -+ } -+ -+ /* If no failure points, don't restore garbage. And if -+ last match is real best match, don't restore second -+ best one. */ -+ else if (best_regs_set && !best_match_p) -+ { -+ restore_best_regs: -+ /* Restore best match. It may happen that `dend == -+ end_match_1' while the restored d is in string2. -+ For example, the pattern `x.*y.*z' against the -+ strings `x-' and `y-z-', if the two strings are -+ not consecutive in memory. */ -+ DEBUG_PRINT1 ("Restoring best registers.\n"); -+ -+ d = match_end; -+ dend = ((d >= string1 && d <= end1) -+ ? end_match_1 : end_match_2); -+ -+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) -+ { -+ regstart[mcnt] = best_regstart[mcnt]; -+ regend[mcnt] = best_regend[mcnt]; -+ } -+ } -+ } /* d != end_match_2 */ -+ -+ succeed_label: -+ DEBUG_PRINT1 ("Accepting match.\n"); -+ /* If caller wants register contents data back, do it. */ -+ if (regs && !bufp->no_sub) -+ { -+ /* Have the register data arrays been allocated? */ -+ if (bufp->regs_allocated == REGS_UNALLOCATED) -+ { /* No. So allocate them with malloc. We need one -+ extra element beyond `num_regs' for the `-1' marker -+ GNU code uses. */ -+ regs->num_regs = MAX (RE_NREGS, num_regs + 1); -+ regs->start = TALLOC (regs->num_regs, regoff_t); -+ regs->end = TALLOC (regs->num_regs, regoff_t); -+ if (regs->start == NULL || regs->end == NULL) -+ { -+ FREE_VARIABLES (); -+ return -2; -+ } -+ bufp->regs_allocated = REGS_REALLOCATE; -+ } -+ else if (bufp->regs_allocated == REGS_REALLOCATE) -+ { /* Yes. If we need more elements than were already -+ allocated, reallocate them. If we need fewer, just -+ leave it alone. */ -+ if (regs->num_regs < num_regs + 1) -+ { -+ regs->num_regs = num_regs + 1; -+ RETALLOC (regs->start, regs->num_regs, regoff_t); -+ RETALLOC (regs->end, regs->num_regs, regoff_t); -+ if (regs->start == NULL || regs->end == NULL) -+ { -+ FREE_VARIABLES (); -+ return -2; -+ } -+ } -+ } -+ else -+ { -+ /* These braces fend off a "empty body in an else-statement" -+ warning under GCC when assert expands to nothing. */ -+ assert (bufp->regs_allocated == REGS_FIXED); -+ } -+ -+ /* Convert the pointer data in `regstart' and `regend' to -+ indices. Register zero has to be set differently, -+ since we haven't kept track of any info for it. */ -+ if (regs->num_regs > 0) -+ { -+ regs->start[0] = pos; -+#ifdef WCHAR -+ if (MATCHING_IN_FIRST_STRING) -+ regs->end[0] = mbs_offset1 != NULL ? -+ mbs_offset1[d-string1] : 0; -+ else -+ regs->end[0] = csize1 + (mbs_offset2 != NULL ? -+ mbs_offset2[d-string2] : 0); -+#else -+ regs->end[0] = (MATCHING_IN_FIRST_STRING -+ ? ((regoff_t) (d - string1)) -+ : ((regoff_t) (d - string2 + size1))); -+#endif /* WCHAR */ -+ } -+ -+ /* Go through the first `min (num_regs, regs->num_regs)' -+ registers, since that is all we initialized. */ -+ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); -+ mcnt++) -+ { -+ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) -+ regs->start[mcnt] = regs->end[mcnt] = -1; -+ else -+ { -+ regs->start[mcnt] -+ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); -+ regs->end[mcnt] -+ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); -+ } -+ } -+ -+ /* If the regs structure we return has more elements than -+ were in the pattern, set the extra elements to -1. If -+ we (re)allocated the registers, this is the case, -+ because we always allocate enough to have at least one -+ -1 at the end. */ -+ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) -+ regs->start[mcnt] = regs->end[mcnt] = -1; -+ } /* regs && !bufp->no_sub */ -+ -+ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", -+ nfailure_points_pushed, nfailure_points_popped, -+ nfailure_points_pushed - nfailure_points_popped); -+ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); -+ -+#ifdef WCHAR -+ if (MATCHING_IN_FIRST_STRING) -+ mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; -+ else -+ mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + -+ csize1; -+ mcnt -= pos; -+#else -+ mcnt = d - pos - (MATCHING_IN_FIRST_STRING -+ ? string1 -+ : string2 - size1); -+#endif /* WCHAR */ -+ -+ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); -+ -+ FREE_VARIABLES (); -+ return mcnt; -+ } -+ -+ /* Otherwise match next pattern command. */ -+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) -+ { -+ /* Ignore these. Used to ignore the n of succeed_n's which -+ currently have n == 0. */ -+ case no_op: -+ DEBUG_PRINT1 ("EXECUTING no_op.\n"); -+ break; -+ -+ case succeed: -+ DEBUG_PRINT1 ("EXECUTING succeed.\n"); -+ goto succeed_label; -+ -+ /* Match the next n pattern characters exactly. The following -+ byte in the pattern defines n, and the n bytes after that -+ are the characters to match. */ -+ case exactn: -+#ifdef MBS_SUPPORT -+ case exactn_bin: -+#endif -+ mcnt = *p++; -+ DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); -+ -+ /* This is written out as an if-else so we don't waste time -+ testing `translate' inside the loop. */ -+ if (translate) -+ { -+ do -+ { -+ PREFETCH (); -+#ifdef WCHAR -+ if (*d <= 0xff) -+ { -+ if ((UCHAR_T) translate[(unsigned char) *d++] -+ != (UCHAR_T) *p++) -+ goto fail; -+ } -+ else -+ { -+ if (*d++ != (CHAR_T) *p++) -+ goto fail; -+ } -+#else -+ if ((UCHAR_T) translate[(unsigned char) *d++] -+ != (UCHAR_T) *p++) -+ goto fail; -+#endif /* WCHAR */ -+ } -+ while (--mcnt); -+ } -+ else -+ { -+ do -+ { -+ PREFETCH (); -+ if (*d++ != (CHAR_T) *p++) goto fail; -+ } -+ while (--mcnt); -+ } -+ SET_REGS_MATCHED (); -+ break; -+ -+ -+ /* Match any character except possibly a newline or a null. */ -+ case anychar: -+ DEBUG_PRINT1 ("EXECUTING anychar.\n"); -+ -+ PREFETCH (); -+ -+ if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') -+ || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) -+ goto fail; -+ -+ SET_REGS_MATCHED (); -+ DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); -+ d++; -+ break; -+ -+ -+ case charset: -+ case charset_not: -+ { -+ register UCHAR_T c; -+#ifdef WCHAR -+ unsigned int i, char_class_length, coll_symbol_length, -+ equiv_class_length, ranges_length, chars_length, length; -+ CHAR_T *workp, *workp2, *charset_top; -+#define WORK_BUFFER_SIZE 128 -+ CHAR_T str_buf[WORK_BUFFER_SIZE]; -+# ifdef _LIBC -+ uint32_t nrules; -+# endif /* _LIBC */ -+#endif /* WCHAR */ -+ boolean negate = (re_opcode_t) *(p - 1) == charset_not; -+ -+ DEBUG_PRINT2 ("EXECUTING charset%s.\n", negate ? "_not" : ""); -+ PREFETCH (); -+ c = TRANSLATE (*d); /* The character to match. */ -+#ifdef WCHAR -+# ifdef _LIBC -+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); -+# endif /* _LIBC */ -+ charset_top = p - 1; -+ char_class_length = *p++; -+ coll_symbol_length = *p++; -+ equiv_class_length = *p++; -+ ranges_length = *p++; -+ chars_length = *p++; -+ /* p points charset[6], so the address of the next instruction -+ (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'], -+ where l=length of char_classes, m=length of collating_symbol, -+ n=equivalence_class, o=length of char_range, -+ p'=length of character. */ -+ workp = p; -+ /* Update p to indicate the next instruction. */ -+ p += char_class_length + coll_symbol_length+ equiv_class_length + -+ 2*ranges_length + chars_length; -+ -+ /* match with char_class? */ -+ for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE) -+ { -+ wctype_t wctype; -+ uintptr_t alignedp = ((uintptr_t)workp -+ + __alignof__(wctype_t) - 1) -+ & ~(uintptr_t)(__alignof__(wctype_t) - 1); -+ wctype = *((wctype_t*)alignedp); -+ workp += CHAR_CLASS_SIZE; -+# ifdef _LIBC -+ if (__iswctype((wint_t)c, wctype)) -+ goto char_set_matched; -+# else -+ if (iswctype((wint_t)c, wctype)) -+ goto char_set_matched; -+# endif -+ } -+ -+ /* match with collating_symbol? */ -+# ifdef _LIBC -+ if (nrules != 0) -+ { -+ const unsigned char *extra = (const unsigned char *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); -+ -+ for (workp2 = workp + coll_symbol_length ; workp < workp2 ; -+ workp++) -+ { -+ int32_t *wextra; -+ wextra = (int32_t*)(extra + *workp++); -+ for (i = 0; i < *wextra; ++i) -+ if (TRANSLATE(d[i]) != wextra[1 + i]) -+ break; -+ -+ if (i == *wextra) -+ { -+ /* Update d, however d will be incremented at -+ char_set_matched:, we decrement d here. */ -+ d += i - 1; -+ goto char_set_matched; -+ } -+ } -+ } -+ else /* (nrules == 0) */ -+# endif -+ /* If we can't look up collation data, we use wcscoll -+ instead. */ -+ { -+ for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) -+ { -+ const CHAR_T *backup_d = d, *backup_dend = dend; -+# ifdef _LIBC -+ length = __wcslen (workp); -+# else -+ length = wcslen (workp); -+# endif -+ -+ /* If wcscoll(the collating symbol, whole string) > 0, -+ any substring of the string never match with the -+ collating symbol. */ -+# ifdef _LIBC -+ if (__wcscoll (workp, d) > 0) -+# else -+ if (wcscoll (workp, d) > 0) -+# endif -+ { -+ workp += length + 1; -+ continue; -+ } -+ -+ /* First, we compare the collating symbol with -+ the first character of the string. -+ If it don't match, we add the next character to -+ the compare buffer in turn. */ -+ for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++) -+ { -+ int match; -+ if (d == dend) -+ { -+ if (dend == end_match_2) -+ break; -+ d = string2; -+ dend = end_match_2; -+ } -+ -+ /* add next character to the compare buffer. */ -+ str_buf[i] = TRANSLATE(*d); -+ str_buf[i+1] = '\0'; -+ -+# ifdef _LIBC -+ match = __wcscoll (workp, str_buf); -+# else -+ match = wcscoll (workp, str_buf); -+# endif -+ if (match == 0) -+ goto char_set_matched; -+ -+ if (match < 0) -+ /* (str_buf > workp) indicate (str_buf + X > workp), -+ because for all X (str_buf + X > str_buf). -+ So we don't need continue this loop. */ -+ break; -+ -+ /* Otherwise(str_buf < workp), -+ (str_buf+next_character) may equals (workp). -+ So we continue this loop. */ -+ } -+ /* not matched */ -+ d = backup_d; -+ dend = backup_dend; -+ workp += length + 1; -+ } -+ } -+ /* match with equivalence_class? */ -+# ifdef _LIBC -+ if (nrules != 0) -+ { -+ const CHAR_T *backup_d = d, *backup_dend = dend; -+ /* Try to match the equivalence class against -+ those known to the collate implementation. */ -+ const int32_t *table; -+ const int32_t *weights; -+ const int32_t *extra; -+ const int32_t *indirect; -+ int32_t idx, idx2; -+ wint_t *cp; -+ size_t len; -+ -+ table = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); -+ weights = (const wint_t *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); -+ extra = (const wint_t *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); -+ indirect = (const int32_t *) -+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); -+ -+ /* Write 1 collating element to str_buf, and -+ get its index. */ -+ idx2 = 0; -+ -+ for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++) -+ { -+ cp = (wint_t*)str_buf; -+ if (d == dend) -+ { -+ if (dend == end_match_2) -+ break; -+ d = string2; -+ dend = end_match_2; -+ } -+ str_buf[i] = TRANSLATE(*(d+i)); -+ str_buf[i+1] = '\0'; /* sentinel */ -+ idx2 = FINDIDX (table, indirect, extra, &cp, 1); -+ } -+ -+ /* Update d, however d will be incremented at -+ char_set_matched:, we decrement d here. */ -+ d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1); -+ if (d >= dend) -+ { -+ if (dend == end_match_2) -+ d = dend; -+ else -+ { -+ d = string2; -+ dend = end_match_2; -+ } -+ } -+ -+ len = weights[idx2]; -+ -+ for (workp2 = workp + equiv_class_length ; workp < workp2 ; -+ workp++) -+ { -+ idx = (int32_t)*workp; -+ /* We already checked idx != 0 in regex_compile. */ -+ -+ if (idx2 != 0 && len == weights[idx]) -+ { -+ int cnt = 0; -+ while (cnt < len && (weights[idx + 1 + cnt] -+ == weights[idx2 + 1 + cnt])) -+ ++cnt; -+ -+ if (cnt == len) -+ goto char_set_matched; -+ } -+ } -+ /* not matched */ -+ d = backup_d; -+ dend = backup_dend; -+ } -+ else /* (nrules == 0) */ -+# endif -+ /* If we can't look up collation data, we use wcscoll -+ instead. */ -+ { -+ for (workp2 = workp + equiv_class_length ; workp < workp2 ;) -+ { -+ const CHAR_T *backup_d = d, *backup_dend = dend; -+# ifdef _LIBC -+ length = __wcslen (workp); -+# else -+ length = wcslen (workp); -+# endif -+ -+ /* If wcscoll(the collating symbol, whole string) > 0, -+ any substring of the string never match with the -+ collating symbol. */ -+# ifdef _LIBC -+ if (__wcscoll (workp, d) > 0) -+# else -+ if (wcscoll (workp, d) > 0) -+# endif -+ { -+ workp += length + 1; -+ break; -+ } -+ -+ /* First, we compare the equivalence class with -+ the first character of the string. -+ If it don't match, we add the next character to -+ the compare buffer in turn. */ -+ for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++) -+ { -+ int match; -+ if (d == dend) -+ { -+ if (dend == end_match_2) -+ break; -+ d = string2; -+ dend = end_match_2; -+ } -+ -+ /* add next character to the compare buffer. */ -+ str_buf[i] = TRANSLATE(*d); -+ str_buf[i+1] = '\0'; -+ -+# ifdef _LIBC -+ match = __wcscoll (workp, str_buf); -+# else -+ match = wcscoll (workp, str_buf); -+# endif -+ -+ if (match == 0) -+ goto char_set_matched; -+ -+ if (match < 0) -+ /* (str_buf > workp) indicate (str_buf + X > workp), -+ because for all X (str_buf + X > str_buf). -+ So we don't need continue this loop. */ -+ break; -+ -+ /* Otherwise(str_buf < workp), -+ (str_buf+next_character) may equals (workp). -+ So we continue this loop. */ -+ } -+ /* not matched */ -+ d = backup_d; -+ dend = backup_dend; -+ workp += length + 1; -+ } -+ } -+ -+ /* match with char_range? */ -+# ifdef _LIBC -+ if (nrules != 0) -+ { -+ uint32_t collseqval; -+ const char *collseq = (const char *) -+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); -+ -+ collseqval = collseq_table_lookup (collseq, c); -+ -+ for (; workp < p - chars_length ;) -+ { -+ uint32_t start_val, end_val; -+ -+ /* We already compute the collation sequence value -+ of the characters (or collating symbols). */ -+ start_val = (uint32_t) *workp++; /* range_start */ -+ end_val = (uint32_t) *workp++; /* range_end */ -+ -+ if (start_val <= collseqval && collseqval <= end_val) -+ goto char_set_matched; -+ } -+ } -+ else -+# endif -+ { -+ /* We set range_start_char at str_buf[0], range_end_char -+ at str_buf[4], and compared char at str_buf[2]. */ -+ str_buf[1] = 0; -+ str_buf[2] = c; -+ str_buf[3] = 0; -+ str_buf[5] = 0; -+ for (; workp < p - chars_length ;) -+ { -+ wchar_t *range_start_char, *range_end_char; -+ -+ /* match if (range_start_char <= c <= range_end_char). */ -+ -+ /* If range_start(or end) < 0, we assume -range_start(end) -+ is the offset of the collating symbol which is specified -+ as the character of the range start(end). */ -+ -+ /* range_start */ -+ if (*workp < 0) -+ range_start_char = charset_top - (*workp++); -+ else -+ { -+ str_buf[0] = *workp++; -+ range_start_char = str_buf; -+ } -+ -+ /* range_end */ -+ if (*workp < 0) -+ range_end_char = charset_top - (*workp++); -+ else -+ { -+ str_buf[4] = *workp++; -+ range_end_char = str_buf + 4; -+ } -+ -+# ifdef _LIBC -+ if (__wcscoll (range_start_char, str_buf+2) <= 0 -+ && __wcscoll (str_buf+2, range_end_char) <= 0) -+# else -+ if (wcscoll (range_start_char, str_buf+2) <= 0 -+ && wcscoll (str_buf+2, range_end_char) <= 0) -+# endif -+ goto char_set_matched; -+ } -+ } -+ -+ /* match with char? */ -+ for (; workp < p ; workp++) -+ if (c == *workp) -+ goto char_set_matched; -+ -+ negate = !negate; -+ -+ char_set_matched: -+ if (negate) goto fail; -+#else -+ /* Cast to `unsigned' instead of `unsigned char' in case the -+ bit list is a full 32 bytes long. */ -+ if (c < (unsigned) (*p * BYTEWIDTH) -+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) -+ negate = !negate; -+ -+ p += 1 + *p; -+ -+ if (!negate) goto fail; -+#undef WORK_BUFFER_SIZE -+#endif /* WCHAR */ -+ SET_REGS_MATCHED (); -+ d++; -+ break; -+ } -+ -+ -+ /* The beginning of a group is represented by start_memory. -+ The arguments are the register number in the next byte, and the -+ number of groups inner to this one in the next. The text -+ matched within the group is recorded (in the internal -+ registers data structure) under the register number. */ -+ case start_memory: -+ DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", -+ (long int) *p, (long int) p[1]); -+ -+ /* Find out if this group can match the empty string. */ -+ p1 = p; /* To send to group_match_null_string_p. */ -+ -+ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) -+ REG_MATCH_NULL_STRING_P (reg_info[*p]) -+ = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); -+ -+ /* Save the position in the string where we were the last time -+ we were at this open-group operator in case the group is -+ operated upon by a repetition operator, e.g., with `(a*)*b' -+ against `ab'; then we want to ignore where we are now in -+ the string in case this attempt to match fails. */ -+ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) -+ ? REG_UNSET (regstart[*p]) ? d : regstart[*p] -+ : regstart[*p]; -+ DEBUG_PRINT2 (" old_regstart: %d\n", -+ POINTER_TO_OFFSET (old_regstart[*p])); -+ -+ regstart[*p] = d; -+ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); -+ -+ IS_ACTIVE (reg_info[*p]) = 1; -+ MATCHED_SOMETHING (reg_info[*p]) = 0; -+ -+ /* Clear this whenever we change the register activity status. */ -+ set_regs_matched_done = 0; -+ -+ /* This is the new highest active register. */ -+ highest_active_reg = *p; -+ -+ /* If nothing was active before, this is the new lowest active -+ register. */ -+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) -+ lowest_active_reg = *p; -+ -+ /* Move past the register number and inner group count. */ -+ p += 2; -+ just_past_start_mem = p; -+ -+ break; -+ -+ -+ /* The stop_memory opcode represents the end of a group. Its -+ arguments are the same as start_memory's: the register -+ number, and the number of inner groups. */ -+ case stop_memory: -+ DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", -+ (long int) *p, (long int) p[1]); -+ -+ /* We need to save the string position the last time we were at -+ this close-group operator in case the group is operated -+ upon by a repetition operator, e.g., with `((a*)*(b*)*)*' -+ against `aba'; then we want to ignore where we are now in -+ the string in case this attempt to match fails. */ -+ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) -+ ? REG_UNSET (regend[*p]) ? d : regend[*p] -+ : regend[*p]; -+ DEBUG_PRINT2 (" old_regend: %d\n", -+ POINTER_TO_OFFSET (old_regend[*p])); -+ -+ regend[*p] = d; -+ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); -+ -+ /* This register isn't active anymore. */ -+ IS_ACTIVE (reg_info[*p]) = 0; -+ -+ /* Clear this whenever we change the register activity status. */ -+ set_regs_matched_done = 0; -+ -+ /* If this was the only register active, nothing is active -+ anymore. */ -+ if (lowest_active_reg == highest_active_reg) -+ { -+ lowest_active_reg = NO_LOWEST_ACTIVE_REG; -+ highest_active_reg = NO_HIGHEST_ACTIVE_REG; -+ } -+ else -+ { /* We must scan for the new highest active register, since -+ it isn't necessarily one less than now: consider -+ (a(b)c(d(e)f)g). When group 3 ends, after the f), the -+ new highest active register is 1. */ -+ UCHAR_T r = *p - 1; -+ while (r > 0 && !IS_ACTIVE (reg_info[r])) -+ r--; -+ -+ /* If we end up at register zero, that means that we saved -+ the registers as the result of an `on_failure_jump', not -+ a `start_memory', and we jumped to past the innermost -+ `stop_memory'. For example, in ((.)*) we save -+ registers 1 and 2 as a result of the *, but when we pop -+ back to the second ), we are at the stop_memory 1. -+ Thus, nothing is active. */ -+ if (r == 0) -+ { -+ lowest_active_reg = NO_LOWEST_ACTIVE_REG; -+ highest_active_reg = NO_HIGHEST_ACTIVE_REG; -+ } -+ else -+ highest_active_reg = r; -+ } -+ -+ /* If just failed to match something this time around with a -+ group that's operated on by a repetition operator, try to -+ force exit from the ``loop'', and restore the register -+ information for this group that we had before trying this -+ last match. */ -+ if ((!MATCHED_SOMETHING (reg_info[*p]) -+ || just_past_start_mem == p - 1) -+ && (p + 2) < pend) -+ { -+ boolean is_a_jump_n = false; -+ -+ p1 = p + 2; -+ mcnt = 0; -+ switch ((re_opcode_t) *p1++) -+ { -+ case jump_n: -+ is_a_jump_n = true; -+ case pop_failure_jump: -+ case maybe_pop_jump: -+ case jump: -+ case dummy_failure_jump: -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ if (is_a_jump_n) -+ p1 += OFFSET_ADDRESS_SIZE; -+ break; -+ -+ default: -+ /* do nothing */ ; -+ } -+ p1 += mcnt; -+ -+ /* If the next operation is a jump backwards in the pattern -+ to an on_failure_jump right before the start_memory -+ corresponding to this stop_memory, exit from the loop -+ by forcing a failure after pushing on the stack the -+ on_failure_jump's jump in the pattern, and d. */ -+ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump -+ && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory -+ && p1[2+OFFSET_ADDRESS_SIZE] == *p) -+ { -+ /* If this group ever matched anything, then restore -+ what its registers were before trying this last -+ failed match, e.g., with `(a*)*b' against `ab' for -+ regstart[1], and, e.g., with `((a*)*(b*)*)*' -+ against `aba' for regend[3]. -+ -+ Also restore the registers for inner groups for, -+ e.g., `((a*)(b*))*' against `aba' (register 3 would -+ otherwise get trashed). */ -+ -+ if (EVER_MATCHED_SOMETHING (reg_info[*p])) -+ { -+ unsigned r; -+ -+ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; -+ -+ /* Restore this and inner groups' (if any) registers. */ -+ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); -+ r++) -+ { -+ regstart[r] = old_regstart[r]; -+ -+ /* xx why this test? */ -+ if (old_regend[r] >= regstart[r]) -+ regend[r] = old_regend[r]; -+ } -+ } -+ p1++; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2); -+ -+ goto fail; -+ } -+ } -+ -+ /* Move past the register number and the inner group count. */ -+ p += 2; -+ break; -+ -+ -+ /* \ has been turned into a `duplicate' command which is -+ followed by the numeric value of as the register number. */ -+ case duplicate: -+ { -+ register const CHAR_T *d2, *dend2; -+ int regno = *p++; /* Get which register to match against. */ -+ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); -+ -+ /* Can't back reference a group which we've never matched. */ -+ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) -+ goto fail; -+ -+ /* Where in input to try to start matching. */ -+ d2 = regstart[regno]; -+ -+ /* Where to stop matching; if both the place to start and -+ the place to stop matching are in the same string, then -+ set to the place to stop, otherwise, for now have to use -+ the end of the first string. */ -+ -+ dend2 = ((FIRST_STRING_P (regstart[regno]) -+ == FIRST_STRING_P (regend[regno])) -+ ? regend[regno] : end_match_1); -+ for (;;) -+ { -+ /* If necessary, advance to next segment in register -+ contents. */ -+ while (d2 == dend2) -+ { -+ if (dend2 == end_match_2) break; -+ if (dend2 == regend[regno]) break; -+ -+ /* End of string1 => advance to string2. */ -+ d2 = string2; -+ dend2 = regend[regno]; -+ } -+ /* At end of register contents => success */ -+ if (d2 == dend2) break; -+ -+ /* If necessary, advance to next segment in data. */ -+ PREFETCH (); -+ -+ /* How many characters left in this segment to match. */ -+ mcnt = dend - d; -+ -+ /* Want how many consecutive characters we can match in -+ one shot, so, if necessary, adjust the count. */ -+ if (mcnt > dend2 - d2) -+ mcnt = dend2 - d2; -+ -+ /* Compare that many; failure if mismatch, else move -+ past them. */ -+ if (translate -+ ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) -+ : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) -+ goto fail; -+ d += mcnt, d2 += mcnt; -+ -+ /* Do this because we've match some characters. */ -+ SET_REGS_MATCHED (); -+ } -+ } -+ break; -+ -+ -+ /* begline matches the empty string at the beginning of the string -+ (unless `not_bol' is set in `bufp'), and, if -+ `newline_anchor' is set, after newlines. */ -+ case begline: -+ DEBUG_PRINT1 ("EXECUTING begline.\n"); -+ -+ if (AT_STRINGS_BEG (d)) -+ { -+ if (!bufp->not_bol) break; -+ } -+ else if (d[-1] == '\n' && bufp->newline_anchor) -+ { -+ break; -+ } -+ /* In all other cases, we fail. */ -+ goto fail; -+ -+ -+ /* endline is the dual of begline. */ -+ case endline: -+ DEBUG_PRINT1 ("EXECUTING endline.\n"); -+ -+ if (AT_STRINGS_END (d)) -+ { -+ if (!bufp->not_eol) break; -+ } -+ -+ /* We have to ``prefetch'' the next character. */ -+ else if ((d == end1 ? *string2 : *d) == '\n' -+ && bufp->newline_anchor) -+ { -+ break; -+ } -+ goto fail; -+ -+ -+ /* Match at the very beginning of the data. */ -+ case begbuf: -+ DEBUG_PRINT1 ("EXECUTING begbuf.\n"); -+ if (AT_STRINGS_BEG (d)) -+ break; -+ goto fail; -+ -+ -+ /* Match at the very end of the data. */ -+ case endbuf: -+ DEBUG_PRINT1 ("EXECUTING endbuf.\n"); -+ if (AT_STRINGS_END (d)) -+ break; -+ goto fail; -+ -+ -+ /* on_failure_keep_string_jump is used to optimize `.*\n'. It -+ pushes NULL as the value for the string on the stack. Then -+ `pop_failure_point' will keep the current value for the -+ string, instead of restoring it. To see why, consider -+ matching `foo\nbar' against `.*\n'. The .* matches the foo; -+ then the . fails against the \n. But the next thing we want -+ to do is match the \n against the \n; if we restored the -+ string value, we would be back at the foo. -+ -+ Because this is used only in specific cases, we don't need to -+ check all the things that `on_failure_jump' does, to make -+ sure the right things get saved on the stack. Hence we don't -+ share its code. The only reason to push anything on the -+ stack at all is that otherwise we would have to change -+ `anychar's code to do something besides goto fail in this -+ case; that seems worse than this. */ -+ case on_failure_keep_string_jump: -+ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); -+ -+ EXTRACT_NUMBER_AND_INCR (mcnt, p); -+#ifdef _LIBC -+ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); -+#else -+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); -+#endif -+ -+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2); -+ break; -+ -+ -+ /* Uses of on_failure_jump: -+ -+ Each alternative starts with an on_failure_jump that points -+ to the beginning of the next alternative. Each alternative -+ except the last ends with a jump that in effect jumps past -+ the rest of the alternatives. (They really jump to the -+ ending jump of the following alternative, because tensioning -+ these jumps is a hassle.) -+ -+ Repeats start with an on_failure_jump that points past both -+ the repetition text and either the following jump or -+ pop_failure_jump back to this on_failure_jump. */ -+ case on_failure_jump: -+ on_failure: -+ DEBUG_PRINT1 ("EXECUTING on_failure_jump"); -+ -+ EXTRACT_NUMBER_AND_INCR (mcnt, p); -+#ifdef _LIBC -+ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); -+#else -+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); -+#endif -+ -+ /* If this on_failure_jump comes right before a group (i.e., -+ the original * applied to a group), save the information -+ for that group and all inner ones, so that if we fail back -+ to this point, the group's information will be correct. -+ For example, in \(a*\)*\1, we need the preceding group, -+ and in \(zz\(a*\)b*\)\2, we need the inner group. */ -+ -+ /* We can't use `p' to check ahead because we push -+ a failure point to `p + mcnt' after we do this. */ -+ p1 = p; -+ -+ /* We need to skip no_op's before we look for the -+ start_memory in case this on_failure_jump is happening as -+ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 -+ against aba. */ -+ while (p1 < pend && (re_opcode_t) *p1 == no_op) -+ p1++; -+ -+ if (p1 < pend && (re_opcode_t) *p1 == start_memory) -+ { -+ /* We have a new highest active register now. This will -+ get reset at the start_memory we are about to get to, -+ but we will have saved all the registers relevant to -+ this repetition op, as described above. */ -+ highest_active_reg = *(p1 + 1) + *(p1 + 2); -+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) -+ lowest_active_reg = *(p1 + 1); -+ } -+ -+ DEBUG_PRINT1 (":\n"); -+ PUSH_FAILURE_POINT (p + mcnt, d, -2); -+ break; -+ -+ -+ /* A smart repeat ends with `maybe_pop_jump'. -+ We change it to either `pop_failure_jump' or `jump'. */ -+ case maybe_pop_jump: -+ EXTRACT_NUMBER_AND_INCR (mcnt, p); -+ DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); -+ { -+ register UCHAR_T *p2 = p; -+ -+ /* Compare the beginning of the repeat with what in the -+ pattern follows its end. If we can establish that there -+ is nothing that they would both match, i.e., that we -+ would have to backtrack because of (as in, e.g., `a*a') -+ then we can change to pop_failure_jump, because we'll -+ never have to backtrack. -+ -+ This is not true in the case of alternatives: in -+ `(a|ab)*' we do need to backtrack to the `ab' alternative -+ (e.g., if the string was `ab'). But instead of trying to -+ detect that here, the alternative has put on a dummy -+ failure point which is what we will end up popping. */ -+ -+ /* Skip over open/close-group commands. -+ If what follows this loop is a ...+ construct, -+ look at what begins its body, since we will have to -+ match at least one of that. */ -+ while (1) -+ { -+ if (p2 + 2 < pend -+ && ((re_opcode_t) *p2 == stop_memory -+ || (re_opcode_t) *p2 == start_memory)) -+ p2 += 3; -+ else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend -+ && (re_opcode_t) *p2 == dummy_failure_jump) -+ p2 += 2 + 2 * OFFSET_ADDRESS_SIZE; -+ else -+ break; -+ } -+ -+ p1 = p + mcnt; -+ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding -+ to the `maybe_finalize_jump' of this case. Examine what -+ follows. */ -+ -+ /* If we're at the end of the pattern, we can change. */ -+ if (p2 == pend) -+ { -+ /* Consider what happens when matching ":\(.*\)" -+ against ":/". I don't really understand this code -+ yet. */ -+ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) -+ pop_failure_jump; -+ DEBUG_PRINT1 -+ (" End of pattern: change to `pop_failure_jump'.\n"); -+ } -+ -+ else if ((re_opcode_t) *p2 == exactn -+#ifdef MBS_SUPPORT -+ || (re_opcode_t) *p2 == exactn_bin -+#endif -+ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) -+ { -+ register UCHAR_T c -+ = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; -+ -+ if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn -+#ifdef MBS_SUPPORT -+ || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin -+#endif -+ ) && p1[3+OFFSET_ADDRESS_SIZE] != c) -+ { -+ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) -+ pop_failure_jump; -+#ifdef WCHAR -+ DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", -+ (wint_t) c, -+ (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); -+#else -+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", -+ (char) c, -+ (char) p1[3+OFFSET_ADDRESS_SIZE]); -+#endif -+ } -+ -+#ifndef WCHAR -+ else if ((re_opcode_t) p1[3] == charset -+ || (re_opcode_t) p1[3] == charset_not) -+ { -+ int negate = (re_opcode_t) p1[3] == charset_not; -+ -+ if (c < (unsigned) (p1[4] * BYTEWIDTH) -+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) -+ negate = !negate; -+ -+ /* `negate' is equal to 1 if c would match, which means -+ that we can't change to pop_failure_jump. */ -+ if (!negate) -+ { -+ p[-3] = (unsigned char) pop_failure_jump; -+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); -+ } -+ } -+#endif /* not WCHAR */ -+ } -+#ifndef WCHAR -+ else if ((re_opcode_t) *p2 == charset) -+ { -+ /* We win if the first character of the loop is not part -+ of the charset. */ -+ if ((re_opcode_t) p1[3] == exactn -+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] -+ && (p2[2 + p1[5] / BYTEWIDTH] -+ & (1 << (p1[5] % BYTEWIDTH))))) -+ { -+ p[-3] = (unsigned char) pop_failure_jump; -+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); -+ } -+ -+ else if ((re_opcode_t) p1[3] == charset_not) -+ { -+ int idx; -+ /* We win if the charset_not inside the loop -+ lists every character listed in the charset after. */ -+ for (idx = 0; idx < (int) p2[1]; idx++) -+ if (! (p2[2 + idx] == 0 -+ || (idx < (int) p1[4] -+ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) -+ break; -+ -+ if (idx == p2[1]) -+ { -+ p[-3] = (unsigned char) pop_failure_jump; -+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); -+ } -+ } -+ else if ((re_opcode_t) p1[3] == charset) -+ { -+ int idx; -+ /* We win if the charset inside the loop -+ has no overlap with the one after the loop. */ -+ for (idx = 0; -+ idx < (int) p2[1] && idx < (int) p1[4]; -+ idx++) -+ if ((p2[2 + idx] & p1[5 + idx]) != 0) -+ break; -+ -+ if (idx == p2[1] || idx == p1[4]) -+ { -+ p[-3] = (unsigned char) pop_failure_jump; -+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); -+ } -+ } -+ } -+#endif /* not WCHAR */ -+ } -+ p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ -+ if ((re_opcode_t) p[-1] != pop_failure_jump) -+ { -+ p[-1] = (UCHAR_T) jump; -+ DEBUG_PRINT1 (" Match => jump.\n"); -+ goto unconditional_jump; -+ } -+ /* Note fall through. */ -+ -+ -+ /* The end of a simple repeat has a pop_failure_jump back to -+ its matching on_failure_jump, where the latter will push a -+ failure point. The pop_failure_jump takes off failure -+ points put on by this pop_failure_jump's matching -+ on_failure_jump; we got through the pattern to here from the -+ matching on_failure_jump, so didn't fail. */ -+ case pop_failure_jump: -+ { -+ /* We need to pass separate storage for the lowest and -+ highest registers, even though we don't care about the -+ actual values. Otherwise, we will restore only one -+ register from the stack, since lowest will == highest in -+ `pop_failure_point'. */ -+ active_reg_t dummy_low_reg, dummy_high_reg; -+ UCHAR_T *pdummy __attribute__ ((unused)) = NULL; -+ const CHAR_T *sdummy __attribute__ ((unused)) = NULL; -+ -+ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); -+ POP_FAILURE_POINT (sdummy, pdummy, -+ dummy_low_reg, dummy_high_reg, -+ reg_dummy, reg_dummy, reg_info_dummy); -+ } -+ /* Note fall through. */ -+ -+ unconditional_jump: -+#ifdef _LIBC -+ DEBUG_PRINT2 ("\n%p: ", p); -+#else -+ DEBUG_PRINT2 ("\n0x%x: ", p); -+#endif -+ /* Note fall through. */ -+ -+ /* Unconditionally jump (without popping any failure points). */ -+ case jump: -+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ -+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); -+ p += mcnt; /* Do the jump. */ -+#ifdef _LIBC -+ DEBUG_PRINT2 ("(to %p).\n", p); -+#else -+ DEBUG_PRINT2 ("(to 0x%x).\n", p); -+#endif -+ break; -+ -+ -+ /* We need this opcode so we can detect where alternatives end -+ in `group_match_null_string_p' et al. */ -+ case jump_past_alt: -+ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); -+ goto unconditional_jump; -+ -+ -+ /* Normally, the on_failure_jump pushes a failure point, which -+ then gets popped at pop_failure_jump. We will end up at -+ pop_failure_jump, also, and with a pattern of, say, `a+', we -+ are skipping over the on_failure_jump, so we have to push -+ something meaningless for pop_failure_jump to pop. */ -+ case dummy_failure_jump: -+ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); -+ /* It doesn't matter what we push for the string here. What -+ the code at `fail' tests is the value for the pattern. */ -+ PUSH_FAILURE_POINT (NULL, NULL, -2); -+ goto unconditional_jump; -+ -+ -+ /* At the end of an alternative, we need to push a dummy failure -+ point in case we are followed by a `pop_failure_jump', because -+ we don't want the failure point for the alternative to be -+ popped. For example, matching `(a|ab)*' against `aab' -+ requires that we match the `ab' alternative. */ -+ case push_dummy_failure: -+ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); -+ /* See comments just above at `dummy_failure_jump' about the -+ two zeroes. */ -+ PUSH_FAILURE_POINT (NULL, NULL, -2); -+ break; -+ -+ /* Have to succeed matching what follows at least n times. -+ After that, handle like `on_failure_jump'. */ -+ case succeed_n: -+ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); -+ DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); -+ -+ assert (mcnt >= 0); -+ /* Originally, this is how many times we HAVE to succeed. */ -+ if (mcnt > 0) -+ { -+ mcnt--; -+ p += OFFSET_ADDRESS_SIZE; -+ STORE_NUMBER_AND_INCR (p, mcnt); -+#ifdef _LIBC -+ DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE -+ , mcnt); -+#else -+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE -+ , mcnt); -+#endif -+ } -+ else if (mcnt == 0) -+ { -+#ifdef _LIBC -+ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", -+ p + OFFSET_ADDRESS_SIZE); -+#else -+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", -+ p + OFFSET_ADDRESS_SIZE); -+#endif /* _LIBC */ -+ -+#ifdef WCHAR -+ p[1] = (UCHAR_T) no_op; -+#else -+ p[2] = (UCHAR_T) no_op; -+ p[3] = (UCHAR_T) no_op; -+#endif /* WCHAR */ -+ goto on_failure; -+ } -+ break; -+ -+ case jump_n: -+ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); -+ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); -+ -+ /* Originally, this is how many times we CAN jump. */ -+ if (mcnt) -+ { -+ mcnt--; -+ STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt); -+ -+#ifdef _LIBC -+ DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE, -+ mcnt); -+#else -+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE, -+ mcnt); -+#endif /* _LIBC */ -+ goto unconditional_jump; -+ } -+ /* If don't have to jump any more, skip over the rest of command. */ -+ else -+ p += 2 * OFFSET_ADDRESS_SIZE; -+ break; -+ -+ case set_number_at: -+ { -+ DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); -+ -+ EXTRACT_NUMBER_AND_INCR (mcnt, p); -+ p1 = p + mcnt; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p); -+#ifdef _LIBC -+ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); -+#else -+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); -+#endif -+ STORE_NUMBER (p1, mcnt); -+ break; -+ } -+ -+#if 0 -+ /* The DEC Alpha C compiler 3.x generates incorrect code for the -+ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of -+ AT_WORD_BOUNDARY, so this code is disabled. Expanding the -+ macro and introducing temporary variables works around the bug. */ -+ -+ case wordbound: -+ DEBUG_PRINT1 ("EXECUTING wordbound.\n"); -+ if (AT_WORD_BOUNDARY (d)) -+ break; -+ goto fail; -+ -+ case notwordbound: -+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); -+ if (AT_WORD_BOUNDARY (d)) -+ goto fail; -+ break; -+#else -+ case wordbound: -+ { -+ boolean prevchar, thischar; -+ -+ DEBUG_PRINT1 ("EXECUTING wordbound.\n"); -+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) -+ break; -+ -+ prevchar = WORDCHAR_P (d - 1); -+ thischar = WORDCHAR_P (d); -+ if (prevchar != thischar) -+ break; -+ goto fail; -+ } -+ -+ case notwordbound: -+ { -+ boolean prevchar, thischar; -+ -+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); -+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) -+ goto fail; -+ -+ prevchar = WORDCHAR_P (d - 1); -+ thischar = WORDCHAR_P (d); -+ if (prevchar != thischar) -+ goto fail; -+ break; -+ } -+#endif -+ -+ case wordbeg: -+ DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); -+ if (!AT_STRINGS_END (d) && WORDCHAR_P (d) -+ && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) -+ break; -+ goto fail; -+ -+ case wordend: -+ DEBUG_PRINT1 ("EXECUTING wordend.\n"); -+ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) -+ && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) -+ break; -+ goto fail; -+ -+#ifdef emacs -+ case before_dot: -+ DEBUG_PRINT1 ("EXECUTING before_dot.\n"); -+ if (PTR_CHAR_POS ((unsigned char *) d) >= point) -+ goto fail; -+ break; -+ -+ case at_dot: -+ DEBUG_PRINT1 ("EXECUTING at_dot.\n"); -+ if (PTR_CHAR_POS ((unsigned char *) d) != point) -+ goto fail; -+ break; -+ -+ case after_dot: -+ DEBUG_PRINT1 ("EXECUTING after_dot.\n"); -+ if (PTR_CHAR_POS ((unsigned char *) d) <= point) -+ goto fail; -+ break; -+ -+ case syntaxspec: -+ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); -+ mcnt = *p++; -+ goto matchsyntax; -+ -+ case wordchar: -+ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); -+ mcnt = (int) Sword; -+ matchsyntax: -+ PREFETCH (); -+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ -+ d++; -+ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) -+ goto fail; -+ SET_REGS_MATCHED (); -+ break; -+ -+ case notsyntaxspec: -+ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); -+ mcnt = *p++; -+ goto matchnotsyntax; -+ -+ case notwordchar: -+ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); -+ mcnt = (int) Sword; -+ matchnotsyntax: -+ PREFETCH (); -+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ -+ d++; -+ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) -+ goto fail; -+ SET_REGS_MATCHED (); -+ break; -+ -+#else /* not emacs */ -+ case wordchar: -+ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); -+ PREFETCH (); -+ if (!WORDCHAR_P (d)) -+ goto fail; -+ SET_REGS_MATCHED (); -+ d++; -+ break; -+ -+ case notwordchar: -+ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); -+ PREFETCH (); -+ if (WORDCHAR_P (d)) -+ goto fail; -+ SET_REGS_MATCHED (); -+ d++; -+ break; -+#endif /* not emacs */ -+ -+ default: -+ abort (); -+ } -+ continue; /* Successfully executed one pattern command; keep going. */ -+ -+ -+ /* We goto here if a matching operation fails. */ -+ fail: -+ if (!FAIL_STACK_EMPTY ()) -+ { /* A restart point is known. Restore to that state. */ -+ DEBUG_PRINT1 ("\nFAIL:\n"); -+ POP_FAILURE_POINT (d, p, -+ lowest_active_reg, highest_active_reg, -+ regstart, regend, reg_info); -+ -+ /* If this failure point is a dummy, try the next one. */ -+ if (!p) -+ goto fail; -+ -+ /* If we failed to the end of the pattern, don't examine *p. */ -+ assert (p <= pend); -+ if (p < pend) -+ { -+ boolean is_a_jump_n = false; -+ -+ /* If failed to a backwards jump that's part of a repetition -+ loop, need to pop this failure point and use the next one. */ -+ switch ((re_opcode_t) *p) -+ { -+ case jump_n: -+ is_a_jump_n = true; -+ case maybe_pop_jump: -+ case pop_failure_jump: -+ case jump: -+ p1 = p + 1; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ p1 += mcnt; -+ -+ if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) -+ || (!is_a_jump_n -+ && (re_opcode_t) *p1 == on_failure_jump)) -+ goto fail; -+ break; -+ default: -+ /* do nothing */ ; -+ } -+ } -+ -+ if (d >= string1 && d <= end1) -+ dend = end_match_1; -+ } -+ else -+ break; /* Matching at this starting point really fails. */ -+ } /* for (;;) */ -+ -+ if (best_regs_set) -+ goto restore_best_regs; -+ -+ FREE_VARIABLES (); -+ -+ return -1; /* Failure to match. */ -+} /* re_match_2 */ -+ -+/* Subroutine definitions for re_match_2. */ -+ -+ -+/* We are passed P pointing to a register number after a start_memory. -+ -+ Return true if the pattern up to the corresponding stop_memory can -+ match the empty string, and false otherwise. -+ -+ If we find the matching stop_memory, sets P to point to one past its number. -+ Otherwise, sets P to an undefined byte less than or equal to END. -+ -+ We don't handle duplicates properly (yet). */ -+ -+static boolean -+PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, -+ PREFIX(register_info_type) *reg_info) -+{ -+ int mcnt; -+ /* Point to after the args to the start_memory. */ -+ UCHAR_T *p1 = *p + 2; -+ -+ while (p1 < end) -+ { -+ /* Skip over opcodes that can match nothing, and return true or -+ false, as appropriate, when we get to one that can't, or to the -+ matching stop_memory. */ -+ -+ switch ((re_opcode_t) *p1) -+ { -+ /* Could be either a loop or a series of alternatives. */ -+ case on_failure_jump: -+ p1++; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ -+ /* If the next operation is not a jump backwards in the -+ pattern. */ -+ -+ if (mcnt >= 0) -+ { -+ /* Go through the on_failure_jumps of the alternatives, -+ seeing if any of the alternatives cannot match nothing. -+ The last alternative starts with only a jump, -+ whereas the rest start with on_failure_jump and end -+ with a jump, e.g., here is the pattern for `a|b|c': -+ -+ /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 -+ /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 -+ /exactn/1/c -+ -+ So, we have to first go through the first (n-1) -+ alternatives and then deal with the last one separately. */ -+ -+ -+ /* Deal with the first (n-1) alternatives, which start -+ with an on_failure_jump (see above) that jumps to right -+ past a jump_past_alt. */ -+ -+ while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] == -+ jump_past_alt) -+ { -+ /* `mcnt' holds how many bytes long the alternative -+ is, including the ending `jump_past_alt' and -+ its number. */ -+ -+ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - -+ (1 + OFFSET_ADDRESS_SIZE), -+ reg_info)) -+ return false; -+ -+ /* Move to right after this alternative, including the -+ jump_past_alt. */ -+ p1 += mcnt; -+ -+ /* Break if it's the beginning of an n-th alternative -+ that doesn't begin with an on_failure_jump. */ -+ if ((re_opcode_t) *p1 != on_failure_jump) -+ break; -+ -+ /* Still have to check that it's not an n-th -+ alternative that starts with an on_failure_jump. */ -+ p1++; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] != -+ jump_past_alt) -+ { -+ /* Get to the beginning of the n-th alternative. */ -+ p1 -= 1 + OFFSET_ADDRESS_SIZE; -+ break; -+ } -+ } -+ -+ /* Deal with the last alternative: go back and get number -+ of the `jump_past_alt' just before it. `mcnt' contains -+ the length of the alternative. */ -+ EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); -+ -+ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) -+ return false; -+ -+ p1 += mcnt; /* Get past the n-th alternative. */ -+ } /* if mcnt > 0 */ -+ break; -+ -+ -+ case stop_memory: -+ assert (p1[1] == **p); -+ *p = p1 + 2; -+ return true; -+ -+ -+ default: -+ if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) -+ return false; -+ } -+ } /* while p1 < end */ -+ -+ return false; -+} /* group_match_null_string_p */ -+ -+ -+/* Similar to group_match_null_string_p, but doesn't deal with alternatives: -+ It expects P to be the first byte of a single alternative and END one -+ byte past the last. The alternative can contain groups. */ -+ -+static boolean -+PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end, -+ PREFIX(register_info_type) *reg_info) -+{ -+ int mcnt; -+ UCHAR_T *p1 = p; -+ -+ while (p1 < end) -+ { -+ /* Skip over opcodes that can match nothing, and break when we get -+ to one that can't. */ -+ -+ switch ((re_opcode_t) *p1) -+ { -+ /* It's a loop. */ -+ case on_failure_jump: -+ p1++; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ p1 += mcnt; -+ break; -+ -+ default: -+ if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) -+ return false; -+ } -+ } /* while p1 < end */ -+ -+ return true; -+} /* alt_match_null_string_p */ -+ -+ -+/* Deals with the ops common to group_match_null_string_p and -+ alt_match_null_string_p. -+ -+ Sets P to one after the op and its arguments, if any. */ -+ -+static boolean -+PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, -+ PREFIX(register_info_type) *reg_info) -+{ -+ int mcnt; -+ boolean ret; -+ int reg_no; -+ UCHAR_T *p1 = *p; -+ -+ switch ((re_opcode_t) *p1++) -+ { -+ case no_op: -+ case begline: -+ case endline: -+ case begbuf: -+ case endbuf: -+ case wordbeg: -+ case wordend: -+ case wordbound: -+ case notwordbound: -+#ifdef emacs -+ case before_dot: -+ case at_dot: -+ case after_dot: -+#endif -+ break; -+ -+ case start_memory: -+ reg_no = *p1; -+ assert (reg_no > 0 && reg_no <= MAX_REGNUM); -+ ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); -+ -+ /* Have to set this here in case we're checking a group which -+ contains a group and a back reference to it. */ -+ -+ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) -+ REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; -+ -+ if (!ret) -+ return false; -+ break; -+ -+ /* If this is an optimized succeed_n for zero times, make the jump. */ -+ case jump: -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ if (mcnt >= 0) -+ p1 += mcnt; -+ else -+ return false; -+ break; -+ -+ case succeed_n: -+ /* Get to the number of times to succeed. */ -+ p1 += OFFSET_ADDRESS_SIZE; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ -+ if (mcnt == 0) -+ { -+ p1 -= 2 * OFFSET_ADDRESS_SIZE; -+ EXTRACT_NUMBER_AND_INCR (mcnt, p1); -+ p1 += mcnt; -+ } -+ else -+ return false; -+ break; -+ -+ case duplicate: -+ if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) -+ return false; -+ break; -+ -+ case set_number_at: -+ p1 += 2 * OFFSET_ADDRESS_SIZE; -+ -+ default: -+ /* All other opcodes mean we cannot match the empty string. */ -+ return false; -+ } -+ -+ *p = p1; -+ return true; -+} /* common_op_match_null_string_p */ -+ -+ -+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN -+ bytes; nonzero otherwise. */ -+ -+static int -+PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, register int len, -+ RE_TRANSLATE_TYPE translate) -+{ -+ register const UCHAR_T *p1 = (const UCHAR_T *) s1; -+ register const UCHAR_T *p2 = (const UCHAR_T *) s2; -+ while (len) -+ { -+#ifdef WCHAR -+ if (((*p1<=0xff)?translate[*p1++]:*p1++) -+ != ((*p2<=0xff)?translate[*p2++]:*p2++)) -+ return 1; -+#else /* BYTE */ -+ if (translate[*p1++] != translate[*p2++]) return 1; -+#endif /* WCHAR */ -+ len--; -+ } -+ return 0; -+} -+ -+ -+#else /* not INSIDE_RECURSION */ -+ -+/* Entry points for GNU code. */ -+ -+/* re_compile_pattern is the GNU regular expression compiler: it -+ compiles PATTERN (of length SIZE) and puts the result in BUFP. -+ Returns 0 if the pattern was valid, otherwise an error string. -+ -+ Assumes the `allocated' (and perhaps `buffer') and `translate' fields -+ are set in BUFP on entry. -+ -+ We call regex_compile to do the actual compilation. */ -+ -+const char * -+re_compile_pattern (const char *pattern, size_t length, -+ struct re_pattern_buffer *bufp) -+{ -+ reg_errcode_t ret; -+ -+ /* GNU code is written to assume at least RE_NREGS registers will be set -+ (and at least one extra will be -1). */ -+ bufp->regs_allocated = REGS_UNALLOCATED; -+ -+ /* And GNU code determines whether or not to get register information -+ by passing null for the REGS argument to re_match, etc., not by -+ setting no_sub. */ -+ bufp->no_sub = 0; -+ -+ /* Match anchors at newline. */ -+ bufp->newline_anchor = 1; -+ -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); -+ else -+# endif -+ ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); -+ -+ if (!ret) -+ return NULL; -+ return gettext (re_error_msgid[(int) ret]); -+} -+#ifdef _LIBC -+weak_alias (__re_compile_pattern, re_compile_pattern) -+#endif -+ -+/* Entry points compatible with 4.2 BSD regex library. We don't define -+ them unless specifically requested. */ -+ -+#if defined _REGEX_RE_COMP || defined _LIBC -+ -+/* BSD has one and only one pattern buffer. */ -+static struct re_pattern_buffer re_comp_buf; -+ -+char * -+#ifdef _LIBC -+/* Make these definitions weak in libc, so POSIX programs can redefine -+ these names if they don't use our functions, and still use -+ regcomp/regexec below without link errors. */ -+weak_function -+#endif -+re_comp (const char *s) -+{ -+ reg_errcode_t ret; -+ -+ if (!s) -+ { -+ if (!re_comp_buf.buffer) -+ return (char *) gettext ("No previous regular expression"); -+ return 0; -+ } -+ -+ if (!re_comp_buf.buffer) -+ { -+ re_comp_buf.buffer = (unsigned char *) malloc (200); -+ if (re_comp_buf.buffer == NULL) -+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); -+ re_comp_buf.allocated = 200; -+ -+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); -+ if (re_comp_buf.fastmap == NULL) -+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); -+ } -+ -+ /* Since `re_exec' always passes NULL for the `regs' argument, we -+ don't need to initialize the pattern buffer fields which affect it. */ -+ -+ /* Match anchors at newlines. */ -+ re_comp_buf.newline_anchor = 1; -+ -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); -+ else -+# endif -+ ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); -+ -+ if (!ret) -+ return NULL; -+ -+ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ -+ return (char *) gettext (re_error_msgid[(int) ret]); -+} -+ -+ -+int -+#ifdef _LIBC -+weak_function -+#endif -+re_exec (const char *s) -+{ -+ const int len = strlen (s); -+ return -+ 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); -+} -+ -+#endif /* _REGEX_RE_COMP */ -+ -+/* POSIX.2 functions. Don't define these for Emacs. */ -+ -+#ifndef emacs -+ -+/* regcomp takes a regular expression as a string and compiles it. -+ -+ PREG is a regex_t *. We do not expect any fields to be initialized, -+ since POSIX says we shouldn't. Thus, we set -+ -+ `buffer' to the compiled pattern; -+ `used' to the length of the compiled pattern; -+ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the -+ REG_EXTENDED bit in CFLAGS is set; otherwise, to -+ RE_SYNTAX_POSIX_BASIC; -+ `newline_anchor' to REG_NEWLINE being set in CFLAGS; -+ `fastmap' to an allocated space for the fastmap; -+ `fastmap_accurate' to zero; -+ `re_nsub' to the number of subexpressions in PATTERN. -+ -+ PATTERN is the address of the pattern string. -+ -+ CFLAGS is a series of bits which affect compilation. -+ -+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we -+ use POSIX basic syntax. -+ -+ If REG_NEWLINE is set, then . and [^...] don't match newline. -+ Also, regexec will try a match beginning after every newline. -+ -+ If REG_ICASE is set, then we considers upper- and lowercase -+ versions of letters to be equivalent when matching. -+ -+ If REG_NOSUB is set, then when PREG is passed to regexec, that -+ routine will report only success or failure, and nothing about the -+ registers. -+ -+ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for -+ the return codes and their meanings.) */ -+ -+int -+regcomp (regex_t *preg, const char *pattern, int cflags) -+{ -+ reg_errcode_t ret; -+ reg_syntax_t syntax -+ = (cflags & REG_EXTENDED) ? -+ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; -+ -+ /* regex_compile will allocate the space for the compiled pattern. */ -+ preg->buffer = 0; -+ preg->allocated = 0; -+ preg->used = 0; -+ -+ /* Try to allocate space for the fastmap. */ -+ preg->fastmap = (char *) malloc (1 << BYTEWIDTH); -+ -+ if (cflags & REG_ICASE) -+ { -+ int i; -+ -+ preg->translate -+ = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE -+ * sizeof (*(RE_TRANSLATE_TYPE)0)); -+ if (preg->translate == NULL) -+ return (int) REG_ESPACE; -+ -+ /* Map uppercase characters to corresponding lowercase ones. */ -+ for (i = 0; i < CHAR_SET_SIZE; i++) -+ preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; -+ } -+ else -+ preg->translate = NULL; -+ -+ /* If REG_NEWLINE is set, newlines are treated differently. */ -+ if (cflags & REG_NEWLINE) -+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */ -+ syntax &= ~RE_DOT_NEWLINE; -+ syntax |= RE_HAT_LISTS_NOT_NEWLINE; -+ /* It also changes the matching behavior. */ -+ preg->newline_anchor = 1; -+ } -+ else -+ preg->newline_anchor = 0; -+ -+ preg->no_sub = !!(cflags & REG_NOSUB); -+ -+ /* POSIX says a null character in the pattern terminates it, so we -+ can use strlen here in compiling the pattern. */ -+# ifdef MBS_SUPPORT -+ if (MB_CUR_MAX != 1) -+ ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); -+ else -+# endif -+ ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); -+ -+ /* POSIX doesn't distinguish between an unmatched open-group and an -+ unmatched close-group: both are REG_EPAREN. */ -+ if (ret == REG_ERPAREN) ret = REG_EPAREN; -+ -+ if (ret == REG_NOERROR && preg->fastmap) -+ { -+ /* Compute the fastmap now, since regexec cannot modify the pattern -+ buffer. */ -+ if (re_compile_fastmap (preg) == -2) -+ { -+ /* Some error occurred while computing the fastmap, just forget -+ about it. */ -+ free (preg->fastmap); -+ preg->fastmap = NULL; -+ } -+ } -+ -+ return (int) ret; -+} -+#ifdef _LIBC -+weak_alias (__regcomp, regcomp) -+#endif -+ -+ -+/* regexec searches for a given pattern, specified by PREG, in the -+ string STRING. -+ -+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to -+ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at -+ least NMATCH elements, and we set them to the offsets of the -+ corresponding matched substrings. -+ -+ EFLAGS specifies `execution flags' which affect matching: if -+ REG_NOTBOL is set, then ^ does not match at the beginning of the -+ string; if REG_NOTEOL is set, then $ does not match at the end. -+ -+ We return 0 if we find a match and REG_NOMATCH if not. */ -+ -+int -+regexec (const regex_t *preg, const char *string, size_t nmatch, -+ regmatch_t pmatch[], int eflags) -+{ -+ int ret; -+ struct re_registers regs; -+ regex_t private_preg; -+ int len = strlen (string); -+ boolean want_reg_info = !preg->no_sub && nmatch > 0; -+ -+ private_preg = *preg; -+ -+ private_preg.not_bol = !!(eflags & REG_NOTBOL); -+ private_preg.not_eol = !!(eflags & REG_NOTEOL); -+ -+ /* The user has told us exactly how many registers to return -+ information about, via `nmatch'. We have to pass that on to the -+ matching routines. */ -+ private_preg.regs_allocated = REGS_FIXED; -+ -+ if (want_reg_info) -+ { -+ regs.num_regs = nmatch; -+ regs.start = TALLOC (nmatch * 2, regoff_t); -+ if (regs.start == NULL) -+ return (int) REG_NOMATCH; -+ regs.end = regs.start + nmatch; -+ } -+ -+ /* Perform the searching operation. */ -+ ret = re_search (&private_preg, string, len, -+ /* start: */ 0, /* range: */ len, -+ want_reg_info ? ®s : (struct re_registers *) 0); -+ -+ /* Copy the register information to the POSIX structure. */ -+ if (want_reg_info) -+ { -+ if (ret >= 0) -+ { -+ unsigned r; -+ -+ for (r = 0; r < nmatch; r++) -+ { -+ pmatch[r].rm_so = regs.start[r]; -+ pmatch[r].rm_eo = regs.end[r]; -+ } -+ } -+ -+ /* If we needed the temporary register info, free the space now. */ -+ free (regs.start); -+ } -+ -+ /* We want zero return to mean success, unlike `re_search'. */ -+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; -+} -+#ifdef _LIBC -+/* EGLIBC: This is handled in regexec-compat.c. */ -+/*weak_alias (__regexec, regexec)*/ -+#include "regexec-compat.c" -+#endif -+ -+ -+/* Returns a message corresponding to an error code, ERRCODE, returned -+ from either regcomp or regexec. We don't use PREG here. */ -+ -+size_t -+regerror (int errcode, const regex_t *preg __attribute__ ((unused)), -+ char *errbuf, size_t errbuf_size) -+{ -+ const char *msg; -+ size_t msg_size; -+ -+ if (errcode < 0 -+ || errcode >= (int) (sizeof (re_error_msgid) -+ / sizeof (re_error_msgid[0]))) -+ /* Only error codes returned by the rest of the code should be passed -+ to this routine. If we are given anything else, or if other regex -+ code generates an invalid error code, then the program has a bug. -+ Dump core so we can fix it. */ -+ abort (); -+ -+ msg = gettext (re_error_msgid[errcode]); -+ -+ msg_size = strlen (msg) + 1; /* Includes the null. */ -+ -+ if (errbuf_size != 0) -+ { -+ if (msg_size > errbuf_size) -+ { -+#if defined HAVE_MEMPCPY || defined _LIBC -+ *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; -+#else -+ memcpy (errbuf, msg, errbuf_size - 1); -+ errbuf[errbuf_size - 1] = 0; -+#endif -+ } -+ else -+ memcpy (errbuf, msg, msg_size); -+ } -+ -+ return msg_size; -+} -+#ifdef _LIBC -+weak_alias (__regerror, regerror) -+#endif -+ -+ -+/* Free dynamically allocated space used by PREG. */ -+ -+void -+regfree (regex_t *preg) -+{ -+ if (preg->buffer != NULL) -+ free (preg->buffer); -+ preg->buffer = NULL; -+ -+ preg->allocated = 0; -+ preg->used = 0; -+ -+ if (preg->fastmap != NULL) -+ free (preg->fastmap); -+ preg->fastmap = NULL; -+ preg->fastmap_accurate = 0; -+ -+ if (preg->translate != NULL) -+ free (preg->translate); -+ preg->translate = NULL; -+} -+#ifdef _LIBC -+weak_alias (__regfree, regfree) -+#endif -+ -+#endif /* not emacs */ -+ -+#endif /* not INSIDE_RECURSION */ -+ -+ -+#undef STORE_NUMBER -+#undef STORE_NUMBER_AND_INCR -+#undef EXTRACT_NUMBER -+#undef EXTRACT_NUMBER_AND_INCR -+ -+#undef DEBUG_PRINT_COMPILED_PATTERN -+#undef DEBUG_PRINT_DOUBLE_STRING -+ -+#undef INIT_FAIL_STACK -+#undef RESET_FAIL_STACK -+#undef DOUBLE_FAIL_STACK -+#undef PUSH_PATTERN_OP -+#undef PUSH_FAILURE_POINTER -+#undef PUSH_FAILURE_INT -+#undef PUSH_FAILURE_ELT -+#undef POP_FAILURE_POINTER -+#undef POP_FAILURE_INT -+#undef POP_FAILURE_ELT -+#undef DEBUG_PUSH -+#undef DEBUG_POP -+#undef PUSH_FAILURE_POINT -+#undef POP_FAILURE_POINT -+ -+#undef REG_UNSET_VALUE -+#undef REG_UNSET -+ -+#undef PATFETCH -+#undef PATFETCH_RAW -+#undef PATUNFETCH -+#undef TRANSLATE -+ -+#undef INIT_BUF_SIZE -+#undef GET_BUFFER_SPACE -+#undef BUF_PUSH -+#undef BUF_PUSH_2 -+#undef BUF_PUSH_3 -+#undef STORE_JUMP -+#undef STORE_JUMP2 -+#undef INSERT_JUMP -+#undef INSERT_JUMP2 -+#undef EXTEND_BUFFER -+#undef GET_UNSIGNED_NUMBER -+#undef FREE_STACK_RETURN -+ -+# undef POINTER_TO_OFFSET -+# undef MATCHING_IN_FRST_STRING -+# undef PREFETCH -+# undef AT_STRINGS_BEG -+# undef AT_STRINGS_END -+# undef WORDCHAR_P -+# undef FREE_VAR -+# undef FREE_VARIABLES -+# undef NO_HIGHEST_ACTIVE_REG -+# undef NO_LOWEST_ACTIVE_REG -+ -+# undef CHAR_T -+# undef UCHAR_T -+# undef COMPILED_BUFFER_VAR -+# undef OFFSET_ADDRESS_SIZE -+# undef CHAR_CLASS_SIZE -+# undef PREFIX -+# undef ARG_PREFIX -+# undef PUT_CHAR -+# undef BYTE -+# undef WCHAR -+ -+# define DEFINED_ONCE -Index: git/pwd/Makefile -=================================================================== ---- git.orig/pwd/Makefile -+++ git/pwd/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for pwd portion of the library. - # -+include ../option-groups.mak -+ - subdir := pwd - - include ../Makeconfig -Index: git/resolv/Makefile -=================================================================== ---- git.orig/resolv/Makefile -+++ git/resolv/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for resolv portion of the library. - # -+include ../option-groups.mak -+ - subdir := resolv - - include ../Makeconfig -@@ -27,20 +29,21 @@ headers := resolv.h \ - arpa/nameser.h arpa/nameser_compat.h \ - sys/bitypes.h - --routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ -- res_hconf res_libc res-state -+routines-$(OPTION_EGLIBC_INET) \ -+ += herror inet_addr inet_ntop inet_pton nsap_addr res_init \ -+ res_hconf res_libc res-state - --tests = tst-aton tst-leaks tst-inet_ntop --xtests = tst-leaks2 -+tests-$(OPTION_EGLIBC_INET) += tst-aton tst-leaks tst-inet_ntop -+xtests-$(OPTION_EGLIBC_INET) += tst-leaks2 - - generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace - --extra-libs := libresolv libnss_dns -+extra-libs-$(OPTION_EGLIBC_INET) += libresolv libnss_dns - ifeq ($(have-thread-library),yes) --extra-libs += libanl --routines += gai_sigqueue -+extra-libs-$(OPTION_EGLIBC_INET_ANL) += libanl -+routines-$(OPTION_EGLIBC_INET) += gai_sigqueue - endif --extra-libs-others = $(extra-libs) -+extra-libs-others-y += $(extra-libs-y) - libresolv-routines := gethnamaddr res_comp res_debug \ - res_data res_mkquery res_query res_send \ - inet_net_ntop inet_net_pton inet_neta base64 \ -@@ -60,7 +63,7 @@ routines += $(libnss_dns- - static-only-routines += $(libnss_dns-routines) $(libresolv-routines) - endif - --ifeq (yesyes,$(build-shared)$(have-thread-library)) -+ifeq (yesyesy,$(build-shared)$(have-thread-library)$(OPTION_EGLIBC_INET_ANL)) - tests: $(objpfx)ga_test - endif - -Index: git/stdio-common/fxprintf.c -=================================================================== ---- git.orig/stdio-common/fxprintf.c -+++ git/stdio-common/fxprintf.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - - int -@@ -37,6 +38,7 @@ __fxprintf (FILE *fp, const char *fmt, . - int res; - if (_IO_fwide (fp, 0) > 0) - { -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - size_t len = strlen (fmt) + 1; - wchar_t wfmt[len]; - for (size_t i = 0; i < len; ++i) -@@ -45,6 +47,9 @@ __fxprintf (FILE *fp, const char *fmt, . - wfmt[i] = fmt[i]; - } - res = __vfwprintf (fp, wfmt, ap); -+#else -+ abort(); -+#endif - } - else - res = _IO_vfprintf (fp, fmt, ap); -Index: git/stdio-common/_i18n_number.h -=================================================================== ---- git.orig/stdio-common/_i18n_number.h -+++ git/stdio-common/_i18n_number.h -@@ -19,10 +19,13 @@ - #include - #include - #include -+#include - - #include "../locale/outdigits.h" - #include "../locale/outdigitswc.h" - -+#if __OPTION_EGLIBC_LOCALE_CODE -+ - static CHAR_T * - _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) - { -@@ -115,3 +118,13 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T - - return w; - } -+ -+#else -+ -+static CHAR_T * -+_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) -+{ -+ return w; -+} -+ -+#endif -Index: git/stdio-common/Makefile -=================================================================== ---- git.orig/stdio-common/Makefile -+++ git/stdio-common/Makefile -@@ -18,6 +18,8 @@ - # - # Specific makefile for stdio-common. - # -+include ../option-groups.mak -+ - subdir := stdio-common - - include ../Makeconfig -@@ -30,7 +32,7 @@ routines := \ - vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \ - reg-modifier reg-type \ - printf_size fprintf printf snprintf sprintf asprintf dprintf \ -- vfwprintf vfscanf vfwscanf \ -+ vfscanf \ - fscanf scanf sscanf \ - perror psignal \ - tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ -@@ -41,23 +43,36 @@ routines := \ - isoc99_vsscanf \ - psiginfo - --aux := errlist siglist printf-parsemb printf-parsewc fxprintf -+# Ideally, _itowa and itowa-digits would be in this option group as -+# well, but it is used unconditionally by printf_fp and printf_fphex, -+# and it didn't seem straightforward to disentangle it. -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += vfwprintf vfwscanf -+ -+aux := errlist siglist printf-parsemb fxprintf -+aux-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += printf-parsewc - - tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ - temptest tst-fileno test-fwrite tst-ungetc tst-ferror \ - xbug errnobug \ - bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \ -- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \ -+ tfformat tiformat tllformat tstdiomisc tst-printfsz \ - scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \ -- scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ -- tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ -- tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \ -+ scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf \ -+ tst-fseek tst-fmemopen tst-gets \ -+ tst-sprintf tst-rndseek tst-fdopen tst-fphex \ - tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ -- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \ -- bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ -- scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ -- bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ -+ tst-fwrite bug16 bug17 tst-sprintf2 bug18 \ -+ bug19 tst-popen2 scanf14 scanf15 bug21 bug22 \ -+ scanf16 scanf17 tst-setvbuf1 bug23 bug24 \ -+ bug-vfprintf-nargs tst-sprintf3 \ - bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-sscanf tst-swprintf test-vfprintf bug14 scanf13 tst-grouping -+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ -+ += tst-perror bug19a bug20 tst-long-dbl-fphex tst-fphex-wide -+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += bug18a tst-swscanf tst-wc-printf - - test-srcs = tst-unbputc tst-printf - -Index: git/stdio-common/printf_fp.c -=================================================================== ---- git.orig/stdio-common/printf_fp.c -+++ git/stdio-common/printf_fp.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -142,6 +143,10 @@ extern mp_size_t __mpn_extract_long_doub - extern unsigned int __guess_grouping (unsigned int intdig_max, - const char *grouping); - -+/* Ideally, when OPTION_EGLIBC_LOCALE_CODE is disabled, this should do -+ all its work in ordinary characters, rather than doing it in wide -+ characters and then converting at the end. But that is a challenge -+ for another day. */ - - static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, - unsigned int intdig_no, const char *grouping, -@@ -251,7 +256,14 @@ ___printf_fp (FILE *fp, - mp_limb_t cy; - - /* Nonzero if this is output on a wide character stream. */ -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - int wide = info->wide; -+#else -+ /* This should never be called on a wide-oriented stream when -+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't -+ be trusted to figure that out. */ -+ const int wide = 0; -+#endif - - /* Buffer in which we produce the output. */ - wchar_t *wbuffer = NULL; -@@ -261,6 +273,7 @@ ___printf_fp (FILE *fp, - p.expsign = 0; - - /* Figure out the decimal point character. */ -+#if __OPTION_EGLIBC_LOCALE_CODE - if (info->extra == 0) - { - decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); -@@ -280,7 +293,13 @@ ___printf_fp (FILE *fp, - /* The decimal point character must not be zero. */ - assert (*decimal != '\0'); - assert (decimalwc != L'\0'); -+#else -+ /* Hard-code values from 'C' locale. */ -+ decimal = "."; -+ decimalwc = L'.'; -+#endif - -+#if __OPTION_EGLIBC_LOCALE_CODE - if (info->group) - { - if (info->extra == 0) -@@ -324,6 +343,9 @@ ___printf_fp (FILE *fp, - } - else - grouping = NULL; -+#else -+ grouping = NULL; -+#endif - - /* Fetch the argument value. */ - #ifndef __NO_LONG_DOUBLE_MATH -Index: git/stdio-common/printf_fphex.c -=================================================================== ---- git.orig/stdio-common/printf_fphex.c -+++ git/stdio-common/printf_fphex.c -@@ -28,6 +28,7 @@ - #include <_itoa.h> - #include <_itowa.h> - #include -+#include - #include - #include - -@@ -139,10 +140,18 @@ __printf_fphex (FILE *fp, - int done = 0; - - /* Nonzero if this is output on a wide character stream. */ -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - int wide = info->wide; -+#else -+ /* This should never be called on a wide-oriented stream when -+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't -+ be trusted to figure that out. */ -+ const int wide = 0; -+#endif - - - /* Figure out the decimal point character. */ -+#if __OPTION_EGLIBC_LOCALE_CODE - if (info->extra == 0) - { - decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); -@@ -156,6 +165,10 @@ __printf_fphex (FILE *fp, - } - /* The decimal point character must never be zero. */ - assert (*decimal != '\0' && decimalwc != L'\0'); -+#else -+ decimal = "."; -+ decimalwc = L'.'; -+#endif - - - /* Fetch the argument value. */ -Index: git/stdio-common/printf_size.c -=================================================================== ---- git.orig/stdio-common/printf_size.c -+++ git/stdio-common/printf_size.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - - /* This defines make it possible to use the same code for GNU C library and -@@ -116,7 +117,14 @@ __printf_size (FILE *fp, const struct pr - - struct printf_info fp_info; - int done = 0; -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - int wide = info->wide; -+#else -+ /* This should never be called on a wide-oriented stream when -+ OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't -+ be trusted to figure that out. */ -+ const int wide = 0; -+#endif - int res; - - /* Fetch the argument value. */ -Index: git/stdio-common/scanf14.c -=================================================================== ---- git.orig/stdio-common/scanf14.c -+++ git/stdio-common/scanf14.c -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - - #define FAIL() \ - do { \ -@@ -48,6 +49,7 @@ main (void) - /* See explanation above. */ - DIAG_PUSH_NEEDS_COMMENT; - DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat"); -+#if __OPTION_EGLIBC_LOCALE_CODE - if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2) - FAIL (); - else -@@ -57,6 +59,7 @@ main (void) - memset (lsp, 'x', sizeof L"3.25"); - free (lsp); - } -+#endif - if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2) - FAIL (); - else -Index: git/stdio-common/tstdiomisc.c -=================================================================== ---- git.orig/stdio-common/tstdiomisc.c -+++ git/stdio-common/tstdiomisc.c -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - static int - t1 (void) -@@ -134,6 +135,7 @@ F (void) - printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", - buf); - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", - qnanval, qnanval, qnanval, qnanval, - qnanval, qnanval, qnanval, qnanval); -@@ -171,6 +173,7 @@ F (void) - result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; - printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", - wbuf); -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - - lqnanval = NAN; - -@@ -215,6 +218,7 @@ F (void) - printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", - buf); - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), - L"%La %LA %Le %LE %Lf %LF %Lg %LG", - lqnanval, lqnanval, lqnanval, lqnanval, -@@ -259,6 +263,7 @@ F (void) - result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; - printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", - wbuf); -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - - return result; - } -Index: git/stdio-common/tst-popen.c -=================================================================== ---- git.orig/stdio-common/tst-popen.c -+++ git/stdio-common/tst-popen.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - static int - do_test (void) -@@ -34,12 +35,14 @@ do_test (void) - return 1; - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - /* POSIX says that pipe streams are byte-oriented. */ - if (fwide (f, 0) >= 0) - { - puts ("popen did not return byte-oriented stream"); - result = 1; - } -+#endif - - if (getline (&line, &len, f) != 5) - { -Index: git/stdio-common/tst-sprintf.c -=================================================================== ---- git.orig/stdio-common/tst-sprintf.c -+++ git/stdio-common/tst-sprintf.c -@@ -3,7 +3,7 @@ - #include - #include - #include -- -+#include - - static int - do_test (void) -@@ -11,12 +11,14 @@ do_test (void) - char buf[100]; - int result = 0; - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR - if (sprintf (buf, "%.0ls", L"foo") != 0 - || strlen (buf) != 0) - { - puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output"); - result = 1; - } -+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ - - #define SIZE (1024*70000) - #define STR(x) #x -Index: git/stdio-common/vfprintf.c -=================================================================== ---- git.orig/stdio-common/vfprintf.c -+++ git/stdio-common/vfprintf.c -@@ -29,6 +29,7 @@ - #include <_itoa.h> - #include - #include -+#include - - /* This code is shared between the standard stdio implementation found - in GNU C library and the libio implementation originally found in -@@ -138,6 +139,18 @@ - # define EOF WEOF - #endif - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR -+# define MULTIBYTE_SUPPORT (1) -+#else -+# define MULTIBYTE_SUPPORT (0) -+#endif -+ -+#if __OPTION_EGLIBC_LOCALE_CODE -+# define LOCALE_SUPPORT (1) -+#else -+# define LOCALE_SUPPORT (0) -+#endif -+ - #include "_i18n_number.h" - - /* Include the shared code for parsing the format string. */ -@@ -1129,8 +1142,11 @@ vfprintf (FILE *s, const CHAR_T *format, - # define process_string_arg(fspec) \ - LABEL (form_character): \ - /* Character. */ \ -- if (is_long) \ -- goto LABEL (form_wcharacter); \ -+ if (is_long) \ -+ { \ -+ assert (MULTIBYTE_SUPPORT); \ -+ goto LABEL (form_wcharacter); \ -+ } \ - --width; /* Account for the character itself. */ \ - if (!left) \ - PAD (' '); \ -@@ -1143,6 +1159,7 @@ vfprintf (FILE *s, const CHAR_T *format, - break; \ - \ - LABEL (form_wcharacter): \ -+ assert (MULTIBYTE_SUPPORT); \ - { \ - /* Wide character. */ \ - char buf[MB_CUR_MAX]; \ -@@ -1209,6 +1226,7 @@ vfprintf (FILE *s, const CHAR_T *format, - } \ - else \ - { \ -+ assert (MULTIBYTE_SUPPORT); \ - const wchar_t *s2 = (const wchar_t *) string; \ - mbstate_t mbstate; \ - \ -@@ -1409,7 +1427,9 @@ vfprintf (FILE *s, const CHAR_T *format, - LABEL (flag_quote): - group = 1; - -- if (grouping == (const char *) -1) -+ if (! LOCALE_SUPPORT) -+ grouping = NULL; -+ else if (grouping == (const char *) -1) - { - #ifdef COMPILE_WPRINTF - thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, -@@ -1708,7 +1728,9 @@ do_positional: - free (workstart); - workstart = NULL; - -- if (grouping == (const char *) -1) -+ if (! LOCALE_SUPPORT) -+ grouping = NULL; -+ else if (grouping == (const char *) -1) - { - #ifdef COMPILE_WPRINTF - thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, -Index: git/stdio-common/vfscanf.c -=================================================================== ---- git.orig/stdio-common/vfscanf.c -+++ git/stdio-common/vfscanf.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - - #ifdef __GNUC__ - # define HAVE_LONGLONG -@@ -133,6 +134,12 @@ - # define WINT_T int - #endif - -+#if __OPTION_POSIX_C_LANG_WIDE_CHAR -+# define MULTIBYTE_SUPPORT (1) -+#else -+# define MULTIBYTE_SUPPORT (0) -+#endif -+ - #define encode_error() do { \ - errval = 4; \ - __set_errno (EILSEQ); \ -@@ -316,24 +323,35 @@ _IO_vfscanf_internal (_IO_FILE *s, const - ARGCHECK (s, format); - - { --#ifndef COMPILE_WSCANF -+#if __OPTION_EGLIBC_LOCALE_CODE && !defined (COMPILE_WSCANF) - struct __locale_data *const curnumeric = loc->__locales[LC_NUMERIC]; - #endif - -+#if __OPTION_EGLIBC_LOCALE_CODE - /* Figure out the decimal point character. */ --#ifdef COMPILE_WSCANF -+# ifdef COMPILE_WSCANF - decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); --#else -+# else - decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string; --#endif -+# endif - /* Figure out the thousands separator character. */ --#ifdef COMPILE_WSCANF -+# ifdef COMPILE_WSCANF - thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); --#else -+# else - thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string; - if (*thousands == '\0') - thousands = NULL; --#endif -+# endif -+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */ -+ /* Hard-code values from the C locale. */ -+# ifdef COMPILE_WSCANF -+ decimal = L'.'; -+ thousands = L'\0'; -+# else -+ decimal = "."; -+ thousands = NULL; -+# endif -+#endif /* __OPTION_EGLIBC_LOCALE_CODE */ - } - - /* Lock the stream. */ -@@ -385,6 +403,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const - #ifndef COMPILE_WSCANF - if (!isascii ((unsigned char) *f)) - { -+ assert (MULTIBYTE_SUPPORT); -+ - /* Non-ASCII, may be a multibyte. */ - int len = __mbrlen (f, strlen (f), &state); - if (len > 0) -@@ -830,6 +850,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const - } - /* FALLTHROUGH */ - case L_('C'): -+ assert (MULTIBYTE_SUPPORT); -+ - if (width == -1) - width = 1; - -@@ -1172,6 +1194,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const - /* FALLTHROUGH */ - - case L_('S'): -+ assert (MULTIBYTE_SUPPORT); -+ - { - #ifndef COMPILE_WSCANF - mbstate_t cstate; -@@ -1419,10 +1443,17 @@ _IO_vfscanf_internal (_IO_FILE *s, const - const char *mbdigits[10]; - const char *mbdigits_extended[10]; - #endif -+#if __OPTION_EGLIBC_LOCALE_CODE - /* "to_inpunct" is a map from ASCII digits to their - equivalent in locale. This is defined for locales - which use an extra digits set. */ - wctrans_t map = __wctrans ("to_inpunct"); -+#else -+ /* This will always be the case when -+ OPTION_EGLIBC_LOCALE_CODE is disabled, but the -+ compiler can't figure that out. */ -+ wctrans_t map = NULL; -+#endif - int n; - - from_level = 0; -@@ -2088,6 +2119,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const - --width; - } - -+#if __OPTION_EGLIBC_LOCALE_CODE - wctrans_t map; - if (__builtin_expect ((flags & I18N) != 0, 0) - /* Hexadecimal floats make no sense, fixing localized -@@ -2304,6 +2336,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const - ; - #endif - } -+#endif /* __OPTION_EGLIBC_LOCALE_CODE */ - - /* Have we read any character? If we try to read a number - in hexadecimal notation and we have read only the `0x' -@@ -2343,7 +2376,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const - - case L_('['): /* Character class. */ - if (flags & LONG) -- STRING_ARG (wstr, wchar_t, 100); -+ { -+ assert (MULTIBYTE_SUPPORT); -+ STRING_ARG (wstr, wchar_t, 100); -+ } - else - STRING_ARG (str, char, 100); - -@@ -2417,6 +2453,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const - if (flags & LONG) - { - size_t now = read_in; -+ assert (MULTIBYTE_SUPPORT); - #ifdef COMPILE_WSCANF - if (__glibc_unlikely (inchar () == WEOF)) - input_error (); -Index: git/stdlib/Makefile -=================================================================== ---- git.orig/stdlib/Makefile -+++ git/stdlib/Makefile -@@ -18,6 +18,8 @@ - # - # Makefile for stdlib routines - # -+include ../option-groups.mak -+ - subdir := stdlib - - include ../Makeconfig -@@ -30,7 +32,7 @@ headers := stdlib.h bits/stdlib.h bits/s - alloca.h fmtmsg.h \ - bits/stdlib-bsearch.h - --routines := \ -+routines-y := \ - atof atoi atol atoll \ - abort \ - bsearch qsort msort \ -@@ -39,7 +41,6 @@ routines := \ - quick_exit at_quick_exit cxa_at_quick_exit cxa_thread_atexit_impl \ - abs labs llabs \ - div ldiv lldiv \ -- mblen mbstowcs mbtowc wcstombs wctomb \ - random random_r rand rand_r \ - drand48 erand48 lrand48 nrand48 mrand48 jrand48 \ - srand48 seed48 lcong48 \ -@@ -52,9 +53,18 @@ routines := \ - strtof_l strtod_l strtold_l \ - system canonicalize \ - a64l l64a \ -- rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \ -- strtoimax strtoumax wcstoimax wcstoumax \ -+ getsubopt xpg_basename \ -+ strtoimax strtoumax \ - getcontext setcontext makecontext swapcontext -+routines-$(OPTION_EGLIBC_LOCALE_CODE) += \ -+ strfmon strfmon_l -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \ -+ mblen mbstowcs mbtowc wcstombs wctomb \ -+ wcstoimax wcstoumax -+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP)) -+routines-y += rpmatch -+endif -+routines-$(OPTION_EGLIBC_FMTMSG) += fmtmsg - aux = grouping groupingwc tens_in_limb - - # These routines will be omitted from the libc shared object. -@@ -62,20 +72,22 @@ aux = grouping groupingwc tens_in_limb - # linked against when the shared library will be used. - static-only-routines = atexit at_quick_exit - --test-srcs := tst-fmtmsg --tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ -+test-srcs-$(OPTION_EGLIBC_FMTMSG) := tst-fmtmsg -+tests := tst-strtol tst-strtod testrand testsort testdiv \ - test-canon test-canon2 tst-strtoll tst-environ \ - tst-xpg-basename tst-random tst-random2 tst-bsearch \ - tst-limits tst-rand48 bug-strtod tst-setcontext \ -- test-a64l tst-qsort tst-system testmb2 bug-strtod2 \ -- tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \ -- tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2 \ -- tst-makecontext2 tst-strtod6 tst-unsetenv1 \ -- tst-makecontext3 bug-getcontext bug-fmtmsg1 \ -+ test-a64l tst-qsort tst-system bug-strtod2 \ -+ tst-atof1 tst-atof2 tst-strtod2 tst-rand48-2 \ -+ tst-makecontext tst-qsort2 tst-makecontext2 tst-strtod6 \ -+ tst-unsetenv1 tst-makecontext3 bug-getcontext bug-fmtmsg1 \ - tst-secure-getenv tst-strtod-overflow tst-strtod-round \ - tst-tininess tst-strtod-underflow tst-tls-atexit - tests-static := tst-secure-getenv -- -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-strtod3 tst-strtod4 tst-strtod5 testmb2 -+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += testmb - modules-names = tst-tls-atexit-lib - - ifeq ($(build-shared),yes) -@@ -115,8 +127,10 @@ CFLAGS-tst-makecontext2.c = $(stack-alig - tests-special += $(objpfx)isomac.out - - ifeq ($(run-built-tests),yes) -+ifeq (y,$(OPTION_EGLIBC_FMTMSG)) - tests-special += $(objpfx)tst-fmtmsg.out - endif -+endif - - include ../Rules - -Index: git/stdlib/strtod_l.c -=================================================================== ---- git.orig/stdlib/strtod_l.c -+++ git/stdlib/strtod_l.c -@@ -17,6 +17,7 @@ - License along with the GNU C Library; if not, see - . */ - -+#include - #include - - extern double ____strtod_l_internal (const char *, char **, int, __locale_t); -@@ -548,6 +549,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group - /* Used in several places. */ - int cnt; - -+#if __OPTION_EGLIBC_LOCALE_CODE - struct __locale_data *current = loc->__locales[LC_NUMERIC]; - - if (__glibc_unlikely (group)) -@@ -586,6 +588,17 @@ ____STRTOF_INTERNAL (nptr, endptr, group - decimal_len = strlen (decimal); - assert (decimal_len > 0); - #endif -+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */ -+ /* Hard-code values from the 'C' locale. */ -+ grouping = NULL; -+#ifdef USE_WIDE_CHAR -+ decimal = L'.'; -+# define decimal_len 1 -+#else -+ decimal = "."; -+ decimal_len = 1; -+#endif -+#endif /* __OPTION_EGLIBC_LOCALE_CODE */ - - /* Prepare number representation. */ - exponent = 0; -Index: git/stdlib/tst-strtod.c -=================================================================== ---- git.orig/stdlib/tst-strtod.c -+++ git/stdlib/tst-strtod.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - struct ltest - { -@@ -176,7 +177,9 @@ main (int argc, char ** argv) - - status |= long_dbl (); - -+#if __OPTION_EGLIBC_LOCALE_CODE - status |= locale_test (); -+#endif - - return status ? EXIT_FAILURE : EXIT_SUCCESS; - } -@@ -219,6 +222,7 @@ long_dbl (void) - return 0; - } - -+#if __OPTION_EGLIBC_LOCALE_CODE - /* Perform a few tests in a locale with thousands separators. */ - static int - locale_test (void) -@@ -276,3 +280,4 @@ locale_test (void) - - return result; - } -+#endif /* __OPTION_EGLIBC_LOCALE_CODE */ -Index: git/streams/Makefile -=================================================================== ---- git.orig/streams/Makefile -+++ git/streams/Makefile -@@ -18,11 +18,14 @@ - # - # Makefile for streams. - # -+include ../option-groups.mak -+ - subdir := streams - - include ../Makeconfig - - headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h --routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach -+routines-$(OPTION_EGLIBC_STREAMS) \ -+ += isastream getmsg getpmsg putmsg putpmsg fattach fdetach - - include ../Rules -Index: git/string/Makefile -=================================================================== ---- git.orig/string/Makefile -+++ git/string/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for string portion of library. - # -+include ../option-groups.mak -+ - subdir := string - - include ../Makeconfig -@@ -39,10 +41,12 @@ routines := strcat strchr strcmp strcoll - $(addprefix argz-,append count create ctsep next \ - delete extract insert stringify \ - addsep replace) \ -- envz basename \ -+ basename \ - strcoll_l strxfrm_l string-inlines memrchr \ - xpg-strerror strerror_l - -+routines-$(OPTION_EGLIBC_ENVZ) += envz -+ - strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ - stpcpy stpncpy strcat strchr strcmp strcpy strcspn \ - strlen strncmp strncpy strpbrk strrchr strspn memmem \ -@@ -51,10 +55,12 @@ strop-tests := memchr memcmp memcpy memm - tests := tester inl-tester noinl-tester testcopy test-ffs \ - tst-strlen stratcliff tst-svc tst-inlcall \ - bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \ -- tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ -+ tst-strtok tst-strfry \ - bug-strtok1 $(addprefix test-,$(strop-tests)) \ -- bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ -- tst-strtok_r -+ tst-strxfrm2 tst-endian tst-svc2 tst-strtok_r -+tests-$(OPTION_EGLIBC_ENVZ) += bug-envz1 -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-strxfrm bug-strcoll1 - - xtests = tst-strcoll-overflow - -Index: git/string/strcoll_l.c -=================================================================== ---- git.orig/string/strcoll_l.c -+++ git/string/strcoll_l.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #ifndef STRING_TYPE - # define STRING_TYPE char -@@ -247,7 +248,11 @@ int - STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) - { - struct __locale_data *current = l->__locales[LC_COLLATE]; -+#if __OPTION_EGLIBC_LOCALE_CODE - uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; -+#else -+ const uint_fast32_t nrules = 0; -+#endif - /* We don't assign the following values right away since it might be - unnecessary in case there are no rules. */ - const unsigned char *rulesets; -Index: git/string/strerror_l.c -=================================================================== ---- git.orig/string/strerror_l.c -+++ git/string/strerror_l.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - - static __thread char *last_value; -@@ -29,10 +30,14 @@ static __thread char *last_value; - static const char * - translate (const char *str, locale_t loc) - { -+#if __OPTION_EGLIBC_LOCALE_CODE - locale_t oldloc = __uselocale (loc); - const char *res = _(str); - __uselocale (oldloc); - return res; -+#else -+ return str; -+#endif - } - - -Index: git/string/strxfrm_l.c -=================================================================== ---- git.orig/string/strxfrm_l.c -+++ git/string/strxfrm_l.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #ifndef STRING_TYPE - # define STRING_TYPE char -@@ -670,7 +671,11 @@ STRXFRM (STRING_TYPE *dest, const STRING - { - locale_data_t l_data; - struct __locale_data *current = l->__locales[LC_COLLATE]; -+#if __OPTION_EGLIBC_LOCALE_CODE - l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; -+#else -+ l_data.nrules = 0; -+#endif - - /* Handle byte comparison case. */ - if (l_data.nrules == 0) -Index: git/string/test-strcmp.c -=================================================================== ---- git.orig/string/test-strcmp.c -+++ git/string/test-strcmp.c -@@ -329,34 +329,6 @@ check (void) - FOR_EACH_IMPL (impl, 0) - check_result (impl, s1 + i1, s2 + i2, exp_result); - } -- -- /* Test cases where there are multiple zero bytes after the first. */ -- -- for (size_t i = 0; i < 16 + 1; i++) -- { -- s1[i] = 0x00; -- s2[i] = 0x00; -- } -- -- for (size_t i = 0; i < 16; i++) -- { -- int exp_result; -- -- for (int val = 0x01; val < 0x100; val++) -- { -- for (size_t j = 0; j < i; j++) -- { -- s1[j] = val; -- s2[j] = val; -- } -- -- s2[i] = val; -- -- exp_result = SIMPLE_STRCMP (s1, s2); -- FOR_EACH_IMPL (impl, 0) -- check_result (impl, s1, s2, exp_result); -- } -- } - } - - -Index: git/string/tst-strxfrm2.c -=================================================================== ---- git.orig/string/tst-strxfrm2.c -+++ git/string/tst-strxfrm2.c -@@ -1,6 +1,7 @@ - #include - #include - #include -+#include - - static int - do_test (void) -@@ -38,6 +39,7 @@ do_test (void) - res = 1; - } - -+#if __OPTION_EGLIBC_LOCALE_CODE - if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) - { - puts ("setlocale failed"); -@@ -75,6 +77,7 @@ do_test (void) - res = 1; - } - } -+#endif - - return res; - } -Index: git/string/tst-strxfrm.c -=================================================================== ---- git.orig/string/tst-strxfrm.c -+++ git/string/tst-strxfrm.c -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - - - char const string[] = ""; -@@ -64,8 +65,10 @@ do_test (void) - int result = 0; - - result |= test ("C"); -+#if __OPTION_EGLIBC_LOCALE_CODE - result |= test ("en_US.ISO-8859-1"); - result |= test ("de_DE.UTF-8"); -+#endif - - return result; - } -Index: git/sunrpc/Makefile -=================================================================== ---- git.orig/sunrpc/Makefile -+++ git/sunrpc/Makefile -@@ -18,6 +18,8 @@ - # - # Sub-makefile for sunrpc portion of the library. - # -+include ../option-groups.mak -+ - subdir := sunrpc - - include ../Makeconfig -@@ -55,7 +57,6 @@ headers-in-tirpc = $(addprefix rpc/,auth - headers-not-in-tirpc = $(addprefix rpc/,key_prot.h rpc_des.h) \ - $(rpcsvc:%=rpcsvc/%) rpcsvc/bootparam.h - headers = rpc/netdb.h --install-others = $(inst_sysconfdir)/rpc - generated += $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \ - $(rpcsvc:%.x=rpcsvc/%.stmp) rpcgen - generated-dirs += rpcsvc -@@ -65,18 +66,28 @@ headers += $(headers-in-tirpc) $(headers - endif - - ifeq ($(build-shared),yes) --need-export-routines := auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ -+need-export-routines-$(OPTION_EGLIBC_SUNRPC) += \ -+ auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ - clnt_udp get_myaddr key_call netname pm_getport \ -- rpc_thread svc svc_tcp svc_udp xcrypt xdr_array xdr \ -+ rpc_thread svc svc_tcp svc_udp xdr_array xdr \ - xdr_intXX_t xdr_mem xdr_ref xdr_sizeof xdr_stdio \ - svc_run - --routines := auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ -+need-export-routines-y += xcrypt -+ -+need-export-routines := $(need-export-routines-y) -+ -+routines-$(OPTION_EGLIBC_SUNRPC) \ -+ += auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ - rpc_dtable getrpcport pmap_clnt pm_getmaps pmap_prot pmap_prot2 \ - pmap_rmt rpc_prot rpc_common rpc_cmsg svc_auth svc_authux svc_raw \ - svc_simple xdr_float xdr_rec publickey authdes_prot \ -- des_crypt des_impl des_soft key_prot openchild rtime svcauth_des \ -- clnt_unix svc_unix create_xid $(need-export-routines) -+ key_prot openchild rtime svcauth_des \ -+ clnt_unix svc_unix create_xid -+ -+# xdecrypt is also used by nss/nss_files/files-key.c. -+routines-y += des_crypt des_impl des_soft $(need-export-routines) -+ - ifneq ($(link-obsolete-rpc),yes) - # We only add the RPC for compatibility to libc.so. - shared-only-routines = $(routines) -@@ -85,25 +96,28 @@ endif - - # We do not build rpcinfo anymore. It is not needed for a bootstrap - # and not wanted on complete systems. --# others := rpcinfo --# install-sbin := rpcinfo --install-bin := rpcgen -+# others-$(OPTION_EGLIBC_SUNRPC) += rpcinfo -+# install-sbin-$(OPTION_EGLIBC_SUNRPC) += rpcinfo -+install-bin-$(OPTION_EGLIBC_SUNRPC) += rpcgen - rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ - rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \ - rpc_tblout.o rpc_sample.o --extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) --others += rpcgen -+extra-objs-$(OPTION_EGLIBC_SUNRPC) = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) -+others-$(OPTION_EGLIBC_SUNRPC) += rpcgen -+ -+install-others-$(OPTION_EGLIBC_SUNRPC) += $(inst_sysconfdir)/rpc - --tests = tst-xdrmem tst-xdrmem2 --xtests := tst-getmyaddr -+tests-$(OPTION_EGLIBC_SUNRPC) = tst-xdrmem tst-xdrmem2 -+xtests-$(OPTION_EGLIBC_SUNRPC) := tst-getmyaddr - - ifeq ($(have-thread-library),yes) --xtests += thrsvc -+xtests-$(OPTION_EGLIBC_SUNRPC) += thrsvc - endif - - headers += $(rpcsvc:%.x=rpcsvc/%.h) --extra-libs := librpcsvc --extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass. -+extra-libs-$(OPTION_EGLIBC_SUNRPC) += librpcsvc -+# Make it in `others' pass, not `lib' pass. -+extra-libs-others-y += $(extra-libs-y) - librpcsvc-routines = $(rpcsvc:%.x=x%) - librpcsvc-inhibit-o = .os # Build no shared rpcsvc library. - omit-deps = $(librpcsvc-routines) -Index: git/sysdeps/generic/ldsodefs.h -=================================================================== ---- git.orig/sysdeps/generic/ldsodefs.h -+++ git/sysdeps/generic/ldsodefs.h -@@ -425,6 +425,12 @@ extern struct rtld_global _rtld_global _ - # undef __rtld_global_attribute__ - #endif - -+#if __OPTION_EGLIBC_RTLD_DEBUG -+# define GLRO_dl_debug_mask GLRO(dl_debug_mask) -+#else -+# define GLRO_dl_debug_mask 0 -+#endif -+ - #ifndef SHARED - # define GLRO(name) _##name - #else -@@ -437,8 +443,10 @@ struct rtld_global_ro - { - #endif - -+#if __OPTION_EGLIBC_RTLD_DEBUG - /* If nonzero the appropriate debug information is printed. */ - EXTERN int _dl_debug_mask; -+#endif - #define DL_DEBUG_LIBS (1 << 0) - #define DL_DEBUG_IMPCALLS (1 << 1) - #define DL_DEBUG_BINDINGS (1 << 2) -Index: git/sysdeps/gnu/Makefile -=================================================================== ---- git.orig/sysdeps/gnu/Makefile -+++ git/sysdeps/gnu/Makefile -@@ -59,7 +59,8 @@ $(foreach o,$(object-suffixes) $(object- - endif - - ifeq ($(subdir),login) --sysdep_routines += setutxent getutxent endutxent getutxid getutxline \ -+sysdep_routines-$(OPTION_EGLIBC_UTMPX) \ -+ += setutxent getutxent endutxent getutxid getutxline \ - pututxline utmpxname updwtmpx getutmpx getutmp - - sysdep_headers += utmpx.h bits/utmpx.h -Index: git/sysdeps/ieee754/ldbl-opt/Makefile -=================================================================== ---- git.orig/sysdeps/ieee754/ldbl-opt/Makefile -+++ git/sysdeps/ieee754/ldbl-opt/Makefile -@@ -11,19 +11,18 @@ libm-routines += s_nexttowardfd - routines += math_ldbl_opt nldbl-compat - - extra-libs += libnldbl --libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \ -+libnldbl-calls = asprintf dprintf fprintf fscanf iovfscanf \ - obstack_printf obstack_vprintf printf scanf snprintf \ -- sprintf sscanf swprintf swscanf vasprintf vdprintf vfprintf \ -- vfscanf vfwprintf vfwscanf vprintf vscanf vsnprintf \ -- vsprintf vsscanf vswprintf vswscanf vwprintf vwscanf \ -- wprintf wscanf printf_fp printf_size \ -- fprintf_chk fwprintf_chk printf_chk snprintf_chk sprintf_chk \ -- swprintf_chk vfprintf_chk vfwprintf_chk vprintf_chk \ -- vsnprintf_chk vsprintf_chk vswprintf_chk vwprintf_chk \ -- wprintf_chk asprintf_chk vasprintf_chk dprintf_chk \ -+ sprintf sscanf vasprintf vdprintf vfprintf \ -+ vfscanf vprintf vscanf vsnprintf \ -+ vsprintf vsscanf \ -+ printf_fp printf_size \ -+ fprintf_chk printf_chk snprintf_chk sprintf_chk \ -+ vfprintf_chk vprintf_chk \ -+ vsnprintf_chk vsprintf_chk \ -+ asprintf_chk vasprintf_chk dprintf_chk \ - vdprintf_chk obstack_printf_chk obstack_vprintf_chk \ - syslog syslog_chk vsyslog vsyslog_chk \ -- strfmon strfmon_l \ - strtold strtold_l strtoldint wcstold wcstold_l wcstoldint \ - qecvt qfcvt qgcvt qecvt_r qfcvt_r \ - isinf isnan finite signbit scalb log2 lgamma_r ceil \ -@@ -38,9 +37,15 @@ libnldbl-calls = asprintf dprintf fprint - casinh cexp clog cproj csin csinh csqrt ctan ctanh cpow \ - cabs carg cimag creal clog10 \ - isoc99_scanf isoc99_fscanf isoc99_sscanf \ -- isoc99_vscanf isoc99_vfscanf isoc99_vsscanf \ -+ isoc99_vscanf isoc99_vfscanf isoc99_vsscanf -+libnldbl-calls-$(OPTION_EGLIBC_LOCALE_CODE) += strfmon strfmon_l -+libnldbl-calls-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += fwprintf fwscanf \ -+ swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf \ -+ vwprintf vwscanf wprintf wscanf fwprintf_chk swprintf_chk \ -+ vfwprintf_chk vswprintf_chk vwprintf_chk wprintf_chk \ - isoc99_wscanf isoc99_fwscanf isoc99_swscanf \ - isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf -+libnldbl-calls += $(libnldbl-calls-y) - libnldbl-routines = $(libnldbl-calls:%=nldbl-%) - libnldbl-inhibit-o = $(object-suffixes) - libnldbl-static-only-routines = $(libnldbl-routines) -Index: git/sysdeps/ieee754/ldbl-opt/nldbl-compat.c -=================================================================== ---- git.orig/sysdeps/ieee754/ldbl-opt/nldbl-compat.c -+++ git/sysdeps/ieee754/ldbl-opt/nldbl-compat.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include "nldbl-compat.h" - -@@ -33,20 +34,14 @@ libc_hidden_proto (__nldbl_vfprintf) - libc_hidden_proto (__nldbl_vsscanf) - libc_hidden_proto (__nldbl_vsprintf) - libc_hidden_proto (__nldbl_vfscanf) --libc_hidden_proto (__nldbl_vfwscanf) - libc_hidden_proto (__nldbl_vdprintf) --libc_hidden_proto (__nldbl_vswscanf) --libc_hidden_proto (__nldbl_vfwprintf) --libc_hidden_proto (__nldbl_vswprintf) - libc_hidden_proto (__nldbl_vsnprintf) - libc_hidden_proto (__nldbl_vasprintf) - libc_hidden_proto (__nldbl_obstack_vprintf) --libc_hidden_proto (__nldbl___vfwprintf_chk) - libc_hidden_proto (__nldbl___vsnprintf_chk) - libc_hidden_proto (__nldbl___vfprintf_chk) - libc_hidden_proto (__nldbl___vsyslog_chk) - libc_hidden_proto (__nldbl___vsprintf_chk) --libc_hidden_proto (__nldbl___vswprintf_chk) - libc_hidden_proto (__nldbl___vasprintf_chk) - libc_hidden_proto (__nldbl___vdprintf_chk) - libc_hidden_proto (__nldbl___obstack_vprintf_chk) -@@ -54,8 +49,17 @@ libc_hidden_proto (__nldbl___vstrfmon) - libc_hidden_proto (__nldbl___vstrfmon_l) - libc_hidden_proto (__nldbl___isoc99_vsscanf) - libc_hidden_proto (__nldbl___isoc99_vfscanf) -+ -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO -+libc_hidden_proto (__nldbl_vfwscanf) -+libc_hidden_proto (__nldbl_vswscanf) -+libc_hidden_proto (__nldbl_vfwprintf) -+libc_hidden_proto (__nldbl_vswprintf) -+libc_hidden_proto (__nldbl___vfwprintf_chk) -+libc_hidden_proto (__nldbl___vswprintf_chk) - libc_hidden_proto (__nldbl___isoc99_vswscanf) - libc_hidden_proto (__nldbl___isoc99_vfwscanf) -+#endif - - static void - __nldbl_cleanup (void *arg) -@@ -117,6 +121,7 @@ __nldbl_fprintf (FILE *stream, const cha - } - weak_alias (__nldbl_fprintf, __nldbl__IO_fprintf) - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section weak_function - __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...) -@@ -130,6 +135,7 @@ __nldbl_fwprintf (FILE *stream, const wc - - return done; - } -+#endif - - int - attribute_compat_text_section -@@ -226,6 +232,7 @@ __nldbl_snprintf (char *s, size_t maxlen - return done; - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...) -@@ -239,6 +246,7 @@ __nldbl_swprintf (wchar_t *s, size_t n, - - return done; - } -+#endif - - int - attribute_compat_text_section weak_function -@@ -264,6 +272,7 @@ __nldbl_vdprintf (int d, const char *fmt - } - libc_hidden_def (__nldbl_vdprintf) - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section weak_function - __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap) -@@ -275,6 +284,7 @@ __nldbl_vfwprintf (FILE *s, const wchar_ - return res; - } - libc_hidden_def (__nldbl_vfwprintf) -+#endif - - int - attribute_compat_text_section -@@ -297,6 +307,7 @@ __nldbl_vsnprintf (char *string, size_t - libc_hidden_def (__nldbl_vsnprintf) - weak_alias (__nldbl_vsnprintf, __nldbl___vsnprintf) - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section weak_function - __nldbl_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *fmt, -@@ -330,6 +341,7 @@ __nldbl_wprintf (const wchar_t *fmt, ... - - return done; - } -+#endif - - int - attribute_compat_text_section -@@ -419,6 +431,7 @@ __nldbl_scanf (const char *fmt, ...) - return done; - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) -@@ -491,6 +504,7 @@ __nldbl_wscanf (const wchar_t *fmt, ...) - - return done; - } -+#endif - - int - attribute_compat_text_section -@@ -506,6 +520,7 @@ __nldbl___fprintf_chk (FILE *stream, int - return done; - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...) -@@ -519,6 +534,7 @@ __nldbl___fwprintf_chk (FILE *stream, in - - return done; - } -+#endif - - int - attribute_compat_text_section -@@ -563,6 +579,7 @@ __nldbl___sprintf_chk (char *s, int flag - return done; - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen, -@@ -577,6 +594,7 @@ __nldbl___swprintf_chk (wchar_t *s, size - - return done; - } -+#endif - - int - attribute_compat_text_section -@@ -590,6 +608,7 @@ __nldbl___vfprintf_chk (FILE *s, int fla - } - libc_hidden_def (__nldbl___vfprintf_chk) - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap) -@@ -601,6 +620,7 @@ __nldbl___vfwprintf_chk (FILE *s, int fl - return res; - } - libc_hidden_def (__nldbl___vfwprintf_chk) -+#endif - - int - attribute_compat_text_section -@@ -635,6 +655,7 @@ __nldbl___vsprintf_chk (char *string, in - } - libc_hidden_def (__nldbl___vsprintf_chk) - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl___vswprintf_chk (wchar_t *string, size_t maxlen, int flag, size_t slen, -@@ -668,6 +689,7 @@ __nldbl___wprintf_chk (int flag, const w - - return done; - } -+#endif - - int - attribute_compat_text_section -@@ -775,6 +797,7 @@ __nldbl___printf_fp (FILE *fp, const str - return ___printf_fp (fp, &info_no_ldbl, args); - } - -+#if __OPTION_EGLIBC_LOCALE_CODE - ssize_t - attribute_compat_text_section - __nldbl_strfmon (char *s, size_t maxsize, const char *format, ...) -@@ -829,6 +852,7 @@ __nldbl___vstrfmon_l (char *s, size_t ma - return res; - } - libc_hidden_def (__nldbl___vstrfmon_l) -+#endif - - void - attribute_compat_text_section -@@ -941,6 +965,7 @@ __nldbl___isoc99_scanf (const char *fmt, - return done; - } - -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - int - attribute_compat_text_section - __nldbl___isoc99_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) -@@ -1014,6 +1039,7 @@ __nldbl___isoc99_wscanf (const wchar_t * - - return done; - } -+#endif - - #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0) - compat_symbol (libc, __nldbl__IO_printf, _IO_printf, GLIBC_2_0); -@@ -1057,6 +1083,7 @@ compat_symbol (libc, __nldbl_printf_size - compat_symbol (libc, __nldbl___strfmon_l, __strfmon_l, GLIBC_2_1); - #endif - #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_2) -+# if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO - compat_symbol (libc, __nldbl_swprintf, swprintf, GLIBC_2_2); - compat_symbol (libc, __nldbl_vwprintf, vwprintf, GLIBC_2_2); - compat_symbol (libc, __nldbl_wprintf, wprintf, GLIBC_2_2); -@@ -1069,6 +1096,7 @@ compat_symbol (libc, __nldbl_vfwscanf, v - compat_symbol (libc, __nldbl_vswscanf, vswscanf, GLIBC_2_2); - compat_symbol (libc, __nldbl_vwscanf, vwscanf, GLIBC_2_2); - compat_symbol (libc, __nldbl_wscanf, wscanf, GLIBC_2_2); -+# endif - #endif - #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_3) - compat_symbol (libc, __nldbl_strfmon_l, strfmon_l, GLIBC_2_3); -Index: git/sysdeps/ieee754/ldbl-opt/nldbl-compat.h -=================================================================== ---- git.orig/sysdeps/ieee754/ldbl-opt/nldbl-compat.h -+++ git/sysdeps/ieee754/ldbl-opt/nldbl-compat.h -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - - /* Declare the __nldbl_NAME function the wrappers call that's in libc.so. */ -@@ -37,19 +38,15 @@ - - NLDBL_DECL (_IO_vfscanf); - NLDBL_DECL (vfscanf); --NLDBL_DECL (vfwscanf); - NLDBL_DECL (obstack_vprintf); - NLDBL_DECL (vasprintf); - NLDBL_DECL (dprintf); - NLDBL_DECL (vdprintf); - NLDBL_DECL (fprintf); - NLDBL_DECL (vfprintf); --NLDBL_DECL (vfwprintf); - NLDBL_DECL (vsnprintf); - NLDBL_DECL (vsprintf); - NLDBL_DECL (vsscanf); --NLDBL_DECL (vswprintf); --NLDBL_DECL (vswscanf); - NLDBL_DECL (__asprintf); - NLDBL_DECL (asprintf); - NLDBL_DECL (__printf_fp); -@@ -66,12 +63,18 @@ NLDBL_DECL (__isoc99_sscanf); - NLDBL_DECL (__isoc99_vscanf); - NLDBL_DECL (__isoc99_vfscanf); - NLDBL_DECL (__isoc99_vsscanf); -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO -+NLDBL_DECL (vfwscanf); -+NLDBL_DECL (vfwprintf); -+NLDBL_DECL (vswprintf); -+NLDBL_DECL (vswscanf); - NLDBL_DECL (__isoc99_wscanf); - NLDBL_DECL (__isoc99_fwscanf); - NLDBL_DECL (__isoc99_swscanf); - NLDBL_DECL (__isoc99_vwscanf); - NLDBL_DECL (__isoc99_vfwscanf); - NLDBL_DECL (__isoc99_vswscanf); -+#endif - - /* This one does not exist in the normal interface, only - __nldbl___vstrfmon really exists. */ -@@ -82,22 +85,23 @@ extern ssize_t __nldbl___vstrfmon (char - since we don't compile with _FORTIFY_SOURCE. */ - extern int __nldbl___vfprintf_chk (FILE *__restrict, int, - const char *__restrict, _G_va_list); --extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, -- const wchar_t *__restrict, __gnuc_va_list); - extern int __nldbl___vsprintf_chk (char *__restrict, int, size_t, - const char *__restrict, _G_va_list) __THROW; - extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t, - const char *__restrict, _G_va_list) - __THROW; --extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, -- const wchar_t *__restrict, __gnuc_va_list) -- __THROW; - extern int __nldbl___vasprintf_chk (char **, int, const char *, _G_va_list) - __THROW; - extern int __nldbl___vdprintf_chk (int, int, const char *, _G_va_list); - extern int __nldbl___obstack_vprintf_chk (struct obstack *, int, const char *, - _G_va_list) __THROW; - extern void __nldbl___vsyslog_chk (int, int, const char *, va_list); -- -+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO -+extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, -+ const wchar_t *__restrict, __gnuc_va_list); -+extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, -+ const wchar_t *__restrict, __gnuc_va_list) -+ __THROW; -+#endif - - #endif /* __NLDBL_COMPAT_H */ -Index: git/sysdeps/unix/sysv/linux/gethostid.c -=================================================================== ---- git.orig/sysdeps/unix/sysv/linux/gethostid.c -+++ git/sysdeps/unix/sysv/linux/gethostid.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - #define HOSTIDFILE "/etc/hostid" - -@@ -89,6 +90,7 @@ gethostid (void) - return id; - } - -+#if __OPTION_EGLIBC_INET - /* Getting from the file was not successful. An intelligent guess for - a unique number of a host is its IP address. Return this. */ - if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0') -@@ -115,5 +117,9 @@ gethostid (void) - /* For the return value to be not exactly the IP address we do some - bit fiddling. */ - return (int32_t) (in.s_addr << 16 | in.s_addr >> 16); -+#else -+ /* Return an arbitrary value. */ -+ return 0; -+#endif - } - #endif -Index: git/sysdeps/unix/sysv/linux/libc_fatal.c -=================================================================== ---- git.orig/sysdeps/unix/sysv/linux/libc_fatal.c -+++ git/sysdeps/unix/sysv/linux/libc_fatal.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - static bool - writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total) -@@ -40,6 +41,7 @@ writev_for_fatal (int fd, const struct i - static void - backtrace_and_maps (int do_abort, bool written, int fd) - { -+#if __OPTION_EGLIBC_BACKTRACE - if (do_abort > 1 && written) - { - void *addrs[64]; -@@ -62,6 +64,7 @@ backtrace_and_maps (int do_abort, bool w - close_not_cancel_no_status (fd2); - } - } -+#endif /* __OPTION_EGLIBC_BACKTRACE */ - } - #define BEFORE_ABORT backtrace_and_maps - -Index: git/time/Makefile -=================================================================== ---- git.orig/time/Makefile -+++ git/time/Makefile -@@ -18,6 +18,8 @@ - # - # Makefile for time routines - # -+include ../option-groups.mak -+ - subdir := time - - include ../Makeconfig -@@ -30,15 +32,23 @@ routines := offtime asctime clock ctime - tzfile getitimer setitimer \ - stime dysize timegm ftime \ - getdate strptime strptime_l \ -- strftime wcsftime strftime_l wcsftime_l \ -+ strftime strftime_l \ - timespec_get --aux := era alt_digit lc-time-cleanup - --tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ -- tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ := wcsftime wcsftime_l -+aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup -+ -+tests := test_time clocktest tst-posixtz \ -+ tst-getdate tst-mktime tst-mktime2 tst-strftime \ - tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ - tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime - -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-strptime tst-ftime_l -+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ -+ += tst_wcsftime -+ - include ../Rules - - tz-cflags = -DTZDIR='"$(zonedir)"' \ -Index: git/time/strftime_l.c -=================================================================== ---- git.orig/time/strftime_l.c -+++ git/time/strftime_l.c -@@ -35,6 +35,10 @@ - # include "../locale/localeinfo.h" - #endif - -+#ifdef _LIBC -+# include -+#endif -+ - #if defined emacs && !defined HAVE_BCOPY - # define HAVE_MEMCPY 1 - #endif -@@ -882,7 +886,7 @@ __strftime_internal (s, maxsize, format, - case L_('C'): - if (modifier == L_('E')) - { --#if HAVE_STRUCT_ERA_ENTRY -+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY - struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); - if (era) - { -@@ -955,7 +959,7 @@ __strftime_internal (s, maxsize, format, - - if (modifier == L_('O') && 0 <= number_value) - { --#ifdef _NL_CURRENT -+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT) - /* Get the locale specific alternate representation of - the number NUMBER_VALUE. If none exist NULL is returned. */ - const CHAR_T *cp = nl_get_alt_digit (number_value -@@ -1260,7 +1264,7 @@ __strftime_internal (s, maxsize, format, - case L_('Y'): - if (modifier == 'E') - { --#if HAVE_STRUCT_ERA_ENTRY -+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY - struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); - if (era) - { -@@ -1285,7 +1289,7 @@ __strftime_internal (s, maxsize, format, - case L_('y'): - if (modifier == L_('E')) - { --#if HAVE_STRUCT_ERA_ENTRY -+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY - struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); - if (era) - { -Index: git/time/strptime_l.c -=================================================================== ---- git.orig/time/strptime_l.c -+++ git/time/strptime_l.c -@@ -29,6 +29,7 @@ - - #ifdef _LIBC - # define HAVE_LOCALTIME_R 0 -+# include - # include "../locale/localeinfo.h" - #endif - -@@ -84,7 +85,7 @@ localtime_r (t, tp) - if (val < from || val > to) \ - return NULL; \ - } while (0) --#ifdef _NL_CURRENT -+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT) - # define get_alt_number(from, to, n) \ - ({ \ - __label__ do_normal; \ -@@ -257,8 +258,10 @@ __strptime_internal (rp, fmt, tmp, state - int cnt; - int cnt_longest; - size_t val; -+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE - size_t num_eras; - struct era_entry *era = NULL; -+#endif - enum ptime_locale_status { not, loc, raw } decided_longest; - struct __strptime_state - { -@@ -820,6 +823,7 @@ __strptime_internal (rp, fmt, tmp, state - s.want_xday = 1; - break; - case 'C': -+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE - if (s.decided != raw) - { - if (s.era_cnt >= 0) -@@ -856,10 +860,12 @@ __strptime_internal (rp, fmt, tmp, state - - s.decided = raw; - } -+#endif - /* The C locale has no era information, so use the - normal representation. */ - goto match_century; - case 'y': -+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE - if (s.decided != raw) - { - get_number(0, 9999, 4); -@@ -918,9 +924,10 @@ __strptime_internal (rp, fmt, tmp, state - - s.decided = raw; - } -- -+#endif - goto match_year_in_century; - case 'Y': -+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE - if (s.decided != raw) - { - num_eras = _NL_CURRENT_WORD (LC_TIME, -@@ -948,6 +955,7 @@ __strptime_internal (rp, fmt, tmp, state - - s.decided = raw; - } -+#endif - get_number (0, 9999, 4); - tm->tm_year = val - 1900; - s.want_century = 0; -@@ -1118,6 +1126,7 @@ __strptime_internal (rp, fmt, tmp, state - tm->tm_year = (s.century - 19) * 100; - } - -+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE - if (s.era_cnt != -1) - { - era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG); -@@ -1132,6 +1141,7 @@ __strptime_internal (rp, fmt, tmp, state - tm->tm_year = era->start_date[0]; - } - else -+#endif - if (s.want_era) - { - /* No era found but we have seen an E modifier. Rectify some -Index: git/timezone/Makefile -=================================================================== ---- git.orig/timezone/Makefile -+++ git/timezone/Makefile -@@ -117,7 +117,7 @@ $(testdata)/Asia/Tokyo: asia $(zic-deps) - - $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make - sed -e 's|/bin/bash|/bin/sh|' \ -- -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ -+ -e '/TZDIR=/s|\$$(pwd)|$(zonedir)|' \ - -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \ - -e '/PKGVERSION=/s|=.*|="$(PKGVERSION)"|' \ - -e '/REPORT_BUGS_TO=/s|=.*|="$(REPORT_BUGS_TO)"|' \ -Index: git/wcsmbs/Makefile -=================================================================== ---- git.orig/wcsmbs/Makefile -+++ git/wcsmbs/Makefile -@@ -18,15 +18,21 @@ - # - # Sub-makefile for wcsmbs portion of the library. - # -+include ../option-groups.mak -+ - subdir := wcsmbs - - include ../Makeconfig - - headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h - --routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ -+# These functions are used by printf_fp.c, even in the plain case; see -+# comments there for OPTION_EGLIBC_LOCALE_CODE. -+routines := wmemcpy wmemset -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ - wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \ -- wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \ -+ wmemcmp wmemmove wcpcpy wcpncpy wmempcpy \ - btowc wctob mbsinit \ - mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \ - mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \ -@@ -38,14 +44,21 @@ routines := wcscat wcschr wcscmp wcscpy - wcscoll_l wcsxfrm_l \ - wcscasecmp wcsncase wcscasecmp_l wcsncase_l \ - wcsmbsload mbsrtowcs_l \ -- isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \ - isoc99_swscanf isoc99_vswscanf \ - mbrtoc16 c16rtomb - -+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ -+ += isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf -+ - strop-tests := wcscmp wmemcmp wcslen wcschr wcsrchr wcscpy --tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \ -- tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \ -- tst-c16c32-1 wcsatcliff $(addprefix test-,$(strop-tests)) -+ -+tests := tst-wchar-h -+tests-$(OPTION_EGLIBC_LOCALE_CODE) \ -+ += tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb tst-c16c32-1 -+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += tst-wcstof wcsmbs-tst1 tst-wcsnlen \ -+ tst-wcpncpy tst-mbsrtowcs \ -+ wcsatcliff $(addprefix test-,$(strop-tests)) - - include ../Rules - -Index: git/wcsmbs/wcsmbsload.c -=================================================================== ---- git.orig/wcsmbs/wcsmbsload.c -+++ git/wcsmbs/wcsmbsload.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -143,6 +144,7 @@ __wcsmbs_getfct (const char *to, const c - }) - - -+#if __OPTION_EGLIBC_LOCALE_CODE - /* Some of the functions here must not be used while setlocale is called. */ - __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) - -@@ -211,6 +213,17 @@ __wcsmbs_load_conv (struct __locale_data - - __libc_rwlock_unlock (__libc_setlocale_lock); - } -+#else -+void -+internal_function -+__wcsmbs_load_conv (struct __locale_data *new_category) -+{ -+ /* When OPTION_EGLIBC_LOCALE_CODE is disabled, we should never reach -+ this point: there is no way to change locales, so every locale -+ passed to get_gconv_fcts should be _nl_C_LC_CTYPE. */ -+ abort (); -+} -+#endif - - - /* Clone the current conversion function set. */ -Index: git/wctype/Makefile -=================================================================== ---- git.orig/wctype/Makefile -+++ git/wctype/Makefile -@@ -18,14 +18,20 @@ - # - # Sub-makefile for wctype portion of the library. - # -+include ../option-groups.mak -+ - subdir := wctype - - include ../Makeconfig - - headers := wctype.h --routines := wcfuncs wctype iswctype wctrans towctrans \ -- wcfuncs_l wctype_l iswctype_l wctrans_l towctrans_l -+routines := wctrans towctrans towctrans_l -+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ := wcfuncs wctype iswctype \ -+ wcfuncs_l wctype_l iswctype_l wctrans_l - --tests := test_wctype test_wcfuncs bug-wctypeh -+tests := -+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ -+ += test_wctype test_wcfuncs bug-wctypeh - - include ../Rules -Index: git/sysdeps/nptl/Makefile -=================================================================== ---- git.orig/sysdeps/nptl/Makefile -+++ git/sysdeps/nptl/Makefile -@@ -18,6 +18,9 @@ - - ifeq ($(subdir),nptl) - libpthread-sysdep_routines += errno-loc -+ifeq ($(OPTION_EGLIBC_BIG_MACROS),n) -+sysdep_routines += small-macros-fns -+endif - endif - - ifeq ($(subdir),rt) -Index: git/sysdeps/nptl/bits/libc-lock.h -=================================================================== ---- git.orig/sysdeps/nptl/bits/libc-lock.h -+++ git/sysdeps/nptl/bits/libc-lock.h -@@ -24,6 +24,14 @@ - #include - - -+#ifdef _LIBC -+# include -+# include -+# include -+# include /* For EBUSY. */ -+# include /* For __OPTION_EGLIBC_BIG_MACROS. */ -+#endif -+ - /* Mutex type. */ - #if defined _LIBC || defined _IO_MTSAFE_IO - # if (!IS_IN (libc) && !IS_IN (libpthread)) || !defined _LIBC -@@ -87,6 +95,15 @@ typedef struct __libc_lock_recursive_opa - - /* Lock the recursive named lock variable. */ - #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) -+# if __OPTION_EGLIBC_BIG_MACROS != 1 -+/* EGLIBC: Declare wrapper function for a big macro if either -+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from -+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ -+extern void __libc_lock_lock_recursive_fn (__libc_lock_recursive_t *); -+libc_hidden_proto (__libc_lock_lock_recursive_fn); -+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ -+# if __OPTION_EGLIBC_BIG_MACROS -+ - # define __libc_lock_lock_recursive(NAME) \ - do { \ - void *self = THREAD_SELF; \ -@@ -97,6 +114,10 @@ typedef struct __libc_lock_recursive_opa - } \ - ++(NAME).cnt; \ - } while (0) -+# else -+# define __libc_lock_lock_recursive(NAME) \ -+ __libc_lock_lock_recursive_fn (&(NAME)) -+# endif /* __OPTION_EGLIBC_BIG_MACROS */ - #else - # define __libc_lock_lock_recursive(NAME) \ - __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) -@@ -104,6 +125,14 @@ typedef struct __libc_lock_recursive_opa - - /* Try to lock the recursive named lock variable. */ - #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) -+# if __OPTION_EGLIBC_BIG_MACROS != 1 -+/* EGLIBC: Declare wrapper function for a big macro if either -+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from -+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ -+extern int __libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *); -+libc_hidden_proto (__libc_lock_trylock_recursive_fn); -+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ -+# if __OPTION_EGLIBC_BIG_MACROS - # define __libc_lock_trylock_recursive(NAME) \ - ({ \ - int result = 0; \ -@@ -122,6 +151,10 @@ typedef struct __libc_lock_recursive_opa - ++(NAME).cnt; \ - result; \ - }) -+# else -+# define __libc_lock_trylock_recursive(NAME) \ -+ __libc_lock_trylock_recursive_fn (&(NAME)) -+# endif /* __OPTION_EGLIBC_BIG_MACROS */ - #else - # define __libc_lock_trylock_recursive(NAME) \ - __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) -@@ -129,6 +162,14 @@ typedef struct __libc_lock_recursive_opa - - /* Unlock the recursive named lock variable. */ - #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) -+# if __OPTION_EGLIBC_BIG_MACROS != 1 -+/* EGLIBC: Declare wrapper function for a big macro if either -+ !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from -+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ -+extern void __libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *); -+libc_hidden_proto (__libc_lock_unlock_recursive_fn); -+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ -+# if __OPTION_EGLIBC_BIG_MACROS - /* We do no error checking here. */ - # define __libc_lock_unlock_recursive(NAME) \ - do { \ -@@ -138,6 +179,10 @@ typedef struct __libc_lock_recursive_opa - lll_unlock ((NAME).lock, LLL_PRIVATE); \ - } \ - } while (0) -+# else -+# define __libc_lock_unlock_recursive(NAME) \ -+ __libc_lock_unlock_recursive_fn (&(NAME)) -+# endif /* __OPTION_EGLIBC_BIG_MACROS */ - #else - # define __libc_lock_unlock_recursive(NAME) \ - __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) -Index: git/sysdeps/nptl/bits/libc-lockP.h -=================================================================== ---- git.orig/sysdeps/nptl/bits/libc-lockP.h -+++ git/sysdeps/nptl/bits/libc-lockP.h -@@ -33,6 +33,8 @@ - #include - #include - #include -+#include /* For EBUSY. */ -+#include /* For __OPTION_EGLIBC_BIG_MACROS. */ - - #if IS_IN (libpthread) - /* This gets us the declarations of the __pthread_* internal names, -@@ -171,10 +173,22 @@ typedef pthread_key_t __libc_key_t; - - /* Lock the named lock variable. */ - #if IS_IN (libc) || IS_IN (libpthread) --# ifndef __libc_lock_lock --# define __libc_lock_lock(NAME) \ -+# if __OPTION_EGLIBC_BIG_MACROS != 1 -+/* EGLIBC: Declare wrapper function for a big macro if either -+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from -+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ -+extern void __libc_lock_lock_fn (__libc_lock_t *); -+libc_hidden_proto (__libc_lock_lock_fn); -+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ -+# if __OPTION_EGLIBC_BIG_MACROS -+# ifndef __libc_lock_lock -+# define __libc_lock_lock(NAME) \ - ({ lll_lock (NAME, LLL_PRIVATE); 0; }) --# endif -+# endif -+# else -+# define __libc_lock_lock(NAME) \ -+ __libc_lock_lock_fn (&(NAME)) -+# endif /* __OPTION_EGLIBC_BIG_MACROS */ - #else - # undef __libc_lock_lock - # define __libc_lock_lock(NAME) \ -@@ -187,10 +201,22 @@ typedef pthread_key_t __libc_key_t; - - /* Try to lock the named lock variable. */ - #if IS_IN (libc) || IS_IN (libpthread) --# ifndef __libc_lock_trylock --# define __libc_lock_trylock(NAME) \ -+# if __OPTION_EGLIBC_BIG_MACROS != 1 -+/* EGLIBC: Declare wrapper function for a big macro if either -+ !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from -+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ -+extern int __libc_lock_trylock_fn (__libc_lock_t *); -+libc_hidden_proto (__libc_lock_trylock_fn); -+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ -+# if __OPTION_EGLIBC_BIG_MACROS -+# ifndef __libc_lock_trylock -+# define __libc_lock_trylock(NAME) \ - lll_trylock (NAME) --# endif -+# endif -+# else -+# define __libc_lock_trylock(NAME) \ -+ __libc_lock_trylock_fn (&(NAME)) -+# endif /* __OPTION_EGLIBC_BIG_MACROS */ - #else - # undef __libc_lock_trylock - # define __libc_lock_trylock(NAME) \ -@@ -206,8 +232,20 @@ typedef pthread_key_t __libc_key_t; - - /* Unlock the named lock variable. */ - #if IS_IN (libc) || IS_IN (libpthread) -+# if __OPTION_EGLIBC_BIG_MACROS != 1 -+/* EGLIBC: Declare wrapper function for a big macro if either -+ !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from -+ small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ -+extern void __libc_lock_unlock_fn (__libc_lock_t *); -+libc_hidden_proto (__libc_lock_unlock_fn); -+# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ -+# if __OPTION_EGLIBC_BIG_MACROS - # define __libc_lock_unlock(NAME) \ - lll_unlock (NAME, LLL_PRIVATE) -+# else -+# define __libc_lock_unlock(NAME) \ -+ __libc_lock_unlock_fn (&(NAME)) -+# endif /* __OPTION_EGLIBC_BIG_MACROS */ - #else - # define __libc_lock_unlock(NAME) \ - __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) -Index: git/sysdeps/nptl/small-macros-fns.c -=================================================================== ---- /dev/null -+++ git/sysdeps/nptl/small-macros-fns.c -@@ -0,0 +1,72 @@ -+/* EGLIBC: function wrappers for big macros. -+ Copyright (C) 2009 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation; either version 2.1 of the -+ License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; see the file COPYING.LIB. If not, -+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ Boston, MA 02111-1307, USA. */ -+ -+#include -+ -+/* Handle macros from ./bits/libc-lock.h. */ -+#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) -+ -+/* Get the macros for function bodies through a back door. */ -+# undef __OPTION_EGLIBC_BIG_MACROS -+# define __OPTION_EGLIBC_BIG_MACROS 2 -+# include -+ -+void -+__libc_lock_lock_fn (__libc_lock_t *name) -+{ -+ __libc_lock_lock (*name); -+} -+libc_hidden_def (__libc_lock_lock_fn); -+ -+void -+__libc_lock_lock_recursive_fn (__libc_lock_recursive_t *name) -+{ -+ __libc_lock_lock_recursive (*name); -+} -+libc_hidden_def (__libc_lock_lock_recursive_fn); -+ -+int -+__libc_lock_trylock_fn (__libc_lock_t *name) -+{ -+ return __libc_lock_trylock (*name); -+} -+libc_hidden_def (__libc_lock_trylock_fn); -+ -+int -+__libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *name) -+{ -+ return __libc_lock_trylock_recursive (*name); -+} -+libc_hidden_def (__libc_lock_trylock_recursive_fn); -+ -+void -+__libc_lock_unlock_fn (__libc_lock_t *name) -+{ -+ __libc_lock_unlock (*name); -+} -+libc_hidden_def (__libc_lock_unlock_fn); -+ -+void -+__libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *name) -+{ -+ __libc_lock_unlock_recursive (*name); -+} -+libc_hidden_def (__libc_lock_unlock_recursive_fn); -+ -+#endif /*defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)*/ -Index: git/crypt/crypt_common.c -=================================================================== ---- /dev/null -+++ git/crypt/crypt_common.c -@@ -0,0 +1,42 @@ -+/* -+ * crypt: crypt(3) implementation -+ * -+ * Copyright (C) 1991-2014 Free Software Foundation, Inc. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; see the file COPYING.LIB. If not, -+ * see . -+ * -+ * General Support routines -+ * -+ */ -+ -+#include "crypt-private.h" -+ -+/* Table with characters for base64 transformation. */ -+static const char b64t[64] = -+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -+ -+void -+__b64_from_24bit (char **cp, int *buflen, -+ unsigned int b2, unsigned int b1, unsigned int b0, -+ int n) -+{ -+ unsigned int w = (b2 << 16) | (b1 << 8) | b0; -+ while (n-- > 0 && (*buflen) > 0) -+ { -+ *(*cp)++ = b64t[w & 0x3f]; -+ --(*buflen); -+ w >>= 6; -+ } -+} -Index: git/crypt/crypt_util.c -=================================================================== ---- git.orig/crypt/crypt_util.c -+++ git/crypt/crypt_util.c -@@ -242,10 +242,6 @@ static ufc_long eperm32tab[4][256][2]; - */ - static ufc_long efp[16][64][2]; - --/* Table with characters for base64 transformation. */ --static const char b64t[64] = --"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -- - /* - * For use by the old, non-reentrant routines - * (crypt/encrypt/setkey) -@@ -949,17 +945,3 @@ setkey(__key) - { - __setkey_r(__key, &_ufc_foobar); - } -- --void --__b64_from_24bit (char **cp, int *buflen, -- unsigned int b2, unsigned int b1, unsigned int b0, -- int n) --{ -- unsigned int w = (b2 << 16) | (b1 << 8) | b0; -- while (n-- > 0 && (*buflen) > 0) -- { -- *(*cp)++ = b64t[w & 0x3f]; -- --(*buflen); -- w >>= 6; -- } --} -Index: git/sysdeps/arm/Makefile -=================================================================== ---- git.orig/sysdeps/arm/Makefile -+++ git/sysdeps/arm/Makefile -@@ -37,10 +37,13 @@ ifeq ($(subdir),csu) - # get offset to rtld_global._dl_hwcap - gen-as-const-headers += rtld-global-offsets.sym tlsdesc.sym - aeabi_constants = aeabi_lcsts aeabi_sighandlers aeabi_math --aeabi_routines = aeabi_assert aeabi_localeconv aeabi_errno_addr \ -+aeabi_routines = aeabi_assert aeabi_errno_addr \ - aeabi_mb_cur_max aeabi_atexit aeabi_memclr aeabi_memcpy \ - aeabi_memmove aeabi_memset \ - aeabi_read_tp libc-aeabi_read_tp -+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) -+aeabi_routines += aeabi_localeconv -+endif - - sysdep_routines += $(aeabi_constants) $(aeabi_routines) - static-only-routines += $(aeabi_constants) aeabi_read_tp diff --git a/meta/recipes-core/glibc/glibc/eglibc.patch b/meta/recipes-core/glibc/glibc/eglibc.patch deleted file mode 100644 index fdfabc3a06..0000000000 --- a/meta/recipes-core/glibc/glibc/eglibc.patch +++ /dev/null @@ -1,602 +0,0 @@ -Instruction documents from eglibc - -Upstream-Status: Pending - -Index: git/EGLIBC.cross-building -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/EGLIBC.cross-building 2014-08-27 07:27:25.580070587 +0000 -@@ -0,0 +1,383 @@ -+ -*- mode: text -*- -+ -+ Cross-Compiling EGLIBC -+ Jim Blandy -+ -+ -+Introduction -+ -+Most GNU tools have a simple build procedure: you run their -+'configure' script, and then you run 'make'. Unfortunately, the -+process of cross-compiling the GNU C library is quite a bit more -+involved: -+ -+1) Build a cross-compiler, with certain facilities disabled. -+ -+2) Configure the C library using the compiler you built in step 1). -+ Build a few of the C run-time object files, but not the rest of the -+ library. Install the library's header files and the run-time -+ object files, and create a dummy libc.so. -+ -+3) Build a second cross-compiler, using the header files and object -+ files you installed in step 2. -+ -+4) Configure, build, and install a fresh C library, using the compiler -+ built in step 3. -+ -+5) Build a third cross-compiler, based on the C library built in step 4. -+ -+The reason for this complexity is that, although GCC and the GNU C -+library are distributed separately, they are not actually independent -+of each other: GCC requires the C library's headers and some object -+files to compile its own libraries, while the C library depends on -+GCC's libraries. EGLIBC includes features and bug fixes to the stock -+GNU C library that simplify this process, but the fundamental -+interdependency stands. -+ -+In this document, we explain how to cross-compile an EGLIBC/GCC pair -+from source. Our intended audience is developers who are already -+familiar with the GNU toolchain and comfortable working with -+cross-development tools. While we do present a worked example to -+accompany the explanation, for clarity's sake we do not cover many of -+the options available to cross-toolchain users. -+ -+ -+Preparation -+ -+EGLIBC requires recent versions of the GNU binutils, GCC, and the -+Linux kernel. The web page -+documents the current requirements, and lists patches needed for -+certain target architectures. As of this writing, these build -+instructions have been tested with binutils 2.22.51, GCC 4.6.2, -+and Linux 3.1. -+ -+First, let's set some variables, to simplify later commands. We'll -+build EGLIBC and GCC for an ARM target, known to the Linux kernel -+as 'arm', and we'll do the build on an Intel x86_64 Linux box: -+ -+ $ build=x86_64-pc-linux-gnu -+ $ host=$build -+ $ target=arm-none-linux-gnueabi -+ $ linux_arch=arm -+ -+We're using the aforementioned versions of Binutils, GCC, and Linux: -+ -+ $ binutilsv=binutils-2.22.51 -+ $ gccv=gcc-4.6.2 -+ $ linuxv=linux-3.1 -+ -+We're carrying out the entire process under '~/cross-build', which -+contains unpacked source trees for binutils, gcc, and linux kernel, -+along with EGLIBC svn trunk (which can be checked-out with -+'svn co http://www.eglibc.org/svn/trunk eglibc'): -+ -+ $ top=$HOME/cross-build/$target -+ $ src=$HOME/cross-build/src -+ $ ls $src -+ binutils-2.22.51 eglibc gcc-4.6.2 linux-3.1 -+ -+We're going to place our build directories in a subdirectory 'obj', -+we'll install the cross-development toolchain in 'tools', and we'll -+place our sysroot (containing files to be installed on the target -+system) in 'sysroot': -+ -+ $ obj=$top/obj -+ $ tools=$top/tools -+ $ sysroot=$top/sysroot -+ -+ -+Binutils -+ -+Configuring and building binutils for the target is straightforward: -+ -+ $ mkdir -p $obj/binutils -+ $ cd $obj/binutils -+ $ $src/$binutilsv/configure \ -+ > --target=$target \ -+ > --prefix=$tools \ -+ > --with-sysroot=$sysroot -+ $ make -+ $ make install -+ -+ -+The First GCC -+ -+For our work, we need a cross-compiler targeting an ARM Linux -+system. However, that configuration includes the shared library -+'libgcc_s.so', which is compiled against the EGLIBC headers (which we -+haven't installed yet) and linked against 'libc.so' (which we haven't -+built yet). -+ -+Fortunately, there are configuration options for GCC which tell it not -+to build 'libgcc_s.so'. The '--without-headers' option is supposed to -+take care of this, but its implementation is incomplete, so you must -+also configure with the '--with-newlib' option. While '--with-newlib' -+appears to mean "Use the Newlib C library", its effect is to tell the -+GCC build machinery, "Don't assume there is a C library available." -+ -+We also need to disable some of the libraries that would normally be -+built along with GCC, and specify that only the compiler for the C -+language is needed. -+ -+So, we create a build directory, configure, make, and install. -+ -+ $ mkdir -p $obj/gcc1 -+ $ cd $obj/gcc1 -+ $ $src/$gccv/configure \ -+ > --target=$target \ -+ > --prefix=$tools \ -+ > --without-headers --with-newlib \ -+ > --disable-shared --disable-threads --disable-libssp \ -+ > --disable-libgomp --disable-libmudflap --disable-libquadmath \ -+ > --disable-decimal-float --disable-libffi \ -+ > --enable-languages=c -+ $ PATH=$tools/bin:$PATH make -+ $ PATH=$tools/bin:$PATH make install -+ -+ -+Linux Kernel Headers -+ -+To configure EGLIBC, we also need Linux kernel headers in place. -+Fortunately, the Linux makefiles have a target that installs them for -+us. Since the process does modify the source tree a bit, we make a -+copy first: -+ -+ $ cp -r $src/$linuxv $obj/linux -+ $ cd $obj/linux -+ -+Now we're ready to install the headers into the sysroot: -+ -+ $ PATH=$tools/bin:$PATH \ -+ > make headers_install \ -+ > ARCH=$linux_arch CROSS_COMPILE=$target- \ -+ > INSTALL_HDR_PATH=$sysroot/usr -+ -+ -+EGLIBC Headers and Preliminary Objects -+ -+Using the cross-compiler we've just built, we can now configure EGLIBC -+well enough to install the headers and build the object files that the -+full cross-compiler will need: -+ -+ $ mkdir -p $obj/eglibc-headers -+ $ cd $obj/eglibc-headers -+ $ BUILD_CC=gcc \ -+ > CC=$tools/bin/$target-gcc \ -+ > CXX=$tools/bin/$target-g++ \ -+ > AR=$tools/bin/$target-ar \ -+ > RANLIB=$tools/bin/$target-ranlib \ -+ > $src/eglibc/libc/configure \ -+ > --prefix=/usr \ -+ > --with-headers=$sysroot/usr/include \ -+ > --build=$build \ -+ > --host=$target \ -+ > --disable-profile --without-gd --without-cvs \ -+ > --enable-add-ons=nptl,libidn,../ports -+ -+The option '--prefix=/usr' may look strange, but you should never -+configure EGLIBC with a prefix other than '/usr': in various places, -+EGLIBC's build system checks whether the prefix is '/usr', and does -+special handling only if that is the case. Unless you use this -+prefix, you will get a sysroot that does not use the standard Linux -+directory layouts and cannot be used as a basis for the root -+filesystem on your target system compatibly with normal GLIBC -+installations. -+ -+The '--with-headers' option tells EGLIBC where the Linux headers have -+been installed. -+ -+The '--enable-add-ons=nptl,libidn,../ports' option tells EGLIBC to look -+for the listed glibc add-ons. Most notably the ports add-on (located -+just above the libc sources in the EGLIBC svn tree) is required to -+support ARM targets. -+ -+We can now use the 'install-headers' makefile target to install the -+headers: -+ -+ $ make install-headers install_root=$sysroot \ -+ > install-bootstrap-headers=yes -+ -+The 'install_root' variable indicates where the files should actually -+be installed; its value is treated as the parent of the '--prefix' -+directory we passed to the configure script, so the headers will go in -+'$sysroot/usr/include'. The 'install-bootstrap-headers' variable -+requests special handling for certain tricky header files. -+ -+Next, there are a few object files needed to link shared libraries, -+which we build and install by hand: -+ -+ $ mkdir -p $sysroot/usr/lib -+ $ make csu/subdir_lib -+ $ cp csu/crt1.o csu/crti.o csu/crtn.o $sysroot/usr/lib -+ -+Finally, 'libgcc_s.so' requires a 'libc.so' to link against. However, -+since we will never actually execute its code, it doesn't matter what -+it contains. So, treating '/dev/null' as a C source file, we produce -+a dummy 'libc.so' in one step: -+ -+ $ $tools/bin/$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null \ -+ > -o $sysroot/usr/lib/libc.so -+ -+ -+The Second GCC -+ -+With the EGLIBC headers and selected object files installed, we can -+now build a GCC that is capable of compiling EGLIBC. We configure, -+build, and install the second GCC, again building only the C compiler, -+and avoiding libraries we won't use: -+ -+ $ mkdir -p $obj/gcc2 -+ $ cd $obj/gcc2 -+ $ $src/$gccv/configure \ -+ > --target=$target \ -+ > --prefix=$tools \ -+ > --with-sysroot=$sysroot \ -+ > --disable-libssp --disable-libgomp --disable-libmudflap \ -+ > --disable-libffi --disable-libquadmath \ -+ > --enable-languages=c -+ $ PATH=$tools/bin:$PATH make -+ $ PATH=$tools/bin:$PATH make install -+ -+ -+EGLIBC, Complete -+ -+With the second compiler built and installed, we're now ready for the -+full EGLIBC build: -+ -+ $ mkdir -p $obj/eglibc -+ $ cd $obj/eglibc -+ $ BUILD_CC=gcc \ -+ > CC=$tools/bin/$target-gcc \ -+ > CXX=$tools/bin/$target-g++ \ -+ > AR=$tools/bin/$target-ar \ -+ > RANLIB=$tools/bin/$target-ranlib \ -+ > $src/eglibc/libc/configure \ -+ > --prefix=/usr \ -+ > --with-headers=$sysroot/usr/include \ -+ > --with-kconfig=$obj/linux/scripts/kconfig \ -+ > --build=$build \ -+ > --host=$target \ -+ > --disable-profile --without-gd --without-cvs \ -+ > --enable-add-ons=nptl,libidn,../ports -+ -+Note the additional '--with-kconfig' option. This tells EGLIBC where to -+find the host config tools used by the kernel 'make config' and 'make -+menuconfig'. These tools can be re-used by EGLIBC for its own 'make -+*config' support, which will create 'option-groups.config' for you. -+But first make sure those tools have been built by running some -+dummy 'make *config' calls in the kernel directory: -+ -+ $ cd $obj/linux -+ $ PATH=$tools/bin:$PATH make config \ -+ > ARCH=$linux_arch CROSS_COMPILE=$target- \ -+ $ PATH=$tools/bin:$PATH make menuconfig \ -+ > ARCH=$linux_arch CROSS_COMPILE=$target- \ -+ -+Now we can configure and build the full EGLIBC: -+ -+ $ cd $obj/eglibc -+ $ PATH=$tools/bin:$PATH make defconfig -+ $ PATH=$tools/bin:$PATH make menuconfig -+ $ PATH=$tools/bin:$PATH make -+ $ PATH=$tools/bin:$PATH make install install_root=$sysroot -+ -+At this point, we have a complete EGLIBC installation in '$sysroot', -+with header files, library files, and most of the C runtime startup -+files in place. -+ -+ -+The Third GCC -+ -+Finally, we recompile GCC against this full installation, enabling -+whatever languages and libraries we would like to use: -+ -+ $ mkdir -p $obj/gcc3 -+ $ cd $obj/gcc3 -+ $ $src/$gccv/configure \ -+ > --target=$target \ -+ > --prefix=$tools \ -+ > --with-sysroot=$sysroot \ -+ > --enable-__cxa_atexit \ -+ > --disable-libssp --disable-libgomp --disable-libmudflap \ -+ > --enable-languages=c,c++ -+ $ PATH=$tools/bin:$PATH make -+ $ PATH=$tools/bin:$PATH make install -+ -+The '--enable-__cxa_atexit' option tells GCC what sort of C++ -+destructor support to expect from the C library; it's required with -+EGLIBC. -+ -+And since GCC's installation process isn't designed to help construct -+sysroot trees, we must manually copy certain libraries into place in -+the sysroot. -+ -+ $ cp -d $tools/$target/lib/libgcc_s.so* $sysroot/lib -+ $ cp -d $tools/$target/lib/libstdc++.so* $sysroot/usr/lib -+ -+ -+Trying Things Out -+ -+At this point, '$tools' contains a cross toolchain ready to use -+the EGLIBC installation in '$sysroot': -+ -+ $ cat > hello.c < #include -+ > int -+ > main (int argc, char **argv) -+ > { -+ > puts ("Hello, world!"); -+ > return 0; -+ > } -+ > EOF -+ $ $tools/bin/$target-gcc -Wall hello.c -o hello -+ $ cat > c++-hello.cc < #include -+ > int -+ > main (int argc, char **argv) -+ > { -+ > std::cout << "Hello, C++ world!" << std::endl; -+ > return 0; -+ > } -+ > EOF -+ $ $tools/bin/$target-g++ -Wall c++-hello.cc -o c++-hello -+ -+ -+We can use 'readelf' to verify that these are indeed executables for -+our target, using our dynamic linker: -+ -+ $ $tools/bin/$target-readelf -hl hello -+ ELF Header: -+ ... -+ Type: EXEC (Executable file) -+ Machine: ARM -+ -+ ... -+ Program Headers: -+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align -+ PHDR 0x000034 0x10000034 0x10000034 0x00100 0x00100 R E 0x4 -+ INTERP 0x000134 0x00008134 0x00008134 0x00013 0x00013 R 0x1 -+ [Requesting program interpreter: /lib/ld-linux.so.3] -+ LOAD 0x000000 0x00008000 0x00008000 0x0042c 0x0042c R E 0x8000 -+ ... -+ -+Looking at the dynamic section of the installed 'libgcc_s.so', we see -+that the 'NEEDED' entry for the C library does include the '.6' -+suffix, indicating that was linked against our fully build EGLIBC, and -+not our dummy 'libc.so': -+ -+ $ $tools/bin/$target-readelf -d $sysroot/lib/libgcc_s.so.1 -+ Dynamic section at offset 0x1083c contains 24 entries: -+ Tag Type Name/Value -+ 0x00000001 (NEEDED) Shared library: [libc.so.6] -+ 0x0000000e (SONAME) Library soname: [libgcc_s.so.1] -+ ... -+ -+ -+And on the target machine, we can run our programs: -+ -+ $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \ -+ > ./hello -+ Hello, world! -+ $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \ -+ > ./c++-hello -+ Hello, C++ world! -Index: git/EGLIBC.cross-testing -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/EGLIBC.cross-testing 2014-08-27 07:24:41.532070587 +0000 -@@ -0,0 +1,205 @@ -+ -*- mode: text -*- -+ -+ Cross-Testing With EGLIBC -+ Jim Blandy -+ -+ -+Introduction -+ -+Developers writing software for embedded systems often use a desktop -+or other similarly capable computer for development, but need to run -+tests on the embedded system, or perhaps on a simulator. When -+configured for cross-compilation, the stock GNU C library simply -+disables running tests altogether: the command 'make tests' builds -+test programs, but does not run them. EGLIBC, however, provides -+facilities for compiling tests and generating data files on the build -+system, but running the test programs themselves on a remote system or -+simulator. -+ -+ -+Test environment requirements -+ -+The test environment must meet certain conditions for EGLIBC's -+cross-testing facilities to work: -+ -+- Shared filesystems. The 'build' system, on which you configure and -+ compile EGLIBC, and the 'host' system, on which you intend to run -+ EGLIBC, must share a filesystem containing the EGLIBC build and -+ source trees. Files must appear at the same paths on both systems. -+ -+- Remote-shell like invocation. There must be a way to run a program -+ on the host system from the build system, passing it properly quoted -+ command-line arguments, setting environment variables, and -+ inheriting the caller's standard input and output. -+ -+ -+Usage -+ -+To use EGLIBC's cross-testing support, provide values for the -+following Make variables when you invoke 'make': -+ -+- cross-test-wrapper -+ -+ This should be the name of the cross-testing wrapper command, along -+ with any arguments. -+ -+- cross-localedef -+ -+ This should be the name of a cross-capable localedef program, like -+ that included in the EGLIBC 'localedef' module, along with any -+ arguments needed. -+ -+These are each explained in detail below. -+ -+ -+The Cross-Testing Wrapper -+ -+To run test programs reliably, the stock GNU C library takes care to -+ensure that test programs use the newly compiled dynamic linker and -+shared libraries, and never the host system's installed libraries. To -+accomplish this, it runs the tests by explicitly invoking the dynamic -+linker from the build tree, passing it a list of build tree -+directories to search for shared libraries, followed by the name of -+the executable to run and its arguments. -+ -+For example, where one might normally run a test program like this: -+ -+ $ ./tst-foo arg1 arg2 -+ -+the GNU C library might run that program like this: -+ -+ $ $objdir/elf/ld-linux.so.3 --library-path $objdir \ -+ ./tst-foo arg1 arg2 -+ -+(where $objdir is the path to the top of the build tree, and the -+trailing backslash indicates a continuation of the command). In other -+words, each test program invocation is 'wrapped up' inside an explicit -+invocation of the dynamic linker, which must itself execute the test -+program, having loaded shared libraries from the appropriate -+directories. -+ -+To support cross-testing, EGLIBC allows the developer to optionally -+set the 'cross-test-wrapper' Make variable to another wrapper command, -+to which it passes the entire dynamic linker invocation shown above as -+arguments. For example, if the developer supplies a wrapper of -+'my-wrapper hostname', then EGLIBC would run the test above as -+follows: -+ -+ $ my-wrapper hostname \ -+ $objdir/elf/ld-linux.so.3 --library-path $objdir \ -+ ./tst-foo arg1 arg2 -+ -+The 'my-wrapper' command is responsible for executing the command -+given on the host system. -+ -+Since tests are run in varying directories, the wrapper should either -+be in your command search path, or 'cross-test-wrapper' should give an -+absolute path for the wrapper. -+ -+The wrapper must meet several requirements: -+ -+- It must preserve the current directory. As explained above, the -+ build directory tree must be visible on both the build and host -+ systems, at the same path. The test wrapper must ensure that the -+ current directory it inherits is also inherited by the dynamic -+ linker (and thus the test program itself). -+ -+- It must preserve environment variables' values. Many EGLIBC tests -+ set environment variables for test runs; in native testing, it -+ invokes programs like this: -+ -+ $ GCONV_PATH=$objdir/iconvdata \ -+ $objdir/elf/ld-linux.so.3 --library-path $objdir \ -+ ./tst-foo arg1 arg2 -+ -+ With the cross-testing wrapper, that invocation becomes: -+ -+ $ GCONV_PATH=$objdir/iconvdata \ -+ my-wrapper hostname \ -+ $objdir/elf/ld-linux.so.3 --library-path $objdir \ -+ ./tst-foo arg1 arg2 -+ -+ Here, 'my-wrapper' must ensure that the value it sees for -+ 'GCONV_PATH' will be seen by the dynamic linker, and thus 'tst-foo' -+ itself. (The wrapper supplied with GLIBC simply preserves the -+ values of *all* enviroment variables, with a fixed set of -+ exceptions.) -+ -+ If your wrapper is a shell script, take care to correctly propagate -+ environment variables whose values contain spaces and shell -+ metacharacters. -+ -+- It must pass the command's arguments, unmodified. The arguments -+ seen by the test program should be exactly those seen by the wrapper -+ (after whatever arguments are given to the wrapper itself). The -+ EGLIBC test framework performs all needed shell word splitting and -+ expansion (wildcard expansion, parameter substitution, and so on) -+ before invoking the wrapper; further expansion may break the tests. -+ -+ -+The 'cross-test-ssh.sh' script -+ -+If you want to use 'ssh' (or something sufficiently similar) to run -+test programs on your host system, EGLIBC includes a shell script, -+'scripts/cross-test-ssh.sh', which you can use as your wrapper -+command. This script takes care of setting the test command's current -+directory, propagating environment variable values, and carrying -+command-line arguments, all across an 'ssh' connection. You may even -+supply an alternative to 'ssh' on the command line, if needed. -+ -+For more details, pass 'cross-test-ssh.sh' the '--help' option. -+ -+ -+The Cross-Compiling Locale Definition Command -+ -+Some EGLIBC tests rely on locales generated especially for the test -+process. In a native configuration, these tests simply run the -+'localedef' command built by the normal EGLIBC build process, -+'locale/localedef', to process and install their locales. However, in -+a cross-compiling configuration, this 'localedef' is built for the -+host system, not the build system, and since it requires quite a bit -+of memory to run (we have seen it fail on systems with 64MiB of -+memory), it may not be practical to run it on the host system. -+ -+If set, EGLIBC uses the 'cross-localedef' Make variable as the command -+to run on the build system to process and install locales. The -+localedef program built from the EGLIBC 'localedef' module is -+suitable. -+ -+The value of 'cross-localedef' may also include command-line arguments -+to be passed to the program; if you are using EGLIBC's 'localedef', -+you may include endianness and 'uint32_t' alignment arguments here. -+ -+ -+Example -+ -+In developing EGLIBC's cross-testing facility, we invoked 'make' with -+the following script: -+ -+ #!/bin/sh -+ -+ srcdir=... -+ test_hostname=... -+ localedefdir=... -+ cross_gxx=...-g++ -+ -+ wrapper="$srcdir/scripts/cross-test-ssh.sh $test_hostname" -+ localedef="$localedefdir/localedef --little-endian --uint32-align=4" -+ -+ make cross-test-wrapper="$wrapper" \ -+ cross-localedef="$localedef" \ -+ CXX="$cross_gxx" \ -+ "$@" -+ -+ -+Other Cross-Testing Concerns -+ -+Here are notes on some other issues which you may encounter in running -+the EGLIBC tests in a cross-compiling environment: -+ -+- Some tests require a C++ cross-compiler; you should set the 'CXX' -+ Make variable to the name of an appropriate cross-compiler. -+ -+- Some tests require access to libstdc++.so.6 and libgcc_s.so.1; we -+ simply place copies of these libraries in the top EGLIBC build -+ directory. diff --git a/meta/recipes-core/glibc/glibc/elf-Makefile-fix-a-typo.patch b/meta/recipes-core/glibc/glibc/elf-Makefile-fix-a-typo.patch deleted file mode 100644 index ec480067a8..0000000000 --- a/meta/recipes-core/glibc/glibc/elf-Makefile-fix-a-typo.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 6207fb45553ee98f2f326883b7c21b76c8267343 Mon Sep 17 00:00:00 2001 -From: Robert Yang -Date: Tue, 31 Mar 2015 02:31:25 -0700 -Subject: [PATCH] elf/Makefile: fix a typo - -Fixed a typo: -name-target-directory -> make-target-directory - -There is no name-target-directory, it should be make-target-directory, -this fixed the error: -/bin/bash: /path/to/elf/runtime-linker.T: No such file or directory -Makefile:361: recipe for target '/path/to/elf/runtime-linker.st' failed - -Upstream-Status: Pending - -Signed-off-by: Robert Yang ---- - elf/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/elf/Makefile b/elf/Makefile -index e5b142c..62fe245 100644 ---- a/elf/Makefile -+++ b/elf/Makefile -@@ -358,7 +358,7 @@ $(objpfx)interp.os: $(elf-objpfx)runtime-linker.h - - $(elf-objpfx)runtime-linker.h: $(elf-objpfx)runtime-linker.st; @: - $(elf-objpfx)runtime-linker.st: $(common-objpfx)config.make -- $(name-target-directory) -+ $(make-target-directory) - echo '#define RUNTIME_LINKER "$(rtlddir)/$(rtld-installed-name)"' \ - > ${@:st=T} - $(move-if-change) ${@:st=T} ${@:st=h} --- -1.7.9.5 - diff --git a/meta/recipes-core/glibc/glibc/fix-tibetian-locales.patch b/meta/recipes-core/glibc/glibc/fix-tibetian-locales.patch deleted file mode 100644 index 9ab9fdcf12..0000000000 --- a/meta/recipes-core/glibc/glibc/fix-tibetian-locales.patch +++ /dev/null @@ -1,38 +0,0 @@ -cross localedef fails to compile these locales because name_fmt field is empty -It is not acceptable for cross localedef and it errors out - -LC_NAME: field `name_fmt' not defined - -We therefore give a dummy string to the format, the real fix needs some native -tibetian person to define proper name_fmt - -Upstream-Status: Pending - -Signed-off-by: Khem Raj - -Index: git/localedata/locales/bo_CN -=================================================================== ---- git.orig/localedata/locales/bo_CN 2014-08-29 10:35:22.464070587 -0700 -+++ git/localedata/locales/bo_CN 2014-08-29 10:35:22.456070587 -0700 -@@ -146,7 +146,7 @@ - LC_NAME - % FIXME - --name_fmt "" -+name_fmt "FIXME" - % name_gen "FIXME" - % name_miss "FIXME" - % name_mr "FIXME" -Index: git/localedata/locales/bo_IN -=================================================================== ---- git.orig/localedata/locales/bo_IN 2014-08-29 10:35:22.464070587 -0700 -+++ git/localedata/locales/bo_IN 2014-08-29 10:35:22.456070587 -0700 -@@ -71,7 +71,7 @@ - - LC_NAME - % FIXME --name_fmt "" -+name_fmt "FIXME" - % name_gen "FIXME" - % name_miss "FIXME" - % name_mr "FIXME" diff --git a/meta/recipes-core/glibc/glibc/fix_am_rootsbindir.patch b/meta/recipes-core/glibc/glibc/fix_am_rootsbindir.patch deleted file mode 100644 index 668e8bf678..0000000000 --- a/meta/recipes-core/glibc/glibc/fix_am_rootsbindir.patch +++ /dev/null @@ -1,29 +0,0 @@ -sysdeps/gnu/configure.ac: handle correctly $libc_cv_rootsbindir - -Upstream-Status:Pending -Signed-off-by: Matthieu Crapet - -Index: git/sysdeps/gnu/configure -=================================================================== ---- git.orig/sysdeps/gnu/configure 2014-08-27 07:24:38.572070587 +0000 -+++ git/sysdeps/gnu/configure 2014-08-27 07:24:41.308070587 +0000 -@@ -32,6 +32,6 @@ - else - libc_cv_localstatedir=$localstatedir - fi -- libc_cv_rootsbindir=/sbin -+ test -n "$libc_cv_rootsbindir" || libc_cv_rootsbindir=/sbin - ;; - esac -Index: git/sysdeps/gnu/configure.ac -=================================================================== ---- git.orig/sysdeps/gnu/configure.ac 2014-08-27 07:24:38.572070587 +0000 -+++ git/sysdeps/gnu/configure.ac 2014-08-27 07:24:41.308070587 +0000 -@@ -21,6 +21,6 @@ - else - libc_cv_localstatedir=$localstatedir - fi -- libc_cv_rootsbindir=/sbin -+ test -n "$libc_cv_rootsbindir" || libc_cv_rootsbindir=/sbin - ;; - esac diff --git a/meta/recipes-core/glibc/glibc/glibc.fix_sqrt2.patch b/meta/recipes-core/glibc/glibc/glibc.fix_sqrt2.patch deleted file mode 100644 index f5ed1bfeef..0000000000 --- a/meta/recipes-core/glibc/glibc/glibc.fix_sqrt2.patch +++ /dev/null @@ -1,1516 +0,0 @@ -Signed-of-by: Edmar Wienskoski -Upstream-Status: Pending - -Index: git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c 2014-08-29 10:34:07.768070587 -0700 -@@ -0,0 +1,134 @@ -+/* Double-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float two108 = 3.245185536584267269e+32; -+static const float twom54 = 5.551115123125782702e-17; -+static const float half = 0.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the actual square root and half of its reciprocal -+ simultaneously. */ -+ -+#ifdef __STDC__ -+double -+__ieee754_sqrt (double b) -+#else -+double -+__ieee754_sqrt (b) -+ double b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+ double y, g, h, d, r; -+ ieee_double_shape_type u; -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ u.value = b; -+ -+ relax_fenv_state (); -+ -+ __asm__ ("frsqrte %[estimate], %[x]\n" -+ : [estimate] "=f" (y) : [x] "f" (b)); -+ -+ /* Following Muller et al, page 168, equation 5.20. -+ -+ h goes to 1/(2*sqrt(b)) -+ g goes to sqrt(b). -+ -+ We need three iterations to get within 1ulp. */ -+ -+ /* Indicate that these can be performed prior to the branch. GCC -+ insists on sinking them below the branch, however; it seems like -+ they'd be better before the branch so that we can cover any latency -+ from storing the argument and loading its high word. Oh well. */ -+ -+ g = b * y; -+ h = 0.5 * y; -+ -+ /* Handle small numbers by scaling. */ -+ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -+ return __ieee754_sqrt (b * two108) * twom54; -+ -+#define FMADD(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ -+ -+ /* Final refinement. */ -+ d = FNMSUB (g, g, b); -+ -+ fesetenv_register (fe); -+ return FMADD (d, h, g); -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_wash (b); -+} -Index: git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c 2014-08-29 10:34:07.768070587 -0700 -@@ -0,0 +1,101 @@ -+/* Single-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float threehalf = 1.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the reciprocal square root and use that to compute the actual -+ square root. */ -+ -+#ifdef __STDC__ -+float -+__ieee754_sqrtf (float b) -+#else -+float -+__ieee754_sqrtf (b) -+ float b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+#define FMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ double y, x; -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ relax_fenv_state (); -+ -+ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ -+ y = FMSUB (threehalf, b, b); -+ -+ /* Initial estimate. */ -+ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); -+ -+ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ -+ /* All done. */ -+ fesetenv_register (fe); -+ return x * b; -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_washf (b); -+} -Index: git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c 2014-08-29 10:34:07.768070587 -0700 -@@ -0,0 +1,134 @@ -+/* Double-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float two108 = 3.245185536584267269e+32; -+static const float twom54 = 5.551115123125782702e-17; -+static const float half = 0.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the actual square root and half of its reciprocal -+ simultaneously. */ -+ -+#ifdef __STDC__ -+double -+__ieee754_sqrt (double b) -+#else -+double -+__ieee754_sqrt (b) -+ double b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+ double y, g, h, d, r; -+ ieee_double_shape_type u; -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ u.value = b; -+ -+ relax_fenv_state (); -+ -+ __asm__ ("frsqrte %[estimate], %[x]\n" -+ : [estimate] "=f" (y) : [x] "f" (b)); -+ -+ /* Following Muller et al, page 168, equation 5.20. -+ -+ h goes to 1/(2*sqrt(b)) -+ g goes to sqrt(b). -+ -+ We need three iterations to get within 1ulp. */ -+ -+ /* Indicate that these can be performed prior to the branch. GCC -+ insists on sinking them below the branch, however; it seems like -+ they'd be better before the branch so that we can cover any latency -+ from storing the argument and loading its high word. Oh well. */ -+ -+ g = b * y; -+ h = 0.5 * y; -+ -+ /* Handle small numbers by scaling. */ -+ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -+ return __ieee754_sqrt (b * two108) * twom54; -+ -+#define FMADD(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ -+ -+ /* Final refinement. */ -+ d = FNMSUB (g, g, b); -+ -+ fesetenv_register (fe); -+ return FMADD (d, h, g); -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_wash (b); -+} -Index: git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,101 @@ -+/* Single-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float threehalf = 1.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the reciprocal square root and use that to compute the actual -+ square root. */ -+ -+#ifdef __STDC__ -+float -+__ieee754_sqrtf (float b) -+#else -+float -+__ieee754_sqrtf (b) -+ float b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+#define FMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ double y, x; -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ relax_fenv_state (); -+ -+ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ -+ y = FMSUB (threehalf, b, b); -+ -+ /* Initial estimate. */ -+ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); -+ -+ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ -+ /* All done. */ -+ fesetenv_register (fe); -+ return x * b; -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_washf (b); -+} -Index: git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,134 @@ -+/* Double-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float two108 = 3.245185536584267269e+32; -+static const float twom54 = 5.551115123125782702e-17; -+static const float half = 0.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the actual square root and half of its reciprocal -+ simultaneously. */ -+ -+#ifdef __STDC__ -+double -+__ieee754_sqrt (double b) -+#else -+double -+__ieee754_sqrt (b) -+ double b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+ double y, g, h, d, r; -+ ieee_double_shape_type u; -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ u.value = b; -+ -+ relax_fenv_state (); -+ -+ __asm__ ("frsqrte %[estimate], %[x]\n" -+ : [estimate] "=f" (y) : [x] "f" (b)); -+ -+ /* Following Muller et al, page 168, equation 5.20. -+ -+ h goes to 1/(2*sqrt(b)) -+ g goes to sqrt(b). -+ -+ We need three iterations to get within 1ulp. */ -+ -+ /* Indicate that these can be performed prior to the branch. GCC -+ insists on sinking them below the branch, however; it seems like -+ they'd be better before the branch so that we can cover any latency -+ from storing the argument and loading its high word. Oh well. */ -+ -+ g = b * y; -+ h = 0.5 * y; -+ -+ /* Handle small numbers by scaling. */ -+ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -+ return __ieee754_sqrt (b * two108) * twom54; -+ -+#define FMADD(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ -+ -+ /* Final refinement. */ -+ d = FNMSUB (g, g, b); -+ -+ fesetenv_register (fe); -+ return FMADD (d, h, g); -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_wash (b); -+} -Index: git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,101 @@ -+/* Single-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float threehalf = 1.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the reciprocal square root and use that to compute the actual -+ square root. */ -+ -+#ifdef __STDC__ -+float -+__ieee754_sqrtf (float b) -+#else -+float -+__ieee754_sqrtf (b) -+ float b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+#define FMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ double y, x; -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ relax_fenv_state (); -+ -+ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ -+ y = FMSUB (threehalf, b, b); -+ -+ /* Initial estimate. */ -+ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); -+ -+ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ -+ /* All done. */ -+ fesetenv_register (fe); -+ return x * b; -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_washf (b); -+} -Index: git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,134 @@ -+/* Double-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float two108 = 3.245185536584267269e+32; -+static const float twom54 = 5.551115123125782702e-17; -+static const float half = 0.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the actual square root and half of its reciprocal -+ simultaneously. */ -+ -+#ifdef __STDC__ -+double -+__ieee754_sqrt (double b) -+#else -+double -+__ieee754_sqrt (b) -+ double b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+ double y, g, h, d, r; -+ ieee_double_shape_type u; -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ u.value = b; -+ -+ relax_fenv_state (); -+ -+ __asm__ ("frsqrte %[estimate], %[x]\n" -+ : [estimate] "=f" (y) : [x] "f" (b)); -+ -+ /* Following Muller et al, page 168, equation 5.20. -+ -+ h goes to 1/(2*sqrt(b)) -+ g goes to sqrt(b). -+ -+ We need three iterations to get within 1ulp. */ -+ -+ /* Indicate that these can be performed prior to the branch. GCC -+ insists on sinking them below the branch, however; it seems like -+ they'd be better before the branch so that we can cover any latency -+ from storing the argument and loading its high word. Oh well. */ -+ -+ g = b * y; -+ h = 0.5 * y; -+ -+ /* Handle small numbers by scaling. */ -+ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -+ return __ieee754_sqrt (b * two108) * twom54; -+ -+#define FMADD(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ -+ -+ /* Final refinement. */ -+ d = FNMSUB (g, g, b); -+ -+ fesetenv_register (fe); -+ return FMADD (d, h, g); -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_wash (b); -+} -Index: git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,101 @@ -+/* Single-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float threehalf = 1.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the reciprocal square root and use that to compute the actual -+ square root. */ -+ -+#ifdef __STDC__ -+float -+__ieee754_sqrtf (float b) -+#else -+float -+__ieee754_sqrtf (b) -+ float b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+#define FMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ double y, x; -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ relax_fenv_state (); -+ -+ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ -+ y = FMSUB (threehalf, b, b); -+ -+ /* Initial estimate. */ -+ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); -+ -+ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ -+ /* All done. */ -+ fesetenv_register (fe); -+ return x * b; -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_washf (b); -+} -Index: git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,134 @@ -+/* Double-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float two108 = 3.245185536584267269e+32; -+static const float twom54 = 5.551115123125782702e-17; -+static const float half = 0.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the actual square root and half of its reciprocal -+ simultaneously. */ -+ -+#ifdef __STDC__ -+double -+__ieee754_sqrt (double b) -+#else -+double -+__ieee754_sqrt (b) -+ double b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+ double y, g, h, d, r; -+ ieee_double_shape_type u; -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ u.value = b; -+ -+ relax_fenv_state (); -+ -+ __asm__ ("frsqrte %[estimate], %[x]\n" -+ : [estimate] "=f" (y) : [x] "f" (b)); -+ -+ /* Following Muller et al, page 168, equation 5.20. -+ -+ h goes to 1/(2*sqrt(b)) -+ g goes to sqrt(b). -+ -+ We need three iterations to get within 1ulp. */ -+ -+ /* Indicate that these can be performed prior to the branch. GCC -+ insists on sinking them below the branch, however; it seems like -+ they'd be better before the branch so that we can cover any latency -+ from storing the argument and loading its high word. Oh well. */ -+ -+ g = b * y; -+ h = 0.5 * y; -+ -+ /* Handle small numbers by scaling. */ -+ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -+ return __ieee754_sqrt (b * two108) * twom54; -+ -+#define FMADD(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ -+ -+ /* Final refinement. */ -+ d = FNMSUB (g, g, b); -+ -+ fesetenv_register (fe); -+ return FMADD (d, h, g); -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_wash (b); -+} -Index: git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,101 @@ -+/* Single-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float threehalf = 1.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the reciprocal square root and use that to compute the actual -+ square root. */ -+ -+#ifdef __STDC__ -+float -+__ieee754_sqrtf (float b) -+#else -+float -+__ieee754_sqrtf (b) -+ float b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+#define FMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ double y, x; -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ relax_fenv_state (); -+ -+ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ -+ y = FMSUB (threehalf, b, b); -+ -+ /* Initial estimate. */ -+ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); -+ -+ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ -+ /* All done. */ -+ fesetenv_register (fe); -+ return x * b; -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_washf (b); -+} -Index: git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c 2014-08-29 10:34:07.772070587 -0700 -@@ -0,0 +1,134 @@ -+/* Double-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float two108 = 3.245185536584267269e+32; -+static const float twom54 = 5.551115123125782702e-17; -+static const float half = 0.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the actual square root and half of its reciprocal -+ simultaneously. */ -+ -+#ifdef __STDC__ -+double -+__ieee754_sqrt (double b) -+#else -+double -+__ieee754_sqrt (b) -+ double b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+ double y, g, h, d, r; -+ ieee_double_shape_type u; -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ u.value = b; -+ -+ relax_fenv_state (); -+ -+ __asm__ ("frsqrte %[estimate], %[x]\n" -+ : [estimate] "=f" (y) : [x] "f" (b)); -+ -+ /* Following Muller et al, page 168, equation 5.20. -+ -+ h goes to 1/(2*sqrt(b)) -+ g goes to sqrt(b). -+ -+ We need three iterations to get within 1ulp. */ -+ -+ /* Indicate that these can be performed prior to the branch. GCC -+ insists on sinking them below the branch, however; it seems like -+ they'd be better before the branch so that we can cover any latency -+ from storing the argument and loading its high word. Oh well. */ -+ -+ g = b * y; -+ h = 0.5 * y; -+ -+ /* Handle small numbers by scaling. */ -+ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -+ return __ieee754_sqrt (b * two108) * twom54; -+ -+#define FMADD(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ r = FNMSUB (g, h, half); -+ g = FMADD (g, r, g); -+ h = FMADD (h, r, h); -+ -+ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */ -+ -+ /* Final refinement. */ -+ d = FNMSUB (g, g, b); -+ -+ fesetenv_register (fe); -+ return FMADD (d, h, g); -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_wash (b); -+} -Index: git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c 2014-08-29 10:34:07.776070587 -0700 -@@ -0,0 +1,101 @@ -+/* Single-precision floating point square root. -+ Copyright (C) 2010 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, write to the Free -+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ 02111-1307 USA. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 }; -+static const ieee_float_shape_type a_inf = {.word = 0x7f800000 }; -+static const float threehalf = 1.5; -+ -+/* The method is based on the descriptions in: -+ -+ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5; -+ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9 -+ -+ We find the reciprocal square root and use that to compute the actual -+ square root. */ -+ -+#ifdef __STDC__ -+float -+__ieee754_sqrtf (float b) -+#else -+float -+__ieee754_sqrtf (b) -+ float b; -+#endif -+{ -+ if (__builtin_expect (b > 0, 1)) -+ { -+#define FMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+#define FNMSUB(a_, c_, b_) \ -+ ({ double __r; \ -+ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \ -+ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \ -+ __r;}) -+ -+ if (__builtin_expect (b != a_inf.value, 1)) -+ { -+ double y, x; -+ fenv_t fe; -+ -+ fe = fegetenv_register (); -+ -+ relax_fenv_state (); -+ -+ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */ -+ y = FMSUB (threehalf, b, b); -+ -+ /* Initial estimate. */ -+ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b)); -+ -+ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */ -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ x = x * FNMSUB (y, x * x, threehalf); -+ -+ /* All done. */ -+ fesetenv_register (fe); -+ return x * b; -+ } -+ } -+ else if (b < 0) -+ { -+ /* For some reason, some PowerPC32 processors don't implement -+ FE_INVALID_SQRT. */ -+#ifdef FE_INVALID_SQRT -+ feraiseexcept (FE_INVALID_SQRT); -+ -+ fenv_union_t u = { .fenv = fegetenv_register () }; -+ if ((u.l & FE_INVALID) == 0) -+#endif -+ feraiseexcept (FE_INVALID); -+ b = a_nan.value; -+ } -+ return f_washf (b); -+} -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies 2014-08-29 10:34:07.776070587 -0700 -@@ -0,0 +1 @@ -+powerpc/powerpc32/603e/fpu -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies 2014-08-29 10:34:07.776070587 -0700 -@@ -0,0 +1,2 @@ -+# e300c3 is a variant of 603e so use the same optimizations for sqrt -+powerpc/powerpc32/603e/fpu -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies 2014-08-29 10:34:07.776070587 -0700 -@@ -0,0 +1 @@ -+powerpc/powerpc32/e500mc/fpu -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies 2014-08-29 10:34:07.776070587 -0700 -@@ -0,0 +1 @@ -+powerpc/powerpc32/e5500/fpu -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies 2014-08-29 10:34:07.776070587 -0700 -@@ -0,0 +1 @@ -+powerpc/powerpc32/e6500/fpu -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies 2014-08-29 10:34:07.780070587 -0700 -@@ -0,0 +1 @@ -+powerpc/powerpc64/e5500/fpu -Index: git/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies 2014-08-29 10:34:07.780070587 -0700 -@@ -0,0 +1 @@ -+powerpc/powerpc64/e6500/fpu diff --git a/meta/recipes-core/glibc/glibc/grok_gold.patch b/meta/recipes-core/glibc/glibc/grok_gold.patch deleted file mode 100644 index 5151802ecf..0000000000 --- a/meta/recipes-core/glibc/glibc/grok_gold.patch +++ /dev/null @@ -1,34 +0,0 @@ -Make ld --version output matching grok gold's output - -adapted from from upstream branch roland/gold-vs-libc - -Signed-off-by: Khem Raj -Upstream-Status: Backport - - -Index: git/configure -=================================================================== ---- git.orig/configure -+++ git/configure -@@ -4593,7 +4593,7 @@ else - # Found it, now check the version. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5 - $as_echo_n "checking version of $LD... " >&6; } -- ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*GNU ld.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'` -+ ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*GNU [Bbinutilsd][^.]* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'` - case $ac_prog_version in - '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; - 2.1[0-9][0-9]*|2.2[2-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*) -Index: git/configure.ac -=================================================================== ---- git.orig/configure.ac -+++ git/configure.ac -@@ -913,7 +913,7 @@ AC_CHECK_PROG_VER(AS, $AS, --version, - [2.1[0-9][0-9]*|2.2[2-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*], - AS=: critic_missing="$critic_missing as") - AC_CHECK_PROG_VER(LD, $LD, --version, -- [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)], -+ [GNU [Bbinutilsd][^.]* \([0-9][0-9]*\.[0-9.]*\)], - [2.1[0-9][0-9]*|2.2[2-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*], - LD=: critic_missing="$critic_missing ld") - diff --git a/meta/recipes-core/glibc/glibc/initgroups_keys.patch b/meta/recipes-core/glibc/glibc/initgroups_keys.patch deleted file mode 100644 index 32aa15a533..0000000000 --- a/meta/recipes-core/glibc/glibc/initgroups_keys.patch +++ /dev/null @@ -1,20 +0,0 @@ -This is needed since initgroups belongs to NET group -so when NET is disabled in eglibc build then it reports -as undefined symbol - -Signed-off-by: Khem Raj -Upstream-Status: Pending - -Index: git/nss/getent.c -=================================================================== ---- git.orig/nss/getent.c 2014-08-27 05:15:25.996070587 +0000 -+++ git/nss/getent.c 2014-08-27 05:16:00.048070587 +0000 -@@ -879,7 +879,7 @@ - D(group) - D(gshadow) - D(hosts) --D(initgroups) -+DN(initgroups) - D(netgroup) - D(networks) - D(passwd) diff --git a/meta/recipes-core/glibc/glibc/ld-search-order.patch b/meta/recipes-core/glibc/glibc/ld-search-order.patch deleted file mode 100644 index f518bc7642..0000000000 --- a/meta/recipes-core/glibc/glibc/ld-search-order.patch +++ /dev/null @@ -1,56 +0,0 @@ -Upstream-Status: Inappropriate [embedded specific] - -The default lib search path order is: - - 1) LD_LIBRARY_PATH - 2) RPATH from the binary - 3) ld.so.cache - 4) default search paths embedded in the linker - -For nativesdk binaries which are being used alongside binaries on a host system, we -need the search paths to firstly search the shipped nativesdk libs but then also -cover the host system. For example we want the host system's libGL and this may be -in a non-standard location like /usr/lib/mesa. The only place the location is know -about is in the ld.so.cache of the host system. - -Since nativesdk has a simple structure and doesn't need to use a cache itself, we -repurpose the cache for use as a last resort in finding host system binaries. This -means we need to switch the order of 3 and 4 above to make this work effectively. - -RP 14/10/2010 - -Index: git/elf/dl-load.c -=================================================================== ---- git.orig/elf/dl-load.c 2014-08-28 17:32:46.292070587 -0700 -+++ git/elf/dl-load.c 2014-08-28 17:33:56.048070587 -0700 -@@ -2050,7 +2050,14 @@ - fd = open_path (name, namelen, mode, - &loader->l_runpath_dirs, &realname, &fb, loader, - LA_SER_RUNPATH, &found_other_class); -- -+ /* try the default path. */ -+ if (fd == -1 -+ && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL -+ || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) -+ && rtld_search_dirs.dirs != (void *) -1) -+ fd = open_path (name, namelen, mode & __RTLD_SECURE, &rtld_search_dirs, -+ &realname, &fb, l, LA_SER_DEFAULT, &found_other_class); -+ /* Finally try ld.so.cache */ - #ifdef USE_LDCONFIG - if (fd == -1 - && (__glibc_likely ((mode & __RTLD_SECURE) == 0) -@@ -2113,14 +2120,6 @@ - } - #endif - -- /* Finally, try the default path. */ -- if (fd == -1 -- && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL -- || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB))) -- && rtld_search_dirs.dirs != (void *) -1) -- fd = open_path (name, namelen, mode, &rtld_search_dirs, -- &realname, &fb, l, LA_SER_DEFAULT, &found_other_class); -- - /* Add another newline when we are tracing the library loading. */ - if (__glibc_unlikely (GLRO_dl_debug_mask & DL_DEBUG_LIBS)) - _dl_debug_printf ("\n"); diff --git a/meta/recipes-core/glibc/glibc/makesyscall.patch b/meta/recipes-core/glibc/glibc/makesyscall.patch deleted file mode 100644 index 9ab597f604..0000000000 --- a/meta/recipes-core/glibc/glibc/makesyscall.patch +++ /dev/null @@ -1,51 +0,0 @@ -On x32 builds, sysd-syscalls appears malformed since the make-target-directory -appears on the wrong line. This causes races during the build process where you can -see failures like: - -Assembler messages: -Fatal error: can't create [...]glibc/2.21-r0/build-x86_64-poky-linux-gnux32/time/gettimeofday.os: No such file or directory -Assembler messages: -Fatal error: can't create [...]glibc/2.21-r0/build-x86_64-poky-linux-gnux32/time/time.os: No such file or directory - -The isue is that the carridge return is being escaped when it should -not be. The change to sysd-syscalls with this change: - -before: - -""" -$(foreach p,$(sysd-rules-targets),$(objpfx)$(patsubst %,$p,time).os): \ - $(..)sysdeps/unix/make-syscalls.sh $(make-target-directory) - (echo '#include '; -""" - -after: - -""" -$(foreach p,$(sysd-rules-targets),$(objpfx)$(patsubst %,$p,time).os): \ - $(..)sysdeps/unix/make-syscalls.sh - $(make-target-directory) - (echo '#include '; -""" - -which ensures the target directory is correctly created. Only x32 uses the vdso -code which contains the bug which is why the error only really appears on x32. - -Upstream Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18409 -Upstream Fix: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d9efd775ba51916b58b899d8b1c8501105a830de - -Upstream-Status: Backport -RP 2015/5/13 - -Index: git/sysdeps/unix/make-syscalls.sh -=================================================================== ---- git.orig/sysdeps/unix/make-syscalls.sh -+++ git/sysdeps/unix/make-syscalls.sh -@@ -278,7 +278,7 @@ while read file srcfile caller syscall a - vdso_symver=`echo "$vdso_symver" | sed 's/\./_/g'` - echo "\ - \$(foreach p,\$(sysd-rules-targets),\$(objpfx)\$(patsubst %,\$p,$file).os): \\ -- \$(..)sysdeps/unix/make-syscalls.sh\ -+ \$(..)sysdeps/unix/make-syscalls.sh - \$(make-target-directory) - (echo '#include '; \\ - echo 'extern void *${strong}_ifunc (void) __asm (\"${strong}\");'; \\ diff --git a/meta/recipes-core/glibc/glibc/mips-rld-map-check.patch b/meta/recipes-core/glibc/glibc/mips-rld-map-check.patch deleted file mode 100644 index 9f593d6359..0000000000 --- a/meta/recipes-core/glibc/glibc/mips-rld-map-check.patch +++ /dev/null @@ -1,27 +0,0 @@ - -On mips target, binutils currently sets DT_MIPS_RLD_MAP to 0 in dynamic -section if a --version-script sets _RLD_MAP to local. This is apparently -a binutils bug, but libc shouldn't segfault in this case. - -see also: http://sourceware.org/bugilla/show_bug.cgi?id=11615 - -Upstream-Status: Pending - -9/19/2010 - added by Qing He - - ---- -Index: git/sysdeps/mips/dl-machine.h -=================================================================== ---- git.orig/sysdeps/mips/dl-machine.h 2014-08-27 04:58:11.840070587 +0000 -+++ git/sysdeps/mips/dl-machine.h 2014-08-27 04:58:11.832070587 +0000 -@@ -70,7 +70,8 @@ - /* If there is a DT_MIPS_RLD_MAP entry in the dynamic section, fill it in - with the run-time address of the r_debug structure */ - #define ELF_MACHINE_DEBUG_SETUP(l,r) \ --do { if ((l)->l_info[DT_MIPS (RLD_MAP)]) \ -+do { if ((l)->l_info[DT_MIPS (RLD_MAP)] && \ -+ (l)->l_info[DT_MIPS (RLD_MAP)]->d_un.d_ptr) \ - *(ElfW(Addr) *)((l)->l_info[DT_MIPS (RLD_MAP)]->d_un.d_ptr) = \ - (ElfW(Addr)) (r); \ - } while (0) diff --git a/meta/recipes-core/glibc/glibc/multilib_readlib.patch b/meta/recipes-core/glibc/glibc/multilib_readlib.patch deleted file mode 100644 index 13ffc46f91..0000000000 --- a/meta/recipes-core/glibc/glibc/multilib_readlib.patch +++ /dev/null @@ -1,19 +0,0 @@ -Upstream-Status: Inappropriate [embedded specific] - -Replace the OECORE_KNOWN_INTERPRETER_NAMES with the value of -variable EGLIBC_KNOWN_INTERPRETER_NAMES. - -Lianhao Lu, 08/01/2011 - -Index: git/elf/readlib.c -=================================================================== ---- git.orig/elf/readlib.c 2014-08-29 10:34:16.824070587 -0700 -+++ git/elf/readlib.c 2014-08-29 10:34:16.816070587 -0700 -@@ -51,6 +51,7 @@ - #ifdef SYSDEP_KNOWN_INTERPRETER_NAMES - SYSDEP_KNOWN_INTERPRETER_NAMES - #endif -+ OECORE_KNOWN_INTERPRETER_NAMES - }; - - static struct known_names known_libs[] = diff --git a/meta/recipes-core/glibc/glibc/option-groups.patch b/meta/recipes-core/glibc/glibc/option-groups.patch deleted file mode 100644 index 198be73524..0000000000 --- a/meta/recipes-core/glibc/glibc/option-groups.patch +++ /dev/null @@ -1,1397 +0,0 @@ -Eglibc option group infrastructure - -Upstream-Status: Pending - -Index: git/option-groups.def -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/option-groups.def 2014-08-27 07:26:51.652070587 +0000 -@@ -0,0 +1,868 @@ -+# This file documents the option groups EGLIBC currently supports, in -+# a format akin to the Linux Kconfig system's. The syntax may change -+# over time. -+# -+# An entry of the form: -+# -+# config GROUP_NAME -+# bool "one-line explanation of what this option group controls" -+# help -+# Multi-line help explaining the option group's meaning in -+# some detail, terminated by indentation level. -+# -+# defines an option group whose variable is GROUP_NAME, with -+# meaningful values 'y' (enabled) and 'n' (disabled). The -+# documentation is formatted to be consumed by some sort of -+# interactive configuration interface, but EGLIBC doesn't have such an -+# interface yet. -+# -+# An option may have a 'depends on' line, indicating which other options -+# must also be enabled if this option is. At present, EGLIBC doesn't -+# check that these dependencies are satisfied. -+# -+# Option group variables get their default values from the file -+# 'option-groups.defaults', in the top directory of the EGLIBC source -+# tree. By default, all EGLIBC option groups are enabled --- their -+# variables are set to 'y'. -+# -+# After including 'option-groups.defaults', the EGLIBC make machinery -+# includes the file 'option-groups.config' from the top of the build -+# tree, if it is present. Developers can place assignments to option -+# group variables in that file to override the defaults. For example, -+# to disable an option group, place a line of the form: -+# -+# OPTION_GROUP_NAME = n -+# -+# in 'option-groups.config' at the top of your build tree. To -+# explicitly enable an option group, you may also write: -+# -+# OPTION_GROUP_NAME = y -+# -+# although this simply reestablishes the value already set by -+# 'option-groups.defaults'. -+ -+config EGLIBC_ADVANCED_INET6 -+ bool "IPv6 Advanced Sockets API support (RFC3542)" -+ depends on EGLIBC_INET -+ help -+ This option group includes the functions specified by RFC 3542, -+ "Advanced Sockets Application Program Interface (API) for -+ IPv6". -+ -+ This option group includes the following functions: -+ -+ inet6_opt_append -+ inet6_opt_find -+ inet6_opt_finish -+ inet6_opt_get_val -+ inet6_opt_init -+ inet6_option_alloc -+ inet6_option_append -+ inet6_option_find -+ inet6_option_init -+ inet6_option_next -+ inet6_option_space -+ inet6_opt_next -+ inet6_opt_set_val -+ inet6_rth_add -+ inet6_rth_getaddr -+ inet6_rth_init -+ inet6_rth_reverse -+ inet6_rth_segments -+ inet6_rth_space -+ -+config EGLIBC_BACKTRACE -+ bool "Functions for producing backtraces" -+ help -+ This option group includes functions for producing a list of -+ the function calls that are currently active in a thread, from -+ within the thread itself. These functions are often used -+ within signal handlers, to produce diagnostic output. -+ -+ This option group includes the following functions: -+ -+ backtrace -+ backtrace_symbols -+ backtrace_symbols_fd -+ -+config EGLIBC_BIG_MACROS -+ bool "Use extensive inline code" -+ help -+ This option group specifies whether certain pieces of code -+ should be inlined to achieve maximum speed. If this option -+ group is not selected, function calls will be used instead, -+ hence reducing the library footprint. -+ -+config EGLIBC_BSD -+ bool "BSD-specific functions, and their compatibility stubs" -+ help -+ This option group includes functions specific to BSD kernels. -+ A number of these functions have stub versions that are also -+ included in libraries built for non-BSD systems for -+ compatibility. -+ -+ This option group includes the following functions: -+ -+ chflags -+ fchflags -+ lchmod -+ revoke -+ setlogin -+ -+config EGLIBC_CXX_TESTS -+ bool "Tests that link against the standard C++ library." -+ depends on POSIX_WIDE_CHAR_DEVICE_IO && EGLIBC_LIBM -+ help -+ This option group does not include any C library functions; -+ instead, it controls which EGLIBC tests an ordinary 'make -+ tests' runs. With this group disabled, tests that would -+ normally link against the standard C++ library are not -+ run. -+ -+ The standard C++ library depends on the math library 'libm' and -+ the wide character I/O functions included in EGLIBC. So those -+ option groups must be enabled if this test is enabled. -+ -+config EGLIBC_CATGETS -+ bool "Functions for accessing message catalogs" -+ depends on EGLIBC_LOCALE_CODE -+ help -+ This option group includes functions for accessing message -+ catalogs: catopen, catclose, and catgets. -+ -+ This option group depends on the EGLIBC_LOCALE_CODE -+ option group. -+ -+config EGLIBC_CHARSETS -+ bool "iconv/gconv character set conversion libraries" -+ help -+ This option group includes support for character sets other -+ than ASCII (ANSI_X3.4-1968) and Unicode and ISO-10646 in their -+ various encodings. This affects both the character sets -+ supported by the wide and multibyte character functions, and -+ those supported by the 'iconv' functions. -+ -+ With this option group disabled, EGLIBC supports only the -+ following character sets: -+ -+ ANSI_X3.4 - ASCII -+ ANSI_X3.4-1968 -+ ANSI_X3.4-1986 -+ ASCII -+ CP367 -+ CSASCII -+ IBM367 -+ ISO-IR-6 -+ ISO646-US -+ ISO_646.IRV:1991 -+ OSF00010020 -+ US -+ US-ASCII -+ -+ 10646-1:1993 - ISO 10646, in big-endian UCS4 form -+ 10646-1:1993/UCS4 -+ CSUCS4 -+ ISO-10646 -+ ISO-10646/UCS4 -+ OSF00010104 -+ OSF00010105 -+ OSF00010106 -+ UCS-4 -+ UCS-4BE -+ UCS4 -+ -+ UCS-4LE - ISO 10646, in little-endian UCS4 form -+ -+ ISO-10646/UTF-8 - ISO 10646, in UTF-8 form -+ ISO-10646/UTF8 -+ ISO-IR-193 -+ OSF05010001 -+ UTF-8 -+ UTF8 -+ -+ ISO-10646/UCS2 - ISO 10646, in target-endian UCS2 form -+ OSF00010100 -+ OSF00010101 -+ OSF00010102 -+ UCS-2 -+ UCS2 -+ -+ UCS-2BE - ISO 10646, in big-endian UCS2 form -+ UNICODEBIG -+ -+ UCS-2LE - ISO 10646, in little-endian UCS2 form -+ UNICODELITTLE -+ -+ WCHAR_T - EGLIBC's internal form (target-endian, -+ 32-bit ISO 10646) -+ -+config EGLIBC_CRYPT -+ bool "Encryption library" -+ help -+ This option group includes the `libcrypt' library which -+ provides functions for one-way encryption. Supported -+ encryption algorithms include MD5, SHA-256, SHA-512 and DES. -+ -+config EGLIBC_CRYPT_UFC -+ bool "Ultra fast `crypt' implementation" -+ depends on EGLIBC_CRYPT -+ help -+ This option group provides ultra fast DES-based implementation of -+ the `crypt' function. When this option group is disabled, -+ (a) the library will not provide the setkey[_r] and encrypt[_r] -+ functions and (b) the crypt[_r] function will return NULL and set the -+ errno to ENOSYS if /salt/ passed does not correspond to either MD5, -+ SHA-256 or SHA-512 algorithm. -+ -+config EGLIBC_DB_ALIASES -+ bool "Functions for accessing the mail aliases database" -+ help -+ This option group includues functions for looking up mail -+ aliases in '/etc/aliases' or using nsswitch. It includes the -+ following functions: -+ -+ endaliasent -+ getaliasbyname -+ getaliasbyname_r -+ getaliasent -+ getaliasent_r -+ setaliasent -+ -+ When this option group is disabled, the NSS service libraries -+ also lack support for querying their mail alias tables. -+ -+config EGLIBC_ENVZ -+ bool "Functions for handling envz-style environment vectors." -+ help -+ This option group contains functions for creating and operating -+ on envz vectors. An "envz vector" is a vector of strings in a -+ contiguous block of memory, where each element is a name-value -+ pair, and elements are separated from their neighbors by null -+ characters. -+ -+ This option group includes the following functions: -+ -+ envz_add envz_merge -+ envz_entry envz_remove -+ envz_get envz_strip -+ -+config EGLIBC_FCVT -+ bool "Functions for converting floating-point numbers to strings" -+ help -+ This option group includes functions for converting -+ floating-point numbers to strings. -+ -+ This option group includes the following functions: -+ -+ ecvt qecvt -+ ecvt_r qecvt_r -+ fcvt qfcvt -+ fcvt_r qfcvt_r -+ gcvt qgcvt -+ -+config EGLIBC_FMTMSG -+ bool "Functions for formatting messages" -+ help -+ This option group includes the following functions: -+ -+ addseverity fmtmsg -+ -+config EGLIBC_FSTAB -+ bool "Access functions for 'fstab'" -+ help -+ This option group includes functions for reading the mount -+ point specification table, '/etc/fstab'. These functions are -+ not included in the POSIX standard, which provides the -+ 'getmntent' family of functions instead. -+ -+ This option group includes the following functions: -+ -+ endfsent getfsspec -+ getfsent setfsent -+ getfsfile -+ -+config EGLIBC_FTRAVERSE -+ bool "Functions for traversing file hierarchies" -+ help -+ This option group includes functions for traversing file -+ UNIX file hierachies. -+ -+ This option group includes the following functions: -+ -+ fts_open ftw -+ fts_read nftw -+ fts_children ftw64 -+ fts_set nftw64 -+ fts_close -+ -+config EGLIBC_GETLOGIN -+ bool "The getlogin function" -+ depends on EGLIBC_UTMP -+ help -+ This function group includes the 'getlogin' and 'getlogin_r' -+ functions, which return the user name associated by the login -+ activity with the current process's controlling terminal. -+ -+ With this option group disabled, the 'glob' function will not -+ fall back on 'getlogin' to find the user's login name for tilde -+ expansion when the 'HOME' environment variable is not set. -+ -+config EGLIBC_IDN -+ bool "International domain names support" -+ help -+ This option group includes the `libcidn' library which -+ provides support for international domain names. -+ -+config EGLIBC_INET -+ bool "Networking support" -+ help -+ This option group includes networking-specific functions and -+ data. With EGLIBC_INET disabled, the EGLIBC -+ installation and API changes as follows: -+ -+ - The following libraries are not installed: -+ -+ libnsl -+ libnss_compat -+ libnss_dns -+ libnss_hesiod -+ libnss_nis -+ libnss_nisplus -+ libresolv -+ -+ - The following functions and variables are omitted from libc: -+ -+ authdes_create hstrerror svc_fdset -+ authdes_getucred htonl svc_getreq -+ authdes_pk_create htons svc_getreq_common -+ authnone_create if_freenameindex svc_getreq_poll -+ authunix_create if_indextoname svc_getreqset -+ authunix_create_default if_nameindex svc_max_pollfd -+ bindresvport if_nametoindex svc_pollfd -+ callrpc in6addr_any svcraw_create -+ cbc_crypt in6addr_loopback svc_register -+ clnt_broadcast inet6_opt_append svc_run -+ clnt_create inet6_opt_find svc_sendreply -+ clnt_pcreateerror inet6_opt_finish svctcp_create -+ clnt_perrno inet6_opt_get_val svcudp_bufcreate -+ clnt_perror inet6_opt_init svcudp_create -+ clntraw_create inet6_option_alloc svcudp_enablecache -+ clnt_spcreateerror inet6_option_append svcunix_create -+ clnt_sperrno inet6_option_find svcunixfd_create -+ clnt_sperror inet6_option_init svc_unregister -+ clnttcp_create inet6_option_next user2netname -+ clntudp_bufcreate inet6_option_space xdecrypt -+ clntudp_create inet6_opt_next xdr_accepted_reply -+ clntunix_create inet6_opt_set_val xdr_array -+ des_setparity inet6_rth_add xdr_authdes_cred -+ ecb_crypt inet6_rth_getaddr xdr_authdes_verf -+ endaliasent inet6_rth_init xdr_authunix_parms -+ endhostent inet6_rth_reverse xdr_bool -+ endnetent inet6_rth_segments xdr_bytes -+ endnetgrent inet6_rth_space xdr_callhdr -+ endprotoent inet_addr xdr_callmsg -+ endrpcent inet_aton xdr_char -+ endservent inet_lnaof xdr_cryptkeyarg -+ ether_aton inet_makeaddr xdr_cryptkeyarg2 -+ ether_aton_r inet_netof xdr_cryptkeyres -+ ether_hostton inet_network xdr_des_block -+ ether_line inet_nsap_addr xdr_double -+ ether_ntoa inet_nsap_ntoa xdr_enum -+ ether_ntoa_r inet_ntoa xdr_float -+ ether_ntohost inet_ntop xdr_free -+ freeaddrinfo inet_pton xdr_getcredres -+ freeifaddrs innetgr xdr_hyper -+ gai_strerror iruserok xdr_int -+ getaddrinfo iruserok_af xdr_int16_t -+ getaliasbyname key_decryptsession xdr_int32_t -+ getaliasbyname_r key_decryptsession_pk xdr_int64_t -+ getaliasent key_encryptsession xdr_int8_t -+ getaliasent_r key_encryptsession_pk xdr_keybuf -+ gethostbyaddr key_gendes xdr_key_netstarg -+ gethostbyaddr_r key_get_conv xdr_key_netstres -+ gethostbyname key_secretkey_is_set xdr_keystatus -+ gethostbyname2 key_setnet xdr_long -+ gethostbyname2_r key_setsecret xdr_longlong_t -+ gethostbyname_r netname2host xdrmem_create -+ gethostent netname2user xdr_netnamestr -+ gethostent_r ntohl xdr_netobj -+ getifaddrs ntohs xdr_opaque -+ getipv4sourcefilter passwd2des xdr_opaque_auth -+ get_myaddress pmap_getmaps xdr_pmap -+ getnameinfo pmap_getport xdr_pmaplist -+ getnetbyaddr pmap_rmtcall xdr_pointer -+ getnetbyaddr_r pmap_set xdr_quad_t -+ getnetbyname pmap_unset xdrrec_create -+ getnetbyname_r rcmd xdrrec_endofrecord -+ getnetent rcmd_af xdrrec_eof -+ getnetent_r registerrpc xdrrec_skiprecord -+ getnetgrent res_init xdr_reference -+ getnetgrent_r rexec xdr_rejected_reply -+ getnetname rexec_af xdr_replymsg -+ getprotobyname rexecoptions xdr_rmtcall_args -+ getprotobyname_r rpc_createerr xdr_rmtcallres -+ getprotobynumber rresvport xdr_short -+ getprotobynumber_r rresvport_af xdr_sizeof -+ getprotoent rtime xdrstdio_create -+ getprotoent_r ruserok xdr_string -+ getpublickey ruserok_af xdr_u_char -+ getrpcbyname ruserpass xdr_u_hyper -+ getrpcbyname_r setaliasent xdr_u_int -+ getrpcbynumber sethostent xdr_uint16_t -+ getrpcbynumber_r setipv4sourcefilter xdr_uint32_t -+ getrpcent setnetent xdr_uint64_t -+ getrpcent_r setnetgrent xdr_uint8_t -+ getrpcport setprotoent xdr_u_long -+ getsecretkey setrpcent xdr_u_longlong_t -+ getservbyname setservent xdr_union -+ getservbyname_r setsourcefilter xdr_unixcred -+ getservbyport svcauthdes_stats xdr_u_quad_t -+ getservbyport_r svcerr_auth xdr_u_short -+ getservent svcerr_decode xdr_vector -+ getservent_r svcerr_noproc xdr_void -+ getsourcefilter svcerr_noprog xdr_wrapstring -+ h_errlist svcerr_progvers xencrypt -+ h_errno svcerr_systemerr xprt_register -+ herror svcerr_weakauth xprt_unregister -+ h_nerr svc_exit -+ host2netname svcfd_create -+ -+ - The rpcgen, nscd, and rpcinfo commands are not installed. -+ -+ - The 'rpc' file (a text file listing RPC services) is not installed. -+ -+ Socket-related system calls do not fall in this option group, -+ because many are also used for other inter-process -+ communication mechanisms. For example, the 'syslog' routines -+ use Unix-domain sockets to communicate with the syslog daemon; -+ syslog is valuable in non-networked contexts. -+ -+config EGLIBC_INET_ANL -+ bool "Asynchronous name lookup" -+ depends on EGLIBC_INET -+ help -+ This option group includes the `libanl' library which -+ provides support for asynchronous name lookup. -+ -+config EGLIBC_LIBM -+ bool "libm (math library)" -+ help -+ This option group includes the 'libm' library, containing -+ mathematical functions. If this option group is omitted, then -+ an EGLIBC installation does not include shared or unshared versions -+ of the math library. -+ -+ Note that this does not remove all floating-point related -+ functionality from EGLIBC; for example, 'printf' and 'scanf' -+ can still print and read floating-point values with this option -+ group disabled. -+ -+ Note that the ISO Standard C++ library 'libstdc++' depends on -+ EGLIBC's math library 'libm'. If you disable this option -+ group, you will not be able to build 'libstdc++' against the -+ resulting EGLIBC installation. -+ -+config EGLIBC_LOCALES -+ bool "Locale definitions" -+ help -+ This option group includes all locale definitions other than -+ that for the "C" locale. If this option group is omitted, then -+ only the "C" locale is supported. -+ -+ -+config EGLIBC_LOCALE_CODE -+ bool "Locale functions" -+ depends on POSIX_C_LANG_WIDE_CHAR -+ help -+ This option group includes locale support functions, programs, -+ and libraries. With EGLIBC_LOCALE_CODE disabled, -+ EGLIBC supports only the 'C' locale (also known as 'POSIX'), -+ and ignores the settings of the 'LANG' and 'LC_*' environment -+ variables. -+ -+ With EGLIBC_LOCALE_CODE disabled, the following -+ functions are omitted from libc: -+ -+ duplocale localeconv nl_langinfo rpmatch strfmon_l -+ freelocale newlocale nl_langinfo_l strfmon uselocale -+ -+ Furthermore, only the LC_CTYPE and LC_TIME categories of the -+ standard "C" locale are available. -+ -+ The EGLIBC_CATGETS option group depends on this option group. -+ -+ -+config EGLIBC_MEMUSAGE -+ bool "Memory profiling library" -+ help -+ This option group includes the `libmemusage' library and -+ the `memusage' and `memusagestat' utilities. -+ These components provide memory profiling functions. -+ -+config EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE -+ int "Memory profiling library buffer size" -+ depends on EGLIBC_MEMUSAGE -+ default "32768" -+ help -+ Libmemusage library buffers the profiling data in memory -+ before writing it out to disk. By default, the library -+ allocates 1.5M buffer, which can be substantial for some -+ systems. EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE option -+ allows to change the default buffer size. It specifies -+ the number of entries the buffer should have. -+ On most architectures one buffer entry amounts to 48 bytes, -+ so setting this option to the value of 512 will reduce the size of -+ the memory buffer to 24K. -+ -+config EGLIBC_NIS -+ bool "Support for NIS, NIS+, and the special 'compat' services." -+ depends on EGLIBC_INET && EGLIBC_SUNRPC -+ help -+ This option group includes the NIS, NIS+, and 'compat' Name -+ Service Switch service libraries. When it is disabled, those -+ services libraries are not installed; you should remove any -+ references to them from your 'nsswitch.conf' file. -+ -+ This option group depends on the EGLIBC_INET option -+ group; you must enable that to enable this option group. -+ -+config EGLIBC_NSSWITCH -+ bool "Name service switch (nsswitch) support" -+ help -+ This option group includes support for the 'nsswitch' facility. -+ With this option group enabled, all EGLIBC functions for -+ accessing various system databases (passwords and groups; -+ networking; aliases; public keys; and so on) consult the -+ '/etc/nsswitch.conf' configuration file to decide how to handle -+ queries. -+ -+ With this option group disabled, EGLIBC uses a fixed list of -+ services to satisfy queries on each database, as requested by -+ configuration files specified when EGLIBC is built. Your -+ 'option-groups.config' file must set the following two -+ variables: -+ -+config EGLIBC_NSSWITCH_FIXED_CONFIG -+ string "Nsswitch fixed config filename" -+ depends on !EGLIBC_NSSWITCH -+ default "" -+ help -+ Set this to the name of a file whose contents observe the -+ same syntax as an ordinary '/etc/nsswitch.conf' file. The -+ EGLIBC build process parses this file just as EGLIBC would -+ at run time if EGLIBC_NSSWITCH were enabled, and -+ produces a C library that uses the nsswitch service -+ libraries to search for database entries as this file -+ specifies, instead of consulting '/etc/nsswitch.conf' at run -+ time. -+ -+ This should be an absolute filename. The EGLIBC build -+ process may use it from several different working -+ directories. It may include references to Makefile -+ variables like 'common-objpfx' (the top of the build tree, -+ with a trailing slash), or '..' (the top of the source tree, -+ with a trailing slash). -+ -+ The EGLIBC source tree includes a sample configuration file -+ named 'nss/fixed-nsswitch.conf'; for simple configurations, -+ you will probably want to delete references to databases not -+ needed on your system. -+ -+config EGLIBC_NSSWITCH_FIXED_FUNCTIONS -+ string "Nsswitch fixed functions filename" -+ depends on !EGLIBC_NSSWITCH -+ default "" -+ help -+ The EGLIBC build process uses this file to decide which -+ functions to make available from which service libraries. -+ The file 'nss/fixed-nsswitch.functions' serves as a sample -+ configuration file for this setting, and explains its syntax -+ and meaning in more detail. -+ -+ This should be an absolute file name. The EGLIBC build -+ process may use it from several different working -+ directories. It may include references to Makefile -+ variables like 'common-objpfx' (the top of the build tree, -+ with a trailing slash), or '..' (the top of the source tree, -+ with a trailing slash). -+ -+ Be sure to mention each function in each service you wish to -+ use. If you do not mention a service's function here, the -+ EGLIBC database access functions will not find it, even if -+ it is listed in the EGLIBC_NSSWITCH_FIXED_CONFIG -+ file. -+ -+ In this arrangement, EGLIBC will not use the 'dlopen' and -+ 'dlsym' functions to find database access functions. Instead, -+ libc hard-codes references to the service libraries' database -+ access functions. You must explicitly link your program -+ against the name service libraries (those whose names start -+ with 'libnss_', in the sysroot's '/lib' directory) whose -+ functions you intend to use. This arrangement helps -+ system-wide static analysis tools decide which functions a -+ system actually uses. -+ -+ Note that some nsswitch service libraries require other option -+ groups to be enabled; for example, the EGLIBC_INET -+ option group must be enabled to use the 'libnss_dns.so.2' -+ service library, which uses the Domain Name System network -+ protocol to answer queries. -+ -+config EGLIBC_RCMD -+ bool "Support for 'rcmd' and related library functions" -+ depends on EGLIBC_INET -+ help -+ This option group includes functions for running commands on -+ remote machines via the 'rsh' protocol, and doing authentication -+ related to those functions. This also includes functions that -+ use the 'rexec' protocol. -+ -+ This option group includes the following functions: -+ -+ rcmd ruserok -+ rcmd_af ruserok_af -+ rexec iruserok -+ rexec_af iruserok_af -+ rresvport ruserpass -+ rresvport_af -+ -+config EGLIBC_RTLD_DEBUG -+ bool "Runtime linker debug print outs" -+ help -+ This option group enables debug output of the runtime linker -+ which is activated via LD_DEBUG and LD_TRACE_PRELINKING -+ environment variables. Disabling this option group yields -+ a smaller runtime linker binary. -+ BEWARE: Disabling this option group is likely to break -+ the `ldd' utility which may also be used by the prelinker. -+ In particular, the `--unused' ldd option will not work correctly. -+ -+config EGLIBC_SPAWN -+ bool "Support for POSIX posix_spawn functions" -+ help -+ This option group includes the POSIX functions for executing -+ programs in child processes without using 'fork' or 'vfork'. -+ -+ This option group includes the following functions: -+ -+ posix_spawn -+ posix_spawnattr_destroy -+ posix_spawnattr_getflags -+ posix_spawnattr_getpgroup -+ posix_spawnattr_getschedparam -+ posix_spawnattr_getschedpolicy -+ posix_spawnattr_getsigdefault -+ posix_spawnattr_getsigmask -+ posix_spawnattr_init -+ posix_spawnattr_setflags -+ posix_spawnattr_setpgroup -+ posix_spawnattr_setschedparam -+ posix_spawnattr_setschedpolicy -+ posix_spawnattr_setsigdefault -+ posix_spawnattr_setsigmask -+ posix_spawn_file_actions_addclose -+ posix_spawn_file_actions_adddup2 -+ posix_spawn_file_actions_addopen -+ posix_spawn_file_actions_destroy -+ posix_spawn_file_actions_init -+ posix_spawnp -+ -+ This option group also provides the ability for the iconv, -+ localedef, and locale programs to operate transparently on -+ compressed charset definitions. When this option group is -+ disabled, those programs will only operate on uncompressed -+ charmap files. -+ -+config EGLIBC_STREAMS -+ bool "Support for accessing STREAMS." -+ help -+ This option group includes functions for reading and writing -+ messages to and from STREAMS. The STREAMS interface provides a -+ uniform mechanism for implementing networking services and other -+ character-based I/O. (STREAMS are not to be confused with -+ FILE objects, also called 'streams'.) -+ -+ This option group includes the following functions: -+ -+ getmsg putpmsg -+ getpmsg fattach -+ isastream fdetach -+ putmsg -+ -+config EGLIBC_SUNRPC -+ bool "Support for the Sun 'RPC' protocol." -+ depends on EGLIBC_INET -+ help -+ This option group includes support for the Sun RPC protocols, -+ including the 'rpcgen' and 'rpcinfo' programs. -+ -+config EGLIBC_UTMP -+ bool "Older access functions for 'utmp' login records" -+ help -+ This option group includes the older 'utent' family of -+ functions for accessing user login records in the 'utmp' file. -+ POSIX omits these functions in favor of the 'utxent' family, -+ and they are obsolete on systems other than Linux. -+ -+ This option group includes the following functions: -+ -+ endutent -+ getutent -+ getutent_r -+ getutid -+ getutid_r -+ getutline -+ getutline_r -+ logwtmp -+ pututline -+ setutent -+ updwtmp -+ utmpname -+ -+ This option group includes the following libraries: -+ -+ libutil.so (and libutil.a) -+ -+config EGLIBC_UTMPX -+ bool "POSIX access functions for 'utmp' login records" -+ depends on EGLIBC_UTMP -+ help -+ This option group includes the POSIX functions for reading and -+ writing user login records in the 'utmp' file (usually -+ '/var/run/utmp'). The POSIX functions operate on 'struct -+ utmpx' structures, as opposed to the family of older 'utent' -+ functions, which operate on 'struct utmp' structures. -+ -+ This option group includes the following functions: -+ -+ endutxent -+ getutmp -+ getutmpx -+ getutxent -+ getutxid -+ getutxline -+ pututxline -+ setutxent -+ updwtmpx -+ utmpxname -+ -+config EGLIBC_WORDEXP -+ bool "Shell-style word expansion" -+ help -+ This option group includes the 'wordexp' function for -+ performing word expansion in the manner of the shell, and the -+ accompanying 'wordfree' function. -+ -+config POSIX_C_LANG_WIDE_CHAR -+ bool "ISO C library wide character functions, excluding I/O" -+ help -+ This option group includes the functions defined by the ISO C -+ standard for working with wide and multibyte characters in -+ memory. Functions for reading and writing wide and multibyte -+ characters from and to files call in the -+ POSIX_WIDE_CHAR_DEVICE_IO option group. -+ -+ This option group includes the following functions: -+ -+ btowc mbsinit wcscspn wcstoll -+ iswalnum mbsrtowcs wcsftime wcstombs -+ iswalpha mbstowcs wcslen wcstoul -+ iswblank mbtowc wcsncat wcstoull -+ iswcntrl swprintf wcsncmp wcstoumax -+ iswctype swscanf wcsncpy wcsxfrm -+ iswdigit towctrans wcspbrk wctob -+ iswgraph towlower wcsrchr wctomb -+ iswlower towupper wcsrtombs wctrans -+ iswprint vswprintf wcsspn wctype -+ iswpunct vswscanf wcsstr wmemchr -+ iswspace wcrtomb wcstod wmemcmp -+ iswupper wcscat wcstof wmemcpy -+ iswxdigit wcschr wcstoimax wmemmove -+ mblen wcscmp wcstok wmemset -+ mbrlen wcscoll wcstol -+ mbrtowc wcscpy wcstold -+ -+config POSIX_REGEXP -+ bool "Regular expressions" -+ help -+ This option group includes the POSIX regular expression -+ functions, and the associated non-POSIX extensions and -+ compatibility functions. -+ -+ With POSIX_REGEXP disabled, the following functions are -+ omitted from libc: -+ -+ re_comp re_max_failures regcomp -+ re_compile_fastmap re_search regerror -+ re_compile_pattern re_search_2 regexec -+ re_exec re_set_registers regfree -+ re_match re_set_syntax rpmatch -+ re_match_2 re_syntax_options -+ -+ Furthermore, the compatibility regexp interface defined in the -+ header file, 'compile', 'step', and 'advance', is -+ omitted. -+ -+config POSIX_REGEXP_GLIBC -+ bool "Regular expressions from GLIBC" -+ depends on POSIX_REGEXP -+ help -+ This option group specifies which regular expression -+ library to use. The choice is between regex -+ implementation from GLIBC and regex implementation from -+ libiberty. The GLIBC variant is fully POSIX conformant and -+ optimized for speed; regex from libiberty is more than twice -+ as small while still is enough for most practical purposes. -+ -+config POSIX_WIDE_CHAR_DEVICE_IO -+ bool "Input and output functions for wide characters" -+ depends on POSIX_C_LANG_WIDE_CHAR -+ help -+ This option group includes functions for reading and writing -+ wide characters to and from streams. -+ -+ This option group includes the following functions: -+ -+ fgetwc fwprintf putwchar vwscanf -+ fgetws fwscanf ungetwc wprintf -+ fputwc getwc vfwprintf wscanf -+ fputws getwchar vfwscanf -+ fwide putwc vwprintf -+ -+ This option group further includes the following unlocked -+ variants of the above functions: -+ -+ fgetwc_unlocked getwc_unlocked -+ fgetws_unlocked getwchar_unlocked -+ fputwc_unlocked putwc_unlocked -+ fputws_unlocked putwchar_unlocked -+ -+ Note that the GNU standard C++ library, 'libstdc++.so', uses -+ some of these functions; you will not be able to link or run -+ C++ programs if you disable this option group. -+ -+ This option group also affects the behavior of the following -+ functions: -+ -+ fdopen -+ fopen -+ fopen64 -+ freopen -+ freopen64 -+ -+ These functions all take an OPENTYPE parameter which may -+ contain a string of the form ",ccs=CHARSET", indicating that -+ the underlying file uses the character set named CHARSET. -+ This produces a wide-oriented stream, which is only useful -+ when the functions included in this option group are present. -+ If the user attempts to open a file specifying a character set -+ in the OPENTYPE parameter, and EGLIBC was built with this -+ option group disabled, the function returns NULL, and sets -+ errno to EINVAL. -+ -+ -+# This helps Emacs users browse this file using the page motion commands -+# and commands like 'pages-directory'. -+# Local Variables: -+# page-delimiter: "^config\\s-" -+# End: -Index: git/option-groups.mak -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/option-groups.mak 2014-08-27 07:26:51.652070587 +0000 -@@ -0,0 +1,41 @@ -+# Setup file for subdirectory Makefiles that define EGLIBC option groups. -+ -+# EGLIBC shouldn't need to override this. However, the -+# cross-build-friendly localedef includes this makefile to get option -+# group variable definitions; it uses a single build tree for all the -+# multilibs, and needs to be able to specify a different option group -+# configuration file for each multilib. -+option_group_config_file ?= $(objdir)/option-groups.config -+ -+# Read the default settings for all options. -+# We're included before ../Rules, so we can't assume $(..) is set. -+include $(firstword $(..) ../)option-groups.defaults -+ -+# Read the developer's option group selections, overriding the -+# defaults from option-groups.defaults. -+-include $(option_group_config_file) -+ -+# $(call option-disabled, VAR) is 'y' if VAR is not 'y', or 'n' otherwise. -+# VAR should be a variable name, not a variable reference; this is -+# less general, but more terse for the intended use. -+# You can use it to add a file to a list if an option group is -+# disabled, like this: -+# routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += ... -+define option-disabled -+$(firstword $(subst y,n,$(filter y,$($(strip $(1))))) y) -+endef -+ -+# Establish 'routines-y', etc. as simply-expanded variables. -+aux-y := -+extra-libs-others-y := -+extra-libs-y := -+extra-objs-y := -+install-bin-y := -+install-others-y := -+install-sbin-y := -+others-y := -+others-pie-y := -+routines-y := -+test-srcs-y := -+tests-y := -+xtests-y := -Index: git/option-groups.defaults -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/option-groups.defaults 2014-08-27 07:24:41.652070587 +0000 -@@ -0,0 +1,47 @@ -+# This file sets default values for all option group variables -+# mentioned in option-groups.def; see that file for a description of -+# each option group. -+# -+# Subdirectory makefiles include this file before including the user's -+# settings from option-groups.config at the top of the build tree; -+# that file need only refer to those options whose default settings -+# are to be changed. -+# -+# By default, all option groups are enabled. -+OPTION_EGLIBC_ADVANCED_INET6 = y -+OPTION_EGLIBC_BACKTRACE = y -+OPTION_EGLIBC_BIG_MACROS = y -+OPTION_EGLIBC_BSD = y -+OPTION_EGLIBC_CXX_TESTS = y -+OPTION_EGLIBC_CATGETS = y -+OPTION_EGLIBC_CHARSETS = y -+OPTION_EGLIBC_CRYPT = y -+OPTION_EGLIBC_CRYPT_UFC = y -+OPTION_EGLIBC_DB_ALIASES = y -+OPTION_EGLIBC_ENVZ = y -+OPTION_EGLIBC_FCVT = y -+OPTION_EGLIBC_FMTMSG = y -+OPTION_EGLIBC_FSTAB = y -+OPTION_EGLIBC_FTRAVERSE = y -+OPTION_EGLIBC_GETLOGIN = y -+OPTION_EGLIBC_IDN = y -+OPTION_EGLIBC_INET = y -+OPTION_EGLIBC_INET_ANL = y -+OPTION_EGLIBC_LIBM = y -+OPTION_EGLIBC_LOCALES = y -+OPTION_EGLIBC_LOCALE_CODE = y -+OPTION_EGLIBC_MEMUSAGE = y -+OPTION_EGLIBC_NIS = y -+OPTION_EGLIBC_NSSWITCH = y -+OPTION_EGLIBC_RCMD = y -+OPTION_EGLIBC_RTLD_DEBUG = y -+OPTION_EGLIBC_SPAWN = y -+OPTION_EGLIBC_STREAMS = y -+OPTION_EGLIBC_SUNRPC = y -+OPTION_EGLIBC_UTMP = y -+OPTION_EGLIBC_UTMPX = y -+OPTION_EGLIBC_WORDEXP = y -+OPTION_POSIX_C_LANG_WIDE_CHAR = y -+OPTION_POSIX_REGEXP = y -+OPTION_POSIX_REGEXP_GLIBC = y -+OPTION_POSIX_WIDE_CHAR_DEVICE_IO = y -Index: git/Makefile -=================================================================== ---- git.orig/Makefile 2014-08-27 07:24:37.540070587 +0000 -+++ git/Makefile 2014-08-27 07:24:41.656070587 +0000 -@@ -24,6 +24,7 @@ - - include Makeconfig - -+include options-config/Makefile - - # This is the default target; it makes everything except the tests. - .PHONY: all -Index: git/EGLIBC.option-groups -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/EGLIBC.option-groups 2014-08-27 07:24:41.656070587 +0000 -@@ -0,0 +1,122 @@ -+ -*- mode: text -*- -+ -+ The EGLIBC Component Configuration System -+ Jim Blandy -+ -+Introduction -+ -+The GNU C library (GLIBC) provides a broad range of functionality, -+ranging from internationalization support to transcendental -+mathematical functions. Its website boasts that "nearly all known and -+useful functions from any other C library are available." This -+exhaustive approach has been one of GLIBC's strengths on desktop and -+server systems, but it has also given GLIBC a large footprint, both in -+memory and on disk, making it a challenge to use in embedded systems -+with limited resources. -+ -+The Embedded GNU C library (EGLIBC) is a variant of the GNU C library -+designed to work well on embedded systems. In particular, EGLIBC's -+component configuration system allows embedded developers to build -+customized versions of the library that include only the features -+their application uses, reducing its space requirements. -+ -+EGLIBC's component configuration system categorizes the library's -+functions into "option groups", and allows you to include or exclude -+option groups individually. Some option groups depend on others; -+EGLIBC tracks these relationships, and ensures that the selected -+configuration yields a functioning library. -+ -+ -+Consistent and Predictable Behavior -+ -+A flexible configuration system is a mixed blessing: if the options -+offered are poorly designed, it can be hard to see which choices will -+have the desired effects, and choices with obscure consequences can -+make debugging difficult. EGLIBC's configuration follows some general -+principles to reduce these risks: -+ -+- EGLIBC has a single default configuration for each target -+ architecture. -+ -+- In the default configuration, all option groups are enabled, and -+ EGLIBC is upwardly API- and ABI-compatible with GLIBC. -+ -+- As much as possible, configurations only affect what functions are -+ present, not how they behave. If the system works with an option -+ group disabled, it will still work with it enabled. -+ -+- As much as possible, configurations only select option groups --- -+ they do not describe characteristics of the target architecture. -+ -+These rules mean that you have a simple debugging strategy available -+if you suspect that your EGLIBC configuration might be the source of a -+problem: fall back to the default configuration, re-test, and then -+disable option groups one by one, until the problem reappears. -+ -+ -+The Option Groups -+ -+To see the current full list of implemented option groups, refer to the -+file 'option-groups.def' at the top of the source tree, or run -+'make menuconfig' from the top-level build directory. -+ -+The POSIX.1-2001 specification includes a suggested partition of all -+the functions in the POSIX C API into option groups: math functions -+like 'sin' and 'cos'; networking functions like 'socket' and -+'connect'; and so on. EGLIBC could use this partitioning as the basis -+for future option groups. -+ -+ -+Implementation -+ -+The EGLIBC component configuration system resembles the approach used -+by the Linux kernel to select device drivers, network protocols, and -+other features. A file named 'option-groups.config' in the top-level -+build directory contains assignments to Make variables, each of which -+enables or disables a particular option group. If the variable's -+value is set to 'y', then the option group is enabled; if it set to -+anything else, the option group is omitted. The file -+'option-groups.defaults', at the top of the source tree, establishes -+default values for all variables; all option groups are enabled by -+default. -+ -+For example, the following 'option-groups.config' would omit locale -+data, but include mathematical functions, and everything else: -+ -+ OPTION_EGLIBC_LOCALES = n -+ OPTION_EGLIBC_LIBM = y -+ -+Like the Linux kernel, EGLIBC supports a similar set of '*config' make -+targets to make it easier to create 'option-groups.config', with all -+dependencies between option groups automatically satisfied. Run -+'make help' to see the list of supported make config targets. For -+example, 'make menuconfig' will update the current config utilising a -+menu based program. -+ -+The option group names and their type (boolean, int, hex, string), help -+description, and dependencies with other option groups, are described by -+'option-groups.def' at the top of the source tree, analogous to the -+'Kconfig' files in the Linux kernel. -+ -+In general, each option group variable controls whether a given set of -+object files in EGLIBC is compiled and included in the final -+libraries, or omitted from the build. -+ -+Each subdirectory's Makefile categorizes its routines, libraries, and -+executables by option group. For example, EGLIBC's 'math/Makefile' -+places the 'libm' library in the OPTION_EGLIBC_LIBM group as follows: -+ -+ extra-libs-$(OPTION_EGLIBC_LIBM) := libm -+ -+Finally, common code in 'Makerules' cites the value of the variable -+'extra-libs-y', selecting only those libraries that belong to enabled -+option groups to be built. -+ -+ -+Current Status and Future Directions -+ -+The EGLIBC component configuration system described here is still -+under development. -+ -+We have used the system to subset some portions of EGLIBC's -+Index: libc/configure.ac -Index: git/configure.ac -=================================================================== ---- git.orig/configure.ac 2014-08-27 07:24:41.196070587 +0000 -+++ git/configure.ac 2014-08-27 07:24:41.656070587 +0000 -@@ -127,6 +127,16 @@ - [sysheaders='']) - AC_SUBST(sysheaders) - -+AC_ARG_WITH([kconfig], -+ AC_HELP_STRING([--with-kconfig=PATH], -+ [location of kconfig tools to use (from Linux -+ kernel builds) to re-use for configuring EGLIBC -+ option groups]), -+ [KCONFIG_TOOLS=$withval], -+ [KCONFIG_TOOLS='']) -+AC_SUBST(KCONFIG_TOOLS) -+ -+ - AC_SUBST(use_default_link) - AC_ARG_WITH([default-link], - AC_HELP_STRING([--with-default-link], -Index: git/config.make.in -=================================================================== ---- git.orig/config.make.in 2014-08-27 07:24:37.560070587 +0000 -+++ git/config.make.in 2014-08-27 07:24:41.656070587 +0000 -@@ -46,6 +46,8 @@ - c++-sysincludes = @CXX_SYSINCLUDES@ - all-warnings = @all_warnings@ - -+kconfig_tools = @KCONFIG_TOOLS@ -+ - have-z-combreloc = @libc_cv_z_combreloc@ - have-z-execstack = @libc_cv_z_execstack@ - have-Bgroup = @libc_cv_Bgroup@ -Index: git/configure -=================================================================== ---- git.orig/configure 2014-08-27 07:24:41.192070587 +0000 -+++ git/configure 2014-08-27 07:24:41.660070587 +0000 -@@ -619,6 +619,7 @@ - PERL - BASH_SHELL - libc_cv_gcc_static_libgcc -+KCONFIG_TOOLS - CXX_SYSINCLUDES - SYSINCLUDES - AUTOCONF -@@ -733,6 +734,7 @@ - with_binutils - with_selinux - with_headers -+with_kconfig - with_default_link - enable_sanity_checks - enable_shared -@@ -1437,6 +1439,9 @@ - --with-selinux if building with SELinux support - --with-headers=PATH location of system headers to use (for example - /usr/src/linux/include) [default=compiler default] -+ --with-kconfig=PATH location of kconfig tools to use (from Linux kernel -+ builds) to re-use for configuring EGLIBC option -+ groups - --with-default-link do not use explicit linker scripts - --with-cpu=CPU select code for CPU variant - -@@ -3400,6 +3405,14 @@ - - - -+# Check whether --with-kconfig was given. -+if test "${with_kconfig+set}" = set; then -+ withval=$with_kconfig; KCONFIG_TOOLS=$withval -+else -+ KCONFIG_TOOLS='' -+fi -+ -+ - - # Check whether --with-default-link was given. - if test "${with_default_link+set}" = set; then : -Index: git/options-config/Makefile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/options-config/Makefile 2014-08-27 07:24:41.652070587 +0000 -@@ -0,0 +1,55 @@ -+# =========================================================================== -+# EGLIBC option-groups configuration targets -+# These targets are included from top-level makefile -+ -+ifneq ($(kconfig_tools),) -+ifneq (no,$(PERL)) -+ -+ocdir := options-config -+ -+OconfigDefaults := option-groups.defaults -+OconfigDefaults_tmp := $(common-objpfx).tmp.defconfig -+OconfigDef := option-groups.def -+Oconfig := $(common-objpfx)option-groups.config -+Oconfig_tmp := $(common-objpfx).tmp.config -+ -+conf := $(kconfig_tools)/conf -+mconf := $(kconfig_tools)/mconf -+ -+preproc := $(PERL) $(ocdir)/config-preproc.pl -+postproc := $(PERL) $(ocdir)/config-postproc.pl -+ -+PHONY += defconfig config menuconfig -+ -+defconfig: $(conf) $(OconfigDefaults) $(OconfigDef) -+ rm -f $(OconfigDefaults_tmp) -+ rm -f $(Oconfig_tmp) -+ $(preproc) $(OconfigDefaults) > $(OconfigDefaults_tmp) -+ KCONFIG_CONFIG=$(Oconfig_tmp) $< --defconfig=$(OconfigDefaults_tmp) \ -+ $(OconfigDef) -+ $(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig) -+ rm $(Oconfig_tmp) -+ rm $(OconfigDefaults_tmp) -+ -+config: $(conf) $(OconfigDefaults) $(OconfigDef) -+ rm -f $(Oconfig_tmp) -+ $(preproc) $(wildcard $(Oconfig)) > $(Oconfig_tmp) -+ KCONFIG_CONFIG=$(Oconfig_tmp) $< --oldaskconfig $(OconfigDef) -+ $(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig) -+ rm $(Oconfig_tmp) -+ -+menuconfig: $(mconf) $(OconfigDefaults) $(OconfigDef) -+ rm -f $(Oconfig_tmp) -+ $(preproc) $(wildcard $(Oconfig)) > $(Oconfig_tmp) -+ KCONFIG_CONFIG=$(Oconfig_tmp) $< $(OconfigDef) -+ $(postproc) $(OconfigDefaults) $(Oconfig_tmp) > $(Oconfig) -+ rm $(Oconfig_tmp) -+ -+# Help text used by make help -+help: -+ @echo ' defconfig - New config with default from default config' -+ @echo ' config - Update current config utilising a line-oriented program' -+ @echo ' menuconfig - Update current config utilising a menu based program' -+ -+endif -+endif -Index: git/options-config/config-postproc.pl -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/options-config/config-postproc.pl 2014-08-27 07:24:41.652070587 +0000 -@@ -0,0 +1,58 @@ -+#!/usr/bin/perl -+ -+$usage = "usage: $0 \n"; -+ -+die "$usage" unless @ARGV; -+$defaults = shift @ARGV; -+die "$usage" unless @ARGV; -+die "Could not open $ARGV[0]" unless -T $ARGV[0]; -+ -+sub yank { -+ @option = grep(!($_ =~ /$_[0]\s*=/), @option); -+} -+ -+open(DEFAULTS, $defaults) || die "Could not open $defaults\n"; -+ -+# get the full list of available options using the default config file -+$i = 0; -+while () { -+ if (/^\s*OPTION_(\w+\s*=.*$)/) { -+ $option[$i++] = $1; -+ } -+} -+ -+# now go through the config file, making the necessary changes -+while (<>) { -+ if (/Linux Kernel Configuration/) { -+ # change title -+ s/Linux Kernel/Option Groups/; -+ print; -+ } elsif (/^\s*CONFIG_(\w+)\s*=/) { -+ # this is an explicit option set line, change CONFIG_ to OPTION_ -+ # before printing and remove this option from option list -+ $opt = $1; -+ yank($opt); -+ s/CONFIG_/OPTION_/g; -+ print; -+ } elsif (/^\s*#\s+CONFIG_(\w+) is not set/) { -+ # this is a comment line for an unset boolean option, change CONFIG_ -+ # to OPTION_, remove this option from option list, and convert to -+ # explicit OPTION_FOO=n -+ $opt = $1; -+ yank($opt); -+ s/CONFIG_/OPTION_/g; -+ print "OPTION_$opt=n\n"; -+ } else { -+ print; -+ } -+} -+ -+# any boolean options left in @options, are options that were not mentioned in -+# the config file, and implicitly that means the option must be set =n, -+# so do that here. -+foreach $opt (@option) { -+ if ($opt =~ /=\s*[yn]/) { -+ $opt =~ s/=\s*[yn]/=n/; -+ print "OPTION_$opt\n"; -+ } -+} -Index: git/options-config/config-preproc.pl -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/options-config/config-preproc.pl 2014-08-27 07:24:41.652070587 +0000 -@@ -0,0 +1,8 @@ -+#!/usr/bin/perl -+ -+if (@ARGV) { -+ while (<>) { -+ s/OPTION_/CONFIG_/g; -+ print; -+ } -+} -Index: git/scripts/option-groups.awk -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/scripts/option-groups.awk 2014-08-27 07:26:51.652070587 +0000 -@@ -0,0 +1,63 @@ -+# option-groups.awk --- generate option group header file -+# Given input files containing makefile-style assignments to variables, -+# print out a header file that #defines an appropriate preprocessor -+# symbol for each variable left set to 'y'. -+ -+BEGIN { FS="=" } -+ -+# Trim spaces. -+{ gsub (/[[:blank:]]/, "") } -+ -+# Skip comments. -+/^#/ { next } -+ -+# Process assignments. -+NF == 2 { -+ vars[$1] = $2 -+} -+ -+# Print final values. -+END { -+ print "/* This file is automatically generated by scripts/option-groups.awk" -+ print " in the EGLIBC source tree." -+ print "" -+ print " It defines macros that indicate which EGLIBC option groups were" -+ print " configured in 'option-groups.config' when this C library was" -+ print " built. For each option group named OPTION_foo, it #defines" -+ print " __OPTION_foo to be 1 if the group is enabled, or #defines that" -+ print " symbol to be 0 if the group is disabled. */" -+ print "" -+ print "#ifndef __GNU_OPTION_GROUPS_H" -+ print "#define __GNU_OPTION_GROUPS_H" -+ print "" -+ -+ # Produce a sorted list of variable names. -+ i=0 -+ for (var in vars) -+ names[i++] = var -+ n = asort (names) -+ -+ for (i = 1; i <= n; i++) -+ { -+ var = names[i] -+ if (var ~ /^OPTION_/) -+ { -+ if (vars[var] == "y") -+ print "#define __" var " 1" -+ else if (vars[var] == "n") -+ print "#define __" var " 0" -+ else if (vars[var] ~ /^[0-9]+/ || -+ vars[var] ~ /^0x[0-9aAbBcCdDeEfF]+/ || -+ vars[var] ~ /^\"/) -+ print "#define __" var " " vars[var] -+ else -+ print "/* #undef __" var " */" -+ # Ignore variables that don't have boolean, int, hex, or -+ # string values. Ideally, this would be driven by the types -+ # given in option-groups.def. -+ } -+ } -+ -+ print "" -+ print "#endif /* __GNU_OPTION_GROUPS_H */" -+} diff --git a/meta/recipes-core/glibc/glibc/ppc-sqrt_finite.patch b/meta/recipes-core/glibc/glibc/ppc-sqrt_finite.patch deleted file mode 100644 index 6ea666b1d6..0000000000 --- a/meta/recipes-core/glibc/glibc/ppc-sqrt_finite.patch +++ /dev/null @@ -1,184 +0,0 @@ -on ppc fixes the errors like below -| ./.libs/libpulsecore-1.1.so: undefined reference to `__sqrt_finite' -| collect2: ld returned 1 exit status - -Upstream-Status: Pending - -ChangeLog - -2012-01-06 Khem Raj - - * sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c: Add __*_finite alias. - Remove cruft. - * sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c: Ditto. - * sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c: Ditto. - * sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c: Ditto. - -Index: libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c -+++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c -@@ -39,14 +39,8 @@ static const float half = 0.5; - We find the actual square root and half of its reciprocal - simultaneously. */ - --#ifdef __STDC__ - double - __ieee754_sqrt (double b) --#else --double --__ieee754_sqrt (b) -- double b; --#endif - { - if (__builtin_expect (b > 0, 1)) - { -@@ -132,3 +126,4 @@ __ieee754_sqrt (b) - } - return f_wash (b); - } -+strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c -+++ libc/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c -@@ -37,14 +37,8 @@ static const float threehalf = 1.5; - We find the reciprocal square root and use that to compute the actual - square root. */ - --#ifdef __STDC__ - float - __ieee754_sqrtf (float b) --#else --float --__ieee754_sqrtf (b) -- float b; --#endif - { - if (__builtin_expect (b > 0, 1)) - { -@@ -99,3 +93,4 @@ __ieee754_sqrtf (b) - } - return f_washf (b); - } -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c -+++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c -@@ -39,14 +39,8 @@ static const float half = 0.5; - We find the actual square root and half of its reciprocal - simultaneously. */ - --#ifdef __STDC__ - double - __ieee754_sqrt (double b) --#else --double --__ieee754_sqrt (b) -- double b; --#endif - { - if (__builtin_expect (b > 0, 1)) - { -@@ -132,3 +126,4 @@ __ieee754_sqrt (b) - } - return f_wash (b); - } -+strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c -+++ libc/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c -@@ -37,14 +37,8 @@ static const float threehalf = 1.5; - We find the reciprocal square root and use that to compute the actual - square root. */ - --#ifdef __STDC__ - float - __ieee754_sqrtf (float b) --#else --float --__ieee754_sqrtf (b) -- float b; --#endif - { - if (__builtin_expect (b > 0, 1)) - { -@@ -99,3 +93,4 @@ __ieee754_sqrtf (b) - } - return f_washf (b); - } -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c -+++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c -@@ -132,3 +132,4 @@ __ieee754_sqrt (b) - } - return f_wash (b); - } -+strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c -+++ libc/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c -@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) - } - return f_washf (b); - } -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c -+++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c -@@ -132,3 +132,4 @@ __ieee754_sqrt (b) - } - return f_wash (b); - } -+strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c -+++ libc/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c -@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) - } - return f_washf (b); - } -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c -+++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c -@@ -132,3 +132,4 @@ __ieee754_sqrt (b) - } - return f_wash (b); - } -+strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c -+++ libc/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c -@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) - } - return f_washf (b); - } -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c -+++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c -@@ -132,3 +132,4 @@ __ieee754_sqrt (b) - } - return f_wash (b); - } -+strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c -=================================================================== ---- libc.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c -+++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c -@@ -99,3 +99,4 @@ __ieee754_sqrtf (b) - } - return f_washf (b); - } -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) diff --git a/meta/recipes-core/glibc/glibc/ppc_slow_ieee754_sqrt.patch b/meta/recipes-core/glibc/glibc/ppc_slow_ieee754_sqrt.patch deleted file mode 100644 index 5b819bc458..0000000000 --- a/meta/recipes-core/glibc/glibc/ppc_slow_ieee754_sqrt.patch +++ /dev/null @@ -1,365 +0,0 @@ - __ieee754_sqrt{,f} are now inline functions and call out __slow versions - - -Signed-off-by: Khem Raj -Upstream-Status: Pending -Index: git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c 2014-08-29 10:35:02.604070587 -0700 -@@ -40,7 +40,7 @@ - simultaneously. */ - - double --__ieee754_sqrt (double b) -+__slow_ieee754_sqrt (double b) - { - if (__builtin_expect (b > 0, 1)) - { -@@ -77,7 +77,7 @@ - - /* Handle small numbers by scaling. */ - if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -- return __ieee754_sqrt (b * two108) * twom54; -+ return __slow_ieee754_sqrt (b * two108) * twom54; - - #define FMADD(a_, c_, b_) \ - ({ double __r; \ -@@ -126,4 +126,12 @@ - } - return f_wash (b); - } -+ -+#undef __ieee754_sqrt -+double -+__ieee754_sqrt (double x) -+{ -+ return __slow_ieee754_sqrt (x); -+} -+ - strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c 2014-08-29 10:35:02.604070587 -0700 -@@ -38,7 +38,7 @@ - square root. */ - - float --__ieee754_sqrtf (float b) -+__slow_ieee754_sqrtf (float b) - { - if (__builtin_expect (b > 0, 1)) - { -@@ -93,4 +93,10 @@ - } - return f_washf (b); - } -+#undef __ieee754_sqrtf -+float -+__ieee754_sqrtf (float x) -+{ -+ return __slow_ieee754_sqrtf (x); -+} - strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c 2014-08-29 10:35:02.604070587 -0700 -@@ -40,7 +40,7 @@ - simultaneously. */ - - double --__ieee754_sqrt (double b) -+__slow_ieee754_sqrt (double b) - { - if (__builtin_expect (b > 0, 1)) - { -@@ -77,7 +77,7 @@ - - /* Handle small numbers by scaling. */ - if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -- return __ieee754_sqrt (b * two108) * twom54; -+ return __slow_ieee754_sqrt (b * two108) * twom54; - - #define FMADD(a_, c_, b_) \ - ({ double __r; \ -@@ -126,4 +126,12 @@ - } - return f_wash (b); - } -+ -+#undef __ieee754_sqrt -+double -+__ieee754_sqrt (double x) -+{ -+ return __slow_ieee754_sqrt (x); -+} -+ - strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c 2014-08-29 10:35:02.604070587 -0700 -@@ -38,7 +38,7 @@ - square root. */ - - float --__ieee754_sqrtf (float b) -+__slow_ieee754_sqrtf (float b) - { - if (__builtin_expect (b > 0, 1)) - { -@@ -93,4 +93,11 @@ - } - return f_washf (b); - } -+#undef __ieee754_sqrtf -+float -+__ieee754_sqrtf (float x) -+{ -+ return __slow_ieee754_sqrtf (x); -+} -+ - strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c 2014-08-29 10:35:02.604070587 -0700 -@@ -41,10 +41,10 @@ - - #ifdef __STDC__ - double --__ieee754_sqrt (double b) -+__slow_ieee754_sqrt (double b) - #else - double --__ieee754_sqrt (b) -+__slow_ieee754_sqrt (b) - double b; - #endif - { -@@ -83,7 +83,7 @@ - - /* Handle small numbers by scaling. */ - if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -- return __ieee754_sqrt (b * two108) * twom54; -+ return __slow_ieee754_sqrt (b * two108) * twom54; - - #define FMADD(a_, c_, b_) \ - ({ double __r; \ -@@ -132,4 +132,12 @@ - } - return f_wash (b); - } -+ -+#undef __ieee754_sqrt -+double -+__ieee754_sqrt (double x) -+{ -+ return __slow_ieee754_sqrt (x); -+} -+ - strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c 2014-08-29 10:35:02.604070587 -0700 -@@ -39,10 +39,10 @@ - - #ifdef __STDC__ - float --__ieee754_sqrtf (float b) -+__slow_ieee754_sqrtf (float b) - #else - float --__ieee754_sqrtf (b) -+__slow_ieee754_sqrtf (b) - float b; - #endif - { -@@ -99,4 +99,12 @@ - } - return f_washf (b); - } -+ -+#undef __ieee754_sqrtf -+float -+__ieee754_sqrtf (float x) -+{ -+ return __slow_ieee754_sqrtf (x); -+} -+ - strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c 2014-08-29 10:35:02.608070587 -0700 -@@ -41,10 +41,10 @@ - - #ifdef __STDC__ - double --__ieee754_sqrt (double b) -+__slow_ieee754_sqrt (double b) - #else - double --__ieee754_sqrt (b) -+__slow_ieee754_sqrt (b) - double b; - #endif - { -@@ -83,7 +83,7 @@ - - /* Handle small numbers by scaling. */ - if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -- return __ieee754_sqrt (b * two108) * twom54; -+ return __slow_ieee754_sqrt (b * two108) * twom54; - - #define FMADD(a_, c_, b_) \ - ({ double __r; \ -@@ -132,4 +132,12 @@ - } - return f_wash (b); - } -+ -+#undef __ieee754_sqrt -+double -+__ieee754_sqrt (double x) -+{ -+ return __slow_ieee754_sqrt (x); -+} -+ - strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c 2014-08-29 10:35:02.608070587 -0700 -@@ -39,10 +39,10 @@ - - #ifdef __STDC__ - float --__ieee754_sqrtf (float b) -+__slow_ieee754_sqrtf (float b) - #else - float --__ieee754_sqrtf (b) -+__slow_ieee754_sqrtf (b) - float b; - #endif - { -@@ -99,4 +99,12 @@ - } - return f_washf (b); - } -+ -+#undef __ieee754_sqrtf -+float -+__ieee754_sqrtf (float x) -+{ -+ return __slow_ieee754_sqrtf (x); -+} -+ - strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c 2014-08-29 10:35:02.608070587 -0700 -@@ -41,10 +41,10 @@ - - #ifdef __STDC__ - double --__ieee754_sqrt (double b) -+__slow_ieee754_sqrt (double b) - #else - double --__ieee754_sqrt (b) -+__slow_ieee754_sqrt (b) - double b; - #endif - { -@@ -83,7 +83,7 @@ - - /* Handle small numbers by scaling. */ - if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -- return __ieee754_sqrt (b * two108) * twom54; -+ return __slow_ieee754_sqrt (b * two108) * twom54; - - #define FMADD(a_, c_, b_) \ - ({ double __r; \ -@@ -132,4 +132,12 @@ - } - return f_wash (b); - } -+ -+#undef __ieee754_sqrt -+double -+__ieee754_sqrt (double x) -+{ -+ return __slow_ieee754_sqrt (x); -+} -+ - strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c 2014-08-29 10:35:02.608070587 -0700 -@@ -39,10 +39,10 @@ - - #ifdef __STDC__ - float --__ieee754_sqrtf (float b) -+__slow_ieee754_sqrtf (float b) - #else - float --__ieee754_sqrtf (b) -+__slow_ieee754_sqrtf (b) - float b; - #endif - { -@@ -99,4 +99,12 @@ - } - return f_washf (b); - } -+ -+#undef __ieee754_sqrtf -+float -+__ieee754_sqrtf (float x) -+{ -+ return __slow_ieee754_sqrtf (x); -+} -+ - strong_alias (__ieee754_sqrtf, __sqrtf_finite) -Index: git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c 2014-08-29 10:35:02.608070587 -0700 -@@ -132,4 +132,12 @@ - } - return f_wash (b); - } -+ -+#undef __ieee754_sqrt -+double -+__ieee754_sqrt (double x) -+{ -+ return __slow_ieee754_sqrt (x); -+} -+ - strong_alias (__ieee754_sqrt, __sqrt_finite) -Index: git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c -=================================================================== ---- git.orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c 2014-08-29 10:35:02.616070587 -0700 -+++ git/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c 2014-08-29 10:35:02.608070587 -0700 -@@ -99,4 +99,12 @@ - } - return f_washf (b); - } -+ -+#undef __ieee754_sqrtf -+float -+__ieee754_sqrtf (float x) -+{ -+ return __slow_ieee754_sqrtf (x); -+} -+ - strong_alias (__ieee754_sqrtf, __sqrtf_finite) diff --git a/meta/recipes-core/glibc/glibc/ppce6500-32b_slow_ieee754_sqrt.patch b/meta/recipes-core/glibc/glibc/ppce6500-32b_slow_ieee754_sqrt.patch deleted file mode 100644 index 4c6c1070c3..0000000000 --- a/meta/recipes-core/glibc/glibc/ppce6500-32b_slow_ieee754_sqrt.patch +++ /dev/null @@ -1,47 +0,0 @@ - __ieee754_sqrt{,f} are now inline functions and call out __slow versions - - -Signed-off-by: chunrong guo -Upstream-Status: Pending - -diff -rNu libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c ---- libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c 2014-04-08 04:39:58.487229887 -0500 -+++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c 2014-04-08 04:40:52.643069198 -0500 -@@ -41,10 +41,10 @@ - - #ifdef __STDC__ - double --__ieee754_sqrt (double b) -+__slow_ieee754_sqrt (double b) - #else - double --__ieee754_sqrt (b) -+__slow_ieee754_sqrt (b) - double b; - #endif - { -@@ -83,7 +83,7 @@ - - /* Handle small numbers by scaling. */ - if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0)) -- return __ieee754_sqrt (b * two108) * twom54; -+ return __slow_ieee754_sqrt (b * two108) * twom54; - - #define FMADD(a_, c_, b_) \ - ({ double __r; \ -diff -rNu libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c ---- libc-orig/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c 2014-04-08 04:39:58.487229887 -0500 -+++ libc/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c 2014-04-08 04:41:26.017067682 -0500 -@@ -39,10 +39,10 @@ - - #ifdef __STDC__ - float --__ieee754_sqrtf (float b) -+__slow_ieee754_sqrtf (float b) - #else - float --__ieee754_sqrtf (b) -+__slow_ieee754_sqrtf (b) - float b; - #endif - { diff --git a/meta/recipes-core/glibc/glibc/relocatable_sdk.patch b/meta/recipes-core/glibc/glibc/relocatable_sdk.patch deleted file mode 100644 index ca5f17ba58..0000000000 --- a/meta/recipes-core/glibc/glibc/relocatable_sdk.patch +++ /dev/null @@ -1,108 +0,0 @@ -Upstream-Status: Inappropriate [SDK specific] - -This patch puts the dynamic loader path in the binaries, SYSTEM_DIRS strings -and lengths as well as ld.so.cache path in the dynamic loader to specific -sections in memory. The sections that contain paths have been allocated a 4096 -byte section, which is the maximum path length in linux. This will allow the -relocating script to parse the ELF binary, detect the section and easily replace -the strings in a certain path. - -Signed-off-by: Laurentiu Palcu - -Index: libc/elf/interp.c -=================================================================== ---- libc.orig/elf/interp.c -+++ libc/elf/interp.c -@@ -16,5 +16,5 @@ - License along with the GNU C Library; if not, see - . */ - --const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp"))) -+const char __invoke_dynamic_linker__[4096] __attribute__ ((section (".interp"))) - = RUNTIME_LINKER; -Index: libc/elf/dl-load.c -=================================================================== ---- libc.orig/elf/dl-load.c -+++ libc/elf/dl-load.c -@@ -144,8 +144,8 @@ static size_t max_capstrlen attribute_re - /* Get the generated information about the trusted directories. */ - #include "trusted-dirs.h" - --static const char system_dirs[] = SYSTEM_DIRS; --static const size_t system_dirs_len[] = -+static const char system_dirs[4096] __attribute__ ((section (".sysdirs"))) = SYSTEM_DIRS; -+volatile static const size_t system_dirs_len[] __attribute__ ((section (".sysdirslen"))) = - { - SYSTEM_DIRS_LEN - }; -Index: libc/elf/dl-cache.c -=================================================================== ---- libc.orig/elf/dl-cache.c -+++ libc/elf/dl-cache.c -@@ -133,6 +133,10 @@ do \ - while (0) - - -+const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))) = -+ SYSCONFDIR "/ld.so.cache"; -+ -+ - int - internal_function - _dl_cache_libcmp (const char *p1, const char *p2) -Index: libc/elf/ldconfig.c -=================================================================== ---- libc.orig/elf/ldconfig.c -+++ libc/elf/ldconfig.c -@@ -166,6 +166,9 @@ static struct argp argp = - options, parse_opt, NULL, doc, NULL, more_help, NULL - }; - -+ -+extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))); -+ - /* Check if string corresponds to an important hardware capability or - a platform. */ - static int -Index: libc/sysdeps/generic/dl-cache.h -=================================================================== ---- libc.orig/sysdeps/generic/dl-cache.h -+++ libc/sysdeps/generic/dl-cache.h -@@ -27,10 +27,6 @@ - ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID) - #endif - --#ifndef LD_SO_CACHE --# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache" --#endif -- - #ifndef add_system_dir - # define add_system_dir(dir) add_dir (dir) - #endif -Index: libc/elf/rtld.c -=================================================================== ---- libc.orig/elf/rtld.c -+++ libc/elf/rtld.c -@@ -99,6 +99,7 @@ uintptr_t __pointer_chk_guard_local - strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) - #endif - -+extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))); - - /* List of auditing DSOs. */ - static struct audit_list -@@ -1031,12 +1032,12 @@ of this helper program; chances are you - --list list all dependencies and how they are resolved\n\ - --verify verify that given object really is a dynamically linked\n\ - object we can handle\n\ -- --inhibit-cache Do not use " LD_SO_CACHE "\n\ -+ --inhibit-cache Do not use %s\n\ - --library-path PATH use given PATH instead of content of the environment\n\ - variable LD_LIBRARY_PATH\n\ - --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ - in LIST\n\ -- --audit LIST use objects named in LIST as auditors\n"); -+ --audit LIST use objects named in LIST as auditors\n", LD_SO_CACHE); - - ++_dl_skip_args; - --_dl_argc; diff --git a/meta/recipes-core/glibc/glibc/relocatable_sdk_fix_openpath.patch b/meta/recipes-core/glibc/glibc/relocatable_sdk_fix_openpath.patch deleted file mode 100644 index f164f8f9ae..0000000000 --- a/meta/recipes-core/glibc/glibc/relocatable_sdk_fix_openpath.patch +++ /dev/null @@ -1,41 +0,0 @@ -Upstream-Status: Inappropriate [SDK specific] - -eglibc-nativesdk: Fix buffer overrun with a relocated SDK - -When ld-linux-*.so.2 is relocated to a path that is longer than the -original fixed location, the dynamic loader will crash in open_path -because it implicitly assumes that max_dirnamelen is a fixed size that -never changes. - -The allocated buffer will not be large enough to contain the directory -path string which is larger than the fixed location provided at build -time. - -Signed-off-by: Jason Wessel - ---- - elf/dl-load.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/elf/dl-load.c -+++ b/elf/dl-load.c -@@ -1919,7 +1919,19 @@ open_path (const char *name, size_t name - given on the command line when rtld is run directly. */ - return -1; - -+ do -+ { -+ struct r_search_path_elem *this_dir = *dirs; -+ if (this_dir->dirnamelen > max_dirnamelen) -+ { -+ max_dirnamelen = this_dir->dirnamelen; -+ } -+ } -+ while (*++dirs != NULL); -+ - buf = alloca (max_dirnamelen + max_capstrlen + namelen); -+ -+ dirs = sps->dirs; - do - { - struct r_search_path_elem *this_dir = *dirs; diff --git a/meta/recipes-core/glibc/glibc/timezone-re-written-tzselect-as-posix-sh.patch b/meta/recipes-core/glibc/glibc/timezone-re-written-tzselect-as-posix-sh.patch deleted file mode 100644 index 55547deae7..0000000000 --- a/meta/recipes-core/glibc/glibc/timezone-re-written-tzselect-as-posix-sh.patch +++ /dev/null @@ -1,38 +0,0 @@ -timezone: re-written tzselect as posix sh - -To avoid the bash dependency. - -Upstream-Status: Pending - -Signed-off-by: Hongxu Jia ---- - timezone/Makefile | 2 +- - timezone/tzselect.ksh | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -Index: git/timezone/Makefile -=================================================================== ---- git.orig/timezone/Makefile 2014-08-27 05:35:58.008070587 +0000 -+++ git/timezone/Makefile 2014-08-27 05:36:37.908070587 +0000 -@@ -114,7 +114,7 @@ - - - $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make -- sed -e 's|/bin/bash|$(BASH)|' \ -+ sed -e 's|/bin/bash|/bin/sh|' \ - -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ - -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \ - -e '/PKGVERSION=/s|=.*|="$(PKGVERSION)"|' \ -Index: git/timezone/tzselect.ksh -=================================================================== ---- git.orig/timezone/tzselect.ksh 2014-08-27 05:35:58.008070587 +0000 -+++ git/timezone/tzselect.ksh 2014-08-27 05:35:58.000070587 +0000 -@@ -35,7 +35,7 @@ - - # Specify default values for environment variables if they are unset. - : ${AWK=awk} --: ${TZDIR=`pwd`} -+: ${TZDIR=$(pwd)} - - # Check for awk Posix compliance. - ($AWK -v x=y 'BEGIN { exit 123 }') /dev/null 2>&1 diff --git a/meta/recipes-core/glibc/glibc_2.21.bb b/meta/recipes-core/glibc/glibc_2.21.bb deleted file mode 100644 index 55424bfaac..0000000000 --- a/meta/recipes-core/glibc/glibc_2.21.bb +++ /dev/null @@ -1,146 +0,0 @@ -require glibc.inc - -DEPENDS += "gperf-native kconfig-frontends-native" - -SRCREV = "4e42b5b8f89f0e288e68be7ad70f9525aebc2cff" - -BRANCH = "release/${PV}/master" - -SRC_URI = "git://sourceware.org/git/glibc.git;branch=${BRANCH} \ - file://IO-acquire-lock-fix.patch \ - file://mips-rld-map-check.patch \ - file://etc/ld.so.conf \ - file://generate-supported.mk \ - file://glibc.fix_sqrt2.patch \ - file://multilib_readlib.patch \ - file://ppc-sqrt_finite.patch \ - file://ppc_slow_ieee754_sqrt.patch \ - file://add_resource_h_to_wait_h.patch \ - file://0001-R_ARM_TLS_DTPOFF32.patch \ - file://0001-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch \ - file://fix-tibetian-locales.patch \ - file://ppce6500-32b_slow_ieee754_sqrt.patch \ - file://grok_gold.patch \ - file://fix_am_rootsbindir.patch \ - file://0001-Add-unused-attribute.patch \ - file://0001-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch \ - file://0001-yes-within-the-path-sets-wrong-config-variables.patch \ - file://elf-Makefile-fix-a-typo.patch \ - file://makesyscall.patch \ - file://Fix-__memcpy_chk-on-non-SSE2-CPUs.patch \ - ${EGLIBCPATCHES} \ - ${CVEPATCHES} \ - " -EGLIBCPATCHES = "\ - file://timezone-re-written-tzselect-as-posix-sh.patch \ - file://eglibc.patch \ - file://option-groups.patch \ - file://GLRO_dl_debug_mask.patch \ - file://eglibc-header-bootstrap.patch \ - file://eglibc-resolv-dynamic.patch \ - file://eglibc-ppc8xx-cache-line-workaround.patch \ - file://eglibc-sh4-fpscr_values.patch \ - file://eglibc-use-option-groups.patch \ - " -# file://eglibc-install-pic-archives.patch \ -# file://initgroups_keys.patch \ -# -CVEPATCHES = "\ - file://CVE-2015-1781-resolv-nss_dns-dns-host.c-buffer-overf.patch \ -" - -LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \ - file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ - file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \ - file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c" - -SRC_URI_append_class-nativesdk = " file://ld-search-order.patch \ - file://relocatable_sdk.patch \ - file://relocatable_sdk_fix_openpath.patch \ - " -S = "${WORKDIR}/git" -B = "${WORKDIR}/build-${TARGET_SYS}" - -PACKAGES_DYNAMIC = "" - -# the -isystem in bitbake.conf screws up glibc do_stage -BUILD_CPPFLAGS = "-I${STAGING_INCDIR_NATIVE}" -TARGET_CPPFLAGS = "-I${STAGING_DIR_TARGET}${includedir}" - -GLIBC_BROKEN_LOCALES = " _ER _ET so_ET yn_ER sid_ET tr_TR mn_MN gez_ET gez_ER bn_BD te_IN es_CR.ISO-8859-1" - -# -# We will skip parsing glibc when target system C library selection is not glibc -# this helps in easing out parsing for non-glibc system libraries -# -COMPATIBLE_HOST_libc-musl_class-target = "null" -COMPATIBLE_HOST_libc-uclibc_class-target = "null" - -EXTRA_OECONF = "--enable-kernel=${OLDEST_KERNEL} \ - --without-cvs --disable-profile \ - --disable-debug --without-gd \ - --enable-clocale=gnu \ - --enable-add-ons \ - --with-headers=${STAGING_INCDIR} \ - --without-selinux \ - --enable-obsolete-rpc \ - --with-kconfig=${STAGING_BINDIR_NATIVE} \ - ${GLIBC_EXTRA_OECONF}" - -EXTRA_OECONF += "${@get_libc_fpu_setting(bb, d)}" -EXTRA_OECONF += "${@bb.utils.contains('DISTRO_FEATURES', 'libc-inet-anl', '--enable-nscd', '--disable-nscd', d)}" - - -do_patch_append() { - bb.build.exec_func('do_fix_readlib_c', d) -} - -do_fix_readlib_c () { - sed -i -e 's#OECORE_KNOWN_INTERPRETER_NAMES#${EGLIBC_KNOWN_INTERPRETER_NAMES}#' ${S}/elf/readlib.c -} - -do_configure () { -# override this function to avoid the autoconf/automake/aclocal/autoheader -# calls for now -# don't pass CPPFLAGS into configure, since it upsets the kernel-headers -# version check and doesn't really help with anything - if [ -z "`which rpcgen`" ]; then - echo "rpcgen not found. Install glibc-devel." - exit 1 - fi - (cd ${S} && gnu-configize) || die "failure in running gnu-configize" - find ${S} -name "configure" | xargs touch - CPPFLAGS="" oe_runconf -} - -rpcsvc = "bootparam_prot.x nlm_prot.x rstat.x \ - yppasswd.x klm_prot.x rex.x sm_inter.x mount.x \ - rusers.x spray.x nfs_prot.x rquota.x key_prot.x" - -do_compile () { - # -Wl,-rpath-link /lib in LDFLAGS can cause breakage if another glibc is in staging - unset LDFLAGS - base_do_compile - ( - cd ${S}/sunrpc/rpcsvc - for r in ${rpcsvc}; do - h=`echo $r|sed -e's,\.x$,.h,'` - rm -f $h - rpcgen -h $r -o $h || bbwarn "${PN}: unable to generate header for $r" - done - ) - echo "Adjust ldd script" - if [ -n "${RTLDLIST}" ] - then - prevrtld=`cat ${B}/elf/ldd | grep "^RTLDLIST=" | sed 's#^RTLDLIST="\?\([^"]*\)"\?$#\1#'` - if [ "${prevrtld}" != "${RTLDLIST}" ] - then - sed -i ${B}/elf/ldd -e "s#^RTLDLIST=.*\$#RTLDLIST=\"${prevrtld} ${RTLDLIST}\"#" - fi - fi - -} - -require glibc-package.inc - -BBCLASSEXTEND = "nativesdk" diff --git a/meta/recipes-core/glibc/glibc_2.22.bb b/meta/recipes-core/glibc/glibc_2.22.bb new file mode 100644 index 0000000000..6aaf72260a --- /dev/null +++ b/meta/recipes-core/glibc/glibc_2.22.bb @@ -0,0 +1,139 @@ +require glibc.inc + +LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \ + file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ + file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \ + file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c" + +DEPENDS += "gperf-native kconfig-frontends-native" + +SRCREV ?= "a34d1c6afc86521d6ad17662a3b5362d8481514c" + +BRANCH ?= "release/${PV}/master" + +GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" + +SRC_URI = "${GLIBC_GIT_URI};branch=${BRANCH};name=glibc \ + file://0004-Backport-https-sourceware.org-ml-libc-ports-2007-12-.patch \ + file://0005-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch \ + file://0006-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch \ + file://0007-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch \ + file://0008-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch \ + file://0009-Quote-from-bug-1443-which-explains-what-the-patch-do.patch \ + file://0010-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch \ + file://0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch \ + file://0012-Make-ld-version-output-matching-grok-gold-s-output.patch \ + file://0013-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch \ + file://0014-Add-unused-attribute.patch \ + file://0015-When-disabling-SSE-also-make-sure-that-fpmath-is-not.patch \ + file://0016-yes-within-the-path-sets-wrong-config-variables.patch \ + file://0017-timezone-re-written-tzselect-as-posix-sh.patch \ + file://0018-eglibc-Cross-building-and-testing-instructions.patch \ + file://0019-eglibc-Bring-Eglibc-option-group-infrastructure-to-g.patch \ + file://0020-eglibc-Help-bootstrap-cross-toolchain.patch \ + file://0021-eglibc-cherry-picked-from-http-www.eglibc.org-archiv.patch \ + file://0022-eglibc-Clear-cache-lines-on-ppc8xx.patch \ + file://0023-eglibc-Resolve-__fpscr_values-on-SH4.patch \ + file://0024-eglibc-Forward-port-eglibc-options-groups-support.patch \ + file://0025-eglibc-Install-PIC-archives.patch \ + file://0026-eglibc-dl_debug_mask-is-controlled-by-__OPTION_EGLIB.patch \ + file://0027-eglibc-use-option-groups-Conditionally-exclude-c-tes.patch \ +" + +SRC_URI += "\ + file://etc/ld.so.conf \ + file://generate-supported.mk \ +" + +SRC_URI_append_class-nativesdk = "\ + file://0001-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch \ + file://0002-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch \ + file://0003-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch \ +" + +S = "${WORKDIR}/git" +B = "${WORKDIR}/build-${TARGET_SYS}" + +PACKAGES_DYNAMIC = "" + +# the -isystem in bitbake.conf screws up glibc do_stage +BUILD_CPPFLAGS = "-I${STAGING_INCDIR_NATIVE}" +TARGET_CPPFLAGS = "-I${STAGING_DIR_TARGET}${includedir}" + +GLIBC_BROKEN_LOCALES = " _ER _ET so_ET yn_ER sid_ET tr_TR mn_MN gez_ET gez_ER bn_BD te_IN es_CR.ISO-8859-1" + +# +# We will skip parsing glibc when target system C library selection is not glibc +# this helps in easing out parsing for non-glibc system libraries +# +COMPATIBLE_HOST_libc-musl_class-target = "null" +COMPATIBLE_HOST_libc-uclibc_class-target = "null" + +EXTRA_OECONF = "--enable-kernel=${OLDEST_KERNEL} \ + --without-cvs --disable-profile \ + --disable-debug --without-gd \ + --enable-clocale=gnu \ + --enable-add-ons \ + --with-headers=${STAGING_INCDIR} \ + --without-selinux \ + --enable-obsolete-rpc \ + --with-kconfig=${STAGING_BINDIR_NATIVE} \ + ${GLIBC_EXTRA_OECONF}" + +EXTRA_OECONF += "${@get_libc_fpu_setting(bb, d)}" +EXTRA_OECONF += "${@bb.utils.contains('DISTRO_FEATURES', 'libc-inet-anl', '--enable-nscd', '--disable-nscd', d)}" + + +do_patch_append() { + bb.build.exec_func('do_fix_readlib_c', d) +} + +do_fix_readlib_c () { + sed -i -e 's#OECORE_KNOWN_INTERPRETER_NAMES#${EGLIBC_KNOWN_INTERPRETER_NAMES}#' ${S}/elf/readlib.c +} + +do_configure () { +# override this function to avoid the autoconf/automake/aclocal/autoheader +# calls for now +# don't pass CPPFLAGS into configure, since it upsets the kernel-headers +# version check and doesn't really help with anything + if [ -z "`which rpcgen`" ]; then + echo "rpcgen not found. Install glibc-devel." + exit 1 + fi + (cd ${S} && gnu-configize) || die "failure in running gnu-configize" + find ${S} -name "configure" | xargs touch + CPPFLAGS="" oe_runconf +} + +rpcsvc = "bootparam_prot.x nlm_prot.x rstat.x \ + yppasswd.x klm_prot.x rex.x sm_inter.x mount.x \ + rusers.x spray.x nfs_prot.x rquota.x key_prot.x" + +do_compile () { + # -Wl,-rpath-link /lib in LDFLAGS can cause breakage if another glibc is in staging + unset LDFLAGS + base_do_compile + ( + cd ${S}/sunrpc/rpcsvc + for r in ${rpcsvc}; do + h=`echo $r|sed -e's,\.x$,.h,'` + rm -f $h + rpcgen -h $r -o $h || bbwarn "${PN}: unable to generate header for $r" + done + ) + echo "Adjust ldd script" + if [ -n "${RTLDLIST}" ] + then + prevrtld=`cat ${B}/elf/ldd | grep "^RTLDLIST=" | sed 's#^RTLDLIST="\?\([^"]*\)"\?$#\1#'` + if [ "${prevrtld}" != "${RTLDLIST}" ] + then + sed -i ${B}/elf/ldd -e "s#^RTLDLIST=.*\$#RTLDLIST=\"${prevrtld} ${RTLDLIST}\"#" + fi + fi + +} + +require glibc-package.inc + +BBCLASSEXTEND = "nativesdk" -- cgit v1.2.3-54-g00ecf