aboutsummaryrefslogtreecommitdiff
path: root/REORG.TODO/intl
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2017-06-08 15:39:03 -0400
committerZack Weinberg <zackw@panix.com>2017-06-08 15:39:03 -0400
commit5046dbb4a7eba5eccfd258f92f4735c9ffc8d069 (patch)
tree4470480d904b65cf14ca524f96f79eca818c3eaf /REORG.TODO/intl
parent199fc19d3aaaf57944ef036e15904febe877fc93 (diff)
downloadglibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.tar
glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.tar.gz
glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.tar.bz2
glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.zip
Prepare for radical source tree reorganization.zack/build-layout-experiment
All top-level files and directories are moved into a temporary storage directory, REORG.TODO, except for files that will certainly still exist in their current form at top level when we're done (COPYING, COPYING.LIB, LICENSES, NEWS, README), all old ChangeLog files (which are moved to the new directory OldChangeLogs, instead), and the generated file INSTALL (which is just deleted; in the new order, there will be no generated files checked into version control).
Diffstat (limited to 'REORG.TODO/intl')
-rw-r--r--REORG.TODO/intl/Depend2
-rw-r--r--REORG.TODO/intl/Makefile157
-rw-r--r--REORG.TODO/intl/Versions31
-rw-r--r--REORG.TODO/intl/bindtextdom.c337
-rw-r--r--REORG.TODO/intl/dcgettext.c54
-rw-r--r--REORG.TODO/intl/dcigettext.c1720
-rw-r--r--REORG.TODO/intl/dcngettext.c55
-rw-r--r--REORG.TODO/intl/dgettext.c56
-rw-r--r--REORG.TODO/intl/dngettext.c57
-rw-r--r--REORG.TODO/intl/eval-plural.h106
-rw-r--r--REORG.TODO/intl/explodename.c133
-rw-r--r--REORG.TODO/intl/finddomain.c204
-rw-r--r--REORG.TODO/intl/gettext.c61
-rw-r--r--REORG.TODO/intl/gettextP.h310
-rw-r--r--REORG.TODO/intl/gmo.h150
-rw-r--r--REORG.TODO/intl/hash-string.c50
-rw-r--r--REORG.TODO/intl/hash-string.h34
-rw-r--r--REORG.TODO/intl/l10nflist.c357
-rw-r--r--REORG.TODO/intl/libintl.h123
-rw-r--r--REORG.TODO/intl/loadinfo.h130
-rw-r--r--REORG.TODO/intl/loadmsgcat.c1351
-rw-r--r--REORG.TODO/intl/locale.alias82
-rw-r--r--REORG.TODO/intl/localealias.c437
-rw-r--r--REORG.TODO/intl/ngettext.c63
-rw-r--r--REORG.TODO/intl/plural-exp.c154
-rw-r--r--REORG.TODO/intl/plural-exp.h127
-rw-r--r--REORG.TODO/intl/plural.c2012
-rw-r--r--REORG.TODO/intl/plural.y383
-rw-r--r--REORG.TODO/intl/po2test.awk46
-rw-r--r--REORG.TODO/intl/textdomain.c125
-rw-r--r--REORG.TODO/intl/translit.po9
-rw-r--r--REORG.TODO/intl/tst-codeset.c60
-rw-r--r--REORG.TODO/intl/tst-gettext.c368
-rwxr-xr-xREORG.TODO/intl/tst-gettext.sh57
-rw-r--r--REORG.TODO/intl/tst-gettext2.c77
-rw-r--r--REORG.TODO/intl/tst-gettext2.sh74
-rw-r--r--REORG.TODO/intl/tst-gettext3.c62
-rw-r--r--REORG.TODO/intl/tst-gettext4-de.po8
-rw-r--r--REORG.TODO/intl/tst-gettext4-fr.po8
-rw-r--r--REORG.TODO/intl/tst-gettext4.c150
-rwxr-xr-xREORG.TODO/intl/tst-gettext4.sh36
-rw-r--r--REORG.TODO/intl/tst-gettext5.c155
-rw-r--r--REORG.TODO/intl/tst-gettext6.c85
-rw-r--r--REORG.TODO/intl/tst-gettext6.sh33
-rw-r--r--REORG.TODO/intl/tst-ngettext.c68
-rw-r--r--REORG.TODO/intl/tst-translit.c54
-rwxr-xr-xREORG.TODO/intl/tst-translit.sh35
-rw-r--r--REORG.TODO/intl/tstcodeset.po8
-rw-r--r--REORG.TODO/intl/tstlang1.po13
-rw-r--r--REORG.TODO/intl/tstlang2.po13
50 files changed, 10280 insertions, 0 deletions
diff --git a/REORG.TODO/intl/Depend b/REORG.TODO/intl/Depend
new file mode 100644
index 0000000000..981111e299
--- /dev/null
+++ b/REORG.TODO/intl/Depend
@@ -0,0 +1,2 @@
+iconvdata
+localedata
diff --git a/REORG.TODO/intl/Makefile b/REORG.TODO/intl/Makefile
new file mode 100644
index 0000000000..60d5d24fa1
--- /dev/null
+++ b/REORG.TODO/intl/Makefile
@@ -0,0 +1,157 @@
+# Copyright (C) 1995-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+# Makefile for intl subdirectory: message handling code from GNU gettext.
+
+subdir = intl
+
+include ../Makeconfig
+
+headers = libintl.h
+routines = bindtextdom dcgettext dgettext gettext \
+ dcigettext dcngettext dngettext ngettext \
+ finddomain loadmsgcat localealias textdomain
+aux = l10nflist explodename plural plural-exp hash-string
+
+multithread-test-srcs := tst-gettext4 tst-gettext5 tst-gettext6
+test-srcs := tst-gettext tst-translit tst-gettext2 tst-codeset tst-gettext3
+ifeq ($(have-thread-library),yes)
+test-srcs += $(multithread-test-srcs)
+endif
+tests = tst-ngettext
+
+before-compile += $(objpfx)msgs.h
+
+install-others = $(inst_localedir)/locale.alias
+
+generated += msgs.h mtrace-tst-gettext.out tst-gettext.mtrace
+generated-dirs += domaindir localedir
+
+ifneq (no,$(BISON))
+plural.c: plural.y
+ $(BISON) $(BISONFLAGS) $@ $^
+endif
+$(objpfx)plural.o: plural.c
+
+ifeq ($(run-built-tests),yes)
+ifeq (yes,$(build-shared))
+ifneq ($(strip $(MSGFMT)),:)
+tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \
+ $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \
+ $(objpfx)tst-gettext3.out
+ifeq ($(have-thread-library),yes)
+tests-special += $(objpfx)tst-gettext4.out $(objpfx)tst-gettext5.out \
+ $(objpfx)tst-gettext6.out
+endif
+ifneq (no,$(PERL))
+tests-special += $(objpfx)mtrace-tst-gettext.out
+endif
+endif
+endif
+endif
+
+include ../Rules
+
+ifeq ($(run-built-tests),yes)
+ifeq (yes,$(build-shared))
+# Multiple tests use this data. Create it once to avoid racing and
+# spurious test failures.
+codeset_mo = $(objpfx)domaindir/de_DE/LC_MESSAGES/codeset.mo
+
+$(codeset_mo): tstcodeset.po
+ $(make-target-directory)
+ msgfmt -o $@T $<
+ mv -f $@T $@
+
+$(objpfx)mtrace-tst-gettext.out: $(objpfx)tst-gettext.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-gettext.mtrace > $@; \
+ $(evaluate-test)
+$(objpfx)tst-gettext.out: tst-gettext.sh $(objpfx)tst-gettext
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
+ '$(run-program-env)' '$(test-program-prefix-after-env)' \
+ $(common-objpfx)intl/ $(objpfx)tst-gettext.mtrace; \
+ $(evaluate-test)
+$(objpfx)tst-translit.out: tst-translit.sh $(objpfx)tst-translit
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
+ $(common-objpfx)intl/; \
+ $(evaluate-test)
+$(objpfx)tst-gettext2.out: tst-gettext2.sh $(objpfx)tst-gettext2
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
+ '$(run-program-env)' '$(test-program-prefix-after-env)' \
+ $(common-objpfx)intl/; \
+ $(evaluate-test)
+$(objpfx)tst-gettext4.out: tst-gettext4.sh $(objpfx)tst-gettext4
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' $(common-objpfx)intl/; \
+ $(evaluate-test)
+$(objpfx)tst-gettext6.out: tst-gettext6.sh $(objpfx)tst-gettext6
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' $(common-objpfx)intl/; \
+ $(evaluate-test)
+
+$(objpfx)tst-codeset.out: $(codeset_mo)
+$(objpfx)tst-gettext3.out: $(codeset_mo)
+$(objpfx)tst-gettext5.out: $(codeset_mo)
+endif
+
+LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 fr_FR.ISO-8859-1 \
+ ja_JP.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)tst-codeset.out: $(gen-locales)
+$(objpfx)tst-gettext.out: $(gen-locales)
+$(objpfx)tst-gettext2.out: $(gen-locales)
+$(objpfx)tst-gettext3.out: $(gen-locales)
+$(objpfx)tst-gettext4.out: $(gen-locales)
+$(objpfx)tst-gettext5.out: $(gen-locales)
+$(objpfx)tst-gettext6.out: $(gen-locales)
+$(objpfx)tst-translit.out: $(gen-locales)
+endif
+
+$(objpfx)msgs.h: po2test.awk ../po/de.po
+ $(make-target-directory)
+ LC_ALL=C $(AWK) -f $^ > $@
+
+CFLAGS-tst-gettext.c = -DTESTSTRS_H=\"$(objpfx)msgs.h\"
+CFLAGS-tst-translit.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-gettext2.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-codeset.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-gettext3.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-gettext4.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-gettext5.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-gettext6.c = -DOBJPFX=\"$(objpfx)\"
+
+ifeq ($(have-thread-library),yes)
+ifeq (yes,$(build-shared))
+$(addprefix $(objpfx),$(multithread-test-srcs)): $(shared-thread-library)
+else
+$(addprefix $(objpfx),$(multithread-test-srcs)): $(static-thread-library)
+endif
+endif
+
+$(objpfx)tst-translit.out: $(objpfx)tst-gettext.out
+$(objpfx)tst-gettext2.out: $(objpfx)tst-gettext.out
+$(objpfx)tst-codeset.out: $(objpfx)tst-gettext.out
+$(objpfx)tst-gettext3.out: $(objpfx)tst-gettext.out
+$(objpfx)tst-gettext4.out: $(objpfx)tst-gettext.out
+$(objpfx)tst-gettext5.out: $(objpfx)tst-gettext.out
+$(objpfx)tst-gettext6.out: $(objpfx)tst-gettext.out
+
+CPPFLAGS += -D'LOCALEDIR="$(localedir)"' \
+ -D'LOCALE_ALIAS_PATH="$(localedir)"'
+BISONFLAGS = --yacc --name-prefix=__gettext --output
+
+$(inst_localedir)/locale.alias: locale.alias $(+force)
+ $(do-install)
diff --git a/REORG.TODO/intl/Versions b/REORG.TODO/intl/Versions
new file mode 100644
index 0000000000..d76982dbe3
--- /dev/null
+++ b/REORG.TODO/intl/Versions
@@ -0,0 +1,31 @@
+libc {
+ GLIBC_2.0 {
+ # global variables
+ _nl_msg_cat_cntr; _nl_default_dirname; _nl_domain_bindings;
+
+ # functions used in inline functions or macros
+ __dcgettext;
+
+ # functions used in other libraries
+ __dgettext;
+
+ # b*
+ bindtextdomain;
+
+ # d*
+ dcgettext; dgettext; gettext;
+
+ # t*
+ textdomain;
+ }
+ GLIBC_2.2 {
+ # b*
+ bind_textdomain_codeset;
+
+ # d*
+ dcngettext; dngettext;
+
+ # n*
+ ngettext;
+ }
+}
diff --git a/REORG.TODO/intl/bindtextdom.c b/REORG.TODO/intl/bindtextdom.c
new file mode 100644
index 0000000000..86ae7f2501
--- /dev/null
+++ b/REORG.TODO/intl/bindtextdom.c
@@ -0,0 +1,337 @@
+/* Implementation of the bindtextdomain(3) function
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+# define gl_rwlock_define __libc_rwlock_define
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Lock variable to protect the global data in the gettext implementation. */
+gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
+
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define BINDTEXTDOMAIN __bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
+# ifndef strdup
+# define strdup(str) __strdup (str)
+# endif
+#else
+# define BINDTEXTDOMAIN libintl_bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
+#endif
+
+/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
+ to be used for the DOMAINNAME message catalog.
+ If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
+ modified, only the current value is returned.
+ If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
+ modified nor returned. */
+static void
+set_binding_values (const char *domainname,
+ const char **dirnamep, const char **codesetp)
+{
+ struct binding *binding;
+ int modified;
+
+ /* Some sanity checks. */
+ if (domainname == NULL || domainname[0] == '\0')
+ {
+ if (dirnamep)
+ *dirnamep = NULL;
+ if (codesetp)
+ *codesetp = NULL;
+ return;
+ }
+
+ gl_rwlock_wrlock (_nl_state_lock);
+
+ modified = 0;
+
+ for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+ {
+ int compare = strcmp (domainname, binding->domainname);
+ if (compare == 0)
+ /* We found it! */
+ break;
+ if (compare < 0)
+ {
+ /* It is not in the list. */
+ binding = NULL;
+ break;
+ }
+ }
+
+ if (binding != NULL)
+ {
+ if (dirnamep)
+ {
+ const char *dirname = *dirnamep;
+
+ if (dirname == NULL)
+ /* The current binding has be to returned. */
+ *dirnamep = binding->dirname;
+ else
+ {
+ /* The domain is already bound. If the new value and the old
+ one are equal we simply do nothing. Otherwise replace the
+ old binding. */
+ char *result = binding->dirname;
+ if (strcmp (dirname, result) != 0)
+ {
+ if (strcmp (dirname, _nl_default_dirname) == 0)
+ result = (char *) _nl_default_dirname;
+ else
+ {
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (dirname);
+#else
+ size_t len = strlen (dirname) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result != NULL, 1))
+ memcpy (result, dirname, len);
+#endif
+ }
+
+ if (__builtin_expect (result != NULL, 1))
+ {
+ if (binding->dirname != _nl_default_dirname)
+ free (binding->dirname);
+
+ binding->dirname = result;
+ modified = 1;
+ }
+ }
+ *dirnamep = result;
+ }
+ }
+
+ if (codesetp)
+ {
+ const char *codeset = *codesetp;
+
+ if (codeset == NULL)
+ /* The current binding has be to returned. */
+ *codesetp = binding->codeset;
+ else
+ {
+ /* The domain is already bound. If the new value and the old
+ one are equal we simply do nothing. Otherwise replace the
+ old binding. */
+ char *result = binding->codeset;
+ if (result == NULL || strcmp (codeset, result) != 0)
+ {
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (codeset);
+#else
+ size_t len = strlen (codeset) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result != NULL, 1))
+ memcpy (result, codeset, len);
+#endif
+
+ if (__builtin_expect (result != NULL, 1))
+ {
+ free (binding->codeset);
+
+ binding->codeset = result;
+ modified = 1;
+ }
+ }
+ *codesetp = result;
+ }
+ }
+ }
+ else if ((dirnamep == NULL || *dirnamep == NULL)
+ && (codesetp == NULL || *codesetp == NULL))
+ {
+ /* Simply return the default values. */
+ if (dirnamep)
+ *dirnamep = _nl_default_dirname;
+ if (codesetp)
+ *codesetp = NULL;
+ }
+ else
+ {
+ /* We have to create a new binding. */
+ size_t len = strlen (domainname) + 1;
+ struct binding *new_binding =
+ (struct binding *) malloc (offsetof (struct binding, domainname) + len);
+
+ if (__builtin_expect (new_binding == NULL, 0))
+ goto failed;
+
+ memcpy (new_binding->domainname, domainname, len);
+
+ if (dirnamep)
+ {
+ const char *dirname = *dirnamep;
+
+ if (dirname == NULL)
+ /* The default value. */
+ dirname = _nl_default_dirname;
+ else
+ {
+ if (strcmp (dirname, _nl_default_dirname) == 0)
+ dirname = _nl_default_dirname;
+ else
+ {
+ char *result;
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (dirname);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_dirname;
+#else
+ size_t len = strlen (dirname) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_dirname;
+ memcpy (result, dirname, len);
+#endif
+ dirname = result;
+ }
+ }
+ *dirnamep = dirname;
+ new_binding->dirname = (char *) dirname;
+ }
+ else
+ /* The default value. */
+ new_binding->dirname = (char *) _nl_default_dirname;
+
+ if (codesetp)
+ {
+ const char *codeset = *codesetp;
+
+ if (codeset != NULL)
+ {
+ char *result;
+
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (codeset);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_codeset;
+#else
+ size_t len = strlen (codeset) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_codeset;
+ memcpy (result, codeset, len);
+#endif
+ codeset = result;
+ }
+ *codesetp = codeset;
+ new_binding->codeset = (char *) codeset;
+ }
+ else
+ new_binding->codeset = NULL;
+
+ /* Now enqueue it. */
+ if (_nl_domain_bindings == NULL
+ || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
+ {
+ new_binding->next = _nl_domain_bindings;
+ _nl_domain_bindings = new_binding;
+ }
+ else
+ {
+ binding = _nl_domain_bindings;
+ while (binding->next != NULL
+ && strcmp (domainname, binding->next->domainname) > 0)
+ binding = binding->next;
+
+ new_binding->next = binding->next;
+ binding->next = new_binding;
+ }
+
+ modified = 1;
+
+ /* Here we deal with memory allocation failures. */
+ if (0)
+ {
+ failed_codeset:
+ if (new_binding->dirname != _nl_default_dirname)
+ free (new_binding->dirname);
+ failed_dirname:
+ free (new_binding);
+ failed:
+ if (dirnamep)
+ *dirnamep = NULL;
+ if (codesetp)
+ *codesetp = NULL;
+ }
+ }
+
+ /* If we modified any binding, we flush the caches. */
+ if (modified)
+ ++_nl_msg_cat_cntr;
+
+ gl_rwlock_unlock (_nl_state_lock);
+}
+
+/* Specify that the DOMAINNAME message catalog will be found
+ in DIRNAME rather than in the system locale data base. */
+char *
+BINDTEXTDOMAIN (const char *domainname, const char *dirname)
+{
+ set_binding_values (domainname, &dirname, NULL);
+ return (char *) dirname;
+}
+
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+char *
+BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
+{
+ set_binding_values (domainname, NULL, &codeset);
+ return (char *) codeset;
+}
+
+#ifdef _LIBC
+/* Aliases for function names in GNU C Library. */
+weak_alias (__bindtextdomain, bindtextdomain);
+weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
+#endif
diff --git a/REORG.TODO/intl/dcgettext.c b/REORG.TODO/intl/dcgettext.c
new file mode 100644
index 0000000000..52b089e293
--- /dev/null
+++ b/REORG.TODO/intl/dcgettext.c
@@ -0,0 +1,54 @@
+/* Implementation of the dcgettext(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DCGETTEXT __dcgettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCGETTEXT libintl_dcgettext
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+ locale. */
+char *
+DCGETTEXT (const char *domainname, const char *msgid, int category)
+{
+ return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dcgettext, dcgettext);
+libc_hidden_def (__dcgettext)
+#endif
diff --git a/REORG.TODO/intl/dcigettext.c b/REORG.TODO/intl/dcigettext.c
new file mode 100644
index 0000000000..3843b7cbdf
--- /dev/null
+++ b/REORG.TODO/intl/dcigettext.c
@@ -0,0 +1,1720 @@
+/* Implementation of the internal dcigettext function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include <locale.h>
+
+#ifdef _LIBC
+ /* Guess whether integer division by zero raises signal SIGFPE.
+ Set to 1 only if you know for sure. In case of doubt, set to 0. */
+# if defined __alpha__ || defined __arm__ || defined __i386__ \
+ || defined __m68k__ || defined __s390__
+# define INTDIV0_RAISES_SIGFPE 1
+# else
+# define INTDIV0_RAISES_SIGFPE 0
+# endif
+#endif
+#if !INTDIV0_RAISES_SIGFPE
+# include <signal.h>
+#endif
+
+#if defined HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+
+#if !defined _LIBC
+# include "localcharset.h"
+#endif
+
+#include "gettextP.h"
+#include "plural-exp.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# ifdef IN_LIBGLOCALE
+# include <libintl.h>
+# endif
+# include "libgnuintl.h"
+#endif
+#include "hash-string.h"
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
+# define gl_rwlock_rdlock __libc_rwlock_rdlock
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* Alignment of types. */
+#if defined __GNUC__ && __GNUC__ >= 2
+# define alignof(TYPE) __alignof__ (TYPE)
+#else
+# define alignof(TYPE) \
+ ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions. This is required by the standard
+ because some ANSI C functions will require linking with this object
+ file and the name space must not be polluted. */
+# define strdup __strdup
+# define getcwd __getcwd
+# ifndef stpcpy
+# define stpcpy __stpcpy
+# endif
+# define tfind __tfind
+#else
+# if !defined HAVE_GETCWD
+char *getwd ();
+# define getcwd(buf, max) getwd (buf)
+# else
+# if VMS
+# define getcwd(buf, max) (getcwd) (buf, max, 0)
+# else
+char *getcwd ();
+# endif
+# endif
+# ifndef HAVE_STPCPY
+static char *stpcpy (char *dest, const char *src);
+# endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy (void *dest, const void *src, size_t n);
+# endif
+#endif
+
+/* Use a replacement if the system does not provide the `tsearch' function
+ family. */
+#if defined HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+#else
+# define tsearch libintl_tsearch
+# define tfind libintl_tfind
+# define tdelete libintl_tdelete
+# define twalk libintl_twalk
+# include "tsearch.h"
+#endif
+
+#ifdef _LIBC
+# define tsearch __tsearch
+#endif
+
+/* Amount to increase buffer size by in each try. */
+#define PATH_INCR 32
+
+/* The following is from pathmax.h. */
+/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
+ PATH_MAX but might cause redefinition warnings when sys/param.h is
+ later included (as on MORE/BSD 4.3). */
+#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_PATH_MAX
+# define _POSIX_PATH_MAX 255
+#endif
+
+#if !defined PATH_MAX && defined _PC_PATH_MAX
+# define PATH_MAX (__pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : __pathconf ("/", _PC_PATH_MAX))
+#endif
+
+/* Don't include sys/param.h if it already has been. */
+#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
+# include <sys/param.h>
+#endif
+
+#if !defined PATH_MAX && defined MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+/* Pathname support.
+ ISSLASH(C) tests whether C is a directory separator character.
+ IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
+ it may be concatenated to a directory pathname.
+ IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+ && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+# define IS_PATH_WITH_DIR(P) \
+ (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+#endif
+
+/* Whether to support different locales in different threads. */
+#if defined _LIBC || HAVE_USELOCALE || defined IN_LIBGLOCALE
+# define HAVE_PER_THREAD_LOCALE
+#endif
+
+/* This is the type used for the search tree where known translations
+ are stored. */
+struct known_translation_t
+{
+ /* Domain in which to search. */
+ const char *domainname;
+
+ /* The category. */
+ int category;
+
+#ifdef HAVE_PER_THREAD_LOCALE
+ /* Name of the relevant locale category, or "" for the global locale. */
+ const char *localename;
+#endif
+
+#ifdef IN_LIBGLOCALE
+ /* The character encoding. */
+ const char *encoding;
+#endif
+
+ /* State of the catalog counter at the point the string was found. */
+ int counter;
+
+ /* Catalog where the string was found. */
+ struct loaded_l10nfile *domain;
+
+ /* And finally the translation. */
+ const char *translation;
+ size_t translation_length;
+
+ /* Pointer to the string in question. */
+ union
+ {
+ char appended[ZERO]; /* used if domain != NULL */
+ const char *ptr; /* used if domain == NULL */
+ }
+ msgid;
+};
+
+gl_rwlock_define_initialized (static, tree_lock)
+
+/* Root of the search tree with known translations. */
+static void *root;
+
+/* Function to compare two entries in the table of known translations. */
+static int
+transcmp (const void *p1, const void *p2)
+{
+ const struct known_translation_t *s1;
+ const struct known_translation_t *s2;
+ int result;
+
+ s1 = (const struct known_translation_t *) p1;
+ s2 = (const struct known_translation_t *) p2;
+
+ result = strcmp (s1->domain != NULL ? s1->msgid.appended : s1->msgid.ptr,
+ s2->domain != NULL ? s2->msgid.appended : s2->msgid.ptr);
+ if (result == 0)
+ {
+ result = strcmp (s1->domainname, s2->domainname);
+ if (result == 0)
+ {
+#ifdef HAVE_PER_THREAD_LOCALE
+ result = strcmp (s1->localename, s2->localename);
+ if (result == 0)
+#endif
+ {
+#ifdef IN_LIBGLOCALE
+ result = strcmp (s1->encoding, s2->encoding);
+ if (result == 0)
+#endif
+ /* We compare the category last (though this is the cheapest
+ operation) since it is hopefully always the same (namely
+ LC_MESSAGES). */
+ result = s1->category - s2->category;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Name of the default domain used for gettext(3) prior any call to
+ textdomain(3). The default value for this is "messages". */
+const char _nl_default_default_domain[] attribute_hidden = "messages";
+
+#ifndef IN_LIBGLOCALE
+/* Value used as the default domain for gettext(3). */
+const char *_nl_current_default_domain attribute_hidden
+ = _nl_default_default_domain;
+#endif
+
+/* Contains the default location of the message catalogs. */
+#if defined __EMX__
+extern const char _nl_default_dirname[];
+#else
+# ifdef _LIBC
+extern const char _nl_default_dirname[];
+libc_hidden_proto (_nl_default_dirname)
+# endif
+const char _nl_default_dirname[] = LOCALEDIR;
+# ifdef _LIBC
+libc_hidden_data_def (_nl_default_dirname)
+# endif
+#endif
+
+#ifndef IN_LIBGLOCALE
+/* List with bindings of specific domains created by bindtextdomain()
+ calls. */
+struct binding *_nl_domain_bindings;
+#endif
+
+/* Prototypes for local functions. */
+static char *plural_lookup (struct loaded_l10nfile *domain,
+ unsigned long int n,
+ const char *translation, size_t translation_len)
+ internal_function;
+
+#ifdef IN_LIBGLOCALE
+static const char *guess_category_value (int category,
+ const char *categoryname,
+ const char *localename)
+ internal_function;
+#else
+static const char *guess_category_value (int category,
+ const char *categoryname)
+ internal_function;
+#endif
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# define category_to_name(category) \
+ _nl_category_names.str + _nl_category_name_idxs[category]
+#else
+static const char *category_to_name (int category) internal_function;
+#endif
+#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
+static const char *get_output_charset (struct binding *domainbinding)
+ internal_function;
+#endif
+
+
+/* For those losing systems which don't have `alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+/* Nothing has to be done. */
+# define freea(p) /* nothing */
+# define ADD_BLOCK(list, address) /* nothing */
+# define FREE_BLOCKS(list) /* nothing */
+#else
+struct block_list
+{
+ void *address;
+ struct block_list *next;
+};
+# define ADD_BLOCK(list, addr) \
+ do { \
+ struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
+ /* If we cannot get a free block we cannot add the new element to \
+ the list. */ \
+ if (newp != NULL) { \
+ newp->address = (addr); \
+ newp->next = (list); \
+ (list) = newp; \
+ } \
+ } while (0)
+# define FREE_BLOCKS(list) \
+ do { \
+ while (list != NULL) { \
+ struct block_list *old = list; \
+ list = list->next; \
+ free (old->address); \
+ free (old); \
+ } \
+ } while (0)
+# undef alloca
+# define alloca(size) (malloc (size))
+# define freea(p) free (p)
+#endif /* have alloca */
+
+
+#ifdef _LIBC
+/* List of blocks allocated for translations. */
+typedef struct transmem_list
+{
+ struct transmem_list *next;
+ char data[ZERO];
+} transmem_block_t;
+static struct transmem_list *transmem_list;
+#else
+typedef unsigned char transmem_block_t;
+#endif
+
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DCIGETTEXT __dcigettext
+#else
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation. */
+gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
+
+/* Checking whether the binaries runs SUID must be done and glibc provides
+ easier methods therefore we make a difference here. */
+#ifdef _LIBC
+# define ENABLE_SECURE __libc_enable_secure
+# define DETERMINE_SECURE
+#else
+# ifndef HAVE_GETUID
+# define getuid() 0
+# endif
+# ifndef HAVE_GETGID
+# define getgid() 0
+# endif
+# ifndef HAVE_GETEUID
+# define geteuid() getuid()
+# endif
+# ifndef HAVE_GETEGID
+# define getegid() getgid()
+# endif
+static int enable_secure;
+# define ENABLE_SECURE (enable_secure == 1)
+# define DETERMINE_SECURE \
+ if (enable_secure == 0) \
+ { \
+ if (getuid () != geteuid () || getgid () != getegid ()) \
+ enable_secure = 1; \
+ else \
+ enable_secure = -1; \
+ }
+#endif
+
+/* Get the function to evaluate the plural expression. */
+#include "eval-plural.h"
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+ CATEGORY locale and, if PLURAL is nonzero, search over string
+ depending on the plural form determined by N. */
+#ifdef IN_LIBGLOCALE
+char *
+gl_dcigettext (const char *domainname,
+ const char *msgid1, const char *msgid2,
+ int plural, unsigned long int n,
+ int category,
+ const char *localename, const char *encoding)
+#else
+char *
+DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
+ int plural, unsigned long int n, int category)
+#endif
+{
+#ifndef HAVE_ALLOCA
+ struct block_list *block_list = NULL;
+#endif
+ struct loaded_l10nfile *domain;
+ struct binding *binding;
+ const char *categoryname;
+ const char *categoryvalue;
+ const char *dirname;
+ char *xdomainname;
+ char *single_locale;
+ char *retval;
+ size_t retlen;
+ int saved_errno;
+ struct known_translation_t search;
+ struct known_translation_t **foundp = NULL;
+#if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
+ const char *localename;
+#endif
+ size_t domainname_len;
+
+ /* If no real MSGID is given return NULL. */
+ if (msgid1 == NULL)
+ return NULL;
+
+#ifdef _LIBC
+ if (category < 0 || category >= __LC_LAST || category == LC_ALL)
+ /* Bogus. */
+ return (plural == 0
+ ? (char *) msgid1
+ /* Use the Germanic plural rule. */
+ : n == 1 ? (char *) msgid1 : (char *) msgid2);
+#endif
+
+ /* Preserve the `errno' value. */
+ saved_errno = errno;
+
+#ifdef _LIBC
+ __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
+ __libc_rwlock_rdlock (__libc_setlocale_lock);
+#endif
+
+ gl_rwlock_rdlock (_nl_state_lock);
+
+ /* If DOMAINNAME is NULL, we are interested in the default domain. If
+ CATEGORY is not LC_MESSAGES this might not make much sense but the
+ definition left this undefined. */
+ if (domainname == NULL)
+ domainname = _nl_current_default_domain;
+
+ /* OS/2 specific: backward compatibility with older libintl versions */
+#ifdef LC_MESSAGES_COMPAT
+ if (category == LC_MESSAGES_COMPAT)
+ category = LC_MESSAGES;
+#endif
+
+ /* Try to find the translation among those which we found at
+ some time. */
+ search.domain = NULL;
+ search.msgid.ptr = msgid1;
+ search.domainname = domainname;
+ search.category = category;
+#ifdef HAVE_PER_THREAD_LOCALE
+# ifndef IN_LIBGLOCALE
+# ifdef _LIBC
+ localename = strdupa (__current_locale_name (category));
+# else
+ categoryname = category_to_name (category);
+# define CATEGORYNAME_INITIALIZED
+ localename = _nl_locale_name_thread_unsafe (category, categoryname);
+ if (localename == NULL)
+ localename = "";
+# endif
+# endif
+ search.localename = localename;
+# ifdef IN_LIBGLOCALE
+ search.encoding = encoding;
+# endif
+
+ /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
+ tsearch calls can be fatal. */
+ gl_rwlock_rdlock (tree_lock);
+
+ foundp = (struct known_translation_t **) tfind (&search, &root, transcmp);
+
+ gl_rwlock_unlock (tree_lock);
+
+ if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+ {
+ /* Now deal with plural. */
+ if (plural)
+ retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
+ (*foundp)->translation_length);
+ else
+ retval = (char *) (*foundp)->translation;
+
+ gl_rwlock_unlock (_nl_state_lock);
+# ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+# endif
+ __set_errno (saved_errno);
+ return retval;
+ }
+#endif
+
+ /* See whether this is a SUID binary or not. */
+ DETERMINE_SECURE;
+
+ /* First find matching binding. */
+#ifdef IN_LIBGLOCALE
+ /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
+ and _nl_load_domain and _nl_find_domain just pass it through. */
+ binding = NULL;
+ dirname = bindtextdomain (domainname, NULL);
+#else
+ for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+ {
+ int compare = strcmp (domainname, binding->domainname);
+ if (compare == 0)
+ /* We found it! */
+ break;
+ if (compare < 0)
+ {
+ /* It is not in the list. */
+ binding = NULL;
+ break;
+ }
+ }
+
+ if (binding == NULL)
+ dirname = _nl_default_dirname;
+ else
+ {
+ dirname = binding->dirname;
+#endif
+ if (!IS_ABSOLUTE_PATH (dirname))
+ {
+ /* We have a relative path. Make it absolute now. */
+ size_t dirname_len = strlen (dirname) + 1;
+ size_t path_max;
+ char *resolved_dirname;
+ char *ret;
+
+ path_max = (unsigned int) PATH_MAX;
+ path_max += 2; /* The getcwd docs say to do this. */
+
+ for (;;)
+ {
+ resolved_dirname = (char *) alloca (path_max + dirname_len);
+ ADD_BLOCK (block_list, tmp_dirname);
+
+ __set_errno (0);
+ ret = getcwd (resolved_dirname, path_max);
+ if (ret != NULL || errno != ERANGE)
+ break;
+
+ path_max += path_max / 2;
+ path_max += PATH_INCR;
+ }
+
+ if (ret == NULL)
+ /* We cannot get the current working directory. Don't signal an
+ error but simply return the default string. */
+ goto return_untranslated;
+
+ stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname);
+ dirname = resolved_dirname;
+ }
+#ifndef IN_LIBGLOCALE
+ }
+#endif
+
+ /* Now determine the symbolic name of CATEGORY and its value. */
+#ifndef CATEGORYNAME_INITIALIZED
+ categoryname = category_to_name (category);
+#endif
+#ifdef IN_LIBGLOCALE
+ categoryvalue = guess_category_value (category, categoryname, localename);
+#else
+ categoryvalue = guess_category_value (category, categoryname);
+#endif
+
+ domainname_len = strlen (domainname);
+ xdomainname = (char *) alloca (strlen (categoryname)
+ + domainname_len + 5);
+ ADD_BLOCK (block_list, xdomainname);
+
+ stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+ domainname, domainname_len),
+ ".mo");
+
+ /* Creating working area. */
+ single_locale = (char *) alloca (strlen (categoryvalue) + 1);
+ ADD_BLOCK (block_list, single_locale);
+
+
+ /* Search for the given string. This is a loop because we perhaps
+ got an ordered list of languages to consider for the translation. */
+ while (1)
+ {
+ /* Make CATEGORYVALUE point to the next element of the list. */
+ while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
+ ++categoryvalue;
+ if (categoryvalue[0] == '\0')
+ {
+ /* The whole contents of CATEGORYVALUE has been searched but
+ no valid entry has been found. We solve this situation
+ by implicitly appending a "C" entry, i.e. no translation
+ will take place. */
+ single_locale[0] = 'C';
+ single_locale[1] = '\0';
+ }
+ else
+ {
+ char *cp = single_locale;
+ while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
+ *cp++ = *categoryvalue++;
+ *cp = '\0';
+
+ /* When this is a SUID binary we must not allow accessing files
+ outside the dedicated directories. */
+ if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
+ /* Ingore this entry. */
+ continue;
+ }
+
+ /* If the current locale value is C (or POSIX) we don't load a
+ domain. Return the MSGID. */
+ if (strcmp (single_locale, "C") == 0
+ || strcmp (single_locale, "POSIX") == 0)
+ break;
+
+ /* Find structure describing the message catalog matching the
+ DOMAINNAME and CATEGORY. */
+ domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
+
+ if (domain != NULL)
+ {
+#if defined IN_LIBGLOCALE
+ retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);
+#else
+ retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
+#endif
+
+ if (retval == NULL)
+ {
+ int cnt;
+
+ for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
+ {
+#if defined IN_LIBGLOCALE
+ retval = _nl_find_msg (domain->successor[cnt], binding,
+ encoding, msgid1, &retlen);
+#else
+ retval = _nl_find_msg (domain->successor[cnt], binding,
+ msgid1, 1, &retlen);
+#endif
+
+ /* Resource problems are not fatal, instead we return no
+ translation. */
+ if (__builtin_expect (retval == (char *) -1, 0))
+ goto return_untranslated;
+
+ if (retval != NULL)
+ {
+ domain = domain->successor[cnt];
+ break;
+ }
+ }
+ }
+
+ /* Returning -1 means that some resource problem exists
+ (likely memory) and that the strings could not be
+ converted. Return the original strings. */
+ if (__builtin_expect (retval == (char *) -1, 0))
+ break;
+
+ if (retval != NULL)
+ {
+ /* Found the translation of MSGID1 in domain DOMAIN:
+ starting at RETVAL, RETLEN bytes. */
+ FREE_BLOCKS (block_list);
+ if (foundp == NULL)
+ {
+ /* Create a new entry and add it to the search tree. */
+ size_t msgid_len;
+ size_t size;
+ struct known_translation_t *newp;
+
+ msgid_len = strlen (msgid1) + 1;
+ size = offsetof (struct known_translation_t, msgid)
+ + msgid_len + domainname_len + 1;
+#ifdef HAVE_PER_THREAD_LOCALE
+ size += strlen (localename) + 1;
+#endif
+ newp = (struct known_translation_t *) malloc (size);
+ if (newp != NULL)
+ {
+ char *new_domainname;
+#ifdef HAVE_PER_THREAD_LOCALE
+ char *new_localename;
+#endif
+
+ new_domainname =
+ (char *) mempcpy (newp->msgid.appended, msgid1,
+ msgid_len);
+ memcpy (new_domainname, domainname, domainname_len + 1);
+#ifdef HAVE_PER_THREAD_LOCALE
+ new_localename = new_domainname + domainname_len + 1;
+ strcpy (new_localename, localename);
+#endif
+ newp->domainname = new_domainname;
+ newp->category = category;
+#ifdef HAVE_PER_THREAD_LOCALE
+ newp->localename = new_localename;
+#endif
+#ifdef IN_LIBGLOCALE
+ newp->encoding = encoding;
+#endif
+ newp->counter = _nl_msg_cat_cntr;
+ newp->domain = domain;
+ newp->translation = retval;
+ newp->translation_length = retlen;
+
+ gl_rwlock_wrlock (tree_lock);
+
+ /* Insert the entry in the search tree. */
+ foundp = (struct known_translation_t **)
+ tsearch (newp, &root, transcmp);
+
+ gl_rwlock_unlock (tree_lock);
+
+ if (foundp == NULL
+ || __builtin_expect (*foundp != newp, 0))
+ /* The insert failed. */
+ free (newp);
+ }
+ }
+ else
+ {
+ /* We can update the existing entry. */
+ (*foundp)->counter = _nl_msg_cat_cntr;
+ (*foundp)->domain = domain;
+ (*foundp)->translation = retval;
+ (*foundp)->translation_length = retlen;
+ }
+
+ __set_errno (saved_errno);
+
+ /* Now deal with plural. */
+ if (plural)
+ retval = plural_lookup (domain, n, retval, retlen);
+
+ gl_rwlock_unlock (_nl_state_lock);
+#ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
+ return retval;
+ }
+ }
+ }
+
+ return_untranslated:
+ /* Return the untranslated MSGID. */
+ FREE_BLOCKS (block_list);
+ gl_rwlock_unlock (_nl_state_lock);
+#ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
+#ifndef _LIBC
+ if (!ENABLE_SECURE)
+ {
+ extern void _nl_log_untranslated (const char *logfilename,
+ const char *domainname,
+ const char *msgid1, const char *msgid2,
+ int plural);
+ const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
+
+ if (logfilename != NULL && logfilename[0] != '\0')
+ _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
+ }
+#endif
+ __set_errno (saved_errno);
+ return (plural == 0
+ ? (char *) msgid1
+ /* Use the Germanic plural rule. */
+ : n == 1 ? (char *) msgid1 : (char *) msgid2);
+}
+
+
+/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
+ Return it if found. Return NULL if not found or in case of a conversion
+ failure (problem in the particular message catalog). Return (char *) -1
+ in case of a memory allocation failure during conversion (only if
+ ENCODING != NULL resp. CONVERT == true). */
+char *
+internal_function
+#ifdef IN_LIBGLOCALE
+_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding, const char *encoding,
+ const char *msgid,
+ size_t *lengthp)
+#else
+_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding,
+ const char *msgid, int convert,
+ size_t *lengthp)
+#endif
+{
+ struct loaded_domain *domain;
+ nls_uint32 nstrings;
+ size_t act;
+ char *result;
+ size_t resultlen;
+
+ if (domain_file->decided <= 0)
+ _nl_load_domain (domain_file, domainbinding);
+
+ if (domain_file->data == NULL)
+ return NULL;
+
+ domain = (struct loaded_domain *) domain_file->data;
+
+ nstrings = domain->nstrings;
+
+ /* Locate the MSGID and its translation. */
+ if (domain->hash_tab != NULL)
+ {
+ /* Use the hashing table. */
+ nls_uint32 len = strlen (msgid);
+ nls_uint32 hash_val = __hash_string (msgid);
+ nls_uint32 idx = hash_val % domain->hash_size;
+ nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
+
+ while (1)
+ {
+ nls_uint32 nstr =
+ W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
+
+ if (nstr == 0)
+ /* Hash table entry is empty. */
+ return NULL;
+
+ nstr--;
+
+ /* Compare msgid with the original string at index nstr.
+ We compare the lengths with >=, not ==, because plural entries
+ are represented by strings with an embedded NUL. */
+ if (nstr < nstrings
+ ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
+ && (strcmp (msgid,
+ domain->data + W (domain->must_swap,
+ domain->orig_tab[nstr].offset))
+ == 0)
+ : domain->orig_sysdep_tab[nstr - nstrings].length > len
+ && (strcmp (msgid,
+ domain->orig_sysdep_tab[nstr - nstrings].pointer)
+ == 0))
+ {
+ act = nstr;
+ goto found;
+ }
+
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+ }
+ /* NOTREACHED */
+ }
+ else
+ {
+ /* Try the default method: binary search in the sorted array of
+ messages. */
+ size_t top, bottom;
+
+ bottom = 0;
+ top = nstrings;
+ while (bottom < top)
+ {
+ int cmp_val;
+
+ act = (bottom + top) / 2;
+ cmp_val = strcmp (msgid, (domain->data
+ + W (domain->must_swap,
+ domain->orig_tab[act].offset)));
+ if (cmp_val < 0)
+ top = act;
+ else if (cmp_val > 0)
+ bottom = act + 1;
+ else
+ goto found;
+ }
+ /* No translation was found. */
+ return NULL;
+ }
+
+ found:
+ /* The translation was found at index ACT. If we have to convert the
+ string to use a different character set, this is the time. */
+ if (act < nstrings)
+ {
+ result = (char *)
+ (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
+ resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
+ }
+ else
+ {
+ result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
+ resultlen = domain->trans_sysdep_tab[act - nstrings].length;
+ }
+
+#if defined _LIBC || HAVE_ICONV
+# ifdef IN_LIBGLOCALE
+ if (encoding != NULL)
+# else
+ if (convert)
+# endif
+ {
+ /* We are supposed to do a conversion. */
+# ifndef IN_LIBGLOCALE
+ const char *encoding = get_output_charset (domainbinding);
+# endif
+ size_t nconversions;
+ struct converted_domain *convd;
+ size_t i;
+
+ /* Protect against reallocation of the table. */
+ gl_rwlock_rdlock (domain->conversions_lock);
+
+ /* Search whether a table with converted translations for this
+ encoding has already been allocated. */
+ nconversions = domain->nconversions;
+ convd = NULL;
+
+ for (i = nconversions; i > 0; )
+ {
+ i--;
+ if (strcmp (domain->conversions[i].encoding, encoding) == 0)
+ {
+ convd = &domain->conversions[i];
+ break;
+ }
+ }
+
+ gl_rwlock_unlock (domain->conversions_lock);
+
+ if (convd == NULL)
+ {
+ /* We have to allocate a new conversions table. */
+ gl_rwlock_wrlock (domain->conversions_lock);
+ nconversions = domain->nconversions;
+
+ /* Maybe in the meantime somebody added the translation.
+ Recheck. */
+ for (i = nconversions; i > 0; )
+ {
+ i--;
+ if (strcmp (domain->conversions[i].encoding, encoding) == 0)
+ {
+ convd = &domain->conversions[i];
+ goto found_convd;
+ }
+ }
+
+ {
+ /* Allocate a table for the converted translations for this
+ encoding. */
+ struct converted_domain *new_conversions =
+ (struct converted_domain *)
+ (domain->conversions != NULL
+ ? realloc (domain->conversions,
+ (nconversions + 1) * sizeof (struct converted_domain))
+ : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
+
+ if (__builtin_expect (new_conversions == NULL, 0))
+ {
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ unlock_fail:
+ gl_rwlock_unlock (domain->conversions_lock);
+ return (char *) -1;
+ }
+
+ domain->conversions = new_conversions;
+
+ /* Copy the 'encoding' string to permanent storage. */
+ encoding = strdup (encoding);
+ if (__builtin_expect (encoding == NULL, 0))
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ goto unlock_fail;
+
+ convd = &new_conversions[nconversions];
+ convd->encoding = encoding;
+
+ /* Find out about the character set the file is encoded with.
+ This can be found (in textual form) in the entry "". If this
+ entry does not exist or if this does not contain the 'charset='
+ information, we will assume the charset matches the one the
+ current locale and we don't have to perform any conversion. */
+# ifdef _LIBC
+ convd->conv = (__gconv_t) -1;
+# else
+# if HAVE_ICONV
+ convd->conv = (iconv_t) -1;
+# endif
+# endif
+ {
+ char *nullentry;
+ size_t nullentrylen;
+
+ /* Get the header entry. This is a recursion, but it doesn't
+ reallocate domain->conversions because we pass
+ encoding = NULL or convert = 0, respectively. */
+ nullentry =
+# ifdef IN_LIBGLOCALE
+ _nl_find_msg (domain_file, domainbinding, NULL, "",
+ &nullentrylen);
+# else
+ _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+# endif
+
+ /* Resource problems are fatal. If we continue onwards we will
+ only attempt to calloc a new conv_tab and fail later. */
+ if (__builtin_expect (nullentry == (char *) -1, 0))
+ return (char *) -1;
+
+ if (nullentry != NULL)
+ {
+ const char *charsetstr;
+
+ charsetstr = strstr (nullentry, "charset=");
+ if (charsetstr != NULL)
+ {
+ size_t len;
+ char *charset;
+ const char *outcharset;
+
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
+
+ charset = (char *) alloca (len + 1);
+# if defined _LIBC || HAVE_MEMPCPY
+ *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+# else
+ memcpy (charset, charsetstr, len);
+ charset[len] = '\0';
+# endif
+
+ outcharset = encoding;
+
+# ifdef _LIBC
+ /* We always want to use transliteration. */
+ outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+ charset = norm_add_slashes (charset, "");
+ int r = __gconv_open (outcharset, charset, &convd->conv,
+ GCONV_AVOID_NOCONV);
+ if (__builtin_expect (r != __GCONV_OK, 0))
+ {
+ /* If the output encoding is the same there is
+ nothing to do. Otherwise do not use the
+ translation at all. */
+ if (__builtin_expect (r != __GCONV_NULCONV, 1))
+ {
+ gl_rwlock_unlock (domain->conversions_lock);
+ free ((char *) encoding);
+ return NULL;
+ }
+
+ convd->conv = (__gconv_t) -1;
+ }
+# else
+# if HAVE_ICONV
+ /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+ we want to use transliteration. */
+# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
+ && !defined __UCLIBC__) \
+ || _LIBICONV_VERSION >= 0x0105
+ if (strchr (outcharset, '/') == NULL)
+ {
+ char *tmp;
+
+ len = strlen (outcharset);
+ tmp = (char *) alloca (len + 10 + 1);
+ memcpy (tmp, outcharset, len);
+ memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+ outcharset = tmp;
+
+ convd->conv = iconv_open (outcharset, charset);
+
+ freea (outcharset);
+ }
+ else
+# endif
+ convd->conv = iconv_open (outcharset, charset);
+# endif
+# endif
+
+ freea (charset);
+ }
+ }
+ }
+ convd->conv_tab = NULL;
+ /* Here domain->conversions is still == new_conversions. */
+ domain->nconversions++;
+ }
+
+ found_convd:
+ gl_rwlock_unlock (domain->conversions_lock);
+ }
+
+ if (
+# ifdef _LIBC
+ convd->conv != (__gconv_t) -1
+# else
+# if HAVE_ICONV
+ convd->conv != (iconv_t) -1
+# endif
+# endif
+ )
+ {
+ /* We are supposed to do a conversion. First allocate an
+ appropriate table with the same structure as the table
+ of translations in the file, where we can put the pointers
+ to the converted strings in.
+ There is a slight complication with plural entries. They
+ are represented by consecutive NUL terminated strings. We
+ handle this case by converting RESULTLEN bytes, including
+ NULs. */
+
+ /* This lock primarily protects the memory management variables
+ freemem, freemem_size. It also protects write accesses to
+ convd->conv_tab. It's not worth using a separate lock (such
+ as domain->conversions_lock) for this purpose, because when
+ modifying convd->conv_tab, we also need to lock freemem,
+ freemem_size for most of the time. */
+ __libc_lock_define_initialized (static, lock)
+
+ if (__builtin_expect (convd->conv_tab == NULL, 0))
+ {
+ __libc_lock_lock (lock);
+ if (convd->conv_tab == NULL)
+ {
+ convd->conv_tab =
+ (char **) calloc (nstrings + domain->n_sysdep_strings,
+ sizeof (char *));
+ if (convd->conv_tab != NULL)
+ goto not_translated_yet;
+ /* Mark that we didn't succeed allocating a table. */
+ convd->conv_tab = (char **) -1;
+ }
+ __libc_lock_unlock (lock);
+ }
+
+ if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ return (char *) -1;
+
+ if (convd->conv_tab[act] == NULL)
+ {
+ /* We haven't used this string so far, so it is not
+ translated yet. Do this now. */
+ /* We use a bit more efficient memory handling.
+ We allocate always larger blocks which get used over
+ time. This is faster than many small allocations. */
+# define INITIAL_BLOCK_SIZE 4080
+ static unsigned char *freemem;
+ static size_t freemem_size;
+
+ const unsigned char *inbuf;
+ unsigned char *outbuf;
+ int malloc_count;
+# ifndef _LIBC
+ transmem_block_t *transmem_list;
+# endif
+
+ __libc_lock_lock (lock);
+ not_translated_yet:
+
+ inbuf = (const unsigned char *) result;
+ outbuf = freemem + sizeof (size_t);
+# ifndef _LIBC
+ transmem_list = NULL;
+# endif
+
+ malloc_count = 0;
+ while (1)
+ {
+ transmem_block_t *newmem;
+# ifdef _LIBC
+ size_t non_reversible;
+ int res;
+
+ if (freemem_size < sizeof (size_t))
+ goto resize_freemem;
+
+ res = __gconv (convd->conv,
+ &inbuf, inbuf + resultlen,
+ &outbuf,
+ outbuf + freemem_size - sizeof (size_t),
+ &non_reversible);
+
+ if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
+ break;
+
+ if (res != __GCONV_FULL_OUTPUT)
+ {
+ /* We should not use the translation at all, it
+ is incorrectly encoded. */
+ __libc_lock_unlock (lock);
+ return NULL;
+ }
+
+ inbuf = (const unsigned char *) result;
+# else
+# if HAVE_ICONV
+ const char *inptr = (const char *) inbuf;
+ size_t inleft = resultlen;
+ char *outptr = (char *) outbuf;
+ size_t outleft;
+
+ if (freemem_size < sizeof (size_t))
+ goto resize_freemem;
+
+ outleft = freemem_size - sizeof (size_t);
+ if (iconv (convd->conv,
+ (ICONV_CONST char **) &inptr, &inleft,
+ &outptr, &outleft)
+ != (size_t) (-1))
+ {
+ outbuf = (unsigned char *) outptr;
+ break;
+ }
+ if (errno != E2BIG)
+ {
+ __libc_lock_unlock (lock);
+ return NULL;
+ }
+# endif
+# endif
+
+ resize_freemem:
+ /* We must allocate a new buffer or resize the old one. */
+ if (malloc_count > 0)
+ {
+ ++malloc_count;
+ freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
+ newmem = (transmem_block_t *) realloc (transmem_list,
+ freemem_size);
+# ifdef _LIBC
+ if (newmem != NULL)
+ transmem_list = newmem;
+ else
+ {
+ struct transmem_list *old = transmem_list;
+
+ transmem_list = transmem_list->next;
+ free (old);
+ }
+# endif
+ }
+ else
+ {
+ malloc_count = 1;
+ freemem_size = INITIAL_BLOCK_SIZE;
+ newmem = (transmem_block_t *) malloc (freemem_size);
+# ifdef _LIBC
+ if (newmem != NULL)
+ {
+ /* Add the block to the list of blocks we have to free
+ at some point. */
+ newmem->next = transmem_list;
+ transmem_list = newmem;
+ }
+ /* Fall through and return -1. */
+# endif
+ }
+ if (__builtin_expect (newmem == NULL, 0))
+ {
+ freemem = NULL;
+ freemem_size = 0;
+ __libc_lock_unlock (lock);
+ return (char *) -1;
+ }
+
+# ifdef _LIBC
+ freemem = (unsigned char *) newmem->data;
+ freemem_size -= offsetof (struct transmem_list, data);
+# else
+ transmem_list = newmem;
+ freemem = newmem;
+# endif
+
+ outbuf = freemem + sizeof (size_t);
+ }
+
+ /* We have now in our buffer a converted string. Put this
+ into the table of conversions. */
+ *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
+ convd->conv_tab[act] = (char *) freemem;
+ /* Shrink freemem, but keep it aligned. */
+ freemem_size -= outbuf - freemem;
+ freemem = outbuf;
+ freemem += freemem_size & (alignof (size_t) - 1);
+ freemem_size = freemem_size & ~ (alignof (size_t) - 1);
+
+ __libc_lock_unlock (lock);
+ }
+
+ /* Now convd->conv_tab[act] contains the translation of all
+ the plural variants. */
+ result = convd->conv_tab[act] + sizeof (size_t);
+ resultlen = *(size_t *) convd->conv_tab[act];
+ }
+ }
+
+ /* The result string is converted. */
+
+#endif /* _LIBC || HAVE_ICONV */
+
+ *lengthp = resultlen;
+ return result;
+}
+
+
+/* Look up a plural variant. */
+static char *
+internal_function
+plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
+ const char *translation, size_t translation_len)
+{
+ struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
+ unsigned long int index;
+ const char *p;
+
+ index = plural_eval (domaindata->plural, n);
+ if (index >= domaindata->nplurals)
+ /* This should never happen. It means the plural expression and the
+ given maximum value do not match. */
+ index = 0;
+
+ /* Skip INDEX strings at TRANSLATION. */
+ p = translation;
+ while (index-- > 0)
+ {
+#ifdef _LIBC
+ p = __rawmemchr (p, '\0');
+#else
+ p = strchr (p, '\0');
+#endif
+ /* And skip over the NUL byte. */
+ p++;
+
+ if (p >= translation + translation_len)
+ /* This should never happen. It means the plural expression
+ evaluated to a value larger than the number of variants
+ available for MSGID1. */
+ return (char *) translation;
+ }
+ return (char *) p;
+}
+
+#ifndef _LIBC
+/* Return string representation of locale CATEGORY. */
+static const char *
+internal_function
+category_to_name (int category)
+{
+ const char *retval;
+
+ switch (category)
+ {
+#ifdef LC_COLLATE
+ case LC_COLLATE:
+ retval = "LC_COLLATE";
+ break;
+#endif
+#ifdef LC_CTYPE
+ case LC_CTYPE:
+ retval = "LC_CTYPE";
+ break;
+#endif
+#ifdef LC_MONETARY
+ case LC_MONETARY:
+ retval = "LC_MONETARY";
+ break;
+#endif
+#ifdef LC_NUMERIC
+ case LC_NUMERIC:
+ retval = "LC_NUMERIC";
+ break;
+#endif
+#ifdef LC_TIME
+ case LC_TIME:
+ retval = "LC_TIME";
+ break;
+#endif
+#ifdef LC_MESSAGES
+ case LC_MESSAGES:
+ retval = "LC_MESSAGES";
+ break;
+#endif
+#ifdef LC_RESPONSE
+ case LC_RESPONSE:
+ retval = "LC_RESPONSE";
+ break;
+#endif
+#ifdef LC_ALL
+ case LC_ALL:
+ /* This might not make sense but is perhaps better than any other
+ value. */
+ retval = "LC_ALL";
+ break;
+#endif
+ default:
+ /* If you have a better idea for a default value let me know. */
+ retval = "LC_XXX";
+ }
+
+ return retval;
+}
+#endif
+
+/* Guess value of current locale from value of the environment variables
+ or system-dependent defaults. */
+static const char *
+internal_function
+#ifdef IN_LIBGLOCALE
+guess_category_value (int category, const char *categoryname,
+ const char *locale)
+
+#else
+guess_category_value (int category, const char *categoryname)
+#endif
+{
+ const char *language;
+#ifndef IN_LIBGLOCALE
+ const char *locale;
+# ifndef _LIBC
+ const char *language_default;
+ int locale_defaulted;
+# endif
+#endif
+
+ /* We use the settings in the following order:
+ 1. The value of the environment variable 'LANGUAGE'. This is a GNU
+ extension. Its value can be a colon-separated list of locale names.
+ 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
+ More precisely, the first among these that is set to a non-empty value.
+ This is how POSIX specifies it. The value is a single locale name.
+ 3. A system-dependent preference list of languages. Its value can be a
+ colon-separated list of locale names.
+ 4. A system-dependent default locale name.
+ This way:
+ - System-dependent settings can be overridden by environment variables.
+ - If the system provides both a list of languages and a default locale,
+ the former is used. */
+
+#ifndef IN_LIBGLOCALE
+ /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
+ `LC_xxx', and `LANG'. On some systems this can be done by the
+ `setlocale' function itself. */
+# ifdef _LIBC
+ locale = __current_locale_name (category);
+# else
+ locale_defaulted = 0;
+# if HAVE_USELOCALE
+ locale = _nl_locale_name_thread_unsafe (category, categoryname);
+ if (locale == NULL)
+# endif
+ {
+ locale = _nl_locale_name_posix (category, categoryname);
+ if (locale == NULL)
+ {
+ locale = _nl_locale_name_default ();
+ locale_defaulted = 1;
+ }
+ }
+# endif
+#endif
+
+ /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
+ to "C" because
+ 1. "C" locale usually uses the ASCII encoding, and most international
+ messages use non-ASCII characters. These characters get displayed
+ as question marks (if using glibc's iconv()) or as invalid 8-bit
+ characters (because other iconv()s refuse to convert most non-ASCII
+ characters to ASCII). In any case, the output is ugly.
+ 2. The precise output of some programs in the "C" locale is specified
+ by POSIX and should not depend on environment variables like
+ "LANGUAGE" or system-dependent information. We allow such programs
+ to use gettext(). */
+ if (strcmp (locale, "C") == 0)
+ return locale;
+
+ /* The highest priority value is the value of the 'LANGUAGE' environment
+ variable. */
+ language = getenv ("LANGUAGE");
+ if (language != NULL && language[0] != '\0')
+ return language;
+#if !defined IN_LIBGLOCALE && !defined _LIBC
+ /* The next priority value is the locale name, if not defaulted. */
+ if (locale_defaulted)
+ {
+ /* The next priority value is the default language preferences list. */
+ language_default = _nl_language_preferences_default ();
+ if (language_default != NULL)
+ return language_default;
+ }
+ /* The least priority value is the locale name, if defaulted. */
+#endif
+ return locale;
+}
+
+#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
+/* Returns the output charset. */
+static const char *
+internal_function
+get_output_charset (struct binding *domainbinding)
+{
+ /* The output charset should normally be determined by the locale. But
+ sometimes the locale is not used or not correctly set up, so we provide
+ a possibility for the user to override this: the OUTPUT_CHARSET
+ environment variable. Moreover, the value specified through
+ bind_textdomain_codeset overrides both. */
+ if (domainbinding != NULL && domainbinding->codeset != NULL)
+ return domainbinding->codeset;
+ else
+ {
+ /* For speed reasons, we look at the value of OUTPUT_CHARSET only
+ once. This is a user variable that is not supposed to change
+ during a program run. */
+ static char *output_charset_cache;
+ static int output_charset_cached;
+
+ if (!output_charset_cached)
+ {
+ const char *value = getenv ("OUTPUT_CHARSET");
+
+ if (value != NULL && value[0] != '\0')
+ {
+ size_t len = strlen (value) + 1;
+ char *value_copy = (char *) malloc (len);
+
+ if (value_copy != NULL)
+ memcpy (value_copy, value, len);
+ output_charset_cache = value_copy;
+ }
+ output_charset_cached = 1;
+ }
+
+ if (output_charset_cache != NULL)
+ return output_charset_cache;
+ else
+ {
+# ifdef _LIBC
+ return _NL_CURRENT (LC_CTYPE, CODESET);
+# else
+# if HAVE_ICONV
+ return locale_charset ();
+# endif
+# endif
+ }
+ }
+}
+#endif
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library. So we
+ avoid the non-standard function stpcpy. In GNU C Library this
+ function is available, though. Also allow the symbol HAVE_STPCPY
+ to be defined. */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (char *dest, const char *src)
+{
+ while ((*dest++ = *src++) != '\0')
+ /* Do nothing. */ ;
+ return dest - 1;
+}
+#endif
+
+#if !_LIBC && !HAVE_MEMPCPY
+static void *
+mempcpy (void *dest, const void *src, size_t n)
+{
+ return (void *) ((char *) memcpy (dest, src, n) + n);
+}
+#endif
+
+#if !_LIBC && !HAVE_TSEARCH
+# include "tsearch.c"
+#endif
+
+
+#ifdef _LIBC
+/* If we want to free all resources we have to do some work at
+ program's end. */
+libc_freeres_fn (free_mem)
+{
+ void *old;
+
+ while (_nl_domain_bindings != NULL)
+ {
+ struct binding *oldp = _nl_domain_bindings;
+ _nl_domain_bindings = _nl_domain_bindings->next;
+ if (oldp->dirname != _nl_default_dirname)
+ /* Yes, this is a pointer comparison. */
+ free (oldp->dirname);
+ free (oldp->codeset);
+ free (oldp);
+ }
+
+ if (_nl_current_default_domain != _nl_default_default_domain)
+ /* Yes, again a pointer comparison. */
+ free ((char *) _nl_current_default_domain);
+
+ /* Remove the search tree with the known translations. */
+ __tdestroy (root, free);
+ root = NULL;
+
+ while (transmem_list != NULL)
+ {
+ old = transmem_list;
+ transmem_list = transmem_list->next;
+ free (old);
+ }
+}
+#endif
diff --git a/REORG.TODO/intl/dcngettext.c b/REORG.TODO/intl/dcngettext.c
new file mode 100644
index 0000000000..70d280cb1e
--- /dev/null
+++ b/REORG.TODO/intl/dcngettext.c
@@ -0,0 +1,55 @@
+/* Implementation of the dcngettext(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DCNGETTEXT __dcngettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCNGETTEXT libintl_dcngettext
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+ locale. */
+char *
+DCNGETTEXT (const char *domainname,
+ const char *msgid1, const char *msgid2, unsigned long int n,
+ int category)
+{
+ return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dcngettext, dcngettext);
+#endif
diff --git a/REORG.TODO/intl/dgettext.c b/REORG.TODO/intl/dgettext.c
new file mode 100644
index 0000000000..d48709a26e
--- /dev/null
+++ b/REORG.TODO/intl/dgettext.c
@@ -0,0 +1,56 @@
+/* Implementation of the dgettext(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+
+#include <locale.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DGETTEXT __dgettext
+# define DCGETTEXT __dcgettext
+#else
+# define DGETTEXT libintl_dgettext
+# define DCGETTEXT libintl_dcgettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+ LC_MESSAGES locale. */
+char *
+DGETTEXT (const char *domainname, const char *msgid)
+{
+ return DCGETTEXT (domainname, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dgettext, dgettext);
+#endif
diff --git a/REORG.TODO/intl/dngettext.c b/REORG.TODO/intl/dngettext.c
new file mode 100644
index 0000000000..dcd1f6fc11
--- /dev/null
+++ b/REORG.TODO/intl/dngettext.c
@@ -0,0 +1,57 @@
+/* Implementation of the dngettext(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+
+#include <locale.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DNGETTEXT __dngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define DNGETTEXT libintl_dngettext
+# define DCNGETTEXT libintl_dcngettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+ LC_MESSAGES locale and skip message according to the plural form. */
+char *
+DNGETTEXT (const char *domainname,
+ const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dngettext, dngettext);
+#endif
diff --git a/REORG.TODO/intl/eval-plural.h b/REORG.TODO/intl/eval-plural.h
new file mode 100644
index 0000000000..664b809c2f
--- /dev/null
+++ b/REORG.TODO/intl/eval-plural.h
@@ -0,0 +1,106 @@
+/* Plural expression evaluation.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+/* Evaluate the plural expression and return an index value. */
+STATIC
+unsigned long int
+internal_function
+plural_eval (const struct expression *pexp, unsigned long int n)
+{
+ switch (pexp->nargs)
+ {
+ case 0:
+ switch (pexp->operation)
+ {
+ case var:
+ return n;
+ case num:
+ return pexp->val.num;
+ default:
+ break;
+ }
+ /* NOTREACHED */
+ break;
+ case 1:
+ {
+ /* pexp->operation must be lnot. */
+ unsigned long int arg = plural_eval (pexp->val.args[0], n);
+ return ! arg;
+ }
+ case 2:
+ {
+ unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
+ if (pexp->operation == lor)
+ return leftarg || plural_eval (pexp->val.args[1], n);
+ else if (pexp->operation == land)
+ return leftarg && plural_eval (pexp->val.args[1], n);
+ else
+ {
+ unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
+
+ switch (pexp->operation)
+ {
+ case mult:
+ return leftarg * rightarg;
+ case divide:
+#if !INTDIV0_RAISES_SIGFPE
+ if (rightarg == 0)
+ raise (SIGFPE);
+#endif
+ return leftarg / rightarg;
+ case module:
+#if !INTDIV0_RAISES_SIGFPE
+ if (rightarg == 0)
+ raise (SIGFPE);
+#endif
+ return leftarg % rightarg;
+ case plus:
+ return leftarg + rightarg;
+ case minus:
+ return leftarg - rightarg;
+ case less_than:
+ return leftarg < rightarg;
+ case greater_than:
+ return leftarg > rightarg;
+ case less_or_equal:
+ return leftarg <= rightarg;
+ case greater_or_equal:
+ return leftarg >= rightarg;
+ case equal:
+ return leftarg == rightarg;
+ case not_equal:
+ return leftarg != rightarg;
+ default:
+ break;
+ }
+ }
+ /* NOTREACHED */
+ break;
+ }
+ case 3:
+ {
+ /* pexp->operation must be qmop. */
+ unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
+ return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
+ }
+ }
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/REORG.TODO/intl/explodename.c b/REORG.TODO/intl/explodename.c
new file mode 100644
index 0000000000..aa2176d379
--- /dev/null
+++ b/REORG.TODO/intl/explodename.c
@@ -0,0 +1,133 @@
+/* Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found. Sigh! */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+# define NULL ((void *) 0)
+# else
+# define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Split a locale name NAME into a leading language part and all the
+ rest. Return a pointer to the first character after the language,
+ i.e. to the first byte of the rest. */
+static char *_nl_find_language (const char *name);
+
+static char *
+_nl_find_language (const char *name)
+{
+ while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '.')
+ ++name;
+
+ return (char *) name;
+}
+
+
+int
+_nl_explode_name (char *name,
+ const char **language, const char **modifier,
+ const char **territory, const char **codeset,
+ const char **normalized_codeset)
+{
+ char *cp;
+ int mask;
+
+ *modifier = NULL;
+ *territory = NULL;
+ *codeset = NULL;
+ *normalized_codeset = NULL;
+
+ /* Now we determine the single parts of the locale name. First
+ look for the language. Termination symbols are `_', '.', and `@'. */
+ mask = 0;
+ *language = cp = name;
+ cp = _nl_find_language (*language);
+
+ if (*language == cp)
+ /* This does not make sense: language has to be specified. Use
+ this entry as it is without exploding. Perhaps it is an alias. */
+ cp = strchr (*language, '\0');
+ else
+ {
+ if (cp[0] == '_')
+ {
+ /* Next is the territory. */
+ cp[0] = '\0';
+ *territory = ++cp;
+
+ while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@')
+ ++cp;
+
+ mask |= XPG_TERRITORY;
+ }
+
+ if (cp[0] == '.')
+ {
+ /* Next is the codeset. */
+ cp[0] = '\0';
+ *codeset = ++cp;
+
+ while (cp[0] != '\0' && cp[0] != '@')
+ ++cp;
+
+ mask |= XPG_CODESET;
+
+ if (*codeset != cp && (*codeset)[0] != '\0')
+ {
+ *normalized_codeset = _nl_normalize_codeset (*codeset,
+ cp - *codeset);
+ if (*normalized_codeset == NULL)
+ return -1;
+ else if (strcmp (*codeset, *normalized_codeset) == 0)
+ free ((char *) *normalized_codeset);
+ else
+ mask |= XPG_NORM_CODESET;
+ }
+ }
+ }
+
+ if (cp[0] == '@')
+ {
+ /* Next is the modifier. */
+ cp[0] = '\0';
+ *modifier = ++cp;
+
+ if (cp[0] != '\0')
+ mask |= XPG_MODIFIER;
+ }
+
+ if (*territory != NULL && (*territory)[0] == '\0')
+ mask &= ~XPG_TERRITORY;
+
+ if (*codeset != NULL && (*codeset)[0] == '\0')
+ mask &= ~XPG_CODESET;
+
+ return mask;
+}
diff --git a/REORG.TODO/intl/finddomain.c b/REORG.TODO/intl/finddomain.c
new file mode 100644
index 0000000000..88fd880dbc
--- /dev/null
+++ b/REORG.TODO/intl/finddomain.c
@@ -0,0 +1,204 @@
+/* Handle list of needed message catalogs
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
+# define gl_rwlock_rdlock __libc_rwlock_rdlock
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* @@ end of prolog @@ */
+/* List of already loaded domains. */
+static struct loaded_l10nfile *_nl_loaded_domains;
+
+
+/* Return a data structure describing the message catalog described by
+ the DOMAINNAME and CATEGORY parameters with respect to the currently
+ established bindings. */
+struct loaded_l10nfile *
+internal_function
+_nl_find_domain (const char *dirname, char *locale,
+ const char *domainname, struct binding *domainbinding)
+{
+ struct loaded_l10nfile *retval;
+ const char *language;
+ const char *modifier;
+ const char *territory;
+ const char *codeset;
+ const char *normalized_codeset;
+ const char *alias_value;
+ int mask;
+
+ /* LOCALE can consist of up to four recognized parts for the XPG syntax:
+
+ language[_territory][.codeset][@modifier]
+
+ Beside the first part all of them are allowed to be missing. If
+ the full specified locale is not found, the less specific one are
+ looked for. The various parts will be stripped off according to
+ the following order:
+ (1) codeset
+ (2) normalized codeset
+ (3) territory
+ (4) modifier
+ */
+
+ /* We need to protect modifying the _NL_LOADED_DOMAINS data. */
+ gl_rwlock_define_initialized (static, lock);
+ gl_rwlock_rdlock (lock);
+
+ /* If we have already tested for this locale entry there has to
+ be one data set in the list of loaded domains. */
+ retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+ strlen (dirname) + 1, 0, locale, NULL, NULL,
+ NULL, NULL, domainname, 0);
+
+ gl_rwlock_unlock (lock);
+
+ if (retval != NULL)
+ {
+ /* We know something about this locale. */
+ int cnt;
+
+ if (retval->decided <= 0)
+ _nl_load_domain (retval, domainbinding);
+
+ if (retval->data != NULL)
+ return retval;
+
+ for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+ {
+ if (retval->successor[cnt]->decided <= 0)
+ _nl_load_domain (retval->successor[cnt], domainbinding);
+
+ if (retval->successor[cnt]->data != NULL)
+ break;
+ }
+
+ return retval;
+ /* NOTREACHED */
+ }
+
+ /* See whether the locale value is an alias. If yes its value
+ *overwrites* the alias name. No test for the original value is
+ done. */
+ alias_value = _nl_expand_alias (locale);
+ if (alias_value != NULL)
+ {
+ size_t len = strlen (alias_value) + 1;
+ locale = (char *) malloc (len);
+ if (locale == NULL)
+ return NULL;
+
+ memcpy (locale, alias_value, len);
+ }
+
+ /* Now we determine the single parts of the locale name. First
+ look for the language. Termination symbols are `_', '.', and `@'. */
+ mask = _nl_explode_name (locale, &language, &modifier, &territory,
+ &codeset, &normalized_codeset);
+ if (mask == -1)
+ /* This means we are out of core. */
+ return NULL;
+
+ /* We need to protect modifying the _NL_LOADED_DOMAINS data. */
+ gl_rwlock_wrlock (lock);
+
+ /* Create all possible locale entries which might be interested in
+ generalization. */
+ retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+ strlen (dirname) + 1, mask, language, territory,
+ codeset, normalized_codeset, modifier,
+ domainname, 1);
+
+ gl_rwlock_unlock (lock);
+
+ if (retval == NULL)
+ /* This means we are out of core. */
+ goto out;
+
+ if (retval->decided <= 0)
+ _nl_load_domain (retval, domainbinding);
+ if (retval->data == NULL)
+ {
+ int cnt;
+ for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+ {
+ if (retval->successor[cnt]->decided <= 0)
+ _nl_load_domain (retval->successor[cnt], domainbinding);
+ if (retval->successor[cnt]->data != NULL)
+ break;
+ }
+ }
+
+ /* The room for an alias was dynamically allocated. Free it now. */
+ if (alias_value != NULL)
+ free (locale);
+
+out:
+ /* The space for normalized_codeset is dynamically allocated. Free it. */
+ if (mask & XPG_NORM_CODESET)
+ free ((void *) normalized_codeset);
+
+ return retval;
+}
+
+
+#ifdef _LIBC
+/* This is called from iconv/gconv_db.c's free_mem, as locales must
+ be freed before freeing gconv steps arrays. */
+void __libc_freeres_fn_section
+_nl_finddomain_subfreeres (void)
+{
+ struct loaded_l10nfile *runp = _nl_loaded_domains;
+
+ while (runp != NULL)
+ {
+ struct loaded_l10nfile *here = runp;
+ if (runp->data != NULL)
+ _nl_unload_domain ((struct loaded_domain *) runp->data);
+ runp = runp->next;
+ free ((char *) here->filename);
+ free (here);
+ }
+}
+#endif
diff --git a/REORG.TODO/intl/gettext.c b/REORG.TODO/intl/gettext.c
new file mode 100644
index 0000000000..b9b082b502
--- /dev/null
+++ b/REORG.TODO/intl/gettext.c
@@ -0,0 +1,61 @@
+/* Implementation of gettext(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h> /* Just for NULL. */
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define GETTEXT __gettext
+# define DCGETTEXT __dcgettext
+#else
+# define GETTEXT libintl_gettext
+# define DCGETTEXT libintl_dcgettext
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+ LC_MESSAGES locale. If not found, returns MSGID itself (the default
+ text). */
+char *
+GETTEXT (const char *msgid)
+{
+ return DCGETTEXT (NULL, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__gettext, gettext);
+#endif
diff --git a/REORG.TODO/intl/gettextP.h b/REORG.TODO/intl/gettextP.h
new file mode 100644
index 0000000000..eeb8970852
--- /dev/null
+++ b/REORG.TODO/intl/gettextP.h
@@ -0,0 +1,310 @@
+/* Header describing internals of libintl library.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _GETTEXTP_H
+#define _GETTEXTP_H
+
+#include <stddef.h> /* Get size_t. */
+
+#ifdef _LIBC
+# include "../iconv/gconv_int.h"
+#else
+# if HAVE_ICONV
+# include <iconv.h>
+# endif
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+# define gl_rwlock_define __libc_rwlock_define
+#else
+# include "lock.h"
+#endif
+
+#ifdef _LIBC
+struct loaded_domain;
+extern char *__gettext (const char *__msgid);
+extern char *__dgettext (const char *__domainname, const char *__msgid);
+extern char *__dcgettext (const char *__domainname, const char *__msgid,
+ int __category);
+extern char *__ngettext (const char *__msgid1, const char *__msgid2,
+ unsigned long int __n);
+extern char *__dngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int n);
+extern char *__dcngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int __n, int __category);
+extern char *__dcigettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ int __plural, unsigned long int __n,
+ int __category);
+extern char *__textdomain (const char *__domainname);
+extern char *__bindtextdomain (const char *__domainname,
+ const char *__dirname);
+extern char *__bind_textdomain_codeset (const char *__domainname,
+ const char *__codeset);
+extern void _nl_finddomain_subfreeres (void) attribute_hidden;
+extern void _nl_unload_domain (struct loaded_domain *__domain)
+ internal_function attribute_hidden;
+#else
+/* Declare the exported libintl_* functions, in a way that allows us to
+ call them under their real name. */
+# undef _INTL_REDIRECT_INLINE
+# undef _INTL_REDIRECT_MACROS
+# define _INTL_REDIRECT_MACROS
+# include "libgnuintl.h"
+# ifdef IN_LIBGLOCALE
+extern char *gl_dcigettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ int __plural, unsigned long int __n,
+ int __category,
+ const char *__localename, const char *__encoding);
+# else
+extern char *libintl_dcigettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ int __plural, unsigned long int __n,
+ int __category);
+# endif
+#endif
+
+#include "loadinfo.h"
+
+#include "gmo.h" /* Get nls_uint32. */
+
+/* @@ end of prolog @@ */
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+ almost always true or almost always false. */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+#ifndef W
+# define W(flag, data) ((flag) ? SWAP (data) : (data))
+#endif
+
+
+#ifdef _LIBC
+# include <byteswap.h>
+# define SWAP(i) bswap_32 (i)
+#else
+static inline nls_uint32
+# ifdef __cplusplus
+SWAP (nls_uint32 i)
+# else
+SWAP (i)
+ nls_uint32 i;
+# endif
+{
+ return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+#endif
+
+
+/* In-memory representation of system dependent string. */
+struct sysdep_string_desc
+{
+ /* Length of addressed string, including the trailing NUL. */
+ size_t length;
+ /* Pointer to addressed string. */
+ const char *pointer;
+};
+
+/* Cache of translated strings after charset conversion.
+ Note: The strings are converted to the target encoding only on an as-needed
+ basis. */
+struct converted_domain
+{
+ /* The target encoding name. */
+ const char *encoding;
+ /* The descriptor for conversion from the message catalog's encoding to
+ this target encoding. */
+#ifdef _LIBC
+ __gconv_t conv;
+#else
+# if HAVE_ICONV
+ iconv_t conv;
+# endif
+#endif
+ /* The table of translated strings after charset conversion. */
+ char **conv_tab;
+};
+
+/* The representation of an opened message catalog. */
+struct loaded_domain
+{
+ /* Pointer to memory containing the .mo file. */
+ const char *data;
+ /* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed. */
+ int use_mmap;
+ /* Size of mmap()ed memory. */
+ size_t mmap_size;
+ /* 1 if the .mo file uses a different endianness than this machine. */
+ int must_swap;
+ /* Pointer to additional malloc()ed memory. */
+ void *malloced;
+
+ /* Number of static strings pairs. */
+ nls_uint32 nstrings;
+ /* Pointer to descriptors of original strings in the file. */
+ const struct string_desc *orig_tab;
+ /* Pointer to descriptors of translated strings in the file. */
+ const struct string_desc *trans_tab;
+
+ /* Number of system dependent strings pairs. */
+ nls_uint32 n_sysdep_strings;
+ /* Pointer to descriptors of original sysdep strings. */
+ const struct sysdep_string_desc *orig_sysdep_tab;
+ /* Pointer to descriptors of translated sysdep strings. */
+ const struct sysdep_string_desc *trans_sysdep_tab;
+
+ /* Size of hash table. */
+ nls_uint32 hash_size;
+ /* Pointer to hash table. */
+ const nls_uint32 *hash_tab;
+ /* 1 if the hash table uses a different endianness than this machine. */
+ int must_swap_hash_tab;
+
+ /* Cache of charset conversions of the translated strings. */
+ struct converted_domain *conversions;
+ size_t nconversions;
+ gl_rwlock_define (, conversions_lock)
+
+ const struct expression *plural;
+ unsigned long int nplurals;
+};
+
+/* We want to allocate a string at the end of the struct. But ISO C
+ doesn't allow zero sized arrays. */
+#ifdef __GNUC__
+# define ZERO 0
+#else
+# define ZERO 1
+#endif
+
+/* A set of settings bound to a message domain. Used to store settings
+ from bindtextdomain() and bind_textdomain_codeset(). */
+struct binding
+{
+ struct binding *next;
+ char *dirname;
+ char *codeset;
+ char domainname[ZERO];
+};
+
+/* A counter which is incremented each time some previous translations
+ become invalid.
+ This variable is part of the external ABI of the GNU libintl. */
+#ifdef IN_LIBGLOCALE
+# include <glocale/config.h>
+extern LIBGLOCALE_DLL_EXPORTED int _nl_msg_cat_cntr;
+#else
+extern LIBINTL_DLL_EXPORTED int _nl_msg_cat_cntr;
+#endif
+
+#ifndef _LIBC
+extern const char *_nl_language_preferences_default (void);
+# define gl_locale_name_canonicalize _nl_locale_name_canonicalize
+extern void _nl_locale_name_canonicalize (char *name);
+# define gl_locale_name_from_win32_LANGID _nl_locale_name_from_win32_LANGID
+/* extern const char *_nl_locale_name_from_win32_LANGID (LANGID langid); */
+# define gl_locale_name_from_win32_LCID _nl_locale_name_from_win32_LCID
+/* extern const char *_nl_locale_name_from_win32_LCID (LCID lcid); */
+# define gl_locale_name_thread_unsafe _nl_locale_name_thread_unsafe
+extern const char *_nl_locale_name_thread_unsafe (int category,
+ const char *categoryname);
+# define gl_locale_name_thread _nl_locale_name_thread
+/* extern const char *_nl_locale_name_thread (int category,
+ const char *categoryname); */
+# define gl_locale_name_posix _nl_locale_name_posix
+extern const char *_nl_locale_name_posix (int category,
+ const char *categoryname);
+# define gl_locale_name_environ _nl_locale_name_environ
+extern const char *_nl_locale_name_environ (int category,
+ const char *categoryname);
+# define gl_locale_name_default _nl_locale_name_default
+extern const char *_nl_locale_name_default (void);
+# define gl_locale_name _nl_locale_name
+/* extern const char *_nl_locale_name (int category,
+ const char *categoryname); */
+#endif
+
+struct loaded_l10nfile *_nl_find_domain (const char *__dirname, char *__locale,
+ const char *__domainname,
+ struct binding *__domainbinding)
+ internal_function;
+void _nl_load_domain (struct loaded_l10nfile *__domain,
+ struct binding *__domainbinding)
+ internal_function;
+
+#ifdef IN_LIBGLOCALE
+char *_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding, const char *encoding,
+ const char *msgid,
+ size_t *lengthp)
+ internal_function;
+#else
+char *_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding, const char *msgid,
+ int convert, size_t *lengthp)
+ internal_function;
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+ names than the internal variables in GNU libc, otherwise programs
+ using libintl.a cannot be linked statically. */
+#if !defined _LIBC
+# define _nl_default_dirname libintl_nl_default_dirname
+# define _nl_domain_bindings libintl_nl_domain_bindings
+#endif
+
+/* Contains the default location of the message catalogs. */
+extern const char _nl_default_dirname[];
+#ifdef _LIBC
+libc_hidden_proto (_nl_default_dirname)
+#endif
+
+/* List with bindings of specific domains. */
+extern struct binding *_nl_domain_bindings;
+
+/* The internal variables in the standalone libintl.a must have different
+ names than the internal variables in GNU libc, otherwise programs
+ using libintl.a cannot be linked statically. */
+#if !defined _LIBC
+# define _nl_default_default_domain libintl_nl_default_default_domain
+# define _nl_current_default_domain libintl_nl_current_default_domain
+#endif
+
+/* Name of the default text domain. */
+extern const char _nl_default_default_domain[] attribute_hidden;
+
+/* Default text domain in which entries for gettext(3) are to be found. */
+extern const char *_nl_current_default_domain attribute_hidden;
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettextP.h */
diff --git a/REORG.TODO/intl/gmo.h b/REORG.TODO/intl/gmo.h
new file mode 100644
index 0000000000..3a9a2e7d27
--- /dev/null
+++ b/REORG.TODO/intl/gmo.h
@@ -0,0 +1,150 @@
+/* Description of GNU message catalog format: general file layout.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _GETTEXT_H
+#define _GETTEXT_H 1
+
+#include <limits.h>
+
+/* @@ end of prolog @@ */
+
+/* The magic number of the GNU message catalog format. */
+#define _MAGIC 0x950412de
+#define _MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format. */
+#define MO_REVISION_NUMBER 0
+#define MO_REVISION_NUMBER_WITH_SYSDEP_I 1
+
+/* The following contortions are an attempt to use the C preprocessor
+ to determine an unsigned integral type that is 32 bits wide. An
+ alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+ as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work
+ when cross-compiling. */
+
+#if __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+#else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+#endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+ This should be valid for all systems GNU cares about because
+ that doesn't include 16-bit systems, and only modern systems
+ (that certainly have <limits.h>) have 64+-bit integral types. */
+
+#ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+#endif
+
+#if UINT_MAX == UINT_MAX_32_BITS
+typedef unsigned nls_uint32;
+#else
+# if USHRT_MAX == UINT_MAX_32_BITS
+typedef unsigned short nls_uint32;
+# else
+# if ULONG_MAX == UINT_MAX_32_BITS
+typedef unsigned long nls_uint32;
+# else
+ /* The following line is intended to throw an error. Using #error is
+ not portable enough. */
+ "Cannot determine unsigned 32-bit data type."
+# endif
+# endif
+#endif
+
+
+/* Header for binary .mo file format. */
+struct mo_file_header
+{
+ /* The magic number. */
+ nls_uint32 magic;
+ /* The revision number of the file format. */
+ nls_uint32 revision;
+
+ /* The following are only used in .mo files with major revision 0 or 1. */
+
+ /* The number of strings pairs. */
+ nls_uint32 nstrings;
+ /* Offset of table with start offsets of original strings. */
+ nls_uint32 orig_tab_offset;
+ /* Offset of table with start offsets of translated strings. */
+ nls_uint32 trans_tab_offset;
+ /* Size of hash table. */
+ nls_uint32 hash_tab_size;
+ /* Offset of first hash table entry. */
+ nls_uint32 hash_tab_offset;
+
+ /* The following are only used in .mo files with minor revision >= 1. */
+
+ /* The number of system dependent segments. */
+ nls_uint32 n_sysdep_segments;
+ /* Offset of table describing system dependent segments. */
+ nls_uint32 sysdep_segments_offset;
+ /* The number of system dependent strings pairs. */
+ nls_uint32 n_sysdep_strings;
+ /* Offset of table with start offsets of original sysdep strings. */
+ nls_uint32 orig_sysdep_tab_offset;
+ /* Offset of table with start offsets of translated sysdep strings. */
+ nls_uint32 trans_sysdep_tab_offset;
+};
+
+/* Descriptor for static string contained in the binary .mo file. */
+struct string_desc
+{
+ /* Length of addressed string, not including the trailing NUL. */
+ nls_uint32 length;
+ /* Offset of string in file. */
+ nls_uint32 offset;
+};
+
+/* The following are only used in .mo files with minor revision >= 1. */
+
+/* Descriptor for system dependent string segment. */
+struct sysdep_segment
+{
+ /* Length of addressed string, including the trailing NUL. */
+ nls_uint32 length;
+ /* Offset of string in file. */
+ nls_uint32 offset;
+};
+
+/* Pair of a static and a system dependent segment, in struct sysdep_string. */
+struct segment_pair
+{
+ /* Size of static segment. */
+ nls_uint32 segsize;
+ /* Reference to system dependent string segment, or ~0 at the end. */
+ nls_uint32 sysdepref;
+};
+
+/* Descriptor for system dependent string. */
+struct sysdep_string
+{
+ /* Offset of static string segments in file. */
+ nls_uint32 offset;
+ /* Alternating sequence of static and system dependent segments.
+ The last segment is a static segment, including the trailing NUL. */
+ struct segment_pair segments[1];
+};
+
+/* Marker for the end of the segments[] array. This has the value 0xFFFFFFFF,
+ regardless whether 'int' is 16 bit, 32 bit, or 64 bit. */
+#define SEGMENTS_END ((nls_uint32) ~0)
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettext.h */
diff --git a/REORG.TODO/intl/hash-string.c b/REORG.TODO/intl/hash-string.c
new file mode 100644
index 0000000000..6a41273284
--- /dev/null
+++ b/REORG.TODO/intl/hash-string.c
@@ -0,0 +1,50 @@
+/* Implements a string hashing function.
+ Copyright (C) 1995-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "hash-string.h"
+
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+unsigned long int
+__hash_string (const char *str_param)
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ /* Compute the hash value for the given string. */
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned char) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
diff --git a/REORG.TODO/intl/hash-string.h b/REORG.TODO/intl/hash-string.h
new file mode 100644
index 0000000000..21dcb16739
--- /dev/null
+++ b/REORG.TODO/intl/hash-string.h
@@ -0,0 +1,34 @@
+/* Description of GNU message catalog format: string hashing function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* @@ end of prolog @@ */
+
+/* We assume to have `unsigned long int' value with at least 32 bits. */
+#define HASHWORDBITS 32
+
+
+#ifndef _LIBC
+# ifdef IN_LIBINTL
+# define __hash_string libintl_hash_string
+# else
+# define __hash_string hash_string
+# endif
+#endif
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+extern unsigned long int __hash_string (const char *str_param);
diff --git a/REORG.TODO/intl/l10nflist.c b/REORG.TODO/intl/l10nflist.c
new file mode 100644
index 0000000000..7625589d3a
--- /dev/null
+++ b/REORG.TODO/intl/l10nflist.c
@@ -0,0 +1,357 @@
+/* Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Tell glibc's <string.h> to provide a prototype for stpcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#if defined _LIBC || defined HAVE_ARGZ_H
+# include <argz.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found. Sigh! */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+# define NULL ((void *) 0)
+# else
+# define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions. This is required by the standard
+ because some ANSI C functions will require linking with this object
+ file and the name space must not be polluted. */
+# ifndef stpcpy
+# define stpcpy(dest, src) __stpcpy(dest, src)
+# endif
+#else
+# ifndef HAVE_STPCPY
+static char *stpcpy (char *dest, const char *src);
+# endif
+#endif
+
+/* Define function which are usually not available. */
+
+#if defined HAVE_ARGZ_COUNT
+# undef __argz_count
+# define __argz_count argz_count
+#else
+/* Returns the number of strings in ARGZ. */
+static size_t
+argz_count__ (const char *argz, size_t len)
+{
+ size_t count = 0;
+ while (len > 0)
+ {
+ size_t part_len = strlen (argz);
+ argz += part_len + 1;
+ len -= part_len + 1;
+ count++;
+ }
+ return count;
+}
+# undef __argz_count
+# define __argz_count(argz, len) argz_count__ (argz, len)
+#endif /* !_LIBC && !HAVE_ARGZ_COUNT */
+
+#if defined HAVE_ARGZ_STRINGIFY
+# undef __argz_stringify
+# define __argz_stringify argz_stringify
+#else
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+ except the last into the character SEP. */
+static void
+argz_stringify__ (char *argz, size_t len, int sep)
+{
+ while (len > 0)
+ {
+ size_t part_len = strlen (argz);
+ argz += part_len;
+ len -= part_len + 1;
+ if (len > 0)
+ *argz++ = sep;
+ }
+}
+# undef __argz_stringify
+# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
+#endif /* !_LIBC && !HAVE_ARGZ_STRINGIFY */
+
+#ifdef _LIBC
+#elif defined HAVE_ARGZ_NEXT
+# undef __argz_next
+# define __argz_next argz_next
+#else
+static char *
+argz_next__ (char *argz, size_t argz_len, const char *entry)
+{
+ if (entry)
+ {
+ if (entry < argz + argz_len)
+ entry = strchr (entry, '\0') + 1;
+
+ return entry >= argz + argz_len ? NULL : (char *) entry;
+ }
+ else
+ if (argz_len > 0)
+ return argz;
+ else
+ return 0;
+}
+# undef __argz_next
+# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
+#endif /* !_LIBC && !HAVE_ARGZ_NEXT */
+
+/* Return number of bits set in X. */
+#ifndef ARCH_POP
+static inline int
+pop (int x)
+{
+ /* We assume that no more than 16 bits are used. */
+ x = ((x & ~0x5555) >> 1) + (x & 0x5555);
+ x = ((x & ~0x3333) >> 2) + (x & 0x3333);
+ x = ((x >> 4) + x) & 0x0f0f;
+ x = ((x >> 8) + x) & 0xff;
+
+ return x;
+}
+#endif
+
+
+struct loaded_l10nfile *
+_nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
+ const char *dirlist, size_t dirlist_len,
+ int mask, const char *language, const char *territory,
+ const char *codeset, const char *normalized_codeset,
+ const char *modifier,
+ const char *filename, int do_allocate)
+{
+ char *abs_filename;
+ struct loaded_l10nfile *last = NULL;
+ struct loaded_l10nfile *retval;
+ char *cp;
+ size_t entries;
+ int cnt;
+
+ /* Allocate room for the full file name. */
+ abs_filename = (char *) malloc (dirlist_len
+ + strlen (language)
+ + ((mask & XPG_TERRITORY) != 0
+ ? strlen (territory) + 1 : 0)
+ + ((mask & XPG_CODESET) != 0
+ ? strlen (codeset) + 1 : 0)
+ + ((mask & XPG_NORM_CODESET) != 0
+ ? strlen (normalized_codeset) + 1 : 0)
+ + ((mask & XPG_MODIFIER) != 0
+ ? strlen (modifier) + 1 : 0)
+ + 1 + strlen (filename) + 1);
+
+ if (abs_filename == NULL)
+ return NULL;
+
+ retval = NULL;
+ last = NULL;
+
+ /* Construct file name. */
+ memcpy (abs_filename, dirlist, dirlist_len);
+ __argz_stringify (abs_filename, dirlist_len, ':');
+ cp = abs_filename + (dirlist_len - 1);
+ *cp++ = '/';
+ cp = stpcpy (cp, language);
+
+ if ((mask & XPG_TERRITORY) != 0)
+ {
+ *cp++ = '_';
+ cp = stpcpy (cp, territory);
+ }
+ if ((mask & XPG_CODESET) != 0)
+ {
+ *cp++ = '.';
+ cp = stpcpy (cp, codeset);
+ }
+ if ((mask & XPG_NORM_CODESET) != 0)
+ {
+ *cp++ = '.';
+ cp = stpcpy (cp, normalized_codeset);
+ }
+ if ((mask & XPG_MODIFIER) != 0)
+ {
+ *cp++ = '@';
+ cp = stpcpy (cp, modifier);
+ }
+
+ *cp++ = '/';
+ stpcpy (cp, filename);
+
+ /* Look in list of already loaded domains whether it is already
+ available. */
+ last = NULL;
+ for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
+ if (retval->filename != NULL)
+ {
+ int compare = strcmp (retval->filename, abs_filename);
+ if (compare == 0)
+ /* We found it! */
+ break;
+ if (compare < 0)
+ {
+ /* It's not in the list. */
+ retval = NULL;
+ break;
+ }
+
+ last = retval;
+ }
+
+ if (retval != NULL || do_allocate == 0)
+ {
+ free (abs_filename);
+ return retval;
+ }
+
+ retval = (struct loaded_l10nfile *)
+ malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
+ * (1 << pop (mask))
+ * sizeof (struct loaded_l10nfile *)));
+ if (retval == NULL)
+ {
+ free (abs_filename);
+ return NULL;
+ }
+
+ retval->filename = abs_filename;
+ /* If more than one directory is in the list this is a pseudo-entry
+ which just references others. We do not try to load data for it,
+ ever. */
+ retval->decided = (__argz_count (dirlist, dirlist_len) != 1
+ || ((mask & XPG_CODESET) != 0
+ && (mask & XPG_NORM_CODESET) != 0));
+ retval->data = NULL;
+
+ if (last == NULL)
+ {
+ retval->next = *l10nfile_list;
+ *l10nfile_list = retval;
+ }
+ else
+ {
+ retval->next = last->next;
+ last->next = retval;
+ }
+
+ entries = 0;
+ /* If the DIRLIST is a real list the RETVAL entry corresponds not to
+ a real file. So we have to use the DIRLIST separation mechanism
+ of the inner loop. */
+ cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
+ for (; cnt >= 0; --cnt)
+ if ((cnt & ~mask) == 0)
+ {
+ /* Iterate over all elements of the DIRLIST. */
+ char *dir = NULL;
+
+ while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
+ != NULL)
+ retval->successor[entries++]
+ = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
+ language, territory, codeset,
+ normalized_codeset, modifier, filename, 1);
+ }
+ retval->successor[entries] = NULL;
+
+ return retval;
+}
+
+/* Normalize codeset name. There is no standard for the codeset
+ names. Normalization allows the user to use any of the common
+ names. The return value is dynamically allocated and has to be
+ freed by the caller. */
+const char *
+_nl_normalize_codeset (const char *codeset, size_t name_len)
+{
+ size_t len = 0;
+ int only_digit = 1;
+ char *retval;
+ char *wp;
+ size_t cnt;
+#if !IS_IN (libc)
+ locale_t locale = newlocale (0, "C", NULL);
+#else
+# define locale _nl_C_locobj_ptr
+#endif
+
+ for (cnt = 0; cnt < name_len; ++cnt)
+ if (__isalnum_l ((unsigned char) codeset[cnt], locale))
+ {
+ ++len;
+
+ if (! __isdigit_l ((unsigned char) codeset[cnt], locale))
+ only_digit = 0;
+ }
+
+ retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
+
+ if (retval != NULL)
+ {
+ if (only_digit)
+ wp = stpcpy (retval, "iso");
+ else
+ wp = retval;
+
+ for (cnt = 0; cnt < name_len; ++cnt)
+ if (__isalpha_l ((unsigned char) codeset[cnt], locale))
+ *wp++ = __tolower_l ((unsigned char) codeset[cnt], locale);
+ else if (__isdigit_l ((unsigned char) codeset[cnt], locale))
+ *wp++ = codeset[cnt];
+
+ *wp = '\0';
+ }
+
+ return (const char *) retval;
+}
+
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library. So we
+ avoid the non-standard function stpcpy. In GNU C Library this
+ function is available, though. Also allow the symbol HAVE_STPCPY
+ to be defined. */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (char *dest, const char *src)
+{
+ while ((*dest++ = *src++) != '\0')
+ /* Do nothing. */ ;
+ return dest - 1;
+}
+#endif
diff --git a/REORG.TODO/intl/libintl.h b/REORG.TODO/intl/libintl.h
new file mode 100644
index 0000000000..2ea214b316
--- /dev/null
+++ b/REORG.TODO/intl/libintl.h
@@ -0,0 +1,123 @@
+/* Message catalogs for internationalization.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ This file is derived from the file libgettext.h in the GNU gettext package.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBINTL_H
+#define _LIBINTL_H 1
+
+#include <features.h>
+
+/* We define an additional symbol to signal that we use the GNU
+ implementation of gettext. */
+#define __USE_GNU_GETTEXT 1
+
+/* Provide information about the supported file formats. Returns the
+ maximum minor revision number supported for a given major revision. */
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \
+ ((major) == 0 ? 1 : -1)
+
+__BEGIN_DECLS
+
+/* Look up MSGID in the current default message catalog for the current
+ LC_MESSAGES locale. If not found, returns MSGID itself (the default
+ text). */
+extern char *gettext (const char *__msgid)
+ __THROW __attribute_format_arg__ (1);
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+ LC_MESSAGES locale. */
+extern char *dgettext (const char *__domainname, const char *__msgid)
+ __THROW __attribute_format_arg__ (2);
+extern char *__dgettext (const char *__domainname, const char *__msgid)
+ __THROW __attribute_format_arg__ (2);
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+ locale. */
+extern char *dcgettext (const char *__domainname,
+ const char *__msgid, int __category)
+ __THROW __attribute_format_arg__ (2);
+extern char *__dcgettext (const char *__domainname,
+ const char *__msgid, int __category)
+ __THROW __attribute_format_arg__ (2);
+
+
+/* Similar to `gettext' but select the plural form corresponding to the
+ number N. */
+extern char *ngettext (const char *__msgid1, const char *__msgid2,
+ unsigned long int __n)
+ __THROW __attribute_format_arg__ (1) __attribute_format_arg__ (2);
+
+/* Similar to `dgettext' but select the plural form corresponding to the
+ number N. */
+extern char *dngettext (const char *__domainname, const char *__msgid1,
+ const char *__msgid2, unsigned long int __n)
+ __THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3);
+
+/* Similar to `dcgettext' but select the plural form corresponding to the
+ number N. */
+extern char *dcngettext (const char *__domainname, const char *__msgid1,
+ const char *__msgid2, unsigned long int __n,
+ int __category)
+ __THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3);
+
+
+/* Set the current default message catalog to DOMAINNAME.
+ If DOMAINNAME is null, return the current default.
+ If DOMAINNAME is "", reset to the default of "messages". */
+extern char *textdomain (const char *__domainname) __THROW;
+
+/* Specify that the DOMAINNAME message catalog will be found
+ in DIRNAME rather than in the system locale data base. */
+extern char *bindtextdomain (const char *__domainname,
+ const char *__dirname) __THROW;
+
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+extern char *bind_textdomain_codeset (const char *__domainname,
+ const char *__codeset) __THROW;
+
+
+/* Optimized version of the function above. */
+#if defined __OPTIMIZE__ && !defined __cplusplus
+
+/* We need NULL for `gettext'. */
+# define __need_NULL
+# include <stddef.h>
+
+/* We need LC_MESSAGES for `dgettext'. */
+# include <locale.h>
+
+/* These must be macros. Inlined functions are useless because the
+ `__builtin_constant_p' predicate in dcgettext would always return
+ false. */
+
+# define gettext(msgid) dgettext (NULL, msgid)
+
+# define dgettext(domainname, msgid) \
+ dcgettext (domainname, msgid, LC_MESSAGES)
+
+# define ngettext(msgid1, msgid2, n) dngettext (NULL, msgid1, msgid2, n)
+
+# define dngettext(domainname, msgid1, msgid2, n) \
+ dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES)
+
+#endif /* Optimizing. */
+
+__END_DECLS
+
+#endif /* libintl.h */
diff --git a/REORG.TODO/intl/loadinfo.h b/REORG.TODO/intl/loadinfo.h
new file mode 100644
index 0000000000..602ee8213f
--- /dev/null
+++ b/REORG.TODO/intl/loadinfo.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LOADINFO_H
+#define _LOADINFO_H 1
+
+/* Declarations of locale dependent catalog lookup functions.
+ Implemented in
+
+ localealias.c Possibly replace a locale name by another.
+ explodename.c Split a locale name into its various fields.
+ l10nflist.c Generate a list of filenames of possible message catalogs.
+ finddomain.c Find and open the relevant message catalogs.
+
+ The main function _nl_find_domain() in finddomain.c is declared
+ in gettextP.h.
+ */
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef LIBINTL_DLL_EXPORTED
+# define LIBINTL_DLL_EXPORTED
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+ almost always true or almost always false. */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+/* Separator in PATH like lists of pathnames. */
+#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
+ /* Win32, OS/2, DOS */
+# define PATH_SEPARATOR ';'
+#else
+ /* Unix */
+# define PATH_SEPARATOR ':'
+#endif
+
+/* Encoding of locale name parts. */
+#define XPG_NORM_CODESET 1
+#define XPG_CODESET 2
+#define XPG_TERRITORY 4
+#define XPG_MODIFIER 8
+
+
+struct loaded_l10nfile
+{
+ const char *filename;
+ int decided;
+
+ const void *data;
+
+ struct loaded_l10nfile *next;
+ struct loaded_l10nfile *successor[1];
+};
+
+
+/* Normalize codeset name. There is no standard for the codeset
+ names. Normalization allows the user to use any of the common
+ names. The return value is dynamically allocated and has to be
+ freed by the caller. */
+extern const char *_nl_normalize_codeset (const char *codeset,
+ size_t name_len);
+
+/* Lookup a locale dependent file.
+ *L10NFILE_LIST denotes a pool of lookup results of locale dependent
+ files of the same kind, sorted in decreasing order of ->filename.
+ DIRLIST and DIRLIST_LEN are an argz list of directories in which to
+ look, containing at least one directory (i.e. DIRLIST_LEN > 0).
+ MASK, LANGUAGE, TERRITORY, CODESET, NORMALIZED_CODESET, MODIFIER
+ are the pieces of the locale name, as produced by _nl_explode_name().
+ FILENAME is the filename suffix.
+ The return value is the lookup result, either found in *L10NFILE_LIST,
+ or - if DO_ALLOCATE is nonzero - freshly allocated, or possibly NULL.
+ If the return value is non-NULL, it is added to *L10NFILE_LIST, and
+ its ->next field denotes the chaining inside *L10NFILE_LIST, and
+ furthermore its ->successor[] field contains a list of other lookup
+ results from which this lookup result inherits. */
+extern struct loaded_l10nfile *
+_nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
+ const char *dirlist, size_t dirlist_len, int mask,
+ const char *language, const char *territory,
+ const char *codeset, const char *normalized_codeset,
+ const char *modifier,
+ const char *filename, int do_allocate);
+
+/* Lookup the real locale name for a locale alias NAME, or NULL if
+ NAME is not a locale alias (but possibly a real locale name).
+ The return value is statically allocated and must not be freed. */
+/* Part of the libintl ABI only for the sake of the gettext.m4 macro. */
+extern LIBINTL_DLL_EXPORTED const char *_nl_expand_alias (const char *name);
+
+/* Split a locale name NAME into its pieces: language, modifier,
+ territory, codeset.
+ NAME gets destructively modified: NUL bytes are inserted here and
+ there. *LANGUAGE gets assigned NAME. Each of *MODIFIER, *TERRITORY,
+ *CODESET gets assigned either a pointer into the old NAME string, or
+ NULL. *NORMALIZED_CODESET gets assigned the expanded *CODESET, if it
+ is different from *CODESET; this one is dynamically allocated and has
+ to be freed by the caller.
+ The return value is a bitmask, where each bit corresponds to one
+ filled-in value:
+ XPG_MODIFIER for *MODIFIER,
+ XPG_TERRITORY for *TERRITORY,
+ XPG_CODESET for *CODESET,
+ XPG_NORM_CODESET for *NORMALIZED_CODESET.
+ */
+extern int _nl_explode_name (char *name, const char **language,
+ const char **modifier, const char **territory,
+ const char **codeset,
+ const char **normalized_codeset);
+
+#endif /* loadinfo.h */
diff --git a/REORG.TODO/intl/loadmsgcat.c b/REORG.TODO/intl/loadmsgcat.c
new file mode 100644
index 0000000000..4dd75deee7
--- /dev/null
+++ b/REORG.TODO/intl/loadmsgcat.c
@@ -0,0 +1,1351 @@
+/* Load needed message catalogs.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef __GNUC__
+# undef alloca
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#ifdef _LIBC
+# include <langinfo.h>
+# include <locale.h>
+#endif
+
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+ || (defined _LIBC && defined _POSIX_MAPPED_FILES)
+# include <sys/mman.h>
+# undef HAVE_MMAP
+# define HAVE_MMAP 1
+#else
+# undef HAVE_MMAP
+#endif
+
+#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
+# include <stdint.h>
+#endif
+#if defined HAVE_INTTYPES_H || defined _LIBC
+# include <inttypes.h>
+#endif
+
+#include "gmo.h"
+#include "gettextP.h"
+#include "hash-string.h"
+#include "plural-exp.h"
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# include <not-cancel.h>
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+#else
+# include "lock.h"
+#endif
+
+#ifdef _LIBC
+# define PRI_MACROS_BROKEN 0
+#endif
+
+/* Provide fallback values for macros that ought to be defined in <inttypes.h>.
+ Note that our fallback values need not be literal strings, because we don't
+ use them with preprocessor string concatenation. */
+#if !defined PRId8 || PRI_MACROS_BROKEN
+# undef PRId8
+# define PRId8 "d"
+#endif
+#if !defined PRIi8 || PRI_MACROS_BROKEN
+# undef PRIi8
+# define PRIi8 "i"
+#endif
+#if !defined PRIo8 || PRI_MACROS_BROKEN
+# undef PRIo8
+# define PRIo8 "o"
+#endif
+#if !defined PRIu8 || PRI_MACROS_BROKEN
+# undef PRIu8
+# define PRIu8 "u"
+#endif
+#if !defined PRIx8 || PRI_MACROS_BROKEN
+# undef PRIx8
+# define PRIx8 "x"
+#endif
+#if !defined PRIX8 || PRI_MACROS_BROKEN
+# undef PRIX8
+# define PRIX8 "X"
+#endif
+#if !defined PRId16 || PRI_MACROS_BROKEN
+# undef PRId16
+# define PRId16 "d"
+#endif
+#if !defined PRIi16 || PRI_MACROS_BROKEN
+# undef PRIi16
+# define PRIi16 "i"
+#endif
+#if !defined PRIo16 || PRI_MACROS_BROKEN
+# undef PRIo16
+# define PRIo16 "o"
+#endif
+#if !defined PRIu16 || PRI_MACROS_BROKEN
+# undef PRIu16
+# define PRIu16 "u"
+#endif
+#if !defined PRIx16 || PRI_MACROS_BROKEN
+# undef PRIx16
+# define PRIx16 "x"
+#endif
+#if !defined PRIX16 || PRI_MACROS_BROKEN
+# undef PRIX16
+# define PRIX16 "X"
+#endif
+#if !defined PRId32 || PRI_MACROS_BROKEN
+# undef PRId32
+# define PRId32 "d"
+#endif
+#if !defined PRIi32 || PRI_MACROS_BROKEN
+# undef PRIi32
+# define PRIi32 "i"
+#endif
+#if !defined PRIo32 || PRI_MACROS_BROKEN
+# undef PRIo32
+# define PRIo32 "o"
+#endif
+#if !defined PRIu32 || PRI_MACROS_BROKEN
+# undef PRIu32
+# define PRIu32 "u"
+#endif
+#if !defined PRIx32 || PRI_MACROS_BROKEN
+# undef PRIx32
+# define PRIx32 "x"
+#endif
+#if !defined PRIX32 || PRI_MACROS_BROKEN
+# undef PRIX32
+# define PRIX32 "X"
+#endif
+#if !defined PRId64 || PRI_MACROS_BROKEN
+# undef PRId64
+# define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
+#endif
+#if !defined PRIi64 || PRI_MACROS_BROKEN
+# undef PRIi64
+# define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
+#endif
+#if !defined PRIo64 || PRI_MACROS_BROKEN
+# undef PRIo64
+# define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
+#endif
+#if !defined PRIu64 || PRI_MACROS_BROKEN
+# undef PRIu64
+# define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
+#endif
+#if !defined PRIx64 || PRI_MACROS_BROKEN
+# undef PRIx64
+# define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
+#endif
+#if !defined PRIX64 || PRI_MACROS_BROKEN
+# undef PRIX64
+# define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
+#endif
+#if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
+# undef PRIdLEAST8
+# define PRIdLEAST8 "d"
+#endif
+#if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
+# undef PRIiLEAST8
+# define PRIiLEAST8 "i"
+#endif
+#if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
+# undef PRIoLEAST8
+# define PRIoLEAST8 "o"
+#endif
+#if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
+# undef PRIuLEAST8
+# define PRIuLEAST8 "u"
+#endif
+#if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
+# undef PRIxLEAST8
+# define PRIxLEAST8 "x"
+#endif
+#if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
+# undef PRIXLEAST8
+# define PRIXLEAST8 "X"
+#endif
+#if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
+# undef PRIdLEAST16
+# define PRIdLEAST16 "d"
+#endif
+#if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
+# undef PRIiLEAST16
+# define PRIiLEAST16 "i"
+#endif
+#if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
+# undef PRIoLEAST16
+# define PRIoLEAST16 "o"
+#endif
+#if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
+# undef PRIuLEAST16
+# define PRIuLEAST16 "u"
+#endif
+#if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
+# undef PRIxLEAST16
+# define PRIxLEAST16 "x"
+#endif
+#if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
+# undef PRIXLEAST16
+# define PRIXLEAST16 "X"
+#endif
+#if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
+# undef PRIdLEAST32
+# define PRIdLEAST32 "d"
+#endif
+#if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
+# undef PRIiLEAST32
+# define PRIiLEAST32 "i"
+#endif
+#if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
+# undef PRIoLEAST32
+# define PRIoLEAST32 "o"
+#endif
+#if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
+# undef PRIuLEAST32
+# define PRIuLEAST32 "u"
+#endif
+#if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
+# undef PRIxLEAST32
+# define PRIxLEAST32 "x"
+#endif
+#if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
+# undef PRIXLEAST32
+# define PRIXLEAST32 "X"
+#endif
+#if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
+# undef PRIdLEAST64
+# define PRIdLEAST64 PRId64
+#endif
+#if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
+# undef PRIiLEAST64
+# define PRIiLEAST64 PRIi64
+#endif
+#if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
+# undef PRIoLEAST64
+# define PRIoLEAST64 PRIo64
+#endif
+#if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
+# undef PRIuLEAST64
+# define PRIuLEAST64 PRIu64
+#endif
+#if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
+# undef PRIxLEAST64
+# define PRIxLEAST64 PRIx64
+#endif
+#if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
+# undef PRIXLEAST64
+# define PRIXLEAST64 PRIX64
+#endif
+#if !defined PRIdFAST8 || PRI_MACROS_BROKEN
+# undef PRIdFAST8
+# define PRIdFAST8 "d"
+#endif
+#if !defined PRIiFAST8 || PRI_MACROS_BROKEN
+# undef PRIiFAST8
+# define PRIiFAST8 "i"
+#endif
+#if !defined PRIoFAST8 || PRI_MACROS_BROKEN
+# undef PRIoFAST8
+# define PRIoFAST8 "o"
+#endif
+#if !defined PRIuFAST8 || PRI_MACROS_BROKEN
+# undef PRIuFAST8
+# define PRIuFAST8 "u"
+#endif
+#if !defined PRIxFAST8 || PRI_MACROS_BROKEN
+# undef PRIxFAST8
+# define PRIxFAST8 "x"
+#endif
+#if !defined PRIXFAST8 || PRI_MACROS_BROKEN
+# undef PRIXFAST8
+# define PRIXFAST8 "X"
+#endif
+#if !defined PRIdFAST16 || PRI_MACROS_BROKEN
+# undef PRIdFAST16
+# define PRIdFAST16 "d"
+#endif
+#if !defined PRIiFAST16 || PRI_MACROS_BROKEN
+# undef PRIiFAST16
+# define PRIiFAST16 "i"
+#endif
+#if !defined PRIoFAST16 || PRI_MACROS_BROKEN
+# undef PRIoFAST16
+# define PRIoFAST16 "o"
+#endif
+#if !defined PRIuFAST16 || PRI_MACROS_BROKEN
+# undef PRIuFAST16
+# define PRIuFAST16 "u"
+#endif
+#if !defined PRIxFAST16 || PRI_MACROS_BROKEN
+# undef PRIxFAST16
+# define PRIxFAST16 "x"
+#endif
+#if !defined PRIXFAST16 || PRI_MACROS_BROKEN
+# undef PRIXFAST16
+# define PRIXFAST16 "X"
+#endif
+#if !defined PRIdFAST32 || PRI_MACROS_BROKEN
+# undef PRIdFAST32
+# define PRIdFAST32 "d"
+#endif
+#if !defined PRIiFAST32 || PRI_MACROS_BROKEN
+# undef PRIiFAST32
+# define PRIiFAST32 "i"
+#endif
+#if !defined PRIoFAST32 || PRI_MACROS_BROKEN
+# undef PRIoFAST32
+# define PRIoFAST32 "o"
+#endif
+#if !defined PRIuFAST32 || PRI_MACROS_BROKEN
+# undef PRIuFAST32
+# define PRIuFAST32 "u"
+#endif
+#if !defined PRIxFAST32 || PRI_MACROS_BROKEN
+# undef PRIxFAST32
+# define PRIxFAST32 "x"
+#endif
+#if !defined PRIXFAST32 || PRI_MACROS_BROKEN
+# undef PRIXFAST32
+# define PRIXFAST32 "X"
+#endif
+#if !defined PRIdFAST64 || PRI_MACROS_BROKEN
+# undef PRIdFAST64
+# define PRIdFAST64 PRId64
+#endif
+#if !defined PRIiFAST64 || PRI_MACROS_BROKEN
+# undef PRIiFAST64
+# define PRIiFAST64 PRIi64
+#endif
+#if !defined PRIoFAST64 || PRI_MACROS_BROKEN
+# undef PRIoFAST64
+# define PRIoFAST64 PRIo64
+#endif
+#if !defined PRIuFAST64 || PRI_MACROS_BROKEN
+# undef PRIuFAST64
+# define PRIuFAST64 PRIu64
+#endif
+#if !defined PRIxFAST64 || PRI_MACROS_BROKEN
+# undef PRIxFAST64
+# define PRIxFAST64 PRIx64
+#endif
+#if !defined PRIXFAST64 || PRI_MACROS_BROKEN
+# undef PRIXFAST64
+# define PRIXFAST64 PRIX64
+#endif
+#if !defined PRIdMAX || PRI_MACROS_BROKEN
+# undef PRIdMAX
+# define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
+#endif
+#if !defined PRIiMAX || PRI_MACROS_BROKEN
+# undef PRIiMAX
+# define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
+#endif
+#if !defined PRIoMAX || PRI_MACROS_BROKEN
+# undef PRIoMAX
+# define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
+#endif
+#if !defined PRIuMAX || PRI_MACROS_BROKEN
+# undef PRIuMAX
+# define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
+#endif
+#if !defined PRIxMAX || PRI_MACROS_BROKEN
+# undef PRIxMAX
+# define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
+#endif
+#if !defined PRIXMAX || PRI_MACROS_BROKEN
+# undef PRIXMAX
+# define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
+#endif
+#if !defined PRIdPTR || PRI_MACROS_BROKEN
+# undef PRIdPTR
+# define PRIdPTR \
+ (sizeof (void *) == sizeof (long) ? "ld" : \
+ sizeof (void *) == sizeof (int) ? "d" : \
+ "lld")
+#endif
+#if !defined PRIiPTR || PRI_MACROS_BROKEN
+# undef PRIiPTR
+# define PRIiPTR \
+ (sizeof (void *) == sizeof (long) ? "li" : \
+ sizeof (void *) == sizeof (int) ? "i" : \
+ "lli")
+#endif
+#if !defined PRIoPTR || PRI_MACROS_BROKEN
+# undef PRIoPTR
+# define PRIoPTR \
+ (sizeof (void *) == sizeof (long) ? "lo" : \
+ sizeof (void *) == sizeof (int) ? "o" : \
+ "llo")
+#endif
+#if !defined PRIuPTR || PRI_MACROS_BROKEN
+# undef PRIuPTR
+# define PRIuPTR \
+ (sizeof (void *) == sizeof (long) ? "lu" : \
+ sizeof (void *) == sizeof (int) ? "u" : \
+ "llu")
+#endif
+#if !defined PRIxPTR || PRI_MACROS_BROKEN
+# undef PRIxPTR
+# define PRIxPTR \
+ (sizeof (void *) == sizeof (long) ? "lx" : \
+ sizeof (void *) == sizeof (int) ? "x" : \
+ "llx")
+#endif
+#if !defined PRIXPTR || PRI_MACROS_BROKEN
+# undef PRIXPTR
+# define PRIXPTR \
+ (sizeof (void *) == sizeof (long) ? "lX" : \
+ sizeof (void *) == sizeof (int) ? "X" : \
+ "llX")
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ISO C functions. This is required by the standard
+ because some ISO C functions will require linking with this object
+ file and the name space must not be polluted. */
+# define open(name, flags) open_not_cancel_2 (name, flags)
+# define close(fd) close_not_cancel_no_status (fd)
+# define read(fd, buf, n) read_not_cancel (fd, buf, n)
+# define mmap(addr, len, prot, flags, fd, offset) \
+ __mmap (addr, len, prot, flags, fd, offset)
+# define munmap(addr, len) __munmap (addr, len)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+/* For systems that distinguish between text and binary I/O.
+ O_BINARY is usually declared in <fcntl.h>. */
+#if !defined O_BINARY && defined _O_BINARY
+ /* For MSC-compatible compilers. */
+# define O_BINARY _O_BINARY
+# define O_TEXT _O_TEXT
+#endif
+#ifdef __BEOS__
+ /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
+# undef O_BINARY
+# undef O_TEXT
+#endif
+/* On reasonable systems, binary I/O is the default. */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+
+/* We need a sign, whether a new catalog was loaded, which can be associated
+ with all translations. This is important if the translations are
+ cached by one of GCC's features. */
+int _nl_msg_cat_cntr;
+
+
+/* Expand a system dependent string segment. Return NULL if unsupported. */
+static const char *
+get_sysdep_segment_value (const char *name)
+{
+ /* Test for an ISO C 99 section 7.8.1 format string directive.
+ Syntax:
+ P R I { d | i | o | u | x | X }
+ { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
+ /* We don't use a table of 14 times 6 'const char *' strings here, because
+ data relocations cost startup time. */
+ if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
+ {
+ if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
+ || name[3] == 'x' || name[3] == 'X')
+ {
+ if (name[4] == '8' && name[5] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId8;
+ if (name[3] == 'i')
+ return PRIi8;
+ if (name[3] == 'o')
+ return PRIo8;
+ if (name[3] == 'u')
+ return PRIu8;
+ if (name[3] == 'x')
+ return PRIx8;
+ if (name[3] == 'X')
+ return PRIX8;
+ abort ();
+ }
+ if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId16;
+ if (name[3] == 'i')
+ return PRIi16;
+ if (name[3] == 'o')
+ return PRIo16;
+ if (name[3] == 'u')
+ return PRIu16;
+ if (name[3] == 'x')
+ return PRIx16;
+ if (name[3] == 'X')
+ return PRIX16;
+ abort ();
+ }
+ if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId32;
+ if (name[3] == 'i')
+ return PRIi32;
+ if (name[3] == 'o')
+ return PRIo32;
+ if (name[3] == 'u')
+ return PRIu32;
+ if (name[3] == 'x')
+ return PRIx32;
+ if (name[3] == 'X')
+ return PRIX32;
+ abort ();
+ }
+ if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId64;
+ if (name[3] == 'i')
+ return PRIi64;
+ if (name[3] == 'o')
+ return PRIo64;
+ if (name[3] == 'u')
+ return PRIu64;
+ if (name[3] == 'x')
+ return PRIx64;
+ if (name[3] == 'X')
+ return PRIX64;
+ abort ();
+ }
+ if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
+ && name[7] == 'S' && name[8] == 'T')
+ {
+ if (name[9] == '8' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST8;
+ if (name[3] == 'i')
+ return PRIiLEAST8;
+ if (name[3] == 'o')
+ return PRIoLEAST8;
+ if (name[3] == 'u')
+ return PRIuLEAST8;
+ if (name[3] == 'x')
+ return PRIxLEAST8;
+ if (name[3] == 'X')
+ return PRIXLEAST8;
+ abort ();
+ }
+ if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST16;
+ if (name[3] == 'i')
+ return PRIiLEAST16;
+ if (name[3] == 'o')
+ return PRIoLEAST16;
+ if (name[3] == 'u')
+ return PRIuLEAST16;
+ if (name[3] == 'x')
+ return PRIxLEAST16;
+ if (name[3] == 'X')
+ return PRIXLEAST16;
+ abort ();
+ }
+ if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST32;
+ if (name[3] == 'i')
+ return PRIiLEAST32;
+ if (name[3] == 'o')
+ return PRIoLEAST32;
+ if (name[3] == 'u')
+ return PRIuLEAST32;
+ if (name[3] == 'x')
+ return PRIxLEAST32;
+ if (name[3] == 'X')
+ return PRIXLEAST32;
+ abort ();
+ }
+ if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST64;
+ if (name[3] == 'i')
+ return PRIiLEAST64;
+ if (name[3] == 'o')
+ return PRIoLEAST64;
+ if (name[3] == 'u')
+ return PRIuLEAST64;
+ if (name[3] == 'x')
+ return PRIxLEAST64;
+ if (name[3] == 'X')
+ return PRIXLEAST64;
+ abort ();
+ }
+ }
+ if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
+ && name[7] == 'T')
+ {
+ if (name[8] == '8' && name[9] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST8;
+ if (name[3] == 'i')
+ return PRIiFAST8;
+ if (name[3] == 'o')
+ return PRIoFAST8;
+ if (name[3] == 'u')
+ return PRIuFAST8;
+ if (name[3] == 'x')
+ return PRIxFAST8;
+ if (name[3] == 'X')
+ return PRIXFAST8;
+ abort ();
+ }
+ if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST16;
+ if (name[3] == 'i')
+ return PRIiFAST16;
+ if (name[3] == 'o')
+ return PRIoFAST16;
+ if (name[3] == 'u')
+ return PRIuFAST16;
+ if (name[3] == 'x')
+ return PRIxFAST16;
+ if (name[3] == 'X')
+ return PRIXFAST16;
+ abort ();
+ }
+ if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST32;
+ if (name[3] == 'i')
+ return PRIiFAST32;
+ if (name[3] == 'o')
+ return PRIoFAST32;
+ if (name[3] == 'u')
+ return PRIuFAST32;
+ if (name[3] == 'x')
+ return PRIxFAST32;
+ if (name[3] == 'X')
+ return PRIXFAST32;
+ abort ();
+ }
+ if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST64;
+ if (name[3] == 'i')
+ return PRIiFAST64;
+ if (name[3] == 'o')
+ return PRIoFAST64;
+ if (name[3] == 'u')
+ return PRIuFAST64;
+ if (name[3] == 'x')
+ return PRIxFAST64;
+ if (name[3] == 'X')
+ return PRIXFAST64;
+ abort ();
+ }
+ }
+ if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
+ && name[7] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdMAX;
+ if (name[3] == 'i')
+ return PRIiMAX;
+ if (name[3] == 'o')
+ return PRIoMAX;
+ if (name[3] == 'u')
+ return PRIuMAX;
+ if (name[3] == 'x')
+ return PRIxMAX;
+ if (name[3] == 'X')
+ return PRIXMAX;
+ abort ();
+ }
+ if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
+ && name[7] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdPTR;
+ if (name[3] == 'i')
+ return PRIiPTR;
+ if (name[3] == 'o')
+ return PRIoPTR;
+ if (name[3] == 'u')
+ return PRIuPTR;
+ if (name[3] == 'x')
+ return PRIxPTR;
+ if (name[3] == 'X')
+ return PRIXPTR;
+ abort ();
+ }
+ }
+ }
+ /* Test for a glibc specific printf() format directive flag. */
+ if (name[0] == 'I' && name[1] == '\0')
+ {
+#if defined _LIBC \
+ || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) \
+ && !defined __UCLIBC__)
+ /* The 'I' flag, in numeric format directives, replaces ASCII digits
+ with the 'outdigits' defined in the LC_CTYPE locale facet. This is
+ used for Farsi (Persian), some Indic languages, and maybe Arabic. */
+ return "I";
+#else
+ return "";
+#endif
+ }
+ /* Other system dependent strings are not valid. */
+ return NULL;
+}
+
+/* Load the message catalogs specified by FILENAME. If it is no valid
+ message catalog do nothing. */
+void
+internal_function
+_nl_load_domain (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding)
+{
+ __libc_lock_define_initialized_recursive (static, lock);
+ int fd = -1;
+ size_t size;
+#ifdef _LIBC
+ struct stat64 st;
+#else
+ struct stat st;
+#endif
+ struct mo_file_header *data = (struct mo_file_header *) -1;
+ int use_mmap = 0;
+ struct loaded_domain *domain;
+ int revision;
+ const char *nullentry;
+ size_t nullentrylen;
+
+ __libc_lock_lock_recursive (lock);
+ if (domain_file->decided != 0)
+ {
+ /* There are two possibilities:
+
+ + this is the same thread calling again during this initialization
+ via _nl_find_msg. We have initialized everything this call needs.
+
+ + this is another thread which tried to initialize this object.
+ Not necessary anymore since if the lock is available this
+ is finished.
+ */
+ goto done;
+ }
+
+ domain_file->decided = -1;
+ domain_file->data = NULL;
+
+ /* Note that it would be useless to store domainbinding in domain_file
+ because domainbinding might be == NULL now but != NULL later (after
+ a call to bind_textdomain_codeset). */
+
+ /* If the record does not represent a valid locale the FILENAME
+ might be NULL. This can happen when according to the given
+ specification the locale file name is different for XPG and CEN
+ syntax. */
+ if (domain_file->filename == NULL)
+ goto out;
+
+ /* Try to open the addressed file. */
+ fd = open (domain_file->filename, O_RDONLY | O_BINARY);
+ if (fd == -1)
+ goto out;
+
+ /* We must know about the size of the file. */
+ if (
+#ifdef _LIBC
+ __builtin_expect (fstat64 (fd, &st) != 0, 0)
+#else
+ __builtin_expect (fstat (fd, &st) != 0, 0)
+#endif
+ || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
+ || __builtin_expect (size < sizeof (struct mo_file_header), 0))
+ /* Something went wrong. */
+ goto out;
+
+#ifdef HAVE_MMAP
+ /* Now we are ready to load the file. If mmap() is available we try
+ this first. If not available or it failed we try to load it. */
+ data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
+ MAP_PRIVATE, fd, 0);
+
+ if (__builtin_expect (data != MAP_FAILED, 1))
+ {
+ /* mmap() call was successful. */
+ close (fd);
+ fd = -1;
+ use_mmap = 1;
+ }
+
+ assert (MAP_FAILED == (void *) -1);
+#endif
+
+ /* If the data is not yet available (i.e. mmap'ed) we try to load
+ it manually. */
+ if (data == (struct mo_file_header *) -1)
+ {
+ size_t to_read;
+ char *read_ptr;
+
+ data = (struct mo_file_header *) malloc (size);
+ if (data == NULL)
+ goto out;
+
+ to_read = size;
+ read_ptr = (char *) data;
+ do
+ {
+ long int nb = (long int) read (fd, read_ptr, to_read);
+ if (nb <= 0)
+ {
+#ifdef EINTR
+ if (nb == -1 && errno == EINTR)
+ continue;
+#endif
+ goto out;
+ }
+ read_ptr += nb;
+ to_read -= nb;
+ }
+ while (to_read > 0);
+
+ close (fd);
+ fd = -1;
+ }
+
+ /* Using the magic number we can test whether it really is a message
+ catalog file. */
+ if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
+ 0))
+ {
+ /* The magic number is wrong: not a message catalog file. */
+#ifdef HAVE_MMAP
+ if (use_mmap)
+ munmap ((caddr_t) data, size);
+ else
+#endif
+ free (data);
+ goto out;
+ }
+
+ domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
+ if (domain == NULL)
+ goto out;
+ domain_file->data = domain;
+
+ domain->data = (char *) data;
+ domain->use_mmap = use_mmap;
+ domain->mmap_size = size;
+ domain->must_swap = data->magic != _MAGIC;
+ domain->malloced = NULL;
+
+ /* Fill in the information about the available tables. */
+ revision = W (domain->must_swap, data->revision);
+ /* We support only the major revisions 0 and 1. */
+ switch (revision >> 16)
+ {
+ case 0:
+ case 1:
+ domain->nstrings = W (domain->must_swap, data->nstrings);
+ domain->orig_tab = (const struct string_desc *)
+ ((char *) data + W (domain->must_swap, data->orig_tab_offset));
+ domain->trans_tab = (const struct string_desc *)
+ ((char *) data + W (domain->must_swap, data->trans_tab_offset));
+ domain->hash_size = W (domain->must_swap, data->hash_tab_size);
+ domain->hash_tab =
+ (domain->hash_size > 2
+ ? (const nls_uint32 *)
+ ((char *) data + W (domain->must_swap, data->hash_tab_offset))
+ : NULL);
+ domain->must_swap_hash_tab = domain->must_swap;
+
+ /* Now dispatch on the minor revision. */
+ switch (revision & 0xffff)
+ {
+ case 0:
+ domain->n_sysdep_strings = 0;
+ domain->orig_sysdep_tab = NULL;
+ domain->trans_sysdep_tab = NULL;
+ break;
+ case 1:
+ default:
+ {
+ nls_uint32 n_sysdep_strings;
+
+ if (domain->hash_tab == NULL)
+ /* This is invalid. These minor revisions need a hash table. */
+ goto invalid;
+
+ n_sysdep_strings =
+ W (domain->must_swap, data->n_sysdep_strings);
+ if (n_sysdep_strings > 0)
+ {
+ nls_uint32 n_sysdep_segments;
+ const struct sysdep_segment *sysdep_segments;
+ const char **sysdep_segment_values;
+ const nls_uint32 *orig_sysdep_tab;
+ const nls_uint32 *trans_sysdep_tab;
+ nls_uint32 n_inmem_sysdep_strings;
+ size_t memneed;
+ char *mem;
+ struct sysdep_string_desc *inmem_orig_sysdep_tab;
+ struct sysdep_string_desc *inmem_trans_sysdep_tab;
+ nls_uint32 *inmem_hash_tab;
+ unsigned int i, j;
+
+ /* Get the values of the system dependent segments. */
+ n_sysdep_segments =
+ W (domain->must_swap, data->n_sysdep_segments);
+ sysdep_segments = (const struct sysdep_segment *)
+ ((char *) data
+ + W (domain->must_swap, data->sysdep_segments_offset));
+ sysdep_segment_values =
+ (const char **)
+ alloca (n_sysdep_segments * sizeof (const char *));
+ for (i = 0; i < n_sysdep_segments; i++)
+ {
+ const char *name =
+ (char *) data
+ + W (domain->must_swap, sysdep_segments[i].offset);
+ nls_uint32 namelen =
+ W (domain->must_swap, sysdep_segments[i].length);
+
+ if (!(namelen > 0 && name[namelen - 1] == '\0'))
+ {
+ freea (sysdep_segment_values);
+ goto invalid;
+ }
+
+ sysdep_segment_values[i] = get_sysdep_segment_value (name);
+ }
+
+ orig_sysdep_tab = (const nls_uint32 *)
+ ((char *) data
+ + W (domain->must_swap, data->orig_sysdep_tab_offset));
+ trans_sysdep_tab = (const nls_uint32 *)
+ ((char *) data
+ + W (domain->must_swap, data->trans_sysdep_tab_offset));
+
+ /* Compute the amount of additional memory needed for the
+ system dependent strings and the augmented hash table.
+ At the same time, also drop string pairs which refer to
+ an undefined system dependent segment. */
+ n_inmem_sysdep_strings = 0;
+ memneed = domain->hash_size * sizeof (nls_uint32);
+ for (i = 0; i < n_sysdep_strings; i++)
+ {
+ int valid = 1;
+ size_t needs[2];
+
+ for (j = 0; j < 2; j++)
+ {
+ const struct sysdep_string *sysdep_string =
+ (const struct sysdep_string *)
+ ((char *) data
+ + W (domain->must_swap,
+ j == 0
+ ? orig_sysdep_tab[i]
+ : trans_sysdep_tab[i]));
+ size_t need = 0;
+ const struct segment_pair *p = sysdep_string->segments;
+
+ if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
+ for (p = sysdep_string->segments;; p++)
+ {
+ nls_uint32 sysdepref;
+
+ need += W (domain->must_swap, p->segsize);
+
+ sysdepref = W (domain->must_swap, p->sysdepref);
+ if (sysdepref == SEGMENTS_END)
+ break;
+
+ if (sysdepref >= n_sysdep_segments)
+ {
+ /* Invalid. */
+ freea (sysdep_segment_values);
+ goto invalid;
+ }
+
+ if (sysdep_segment_values[sysdepref] == NULL)
+ {
+ /* This particular string pair is invalid. */
+ valid = 0;
+ break;
+ }
+
+ need += strlen (sysdep_segment_values[sysdepref]);
+ }
+
+ needs[j] = need;
+ if (!valid)
+ break;
+ }
+
+ if (valid)
+ {
+ n_inmem_sysdep_strings++;
+ memneed += needs[0] + needs[1];
+ }
+ }
+ memneed += 2 * n_inmem_sysdep_strings
+ * sizeof (struct sysdep_string_desc);
+
+ if (n_inmem_sysdep_strings > 0)
+ {
+ unsigned int k;
+
+ /* Allocate additional memory. */
+ mem = (char *) malloc (memneed);
+ if (mem == NULL)
+ goto invalid;
+
+ domain->malloced = mem;
+ inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
+ mem += n_inmem_sysdep_strings
+ * sizeof (struct sysdep_string_desc);
+ inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
+ mem += n_inmem_sysdep_strings
+ * sizeof (struct sysdep_string_desc);
+ inmem_hash_tab = (nls_uint32 *) mem;
+ mem += domain->hash_size * sizeof (nls_uint32);
+
+ /* Compute the system dependent strings. */
+ k = 0;
+ for (i = 0; i < n_sysdep_strings; i++)
+ {
+ int valid = 1;
+
+ for (j = 0; j < 2; j++)
+ {
+ const struct sysdep_string *sysdep_string =
+ (const struct sysdep_string *)
+ ((char *) data
+ + W (domain->must_swap,
+ j == 0
+ ? orig_sysdep_tab[i]
+ : trans_sysdep_tab[i]));
+ const struct segment_pair *p =
+ sysdep_string->segments;
+
+ if (W (domain->must_swap, p->sysdepref)
+ != SEGMENTS_END)
+ for (p = sysdep_string->segments;; p++)
+ {
+ nls_uint32 sysdepref;
+
+ sysdepref =
+ W (domain->must_swap, p->sysdepref);
+ if (sysdepref == SEGMENTS_END)
+ break;
+
+ if (sysdep_segment_values[sysdepref] == NULL)
+ {
+ /* This particular string pair is
+ invalid. */
+ valid = 0;
+ break;
+ }
+ }
+
+ if (!valid)
+ break;
+ }
+
+ if (valid)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ const struct sysdep_string *sysdep_string =
+ (const struct sysdep_string *)
+ ((char *) data
+ + W (domain->must_swap,
+ j == 0
+ ? orig_sysdep_tab[i]
+ : trans_sysdep_tab[i]));
+ const char *static_segments =
+ (char *) data
+ + W (domain->must_swap, sysdep_string->offset);
+ const struct segment_pair *p =
+ sysdep_string->segments;
+
+ /* Concatenate the segments, and fill
+ inmem_orig_sysdep_tab[k] (for j == 0) and
+ inmem_trans_sysdep_tab[k] (for j == 1). */
+
+ struct sysdep_string_desc *inmem_tab_entry =
+ (j == 0
+ ? inmem_orig_sysdep_tab
+ : inmem_trans_sysdep_tab)
+ + k;
+
+ if (W (domain->must_swap, p->sysdepref)
+ == SEGMENTS_END)
+ {
+ /* Only one static segment. */
+ inmem_tab_entry->length =
+ W (domain->must_swap, p->segsize);
+ inmem_tab_entry->pointer = static_segments;
+ }
+ else
+ {
+ inmem_tab_entry->pointer = mem;
+
+ for (p = sysdep_string->segments;; p++)
+ {
+ nls_uint32 segsize =
+ W (domain->must_swap, p->segsize);
+ nls_uint32 sysdepref =
+ W (domain->must_swap, p->sysdepref);
+ size_t n;
+
+ if (segsize > 0)
+ {
+ memcpy (mem, static_segments, segsize);
+ mem += segsize;
+ static_segments += segsize;
+ }
+
+ if (sysdepref == SEGMENTS_END)
+ break;
+
+ n = strlen (sysdep_segment_values[sysdepref]);
+ memcpy (mem, sysdep_segment_values[sysdepref], n);
+ mem += n;
+ }
+
+ inmem_tab_entry->length =
+ mem - inmem_tab_entry->pointer;
+ }
+ }
+
+ k++;
+ }
+ }
+ if (k != n_inmem_sysdep_strings)
+ abort ();
+
+ /* Compute the augmented hash table. */
+ for (i = 0; i < domain->hash_size; i++)
+ inmem_hash_tab[i] =
+ W (domain->must_swap_hash_tab, domain->hash_tab[i]);
+ for (i = 0; i < n_inmem_sysdep_strings; i++)
+ {
+ const char *msgid = inmem_orig_sysdep_tab[i].pointer;
+ nls_uint32 hash_val = __hash_string (msgid);
+ nls_uint32 idx = hash_val % domain->hash_size;
+ nls_uint32 incr =
+ 1 + (hash_val % (domain->hash_size - 2));
+
+ for (;;)
+ {
+ if (inmem_hash_tab[idx] == 0)
+ {
+ /* Hash table entry is empty. Use it. */
+ inmem_hash_tab[idx] = 1 + domain->nstrings + i;
+ break;
+ }
+
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+ }
+ }
+
+ domain->n_sysdep_strings = n_inmem_sysdep_strings;
+ domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
+ domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
+
+ domain->hash_tab = inmem_hash_tab;
+ domain->must_swap_hash_tab = 0;
+ }
+ else
+ {
+ domain->n_sysdep_strings = 0;
+ domain->orig_sysdep_tab = NULL;
+ domain->trans_sysdep_tab = NULL;
+ }
+
+ freea (sysdep_segment_values);
+ }
+ else
+ {
+ domain->n_sysdep_strings = 0;
+ domain->orig_sysdep_tab = NULL;
+ domain->trans_sysdep_tab = NULL;
+ }
+ }
+ break;
+ }
+ break;
+ default:
+ /* This is an invalid revision. */
+ invalid:
+ /* This is an invalid .mo file or we ran out of resources. */
+ free (domain->malloced);
+#ifdef HAVE_MMAP
+ if (use_mmap)
+ munmap ((caddr_t) data, size);
+ else
+#endif
+ free (data);
+ free (domain);
+ domain_file->data = NULL;
+ goto out;
+ }
+
+ /* No caches of converted translations so far. */
+ domain->conversions = NULL;
+ domain->nconversions = 0;
+#ifdef _LIBC
+ __libc_rwlock_init (domain->conversions_lock);
+#else
+ gl_rwlock_init (domain->conversions_lock);
+#endif
+
+ /* Get the header entry and look for a plural specification. */
+#ifdef IN_LIBGLOCALE
+ nullentry =
+ _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
+#else
+ nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+#endif
+ if (__builtin_expect (nullentry == (char *) -1, 0))
+ {
+#ifdef _LIBC
+ __libc_rwlock_fini (domain->conversions_lock);
+#endif
+ goto invalid;
+ }
+ EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+
+ out:
+ if (fd != -1)
+ close (fd);
+
+ domain_file->decided = 1;
+
+ done:
+ __libc_lock_unlock_recursive (lock);
+}
+
+
+#ifdef _LIBC
+void
+internal_function __libc_freeres_fn_section
+_nl_unload_domain (struct loaded_domain *domain)
+{
+ size_t i;
+
+ if (domain->plural != &__gettext_germanic_plural)
+ __gettext_free_exp ((struct expression *) domain->plural);
+
+ for (i = 0; i < domain->nconversions; i++)
+ {
+ struct converted_domain *convd = &domain->conversions[i];
+
+ free ((char *) convd->encoding);
+ if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
+ free (convd->conv_tab);
+ if (convd->conv != (__gconv_t) -1)
+ __gconv_close (convd->conv);
+ }
+ free (domain->conversions);
+ __libc_rwlock_fini (domain->conversions_lock);
+
+ free (domain->malloced);
+
+# ifdef _POSIX_MAPPED_FILES
+ if (domain->use_mmap)
+ munmap ((caddr_t) domain->data, domain->mmap_size);
+ else
+# endif /* _POSIX_MAPPED_FILES */
+ free ((void *) domain->data);
+
+ free (domain);
+}
+#endif
diff --git a/REORG.TODO/intl/locale.alias b/REORG.TODO/intl/locale.alias
new file mode 100644
index 0000000000..ab3d1bb033
--- /dev/null
+++ b/REORG.TODO/intl/locale.alias
@@ -0,0 +1,82 @@
+# Locale name alias data base.
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+# The format of this file is the same as for the corresponding file of
+# the X Window System, which normally can be found in
+# /usr/lib/X11/locale/locale.alias
+# A single line contains two fields: an alias and a substitution value.
+# All entries are case independent.
+
+# Note: This file is obsolete and is kept around for the time being for
+# backward compatibility. Nobody should rely on the names defined here.
+# Locales should always be specified by their full name.
+
+# Note: This file used to contain the following lines:
+# bokmaal nb_NO.ISO-8859-1
+# franc,ais fr_FR.ISO-8859-1
+# except that the "aa" was actually the byte '\0xE5' (the Latin-1
+# encoding for U+00E5 LATIN SMALL LETTER A WITH RING ABOVE) and the
+# "c," was actually the byte '\xE7' (the Latin-1 encoding for U+00E7
+# LATIN SMALL LETTER C WITH CEDILLA). These lines were removed
+# because they caused 'locale -a' to output text encoded in Latin-1,
+# which broke applications in UTF-8 locales. See:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=18412
+
+bokmal nb_NO.ISO-8859-1
+catalan ca_ES.ISO-8859-1
+croatian hr_HR.ISO-8859-2
+czech cs_CZ.ISO-8859-2
+danish da_DK.ISO-8859-1
+dansk da_DK.ISO-8859-1
+deutsch de_DE.ISO-8859-1
+dutch nl_NL.ISO-8859-1
+eesti et_EE.ISO-8859-1
+estonian et_EE.ISO-8859-1
+finnish fi_FI.ISO-8859-1
+french fr_FR.ISO-8859-1
+galego gl_ES.ISO-8859-1
+galician gl_ES.ISO-8859-1
+german de_DE.ISO-8859-1
+greek el_GR.ISO-8859-7
+hebrew he_IL.ISO-8859-8
+hrvatski hr_HR.ISO-8859-2
+hungarian hu_HU.ISO-8859-2
+icelandic is_IS.ISO-8859-1
+italian it_IT.ISO-8859-1
+japanese ja_JP.eucJP
+japanese.euc ja_JP.eucJP
+ja_JP ja_JP.eucJP
+ja_JP.ujis ja_JP.eucJP
+japanese.sjis ja_JP.SJIS
+korean ko_KR.eucKR
+korean.euc ko_KR.eucKR
+ko_KR ko_KR.eucKR
+lithuanian lt_LT.ISO-8859-13
+no_NO nb_NO.ISO-8859-1
+no_NO.ISO-8859-1 nb_NO.ISO-8859-1
+norwegian nb_NO.ISO-8859-1
+nynorsk nn_NO.ISO-8859-1
+polish pl_PL.ISO-8859-2
+portuguese pt_PT.ISO-8859-1
+romanian ro_RO.ISO-8859-2
+russian ru_RU.ISO-8859-5
+slovak sk_SK.ISO-8859-2
+slovene sl_SI.ISO-8859-2
+slovenian sl_SI.ISO-8859-2
+spanish es_ES.ISO-8859-1
+swedish sv_SE.ISO-8859-1
+thai th_TH.TIS-620
+turkish tr_TR.ISO-8859-9
diff --git a/REORG.TODO/intl/localealias.c b/REORG.TODO/intl/localealias.c
new file mode 100644
index 0000000000..9921aa2825
--- /dev/null
+++ b/REORG.TODO/intl/localealias.c
@@ -0,0 +1,437 @@
+/* Handle aliases for locale names.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#if defined _LIBC || defined HAVE___FSETLOCKING
+# include <stdio_ext.h>
+#endif
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# undef alloca
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+
+#ifdef ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions. This is required by the standard
+ because some ANSI C functions will require linking with this object
+ file and the name space must not be polluted. */
+# define strcasecmp(s1, s2) __strcasecmp_l (s1, s2, _nl_C_locobj_ptr)
+
+# ifndef mempcpy
+# define mempcpy __mempcpy
+# endif
+# define HAVE_MEMPCPY 1
+# define HAVE___FSETLOCKING 1
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+#else
+# include "lock.h"
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Some optimizations for glibc. */
+#ifdef _LIBC
+# define FEOF(fp) feof_unlocked (fp)
+# define FGETS(buf, n, fp) __fgets_unlocked (buf, n, fp)
+#else
+# define FEOF(fp) feof (fp)
+# define FGETS(buf, n, fp) fgets (buf, n, fp)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+#if defined _LIBC_REENTRANT || defined HAVE_DECL_FGETS_UNLOCKED
+# undef fgets
+# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
+#endif
+#if defined _LIBC_REENTRANT || defined HAVE_DECL_FEOF_UNLOCKED
+# undef feof
+# define feof(s) feof_unlocked (s)
+#endif
+
+
+__libc_lock_define_initialized (static, lock)
+
+
+struct alias_map
+{
+ const char *alias;
+ const char *value;
+};
+
+
+#ifndef _LIBC
+# define libc_freeres_ptr(decl) decl
+#endif
+
+libc_freeres_ptr (static char *string_space);
+static size_t string_space_act;
+static size_t string_space_max;
+libc_freeres_ptr (static struct alias_map *map);
+static size_t nmap;
+static size_t maxmap;
+
+
+/* Prototypes for local functions. */
+static size_t read_alias_file (const char *fname, int fname_len)
+ internal_function;
+static int extend_alias_table (void);
+static int alias_compare (const struct alias_map *map1,
+ const struct alias_map *map2);
+
+
+const char *
+_nl_expand_alias (const char *name)
+{
+ static const char *locale_alias_path;
+ struct alias_map *retval;
+ const char *result = NULL;
+ size_t added;
+
+ __libc_lock_lock (lock);
+
+ if (locale_alias_path == NULL)
+ locale_alias_path = LOCALE_ALIAS_PATH;
+
+ do
+ {
+ struct alias_map item;
+
+ item.alias = name;
+
+ if (nmap > 0)
+ retval = (struct alias_map *) bsearch (&item, map, nmap,
+ sizeof (struct alias_map),
+ (int (*) (const void *,
+ const void *)
+ ) alias_compare);
+ else
+ retval = NULL;
+
+ /* We really found an alias. Return the value. */
+ if (retval != NULL)
+ {
+ result = retval->value;
+ break;
+ }
+
+ /* Perhaps we can find another alias file. */
+ added = 0;
+ while (added == 0 && locale_alias_path[0] != '\0')
+ {
+ const char *start;
+
+ while (locale_alias_path[0] == PATH_SEPARATOR)
+ ++locale_alias_path;
+ start = locale_alias_path;
+
+ while (locale_alias_path[0] != '\0'
+ && locale_alias_path[0] != PATH_SEPARATOR)
+ ++locale_alias_path;
+
+ if (start < locale_alias_path)
+ added = read_alias_file (start, locale_alias_path - start);
+ }
+ }
+ while (added != 0);
+
+ __libc_lock_unlock (lock);
+
+ return result;
+}
+
+
+static size_t
+internal_function
+read_alias_file (const char *fname, int fname_len)
+{
+ FILE *fp;
+ char *full_fname;
+ size_t added;
+ static const char aliasfile[] = "/locale.alias";
+
+ full_fname = (char *) alloca (fname_len + sizeof aliasfile);
+#ifdef HAVE_MEMPCPY
+ mempcpy (mempcpy (full_fname, fname, fname_len),
+ aliasfile, sizeof aliasfile);
+#else
+ memcpy (full_fname, fname, fname_len);
+ memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
+#endif
+
+#ifdef _LIBC
+ /* Note the file is opened with cancellation in the I/O functions
+ disabled. */
+ fp = fopen (relocate (full_fname), "rce");
+#else
+ fp = fopen (relocate (full_fname), "r");
+#endif
+ freea (full_fname);
+ if (fp == NULL)
+ return 0;
+
+#ifdef HAVE___FSETLOCKING
+ /* No threads present. */
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
+#endif
+
+ added = 0;
+ while (!FEOF (fp))
+ {
+ /* It is a reasonable approach to use a fix buffer here because
+ a) we are only interested in the first two fields
+ b) these fields must be usable as file names and so must not
+ be that long
+ We avoid a multi-kilobyte buffer here since this would use up
+ stack space which we might not have if the program ran out of
+ memory. */
+ char buf[400];
+ char *alias;
+ char *value;
+ char *cp;
+ int complete_line;
+
+ if (FGETS (buf, sizeof buf, fp) == NULL)
+ /* EOF reached. */
+ break;
+
+ /* Determine whether the line is complete. */
+ complete_line = strchr (buf, '\n') != NULL;
+
+ cp = buf;
+ /* Ignore leading white space. */
+ while (isspace ((unsigned char) cp[0]))
+ ++cp;
+
+ /* A leading '#' signals a comment line. */
+ if (cp[0] != '\0' && cp[0] != '#')
+ {
+ alias = cp++;
+ while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+ ++cp;
+ /* Terminate alias name. */
+ if (cp[0] != '\0')
+ *cp++ = '\0';
+
+ /* Now look for the beginning of the value. */
+ while (isspace ((unsigned char) cp[0]))
+ ++cp;
+
+ if (cp[0] != '\0')
+ {
+ value = cp++;
+ while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+ ++cp;
+ /* Terminate value. */
+ if (cp[0] == '\n')
+ {
+ /* This has to be done to make the following test
+ for the end of line possible. We are looking for
+ the terminating '\n' which do not overwrite here. */
+ *cp++ = '\0';
+ *cp = '\n';
+ }
+ else if (cp[0] != '\0')
+ *cp++ = '\0';
+
+#ifdef IN_LIBGLOCALE
+ /* glibc's locale.alias contains entries for ja_JP and ko_KR
+ that make it impossible to use a Japanese or Korean UTF-8
+ locale under the name "ja_JP" or "ko_KR". Ignore these
+ entries. */
+ if (strchr (alias, '_') == NULL)
+#endif
+ {
+ size_t alias_len;
+ size_t value_len;
+
+ if (nmap >= maxmap)
+ if (__builtin_expect (extend_alias_table (), 0))
+ goto out;
+
+ alias_len = strlen (alias) + 1;
+ value_len = strlen (value) + 1;
+
+ if (string_space_act + alias_len + value_len > string_space_max)
+ {
+ /* Increase size of memory pool. */
+ size_t new_size = (string_space_max
+ + (alias_len + value_len > 1024
+ ? alias_len + value_len : 1024));
+ char *new_pool = (char *) realloc (string_space, new_size);
+ if (new_pool == NULL)
+ goto out;
+
+ if (__builtin_expect (string_space != new_pool, 0))
+ {
+ size_t i;
+
+ for (i = 0; i < nmap; i++)
+ {
+ map[i].alias += new_pool - string_space;
+ map[i].value += new_pool - string_space;
+ }
+ }
+
+ string_space = new_pool;
+ string_space_max = new_size;
+ }
+
+ map[nmap].alias =
+ (const char *) memcpy (&string_space[string_space_act],
+ alias, alias_len);
+ string_space_act += alias_len;
+
+ map[nmap].value =
+ (const char *) memcpy (&string_space[string_space_act],
+ value, value_len);
+ string_space_act += value_len;
+
+ ++nmap;
+ ++added;
+ }
+ }
+ }
+
+ /* Possibly not the whole line fits into the buffer. Ignore
+ the rest of the line. */
+ if (! complete_line)
+ do
+ if (FGETS (buf, sizeof buf, fp) == NULL)
+ /* Make sure the inner loop will be left. The outer loop
+ will exit at the `feof' test. */
+ break;
+ while (strchr (buf, '\n') == NULL);
+ }
+
+ out:
+ /* Should we test for ferror()? I think we have to silently ignore
+ errors. --drepper */
+ fclose (fp);
+
+ if (added > 0)
+ qsort (map, nmap, sizeof (struct alias_map),
+ (int (*) (const void *, const void *)) alias_compare);
+
+ return added;
+}
+
+
+static int
+extend_alias_table (void)
+{
+ size_t new_size;
+ struct alias_map *new_map;
+
+ new_size = maxmap == 0 ? 100 : 2 * maxmap;
+ new_map = (struct alias_map *) realloc (map, (new_size
+ * sizeof (struct alias_map)));
+ if (new_map == NULL)
+ /* Simply don't extend: we don't have any more core. */
+ return -1;
+
+ map = new_map;
+ maxmap = new_size;
+ return 0;
+}
+
+
+static int
+alias_compare (const struct alias_map *map1, const struct alias_map *map2)
+{
+#if defined _LIBC || defined HAVE_STRCASECMP
+ return strcasecmp (map1->alias, map2->alias);
+#else
+ const unsigned char *p1 = (const unsigned char *) map1->alias;
+ const unsigned char *p2 = (const unsigned char *) map2->alias;
+ unsigned char c1, c2;
+
+ if (p1 == p2)
+ return 0;
+
+ do
+ {
+ /* I know this seems to be odd but the tolower() function in
+ some systems libc cannot handle nonalpha characters. */
+ c1 = isupper (*p1) ? tolower (*p1) : *p1;
+ c2 = isupper (*p2) ? tolower (*p2) : *p2;
+ if (c1 == '\0')
+ break;
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ return c1 - c2;
+#endif
+}
diff --git a/REORG.TODO/intl/ngettext.c b/REORG.TODO/intl/ngettext.c
new file mode 100644
index 0000000000..d7c81d9b3f
--- /dev/null
+++ b/REORG.TODO/intl/ngettext.c
@@ -0,0 +1,63 @@
+/* Implementation of ngettext(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h> /* Just for NULL. */
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+#include <locale.h>
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define NGETTEXT __ngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define NGETTEXT libintl_ngettext
+# define DCNGETTEXT libintl_dcngettext
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+ LC_MESSAGES locale. If not found, returns MSGID itself (the default
+ text). */
+char *
+NGETTEXT (const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__ngettext, ngettext);
+#endif
diff --git a/REORG.TODO/intl/plural-exp.c b/REORG.TODO/intl/plural-exp.c
new file mode 100644
index 0000000000..f3a45fa92e
--- /dev/null
+++ b/REORG.TODO/intl/plural-exp.c
@@ -0,0 +1,154 @@
+/* Expression parsing for plural form selection.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "plural-exp.h"
+
+#if (defined __GNUC__ && !(defined __APPLE_CC_ && __APPLE_CC__ > 1) && \
+ !defined __cplusplus) \
+ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+
+/* These structs are the constant expression for the germanic plural
+ form determination. It represents the expression "n != 1". */
+static const struct expression plvar =
+{
+ .nargs = 0,
+ .operation = var,
+};
+static const struct expression plone =
+{
+ .nargs = 0,
+ .operation = num,
+ .val =
+ {
+ .num = 1
+ }
+};
+const struct expression GERMANIC_PLURAL =
+{
+ .nargs = 2,
+ .operation = not_equal,
+ .val =
+ {
+ .args =
+ {
+ [0] = (struct expression *) &plvar,
+ [1] = (struct expression *) &plone
+ }
+ }
+};
+
+# define INIT_GERMANIC_PLURAL()
+
+#else
+
+/* For compilers without support for ISO C 99 struct/union initializers:
+ Initialization at run-time. */
+
+static struct expression plvar;
+static struct expression plone;
+struct expression GERMANIC_PLURAL;
+
+static void
+init_germanic_plural (void)
+{
+ if (plone.val.num == 0)
+ {
+ plvar.nargs = 0;
+ plvar.operation = var;
+
+ plone.nargs = 0;
+ plone.operation = num;
+ plone.val.num = 1;
+
+ GERMANIC_PLURAL.nargs = 2;
+ GERMANIC_PLURAL.operation = not_equal;
+ GERMANIC_PLURAL.val.args[0] = &plvar;
+ GERMANIC_PLURAL.val.args[1] = &plone;
+ }
+}
+
+# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
+
+#endif
+
+void
+internal_function
+EXTRACT_PLURAL_EXPRESSION (const char *nullentry,
+ const struct expression **pluralp,
+ unsigned long int *npluralsp)
+{
+ if (nullentry != NULL)
+ {
+ const char *plural;
+ const char *nplurals;
+
+ plural = strstr (nullentry, "plural=");
+ nplurals = strstr (nullentry, "nplurals=");
+ if (plural == NULL || nplurals == NULL)
+ goto no_plural;
+ else
+ {
+ char *endp;
+ unsigned long int n;
+ struct parse_args args;
+
+ /* First get the number. */
+ nplurals += 9;
+ while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
+ ++nplurals;
+ if (!(*nplurals >= '0' && *nplurals <= '9'))
+ goto no_plural;
+#if defined HAVE_STRTOUL || defined _LIBC
+ n = strtoul (nplurals, &endp, 10);
+#else
+ for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
+ n = n * 10 + (*endp - '0');
+#endif
+ if (nplurals == endp)
+ goto no_plural;
+ *npluralsp = n;
+
+ /* Due to the restrictions bison imposes onto the interface of the
+ scanner function we have to put the input string and the result
+ passed up from the parser into the same structure which address
+ is passed down to the parser. */
+ plural += 7;
+ args.cp = plural;
+ if (PLURAL_PARSE (&args) != 0)
+ goto no_plural;
+ *pluralp = args.res;
+ }
+ }
+ else
+ {
+ /* By default we are using the Germanic form: singular form only
+ for `one', the plural form otherwise. Yes, this is also what
+ English is using since English is a Germanic language. */
+ no_plural:
+ INIT_GERMANIC_PLURAL ();
+ *pluralp = &GERMANIC_PLURAL;
+ *npluralsp = 2;
+ }
+}
diff --git a/REORG.TODO/intl/plural-exp.h b/REORG.TODO/intl/plural-exp.h
new file mode 100644
index 0000000000..144aa1ed4b
--- /dev/null
+++ b/REORG.TODO/intl/plural-exp.h
@@ -0,0 +1,127 @@
+/* Expression parsing and evaluation for plural form selection.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _PLURAL_EXP_H
+#define _PLURAL_EXP_H
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum expression_operator
+{
+ /* Without arguments: */
+ var, /* The variable "n". */
+ num, /* Decimal number. */
+ /* Unary operators: */
+ lnot, /* Logical NOT. */
+ /* Binary operators: */
+ mult, /* Multiplication. */
+ divide, /* Division. */
+ module, /* Modulo operation. */
+ plus, /* Addition. */
+ minus, /* Subtraction. */
+ less_than, /* Comparison. */
+ greater_than, /* Comparison. */
+ less_or_equal, /* Comparison. */
+ greater_or_equal, /* Comparison. */
+ equal, /* Comparison for equality. */
+ not_equal, /* Comparison for inequality. */
+ land, /* Logical AND. */
+ lor, /* Logical OR. */
+ /* Ternary operators: */
+ qmop /* Question mark operator. */
+};
+
+/* This is the representation of the expressions to determine the
+ plural form. */
+struct expression
+{
+ int nargs; /* Number of arguments. */
+ enum expression_operator operation;
+ union
+ {
+ unsigned long int num; /* Number value for `num'. */
+ struct expression *args[3]; /* Up to three arguments. */
+ } val;
+};
+
+/* This is the data structure to pass information to the parser and get
+ the result in a thread-safe way. */
+struct parse_args
+{
+ const char *cp;
+ struct expression *res;
+};
+
+
+/* Names for the libintl functions are a problem. This source code is used
+ 1. in the GNU C Library library,
+ 2. in the GNU libintl library,
+ 3. in the GNU gettext tools.
+ The function names in each situation must be different, to allow for
+ binary incompatible changes in 'struct expression'. Furthermore,
+ 1. in the GNU C Library library, the names have a __ prefix,
+ 2.+3. in the GNU libintl library and in the GNU gettext tools, the names
+ must follow ANSI C and not start with __.
+ So we have to distinguish the three cases. */
+#ifdef _LIBC
+# define FREE_EXPRESSION __gettext_free_exp
+# define PLURAL_PARSE __gettextparse
+# define GERMANIC_PLURAL __gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
+#elif defined (IN_LIBINTL)
+# define FREE_EXPRESSION libintl_gettext_free_exp
+# define PLURAL_PARSE libintl_gettextparse
+# define GERMANIC_PLURAL libintl_gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION libintl_gettext_extract_plural
+#else
+# define FREE_EXPRESSION free_plural_expression
+# define PLURAL_PARSE parse_plural_expression
+# define GERMANIC_PLURAL germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression
+#endif
+
+extern void FREE_EXPRESSION (struct expression *exp)
+ internal_function;
+extern int PLURAL_PARSE (struct parse_args *arg);
+extern const struct expression GERMANIC_PLURAL attribute_hidden;
+extern void EXTRACT_PLURAL_EXPRESSION (const char *nullentry,
+ const struct expression **pluralp,
+ unsigned long int *npluralsp)
+ internal_function;
+
+#if !defined (_LIBC) && !defined (IN_LIBINTL) && !defined (IN_LIBGLOCALE)
+extern unsigned long int plural_eval (const struct expression *pexp,
+ unsigned long int n);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PLURAL_EXP_H */
diff --git a/REORG.TODO/intl/plural.c b/REORG.TODO/intl/plural.c
new file mode 100644
index 0000000000..c2aa7d7d02
--- /dev/null
+++ b/REORG.TODO/intl/plural.c
@@ -0,0 +1,2012 @@
+/* A Bison parser, made by GNU Bison 2.7. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.7"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 2
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names. */
+#define yyparse __gettextparse
+#define yylex __gettextlex
+#define yyerror __gettexterror
+#define yylval __gettextlval
+#define yychar __gettextchar
+#define yydebug __gettextdebug
+#define yynerrs __gettextnerrs
+
+/* Copy the first part of user declarations. */
+/* Line 371 of yacc.c */
+#line 1 "plural.y"
+
+/* Expression parsing for plural form selection.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* For bison < 2.0, the bison generated parser uses alloca. AIX 3 forces us
+ to put this declaration at the beginning of the file. The declaration in
+ bison's skeleton file comes too late. This must come before <config.h>
+ because <config.h> may include arbitrary system headers.
+ This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0. */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+ but we want it to be called PLURAL_PARSE. */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+
+/* Line 371 of yacc.c */
+#line 119 "plural.c"
+
+# ifndef YY_NULL
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULL nullptr
+# else
+# define YY_NULL 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int __gettextdebug;
+#endif
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ EQUOP2 = 258,
+ CMPOP2 = 259,
+ ADDOP2 = 260,
+ MULOP2 = 261,
+ NUMBER = 262
+ };
+#endif
+/* Tokens. */
+#define EQUOP2 258
+#define CMPOP2 259
+#define ADDOP2 260
+#define MULOP2 261
+#define NUMBER 262
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+/* Line 387 of yacc.c */
+#line 49 "plural.y"
+
+ unsigned long int num;
+ enum expression_operator op;
+ struct expression *exp;
+
+
+/* Line 387 of yacc.c */
+#line 180 "plural.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int __gettextparse (void *YYPARSE_PARAM);
+#else
+int __gettextparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int __gettextparse (struct parse_args *arg);
+#else
+int __gettextparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* Copy the second part of user declarations. */
+/* Line 390 of yacc.c */
+#line 55 "plural.y"
+
+/* Prototypes for local functions. */
+static int yylex (YYSTYPE *lval, struct parse_args *arg);
+static void yyerror (struct parse_args *arg, const char *str);
+
+/* Allocation of expressions. */
+
+static struct expression *
+new_exp (int nargs, enum expression_operator op,
+ struct expression * const *args)
+{
+ int i;
+ struct expression *newp;
+
+ /* If any of the argument could not be malloc'ed, just return NULL. */
+ for (i = nargs - 1; i >= 0; i--)
+ if (args[i] == NULL)
+ goto fail;
+
+ /* Allocate a new expression. */
+ newp = (struct expression *) malloc (sizeof (*newp));
+ if (newp != NULL)
+ {
+ newp->nargs = nargs;
+ newp->operation = op;
+ for (i = nargs - 1; i >= 0; i--)
+ newp->val.args[i] = args[i];
+ return newp;
+ }
+
+ fail:
+ for (i = nargs - 1; i >= 0; i--)
+ FREE_EXPRESSION (args[i]);
+
+ return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (enum expression_operator op)
+{
+ return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (enum expression_operator op, struct expression *right)
+{
+ struct expression *args[1];
+
+ args[0] = right;
+ return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (enum expression_operator op, struct expression *left,
+ struct expression *right)
+{
+ struct expression *args[2];
+
+ args[0] = left;
+ args[1] = right;
+ return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (enum expression_operator op, struct expression *bexp,
+ struct expression *tbranch, struct expression *fbranch)
+{
+ struct expression *args[3];
+
+ args[0] = bexp;
+ args[1] = tbranch;
+ args[2] = fbranch;
+ return new_exp (3, op, args);
+}
+
+
+/* Line 390 of yacc.c */
+#line 284 "plural.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(N) (N)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 9
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 54
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 16
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 3
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 13
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 27
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 262
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 10, 2, 2, 2, 2, 5, 2,
+ 14, 15, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 12, 2,
+ 2, 2, 2, 3, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 4, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 6, 7,
+ 8, 9, 11
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 11, 15, 19, 23, 27, 31,
+ 35, 38, 40, 42
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 17, 0, -1, 18, -1, 18, 3, 18, 12, 18,
+ -1, 18, 4, 18, -1, 18, 5, 18, -1, 18,
+ 6, 18, -1, 18, 7, 18, -1, 18, 8, 18,
+ -1, 18, 9, 18, -1, 10, 18, -1, 13, -1,
+ 11, -1, 14, 18, 15, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint8 yyrline[] =
+{
+ 0, 152, 152, 160, 164, 168, 172, 176, 180, 184,
+ 188, 192, 196, 201
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2",
+ "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'",
+ "$accept", "start", "exp", YY_NULL
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 63, 124, 38, 258, 259, 260, 261,
+ 33, 262, 58, 110, 40, 41
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 16, 17, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 5, 3, 3, 3, 3, 3, 3,
+ 2, 1, 1, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 12, 11, 0, 0, 2, 10, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 13, 0, 4,
+ 5, 6, 7, 8, 9, 0, 3
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 5, 6
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -10
+static const yytype_int8 yypact[] =
+{
+ -9, -9, -10, -10, -9, 8, 36, -10, 13, -10,
+ -9, -9, -9, -9, -9, -9, -9, -10, 26, 41,
+ 45, 18, -2, 14, -10, -9, 36
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -10, -10, -1
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 7, 1, 2, 8, 3, 4, 15, 16, 9, 18,
+ 19, 20, 21, 22, 23, 24, 10, 11, 12, 13,
+ 14, 15, 16, 16, 26, 14, 15, 16, 17, 10,
+ 11, 12, 13, 14, 15, 16, 0, 0, 25, 10,
+ 11, 12, 13, 14, 15, 16, 12, 13, 14, 15,
+ 16, 13, 14, 15, 16
+};
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-10)))
+
+#define yytable_value_is_error(Yytable_value) \
+ YYID (0)
+
+static const yytype_int8 yycheck[] =
+{
+ 1, 10, 11, 4, 13, 14, 8, 9, 0, 10,
+ 11, 12, 13, 14, 15, 16, 3, 4, 5, 6,
+ 7, 8, 9, 9, 25, 7, 8, 9, 15, 3,
+ 4, 5, 6, 7, 8, 9, -1, -1, 12, 3,
+ 4, 5, 6, 7, 8, 9, 5, 6, 7, 8,
+ 9, 6, 7, 8, 9
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 10, 11, 13, 14, 17, 18, 18, 18, 0,
+ 3, 4, 5, 6, 7, 8, 9, 15, 18, 18,
+ 18, 18, 18, 18, 18, 12, 18
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (arg, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, arg)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, arg); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parse_args *arg)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, arg)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ struct parse_args *arg;
+#endif
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ if (!yyvaluep)
+ return;
+ YYUSE (arg);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parse_args *arg)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, arg)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ struct parse_args *arg;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, arg);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, struct parse_args *arg)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, arg)
+ YYSTYPE *yyvsp;
+ int yyrule;
+ struct parse_args *arg;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , arg);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule, arg); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULL;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - Assume YYFAIL is not used. It's too flawed to consider. See
+ <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+ for details. YYERROR is fine as it does not invoke this
+ function.
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct parse_args *arg)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, arg)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ struct parse_args *arg;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (arg);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (struct parse_args *arg)
+#else
+int
+yyparse (arg)
+ struct parse_args *arg;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+static YYSTYPE yyval_default;
+# define YY_INITIAL_VALUE(Value) = Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+/* Line 1792 of yacc.c */
+#line 153 "plural.y"
+ {
+ if ((yyvsp[(1) - (1)].exp) == NULL)
+ YYABORT;
+ arg->res = (yyvsp[(1) - (1)].exp);
+ }
+ break;
+
+ case 3:
+/* Line 1792 of yacc.c */
+#line 161 "plural.y"
+ {
+ (yyval.exp) = new_exp_3 (qmop, (yyvsp[(1) - (5)].exp), (yyvsp[(3) - (5)].exp), (yyvsp[(5) - (5)].exp));
+ }
+ break;
+
+ case 4:
+/* Line 1792 of yacc.c */
+#line 165 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 (lor, (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 5:
+/* Line 1792 of yacc.c */
+#line 169 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 (land, (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 6:
+/* Line 1792 of yacc.c */
+#line 173 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 7:
+/* Line 1792 of yacc.c */
+#line 177 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 8:
+/* Line 1792 of yacc.c */
+#line 181 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 9:
+/* Line 1792 of yacc.c */
+#line 185 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 10:
+/* Line 1792 of yacc.c */
+#line 189 "plural.y"
+ {
+ (yyval.exp) = new_exp_1 (lnot, (yyvsp[(2) - (2)].exp));
+ }
+ break;
+
+ case 11:
+/* Line 1792 of yacc.c */
+#line 193 "plural.y"
+ {
+ (yyval.exp) = new_exp_0 (var);
+ }
+ break;
+
+ case 12:
+/* Line 1792 of yacc.c */
+#line 197 "plural.y"
+ {
+ if (((yyval.exp) = new_exp_0 (num)) != NULL)
+ (yyval.exp)->val.num = (yyvsp[(1) - (1)].num);
+ }
+ break;
+
+ case 13:
+/* Line 1792 of yacc.c */
+#line 202 "plural.y"
+ {
+ (yyval.exp) = (yyvsp[(2) - (3)].exp);
+ }
+ break;
+
+
+/* Line 1792 of yacc.c */
+#line 1604 "plural.c"
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (arg, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (arg, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, arg);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, arg);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (arg, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, arg);
+ }
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, arg);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+/* Line 2055 of yacc.c */
+#line 207 "plural.y"
+
+
+void
+internal_function
+FREE_EXPRESSION (struct expression *exp)
+{
+ if (exp == NULL)
+ return;
+
+ /* Handle the recursive case. */
+ switch (exp->nargs)
+ {
+ case 3:
+ FREE_EXPRESSION (exp->val.args[2]);
+ /* FALLTHROUGH */
+ case 2:
+ FREE_EXPRESSION (exp->val.args[1]);
+ /* FALLTHROUGH */
+ case 1:
+ FREE_EXPRESSION (exp->val.args[0]);
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+
+ free (exp);
+}
+
+
+static int
+yylex (YYSTYPE *lval, struct parse_args *arg)
+{
+ const char *exp = arg->cp;
+ int result;
+
+ while (1)
+ {
+ if (exp[0] == '\0')
+ {
+ arg->cp = exp;
+ return YYEOF;
+ }
+
+ if (exp[0] != ' ' && exp[0] != '\t')
+ break;
+
+ ++exp;
+ }
+
+ result = *exp++;
+ switch (result)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ unsigned long int n = result - '0';
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ n *= 10;
+ n += exp[0] - '0';
+ ++exp;
+ }
+ lval->num = n;
+ result = NUMBER;
+ }
+ break;
+
+ case '=':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = equal;
+ result = EQUOP2;
+ }
+ else
+ result = YYERRCODE;
+ break;
+
+ case '!':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = not_equal;
+ result = EQUOP2;
+ }
+ break;
+
+ case '&':
+ case '|':
+ if (exp[0] == result)
+ ++exp;
+ else
+ result = YYERRCODE;
+ break;
+
+ case '<':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = less_or_equal;
+ }
+ else
+ lval->op = less_than;
+ result = CMPOP2;
+ break;
+
+ case '>':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = greater_or_equal;
+ }
+ else
+ lval->op = greater_than;
+ result = CMPOP2;
+ break;
+
+ case '*':
+ lval->op = mult;
+ result = MULOP2;
+ break;
+
+ case '/':
+ lval->op = divide;
+ result = MULOP2;
+ break;
+
+ case '%':
+ lval->op = module;
+ result = MULOP2;
+ break;
+
+ case '+':
+ lval->op = plus;
+ result = ADDOP2;
+ break;
+
+ case '-':
+ lval->op = minus;
+ result = ADDOP2;
+ break;
+
+ case 'n':
+ case '?':
+ case ':':
+ case '(':
+ case ')':
+ /* Nothing, just return the character. */
+ break;
+
+ case ';':
+ case '\n':
+ case '\0':
+ /* Be safe and let the user call this function again. */
+ --exp;
+ result = YYEOF;
+ break;
+
+ default:
+ result = YYERRCODE;
+#if YYDEBUG != 0
+ --exp;
+#endif
+ break;
+ }
+
+ arg->cp = exp;
+
+ return result;
+}
+
+
+static void
+yyerror (struct parse_args *arg, const char *str)
+{
+ /* Do nothing. We don't print error messages here. */
+}
diff --git a/REORG.TODO/intl/plural.y b/REORG.TODO/intl/plural.y
new file mode 100644
index 0000000000..5f945659d5
--- /dev/null
+++ b/REORG.TODO/intl/plural.y
@@ -0,0 +1,383 @@
+%{
+/* Expression parsing for plural form selection.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* For bison < 2.0, the bison generated parser uses alloca. AIX 3 forces us
+ to put this declaration at the beginning of the file. The declaration in
+ bison's skeleton file comes too late. This must come before <config.h>
+ because <config.h> may include arbitrary system headers.
+ This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0. */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+ but we want it to be called PLURAL_PARSE. */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+%}
+%parse-param {struct parse_args *arg}
+%lex-param {struct parse_args *arg}
+%define api.pure full
+%expect 7
+
+%union {
+ unsigned long int num;
+ enum expression_operator op;
+ struct expression *exp;
+}
+
+%{
+/* Prototypes for local functions. */
+static int yylex (YYSTYPE *lval, struct parse_args *arg);
+static void yyerror (struct parse_args *arg, const char *str);
+
+/* Allocation of expressions. */
+
+static struct expression *
+new_exp (int nargs, enum expression_operator op,
+ struct expression * const *args)
+{
+ int i;
+ struct expression *newp;
+
+ /* If any of the argument could not be malloc'ed, just return NULL. */
+ for (i = nargs - 1; i >= 0; i--)
+ if (args[i] == NULL)
+ goto fail;
+
+ /* Allocate a new expression. */
+ newp = (struct expression *) malloc (sizeof (*newp));
+ if (newp != NULL)
+ {
+ newp->nargs = nargs;
+ newp->operation = op;
+ for (i = nargs - 1; i >= 0; i--)
+ newp->val.args[i] = args[i];
+ return newp;
+ }
+
+ fail:
+ for (i = nargs - 1; i >= 0; i--)
+ FREE_EXPRESSION (args[i]);
+
+ return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (enum expression_operator op)
+{
+ return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (enum expression_operator op, struct expression *right)
+{
+ struct expression *args[1];
+
+ args[0] = right;
+ return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (enum expression_operator op, struct expression *left,
+ struct expression *right)
+{
+ struct expression *args[2];
+
+ args[0] = left;
+ args[1] = right;
+ return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (enum expression_operator op, struct expression *bexp,
+ struct expression *tbranch, struct expression *fbranch)
+{
+ struct expression *args[3];
+
+ args[0] = bexp;
+ args[1] = tbranch;
+ args[2] = fbranch;
+ return new_exp (3, op, args);
+}
+
+%}
+
+/* This declares that all operators have the same associativity and the
+ precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
+ There is no unary minus and no bitwise operators.
+ Operators with the same syntactic behaviour have been merged into a single
+ token, to save space in the array generated by bison. */
+%right '?' /* ? */
+%left '|' /* || */
+%left '&' /* && */
+%left EQUOP2 /* == != */
+%left CMPOP2 /* < > <= >= */
+%left ADDOP2 /* + - */
+%left MULOP2 /* * / % */
+%right '!' /* ! */
+
+%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
+%token <num> NUMBER
+%type <exp> exp
+
+%%
+
+start: exp
+ {
+ if ($1 == NULL)
+ YYABORT;
+ arg->res = $1;
+ }
+ ;
+
+exp: exp '?' exp ':' exp
+ {
+ $$ = new_exp_3 (qmop, $1, $3, $5);
+ }
+ | exp '|' exp
+ {
+ $$ = new_exp_2 (lor, $1, $3);
+ }
+ | exp '&' exp
+ {
+ $$ = new_exp_2 (land, $1, $3);
+ }
+ | exp EQUOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | exp CMPOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | exp ADDOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | exp MULOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | '!' exp
+ {
+ $$ = new_exp_1 (lnot, $2);
+ }
+ | 'n'
+ {
+ $$ = new_exp_0 (var);
+ }
+ | NUMBER
+ {
+ if (($$ = new_exp_0 (num)) != NULL)
+ $$->val.num = $1;
+ }
+ | '(' exp ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+%%
+
+void
+internal_function
+FREE_EXPRESSION (struct expression *exp)
+{
+ if (exp == NULL)
+ return;
+
+ /* Handle the recursive case. */
+ switch (exp->nargs)
+ {
+ case 3:
+ FREE_EXPRESSION (exp->val.args[2]);
+ /* FALLTHROUGH */
+ case 2:
+ FREE_EXPRESSION (exp->val.args[1]);
+ /* FALLTHROUGH */
+ case 1:
+ FREE_EXPRESSION (exp->val.args[0]);
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+
+ free (exp);
+}
+
+
+static int
+yylex (YYSTYPE *lval, struct parse_args *arg)
+{
+ const char *exp = arg->cp;
+ int result;
+
+ while (1)
+ {
+ if (exp[0] == '\0')
+ {
+ arg->cp = exp;
+ return YYEOF;
+ }
+
+ if (exp[0] != ' ' && exp[0] != '\t')
+ break;
+
+ ++exp;
+ }
+
+ result = *exp++;
+ switch (result)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ unsigned long int n = result - '0';
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ n *= 10;
+ n += exp[0] - '0';
+ ++exp;
+ }
+ lval->num = n;
+ result = NUMBER;
+ }
+ break;
+
+ case '=':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = equal;
+ result = EQUOP2;
+ }
+ else
+ result = YYERRCODE;
+ break;
+
+ case '!':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = not_equal;
+ result = EQUOP2;
+ }
+ break;
+
+ case '&':
+ case '|':
+ if (exp[0] == result)
+ ++exp;
+ else
+ result = YYERRCODE;
+ break;
+
+ case '<':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = less_or_equal;
+ }
+ else
+ lval->op = less_than;
+ result = CMPOP2;
+ break;
+
+ case '>':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = greater_or_equal;
+ }
+ else
+ lval->op = greater_than;
+ result = CMPOP2;
+ break;
+
+ case '*':
+ lval->op = mult;
+ result = MULOP2;
+ break;
+
+ case '/':
+ lval->op = divide;
+ result = MULOP2;
+ break;
+
+ case '%':
+ lval->op = module;
+ result = MULOP2;
+ break;
+
+ case '+':
+ lval->op = plus;
+ result = ADDOP2;
+ break;
+
+ case '-':
+ lval->op = minus;
+ result = ADDOP2;
+ break;
+
+ case 'n':
+ case '?':
+ case ':':
+ case '(':
+ case ')':
+ /* Nothing, just return the character. */
+ break;
+
+ case ';':
+ case '\n':
+ case '\0':
+ /* Be safe and let the user call this function again. */
+ --exp;
+ result = YYEOF;
+ break;
+
+ default:
+ result = YYERRCODE;
+#if YYDEBUG != 0
+ --exp;
+#endif
+ break;
+ }
+
+ arg->cp = exp;
+
+ return result;
+}
+
+
+static void
+yyerror (struct parse_args *arg, const char *str)
+{
+ /* Do nothing. We don't print error messages here. */
+}
diff --git a/REORG.TODO/intl/po2test.awk b/REORG.TODO/intl/po2test.awk
new file mode 100644
index 0000000000..335acb183e
--- /dev/null
+++ b/REORG.TODO/intl/po2test.awk
@@ -0,0 +1,46 @@
+# po2test.awk - Convert Uniforum style .po file to C code for testing.
+# Copyright (C) 2012-2017 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+
+# Output current message (in msg) as argument of the INPUT or OUTPUT macro,
+# depending on msgtype
+function output_message() {
+ # Ignore messages containing <PRI.*> markers which would have to be
+ # replaced by the correct format depending on the word size
+ if (msg && msg !~ /<PRI.*>/)
+ printf ("%s(%s)\n", msgtype == "msgid" ? "INPUT" : "OUTPUT", msg)
+ msg = 0
+}
+
+$1 ~ /msg(id|str)/ {
+ # Output collected message
+ output_message()
+ # Collect next message
+ msgtype = $1
+ sub(/^msg(id|str)[ \t]*/, "", $0)
+ msg = $0
+ next
+}
+
+/^".*"/ {
+ # Append to current message
+ msg = msg "\n" $0
+}
+
+END {
+ # Output last collected message
+ output_message()
+}
diff --git a/REORG.TODO/intl/textdomain.c b/REORG.TODO/intl/textdomain.c
new file mode 100644
index 0000000000..acaf2b2d64
--- /dev/null
+++ b/REORG.TODO/intl/textdomain.c
@@ -0,0 +1,125 @@
+/* Implementation of the textdomain(3) function.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+
+ This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <libc-lock.h>
+# define gl_rwlock_define __libc_rwlock_define
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define TEXTDOMAIN __textdomain
+# ifndef strdup
+# define strdup(str) __strdup (str)
+# endif
+#else
+# define TEXTDOMAIN libintl_textdomain
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation. */
+gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
+
+/* Set the current default message catalog to DOMAINNAME.
+ If DOMAINNAME is null, return the current default.
+ If DOMAINNAME is "", reset to the default of "messages". */
+char *
+TEXTDOMAIN (const char *domainname)
+{
+ char *new_domain;
+ char *old_domain;
+
+ /* A NULL pointer requests the current setting. */
+ if (domainname == NULL)
+ return (char *) _nl_current_default_domain;
+
+ gl_rwlock_wrlock (_nl_state_lock);
+
+ old_domain = (char *) _nl_current_default_domain;
+
+ /* If domain name is the null string set to default domain "messages". */
+ if (domainname[0] == '\0'
+ || strcmp (domainname, _nl_default_default_domain) == 0)
+ {
+ _nl_current_default_domain = _nl_default_default_domain;
+ new_domain = (char *) _nl_current_default_domain;
+ }
+ else if (strcmp (domainname, old_domain) == 0)
+ /* This can happen and people will use it to signal that some
+ environment variable changed. */
+ new_domain = old_domain;
+ else
+ {
+ /* If the following malloc fails `_nl_current_default_domain'
+ will be NULL. This value will be returned and so signals we
+ are out of core. */
+#if defined _LIBC || defined HAVE_STRDUP
+ new_domain = strdup (domainname);
+#else
+ size_t len = strlen (domainname) + 1;
+ new_domain = (char *) malloc (len);
+ if (new_domain != NULL)
+ memcpy (new_domain, domainname, len);
+#endif
+
+ if (new_domain != NULL)
+ _nl_current_default_domain = new_domain;
+ }
+
+ /* We use this possibility to signal a change of the loaded catalogs
+ since this is most likely the case and there is no other easy we
+ to do it. Do it only when the call was successful. */
+ if (new_domain != NULL)
+ {
+ ++_nl_msg_cat_cntr;
+
+ if (old_domain != new_domain && old_domain != _nl_default_default_domain)
+ free (old_domain);
+ }
+
+ gl_rwlock_unlock (_nl_state_lock);
+
+ return new_domain;
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__textdomain, textdomain);
+#endif
diff --git a/REORG.TODO/intl/translit.po b/REORG.TODO/intl/translit.po
new file mode 100644
index 0000000000..5df5d0d064
--- /dev/null
+++ b/REORG.TODO/intl/translit.po
@@ -0,0 +1,9 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+
+msgid "test"
+msgstr "«© Æß»"
+
+msgid "onemore"
+msgstr "½*½=¼"
diff --git a/REORG.TODO/intl/tst-codeset.c b/REORG.TODO/intl/tst-codeset.c
new file mode 100644
index 0000000000..628b2ccc4b
--- /dev/null
+++ b/REORG.TODO/intl/tst-codeset.c
@@ -0,0 +1,60 @@
+/* Test of bind_textdomain_codeset.
+ Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+ char *s;
+ int result = 0;
+
+ unsetenv ("LANGUAGE");
+ unsetenv ("OUTPUT_CHARSET");
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+ textdomain ("codeset");
+ bindtextdomain ("codeset", OBJPFX "domaindir");
+
+ /* Here we expect output in ISO-8859-1. */
+ s = gettext ("cheese");
+ if (strcmp (s, "K\344se"))
+ {
+ printf ("call 1 returned: %s\n", s);
+ result = 1;
+ }
+
+ bind_textdomain_codeset ("codeset", "UTF-8");
+
+ /* Here we expect output in UTF-8. */
+ s = gettext ("cheese");
+ if (strcmp (s, "K\303\244se"))
+ {
+ printf ("call 2 returned: %s\n", s);
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/intl/tst-gettext.c b/REORG.TODO/intl/tst-gettext.c
new file mode 100644
index 0000000000..e8801ef0b3
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext.c
@@ -0,0 +1,368 @@
+/* Test of the gettext functions.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <error.h>
+#include <errno.h>
+
+
+const struct
+{
+ const char *msgid;
+ const char *msgstr;
+} msgs[] =
+{
+#define INPUT(Str) { Str,
+#define OUTPUT(Str) Str },
+#include TESTSTRS_H
+};
+
+const char *catname[] =
+{
+ [LC_MESSAGES] = "LC_MESSAGES",
+ [LC_TIME] = "LC_TIME",
+ [LC_NUMERIC] = "LC_NUMERIC"
+};
+
+
+static int positive_gettext_test (void);
+static int negative_gettext_test (void);
+static int positive_dgettext_test (const char *domain);
+static int positive_dcgettext_test (const char *domain, int category);
+static int negative_dcgettext_test (const char *domain, int category);
+
+
+#define check_setlocale(cat, name) do { \
+ if (setlocale (cat, name) == NULL) \
+ { \
+ printf ("%s:%u: setlocale (%s, \"%s\"): %m\n", \
+ __FILE__, __LINE__, #cat, name); \
+ result = 1; \
+ } \
+ } while (0)
+
+int
+main (int argc, char *argv[])
+{
+ int result = 0;
+
+ /* For debugging. */
+ mtrace ();
+
+ /* This is the place where the .mo files are placed. */
+ if (argc > 1)
+ {
+ bindtextdomain ("existing-domain", argv[1]);
+ bindtextdomain ("existing-time-domain", argv[1]);
+ bindtextdomain ("non-existing-domain", argv[1]);
+ }
+
+ /* The locale the catalog is created for is "existing-category". Now
+ set the various variables in question to this value and run the
+ test. */
+ setenv ("LANGUAGE", "existing-locale", 1);
+ setenv ("LC_ALL", "non-existing-locale", 1);
+ setenv ("LC_MESSAGES", "non-existing-locale", 1);
+ setenv ("LC_CTYPE", "non-existing-locale", 1);
+ setenv ("LANG", "non-existing-locale", 1);
+ check_setlocale (LC_CTYPE, "de_DE.UTF-8");
+ check_setlocale (LC_MESSAGES, "de_DE.UTF-8");
+ unsetenv ("OUTPUT_CHARSET");
+ /* This is the name of the existing domain with a catalog for the
+ LC_MESSAGES category. */
+ textdomain ("existing-domain");
+ puts ("test `gettext' with LANGUAGE set");
+ if (positive_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ /* This is the name of a non-existing domain with a catalog for the
+ LC_MESSAGES category. We leave this value set for the `dgettext'
+ and `dcgettext' tests. */
+ textdomain ("non-existing-domain");
+ puts ("test `gettext' with LANGUAGE set");
+ if (negative_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ puts ("test `dgettext' with LANGUAGE set");
+ if (positive_dgettext_test ("existing-domain") != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+
+ /* Now the same tests with LC_ALL deciding. */
+ unsetenv ("LANGUAGE");
+ setenv ("LC_ALL", "existing-locale", 1);
+ check_setlocale (LC_ALL, "");
+ puts ("test `gettext' with LC_ALL set");
+ /* This is the name of the existing domain with a catalog for the
+ LC_MESSAGES category. */
+ textdomain ("existing-domain");
+ if (positive_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ /* This is the name of a non-existing domain with a catalog for the
+ LC_MESSAGES category. We leave this value set for the `dgettext'
+ and `dcgettext' tests. */
+ textdomain ("non-existing-domain");
+ puts ("test `gettext' with LC_ALL deciding");
+ if (negative_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ puts ("test `dgettext' with LC_ALL deciding");
+ if (positive_dgettext_test ("existing-domain") != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+
+ /* Now the same tests with LC_MESSAGES deciding. */
+ unsetenv ("LC_ALL");
+ setenv ("LC_MESSAGES", "existing-locale", 1);
+ check_setlocale (LC_MESSAGES, "");
+ setenv ("LC_TIME", "existing-locale", 1);
+ check_setlocale (LC_TIME, "");
+ setenv ("LC_NUMERIC", "non-existing-locale", 1);
+ char *what = setlocale (LC_NUMERIC, "");
+ if (what != NULL)
+ {
+ printf ("setlocale succeeded (%s), expected failure\n", what);
+ result = 1;
+ }
+
+ puts ("test `gettext' with LC_MESSAGES set");
+ /* This is the name of the existing domain with a catalog for the
+ LC_MESSAGES category. */
+ textdomain ("existing-domain");
+ if (positive_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ /* This is the name of a non-existing domain with a catalog for the
+ LC_MESSAGES category. We leave this value set for the `dgettext'
+ and `dcgettext' tests. */
+ textdomain ("non-existing-domain");
+ puts ("test `gettext' with LC_MESSAGES deciding");
+ if (negative_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ puts ("test `dgettext' with LC_MESSAGES deciding");
+ if (positive_dgettext_test ("existing-domain") != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ puts ("test `dcgettext' with category == LC_MESSAGES");
+ if (positive_dcgettext_test ("existing-domain", LC_MESSAGES) != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ /* Try a different category. For this we also switch the domain. */
+ puts ("test `dcgettext' with LANGUAGE == LC_TIME");
+ if (positive_dcgettext_test ("existing-time-domain", LC_TIME) != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ /* This time use a category for which there is no catalog. */
+ puts ("test `dcgettext' with LANGUAGE == LC_NUMERIC");
+ if (negative_dcgettext_test ("existing-domain", LC_NUMERIC) != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+
+ /* Now the same tests with LANG deciding. */
+ unsetenv ("LC_MESSAGES");
+ unsetenv ("LC_CTYPE");
+ unsetenv ("LC_TIME");
+ unsetenv ("LC_NUMERIC");
+ setenv ("LANG", "existing-locale", 1);
+ check_setlocale (LC_ALL, "");
+ /* This is the name of the existing domain with a catalog for the
+ LC_MESSAGES category. */
+ textdomain ("existing-domain");
+ puts ("test `gettext' with LANG set");
+ if (positive_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ /* This is the name of a non-existing domain with a catalog for the
+ LC_MESSAGES category. We leave this value set for the `dgettext'
+ and `dcgettext' tests. */
+ textdomain ("non-existing-domain");
+ puts ("test `gettext' with LANG set");
+ if (negative_gettext_test () != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+ puts ("test `dgettext' with LANG set");
+ if (positive_dgettext_test ("existing-domain") != 0)
+ {
+ puts ("FAILED");
+ result = 1;
+ }
+
+ check_setlocale (LC_ALL, "C");
+
+ return result;
+}
+
+
+static int
+positive_gettext_test (void)
+{
+ size_t cnt;
+ int result = 0;
+
+ for (cnt = 0; cnt < sizeof (msgs) / sizeof (msgs[0]); ++cnt)
+ {
+ const char *found = gettext (msgs[cnt].msgid);
+
+ if (found == NULL
+ || (msgs[cnt].msgstr[0] != '\0'
+ && strcmp (found, msgs[cnt].msgstr) != 0))
+ {
+ /* Oops, shouldn't happen. */
+ printf ("\
+ gettext (\"%s\") failed, returned \"%s\", expected \"%s\"\n",
+ msgs[cnt].msgid, found, msgs[cnt].msgstr);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+static int
+negative_gettext_test (void)
+{
+ size_t cnt;
+ int result = 0;
+
+ for (cnt = 0; cnt < sizeof (msgs) / sizeof (msgs[0]); ++cnt)
+ {
+ const char *found = gettext (msgs[cnt].msgid);
+
+ if (found != msgs[cnt].msgid)
+ {
+ /* Oops, shouldn't happen. */
+ printf (" gettext (\"%s\") failed\n", msgs[cnt].msgid);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+static int
+positive_dgettext_test (const char *domain)
+{
+ size_t cnt;
+ int result = 0;
+
+ for (cnt = 0; cnt < sizeof (msgs) / sizeof (msgs[0]); ++cnt)
+ {
+ const char *found = dgettext (domain, msgs[cnt].msgid);
+
+ if (found == NULL
+ || (msgs[cnt].msgstr[0] != '\0'
+ && strcmp (found, msgs[cnt].msgstr) != 0))
+ {
+ /* Oops, shouldn't happen. */
+ printf ("\
+ dgettext (\"%s\", \"%s\") failed, returned \"%s\", expected \"%s\"\n",
+ domain, msgs[cnt].msgid, found, msgs[cnt].msgstr);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+static int
+positive_dcgettext_test (const char *domain, int category)
+{
+ size_t cnt;
+ int result = 0;
+
+ for (cnt = 0; cnt < sizeof (msgs) / sizeof (msgs[0]); ++cnt)
+ {
+ const char *found = dcgettext (domain, msgs[cnt].msgid, category);
+
+ if (found == NULL
+ || (msgs[cnt].msgstr[0] != '\0'
+ && strcmp (found, msgs[cnt].msgstr) != 0))
+ {
+ /* Oops, shouldn't happen. */
+ printf ("\
+ dcgettext (\"%s\", \"%s\", %s) failed, returned \"%s\", expected \"%s\"\n",
+ domain, msgs[cnt].msgid, catname[category], found,
+ msgs[cnt].msgstr);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+static int
+negative_dcgettext_test (const char *domain, int category)
+{
+ size_t cnt;
+ int result = 0;
+
+ for (cnt = 0; cnt < sizeof (msgs) / sizeof (msgs[0]); ++cnt)
+ {
+ const char *found = dcgettext (domain, msgs[cnt].msgid, category);
+
+ if (found != msgs[cnt].msgid)
+ {
+ /* Oops, shouldn't happen. */
+ printf (" dcgettext (\"%s\", \"%s\", %s) failed\n",
+ domain, msgs[cnt].msgid, catname[category]);
+ result = 1;
+ }
+ }
+
+ return result;
+}
diff --git a/REORG.TODO/intl/tst-gettext.sh b/REORG.TODO/intl/tst-gettext.sh
new file mode 100755
index 0000000000..5c4775b817
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# Test of gettext functions.
+# Copyright (C) 2000-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1
+test_program_prefix_before_env=$2
+run_program_env=$3
+test_program_prefix_after_env=$4
+objpfx=$5
+malloc_trace=$6
+
+# Generate the test data.
+
+# Create the locale directories.
+mkdir -p ${objpfx}localedir/existing-locale/LC_MESSAGES
+for f in ADDRESS COLLATE CTYPE IDENTIFICATION MEASUREMENT MONETARY NAME NUMERIC PAPER TELEPHONE TIME; do
+ cp -f ${common_objpfx}localedata/de_DE.UTF-8/LC_$f \
+ ${objpfx}localedir/existing-locale
+done
+cp -f ${common_objpfx}localedata/de_DE.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES \
+ ${objpfx}localedir/existing-locale/LC_MESSAGES
+
+# Create the domain directories.
+mkdir -p ${objpfx}domaindir/existing-locale/LC_MESSAGES
+mkdir -p ${objpfx}domaindir/existing-locale/LC_TIME
+# Populate them.
+msgfmt -o ${objpfx}domaindir/existing-locale/LC_MESSAGES/existing-domain.mo \
+ -f ../po/de.po
+msgfmt -o ${objpfx}domaindir/existing-locale/LC_TIME/existing-time-domain.mo \
+ -f ../po/de.po
+
+# Now run the test.
+${test_program_prefix_before_env} \
+${run_program_env} \
+MALLOC_TRACE=$malloc_trace \
+LOCPATH=${objpfx}localedir:${common_objpfx}localedata \
+${test_program_prefix_after_env} \
+${objpfx}tst-gettext > ${objpfx}tst-gettext.out ${objpfx}domaindir
+
+exit $?
diff --git a/REORG.TODO/intl/tst-gettext2.c b/REORG.TODO/intl/tst-gettext2.c
new file mode 100644
index 0000000000..894e09e41e
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext2.c
@@ -0,0 +1,77 @@
+/* Test of the gettext functions.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Thorsten Kukuk <kukuk@suse.de> and
+ Andreas Jaeger <aj@suse.de>, 2000.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#include <locale.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define N_(msgid) msgid
+
+struct data_t
+{
+ const char *selection;
+ const char *description;
+};
+
+int data_cnt = 2;
+struct data_t strings[] =
+{
+ { "String1", N_("First string for testing.") },
+ { "String2", N_("Another string for testing.") }
+};
+
+const int lang_cnt = 3;
+const char *lang[] = {"lang1", "lang2", "lang3"};
+
+static int
+do_test (void)
+{
+ int i;
+
+ /* Clean up environment. */
+ unsetenv ("LANGUAGE");
+ unsetenv ("LC_ALL");
+ unsetenv ("LC_MESSAGES");
+ unsetenv ("LC_CTYPE");
+ unsetenv ("LANG");
+ unsetenv ("OUTPUT_CHARSET");
+
+ textdomain ("tstlang");
+
+ for (i = 0; i < lang_cnt; ++i)
+ {
+ int j;
+
+ if (setlocale (LC_ALL, lang[i]) == NULL)
+ setlocale (LC_ALL, "C");
+ bindtextdomain ("tstlang", OBJPFX "domaindir");
+
+ for (j = 0; j < data_cnt; ++j)
+ printf ("%s - %s\n", strings[j].selection,
+ gettext (strings[j].description));
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/intl/tst-gettext2.sh b/REORG.TODO/intl/tst-gettext2.sh
new file mode 100644
index 0000000000..ad4f86d76b
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext2.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Test of gettext functions.
+# Copyright (C) 2000-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1
+test_program_prefix_before_env=$2
+run_program_env=$3
+test_program_prefix_after_env=$4
+objpfx=$5
+
+# Generate the test data.
+mkdir -p ${objpfx}domaindir
+# Create the locale directories.
+mkdir -p \
+ ${objpfx}domaindir/lang1/LC_MESSAGES \
+ ${objpfx}domaindir/lang2/LC_MESSAGES
+
+for f in ADDRESS COLLATE CTYPE IDENTIFICATION MEASUREMENT MONETARY NAME NUMERIC PAPER TELEPHONE TIME; do
+ [ -e ${objpfx}domaindir/lang1/LC_$f ] ||
+ cp ${common_objpfx}localedata/de_DE.ISO-8859-1/LC_$f \
+ ${objpfx}domaindir/lang1
+ [ -e ${objpfx}domaindir/lang2/LC_$f ] ||
+ cp ${common_objpfx}localedata/de_DE.ISO-8859-1/LC_$f \
+ ${objpfx}domaindir/lang2
+done
+test -e ${objpfx}domaindir/lang1/LC_MESSAGES/SYS_LC_MESSAGES || {
+ cp ${common_objpfx}localedata/de_DE.ISO-8859-1/LC_MESSAGES/SYS_LC_MESSAGES \
+ ${objpfx}domaindir/lang1/LC_MESSAGES
+}
+test -e ${objpfx}domaindir/lang2/LC_MESSAGES/SYS_LC_MESSAGES || {
+ cp ${common_objpfx}localedata/de_DE.ISO-8859-1/LC_MESSAGES/SYS_LC_MESSAGES \
+ ${objpfx}domaindir/lang2/LC_MESSAGES
+}
+
+# Populate them.
+msgfmt -o ${objpfx}domaindir/lang1/LC_MESSAGES/tstlang.mo \
+ tstlang1.po
+
+msgfmt -o ${objpfx}domaindir/lang2/LC_MESSAGES/tstlang.mo \
+ tstlang2.po
+
+# Now run the test.
+${test_program_prefix_before_env} \
+${run_program_env} \
+LOCPATH=${objpfx}domaindir \
+${test_program_prefix_after_env} \
+${objpfx}tst-gettext2 > ${objpfx}tst-gettext2.out ${objpfx}domaindir &&
+cmp ${objpfx}tst-gettext2.out - <<EOF
+String1 - Lang1: 1st string
+String2 - Lang1: 2nd string
+String1 - Lang2: 1st string
+String2 - Lang2: 2nd string
+String1 - First string for testing.
+String2 - Another string for testing.
+EOF
+
+exit $?
diff --git a/REORG.TODO/intl/tst-gettext3.c b/REORG.TODO/intl/tst-gettext3.c
new file mode 100644
index 0000000000..41f0863e79
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext3.c
@@ -0,0 +1,62 @@
+/* Test that the gettext() results come out in the correct encoding for
+ locales that differ only in their encoding.
+ Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <bruno@clisp.org>, 2001, 2005.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+ char *s;
+ int result = 0;
+
+ unsetenv ("LANGUAGE");
+ unsetenv ("OUTPUT_CHARSET");
+ textdomain ("codeset");
+ bindtextdomain ("codeset", OBJPFX "domaindir");
+
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+
+ /* Here we expect output in ISO-8859-1. */
+ s = gettext ("cheese");
+ if (strcmp (s, "K\344se"))
+ {
+ printf ("call 1 returned: %s\n", s);
+ result = 1;
+ }
+
+ setlocale (LC_ALL, "de_DE.UTF-8");
+
+ /* Here we expect output in UTF-8. */
+ s = gettext ("cheese");
+ if (strcmp (s, "K\303\244se"))
+ {
+ printf ("call 2 returned: %s\n", s);
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/intl/tst-gettext4-de.po b/REORG.TODO/intl/tst-gettext4-de.po
new file mode 100644
index 0000000000..0a8d099398
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext4-de.po
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+msgid "beauty"
+msgstr "Schönheit"
diff --git a/REORG.TODO/intl/tst-gettext4-fr.po b/REORG.TODO/intl/tst-gettext4-fr.po
new file mode 100644
index 0000000000..8332c2d9f8
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext4-fr.po
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+msgid "beauty"
+msgstr "beauté"
diff --git a/REORG.TODO/intl/tst-gettext4.c b/REORG.TODO/intl/tst-gettext4.c
new file mode 100644
index 0000000000..bc4365588a
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext4.c
@@ -0,0 +1,150 @@
+/* Test that gettext() in multithreaded applications works correctly if
+ different threads operate in different locales with the same encoding.
+ Copyright (C) 2005-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <bruno@clisp.org>, 2005.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Set to 1 if the program is not behaving correctly. */
+int result;
+
+/* Denotes which thread should run next. */
+int flipflop;
+/* Lock and wait queue used to switch between the threads. */
+pthread_mutex_t lock;
+pthread_cond_t waitqueue;
+
+/* Waits until the flipflop has a given value.
+ Before the call, the lock is unlocked. After the call, it is locked. */
+static void
+waitfor (int value)
+{
+ if (pthread_mutex_lock (&lock))
+ exit (10);
+ while (flipflop != value)
+ if (pthread_cond_wait (&waitqueue, &lock))
+ exit (11);
+}
+
+/* Sets the flipflop to a given value.
+ Before the call, the lock is locked. After the call, it is unlocked. */
+static void
+setto (int value)
+{
+ flipflop = value;
+ if (pthread_cond_signal (&waitqueue))
+ exit (20);
+ if (pthread_mutex_unlock (&lock))
+ exit (21);
+}
+
+void *
+thread1_execution (void *arg)
+{
+ char *s;
+
+ waitfor (1);
+ uselocale (newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL));
+ setto (2);
+
+ waitfor (1);
+ s = gettext ("beauty");
+ puts (s);
+ if (strcmp (s, "Sch\366nheit"))
+ {
+ fprintf (stderr, "thread 1 call 1 returned: %s\n", s);
+ result = 1;
+ }
+ setto (2);
+
+ waitfor (1);
+ s = gettext ("beauty");
+ puts (s);
+ if (strcmp (s, "Sch\366nheit"))
+ {
+ fprintf (stderr, "thread 1 call 2 returned: %s\n", s);
+ result = 1;
+ }
+ setto (2);
+
+ return NULL;
+}
+
+void *
+thread2_execution (void *arg)
+{
+ char *s;
+
+ waitfor (2);
+ uselocale (newlocale (LC_ALL_MASK, "fr_FR.ISO-8859-1", NULL));
+ setto (1);
+
+ waitfor (2);
+ s = gettext ("beauty");
+ puts (s);
+ if (strcmp (s, "beaut\351"))
+ {
+ fprintf (stderr, "thread 2 call 1 returned: %s\n", s);
+ result = 1;
+ }
+ setto (1);
+
+ waitfor (2);
+ s = gettext ("beauty");
+ puts (s);
+ if (strcmp (s, "beaut\351"))
+ {
+ fprintf (stderr, "thread 2 call 2 returned: %s\n", s);
+ result = 1;
+ }
+ setto (1);
+
+ return NULL;
+}
+
+int
+main (void)
+{
+ pthread_t thread1;
+ pthread_t thread2;
+
+ unsetenv ("LANGUAGE");
+ unsetenv ("OUTPUT_CHARSET");
+ textdomain ("multithread");
+ bindtextdomain ("multithread", OBJPFX "domaindir");
+ result = 0;
+
+ flipflop = 1;
+ if (pthread_mutex_init (&lock, NULL))
+ exit (2);
+ if (pthread_cond_init (&waitqueue, NULL))
+ exit (2);
+ if (pthread_create (&thread1, NULL, &thread1_execution, NULL))
+ exit (2);
+ if (pthread_create (&thread2, NULL, &thread2_execution, NULL))
+ exit (2);
+ if (pthread_join (thread2, NULL))
+ exit (3);
+
+ return result;
+}
diff --git a/REORG.TODO/intl/tst-gettext4.sh b/REORG.TODO/intl/tst-gettext4.sh
new file mode 100755
index 0000000000..3253b0cc09
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext4.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Test that gettext() in multithreaded applications works correctly if
+# different threads operate in different locales with the same encoding.
+# Copyright (C) 2001-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1
+test_program_prefix=$2
+objpfx=$3
+
+# Create the domain directories.
+mkdir -p ${objpfx}domaindir/de_DE/LC_MESSAGES
+mkdir -p ${objpfx}domaindir/fr_FR/LC_MESSAGES
+# Populate them.
+msgfmt -o ${objpfx}domaindir/de_DE/LC_MESSAGES/multithread.mo tst-gettext4-de.po
+msgfmt -o ${objpfx}domaindir/fr_FR/LC_MESSAGES/multithread.mo tst-gettext4-fr.po
+
+${test_program_prefix} ${objpfx}tst-gettext4 > ${objpfx}tst-gettext4.out
+
+exit $?
diff --git a/REORG.TODO/intl/tst-gettext5.c b/REORG.TODO/intl/tst-gettext5.c
new file mode 100644
index 0000000000..f373f354dc
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext5.c
@@ -0,0 +1,155 @@
+/* Test that gettext() in multithreaded applications works correctly if
+ different threads operate in different locales referring to the same
+ catalog file but with different encodings.
+ Copyright (C) 2005-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <bruno@clisp.org>, 2005.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Set to 1 if the program is not behaving correctly. */
+int result;
+
+/* Denotes which thread should run next. */
+int flipflop;
+/* Lock and wait queue used to switch between the threads. */
+pthread_mutex_t lock;
+pthread_cond_t waitqueue;
+
+/* Waits until the flipflop has a given value.
+ Before the call, the lock is unlocked. After the call, it is locked. */
+static void
+waitfor (int value)
+{
+ if (pthread_mutex_lock (&lock))
+ exit (10);
+ while (flipflop != value)
+ if (pthread_cond_wait (&waitqueue, &lock))
+ exit (11);
+}
+
+/* Sets the flipflop to a given value.
+ Before the call, the lock is locked. After the call, it is unlocked. */
+static void
+setto (int value)
+{
+ flipflop = value;
+ if (pthread_cond_signal (&waitqueue))
+ exit (20);
+ if (pthread_mutex_unlock (&lock))
+ exit (21);
+}
+
+void *
+thread1_execution (void *arg)
+{
+ char *s;
+
+ waitfor (1);
+ uselocale (newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL));
+ setto (2);
+
+ /* Here we expect output in ISO-8859-1. */
+
+ waitfor (1);
+ s = gettext ("cheese");
+ puts (s);
+ if (strcmp (s, "K\344se"))
+ {
+ fprintf (stderr, "thread 1 call 1 returned: %s\n", s);
+ result = 1;
+ }
+ setto (2);
+
+ waitfor (1);
+ s = gettext ("cheese");
+ puts (s);
+ if (strcmp (s, "K\344se"))
+ {
+ fprintf (stderr, "thread 1 call 2 returned: %s\n", s);
+ result = 1;
+ }
+ setto (2);
+
+ return NULL;
+}
+
+void *
+thread2_execution (void *arg)
+{
+ char *s;
+
+ waitfor (2);
+ uselocale (newlocale (LC_ALL_MASK, "de_DE.UTF-8", NULL));
+ setto (1);
+
+ /* Here we expect output in UTF-8. */
+
+ waitfor (2);
+ s = gettext ("cheese");
+ puts (s);
+ if (strcmp (s, "K\303\244se"))
+ {
+ fprintf (stderr, "thread 2 call 1 returned: %s\n", s);
+ result = 1;
+ }
+ setto (1);
+
+ waitfor (2);
+ s = gettext ("cheese");
+ puts (s);
+ if (strcmp (s, "K\303\244se"))
+ {
+ fprintf (stderr, "thread 2 call 2 returned: %s\n", s);
+ result = 1;
+ }
+ setto (1);
+
+ return NULL;
+}
+
+int
+main (void)
+{
+ pthread_t thread1;
+ pthread_t thread2;
+
+ unsetenv ("LANGUAGE");
+ unsetenv ("OUTPUT_CHARSET");
+ textdomain ("codeset");
+ bindtextdomain ("codeset", OBJPFX "domaindir");
+ result = 0;
+
+ flipflop = 1;
+ if (pthread_mutex_init (&lock, NULL))
+ exit (2);
+ if (pthread_cond_init (&waitqueue, NULL))
+ exit (2);
+ if (pthread_create (&thread1, NULL, &thread1_execution, NULL))
+ exit (2);
+ if (pthread_create (&thread2, NULL, &thread2_execution, NULL))
+ exit (2);
+ if (pthread_join (thread2, NULL))
+ exit (3);
+
+ return result;
+}
diff --git a/REORG.TODO/intl/tst-gettext6.c b/REORG.TODO/intl/tst-gettext6.c
new file mode 100644
index 0000000000..dca19f50d5
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext6.c
@@ -0,0 +1,85 @@
+/* Test that gettext() in multithreaded applications works correctly.
+ Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2008.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+pthread_barrier_t b;
+
+static void *
+tf (void *arg)
+{
+ pthread_barrier_wait (&b);
+ return gettext ("Operation not permitted");
+}
+
+int
+test (void)
+{
+ pthread_t th[4];
+ unsetenv ("LANGUAGE");
+ unsetenv ("OUTPUT_CHARSET");
+ textdomain ("tstgettext6");
+ bindtextdomain ("tstgettext6", OBJPFX "domaindir");
+ setlocale (LC_ALL, "ja_JP.UTF-8");
+ pthread_barrier_init (&b, NULL, 4);
+ for (int i = 0; i < 4; i++)
+ if (pthread_create (&th[i], NULL, tf, NULL))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+ for (int i = 0; i < 4; i++)
+ pthread_join (th[i], NULL);
+ return 0;
+}
+
+int
+main (void)
+{
+ for (int i = 0; i < 300; i++)
+ {
+ pid_t p = fork ();
+ if (p == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+ if (p == 0)
+ _exit (test ());
+ int status;
+ wait (&status);
+ if (WIFEXITED (status) && WEXITSTATUS (status) != 0)
+ {
+ printf ("child exited with %d\n", WEXITSTATUS (status));
+ return 1;
+ }
+ else if (WIFSIGNALED (status))
+ {
+ printf ("child killed by signal %d\n", WTERMSIG (status));
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/REORG.TODO/intl/tst-gettext6.sh b/REORG.TODO/intl/tst-gettext6.sh
new file mode 100644
index 0000000000..2ef5c9713c
--- /dev/null
+++ b/REORG.TODO/intl/tst-gettext6.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Test that gettext() in multithreaded applications works correctly.
+# Copyright (C) 2008-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1
+test_program_prefix=$2
+objpfx=$3
+
+# Create the domain directory.
+mkdir -p ${objpfx}domaindir/ja_JP/LC_MESSAGES
+# Populate it.
+msgfmt -o ${objpfx}domaindir/ja_JP/LC_MESSAGES/tstgettext6.mo ../po/ja.po
+
+${test_program_prefix} ${objpfx}tst-gettext6 > ${objpfx}tst-gettext6.out
+
+exit $?
diff --git a/REORG.TODO/intl/tst-ngettext.c b/REORG.TODO/intl/tst-ngettext.c
new file mode 100644
index 0000000000..5f562047f0
--- /dev/null
+++ b/REORG.TODO/intl/tst-ngettext.c
@@ -0,0 +1,68 @@
+/* Test of the ngettext functions.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <langinfo.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+ const char *strs[2] = { "singular", "plural" };
+ unsigned long int i;
+ int res = 0;
+
+ /* We don't want any translation here. */
+ setenv ("LANGUAGE", "C", 1);
+ unsetenv ("OUTPUT_CHARSET");
+
+ for (i = 0; i < 30; ++i)
+ {
+ char *tr;
+
+ tr = ngettext (strs[0], strs[1], i);
+#define TEST \
+ do \
+ if (tr != strs[i != 1]) \
+ { \
+ if (strcmp (tr, strs[i != 1]) == 0) \
+ printf ("%lu: correct string, wrong pointer (%s)\n", i, tr); \
+ else \
+ printf ("%lu: wrong result (%s)\n", i, tr); \
+ res = 1; \
+ } \
+ while (0)
+ TEST;
+
+ tr = dngettext ("messages", strs[0], strs[1], i);
+ TEST;
+
+ tr = dcngettext ("messages", strs[0], strs[1], i, LC_MESSAGES);
+ TEST;
+ }
+
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/intl/tst-translit.c b/REORG.TODO/intl/tst-translit.c
new file mode 100644
index 0000000000..b8bd8a86e6
--- /dev/null
+++ b/REORG.TODO/intl/tst-translit.c
@@ -0,0 +1,54 @@
+/* Test of translitation in the gettext functions.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+ int result = 0;
+ const char *s;
+
+ setenv ("LANGUAGE", "existing-locale", 1);
+ unsetenv ("OUTPUT_CHARSET");
+ setlocale (LC_ALL, "en_US.ANSI_X3.4-1968");
+ textdomain ("translit");
+ bindtextdomain ("translit", OBJPFX "domaindir");
+
+#define TEST(in, exp) \
+ s = gettext (in); \
+ puts (s); \
+ result |= strcmp (s, exp) != 0;
+
+ TEST ("test", "<<(C) AEss>>");
+ TEST ("test", "<<(C) AEss>>");
+ TEST ("onemore", " 1/2 * 1/2 = 1/4 ");
+ TEST ("onemore", " 1/2 * 1/2 = 1/4 ");
+ TEST ("test", "<<(C) AEss>>");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/intl/tst-translit.sh b/REORG.TODO/intl/tst-translit.sh
new file mode 100755
index 0000000000..e999564bf3
--- /dev/null
+++ b/REORG.TODO/intl/tst-translit.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Test of transliteration in gettext functions.
+# Copyright (C) 2000-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1
+test_program_prefix=$2
+objpfx=$3
+
+# Create the locale directories.
+mkdir -p ${objpfx}localedir/existing-locale/LC_MESSAGES
+
+msgfmt -o ${objpfx}domaindir/existing-locale/LC_MESSAGES/translit.mo \
+ translit.po
+
+${test_program_prefix} \
+${objpfx}tst-translit > ${objpfx}tst-translit.out ${objpfx}domaindir
+
+exit $?
diff --git a/REORG.TODO/intl/tstcodeset.po b/REORG.TODO/intl/tstcodeset.po
new file mode 100644
index 0000000000..9a6231d600
--- /dev/null
+++ b/REORG.TODO/intl/tstcodeset.po
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+msgid "cheese"
+msgstr "Käse"
diff --git a/REORG.TODO/intl/tstlang1.po b/REORG.TODO/intl/tstlang1.po
new file mode 100644
index 0000000000..c411ce116f
--- /dev/null
+++ b/REORG.TODO/intl/tstlang1.po
@@ -0,0 +1,13 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=US-ASCII\n"
+"Content-Transfer-Encoding: 7-bit\n"
+
+#: tst-gettext2.c:33
+msgid "First string for testing."
+msgstr "Lang1: 1st string"
+
+#: tst-gettext2.c:34
+msgid "Another string for testing."
+msgstr "Lang1: 2nd string"
diff --git a/REORG.TODO/intl/tstlang2.po b/REORG.TODO/intl/tstlang2.po
new file mode 100644
index 0000000000..d1606c8ede
--- /dev/null
+++ b/REORG.TODO/intl/tstlang2.po
@@ -0,0 +1,13 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=US-ASCII\n"
+"Content-Transfer-Encoding: 7-bit\n"
+
+#: tst-gettext2.c:33
+msgid "First string for testing."
+msgstr "Lang2: 1st string"
+
+#: tst-gettext2.c:34
+msgid "Another string for testing."
+msgstr "Lang2: 2nd string"