Quellcode durchsuchen

Added intl/*
Added src/alloca.c

Tatsuhiro Tsujikawa vor 19 Jahren
Ursprung
Commit
46354b7c91
53 geänderte Dateien mit 14255 neuen und 184 gelöschten Zeilen
  1. 5 0
      ChangeLog
  2. 1 1
      Makefile.am
  3. 31 11
      Makefile.in
  4. 10 0
      aclocal.m4
  5. 150 1
      config.h.in
  6. 2324 145
      configure
  7. 2 2
      configure.in
  8. 4 0
      intl/ChangeLog
  9. 479 0
      intl/Makefile.in
  10. 1 0
      intl/VERSION
  11. 374 0
      intl/bindtextdom.c
  12. 467 0
      intl/config.charset
  13. 59 0
      intl/dcgettext.c
  14. 1238 0
      intl/dcigettext.c
  15. 60 0
      intl/dcngettext.c
  16. 59 0
      intl/dgettext.c
  17. 61 0
      intl/dngettext.c
  18. 114 0
      intl/eval-plural.h
  19. 192 0
      intl/explodename.c
  20. 195 0
      intl/finddomain.c
  21. 64 0
      intl/gettext.c
  22. 224 0
      intl/gettextP.h
  23. 148 0
      intl/gmo.h
  24. 59 0
      intl/hash-string.h
  25. 151 0
      intl/intl-compat.c
  26. 453 0
      intl/l10nflist.c
  27. 309 0
      intl/libgnuintl.h.in
  28. 156 0
      intl/loadinfo.h
  29. 1322 0
      intl/loadmsgcat.c
  30. 398 0
      intl/localcharset.c
  31. 42 0
      intl/localcharset.h
  32. 78 0
      intl/locale.alias
  33. 419 0
      intl/localealias.c
  34. 772 0
      intl/localename.c
  35. 104 0
      intl/log.c
  36. 68 0
      intl/ngettext.c
  37. 98 0
      intl/os2compat.c
  38. 46 0
      intl/os2compat.h
  39. 24 0
      intl/osdep.c
  40. 156 0
      intl/plural-exp.c
  41. 126 0
      intl/plural-exp.h
  42. 1518 0
      intl/plural.c
  43. 409 0
      intl/plural.y
  44. 31 0
      intl/ref-add.sin
  45. 26 0
      intl/ref-del.sin
  46. 439 0
      intl/relocatable.c
  47. 67 0
      intl/relocatable.h
  48. 142 0
      intl/textdomain.c
  49. 21 5
      m4/Makefile.in
  50. 4 2
      src/Makefile.am
  51. 30 12
      src/Makefile.in
  52. 504 0
      src/alloca.c
  53. 21 5
      test/Makefile.in

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+2006-03-07  gettextize  <bug-gnu-gettext@gnu.org>
+
+	* Makefile.am (SUBDIRS): Add intl.
+	* configure.in (AC_CONFIG_FILES): Add intl/Makefile.
+
 2006-03-05  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	* main.cc: correct help message for --http-auth-scheme.

+ 1 - 1
Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = m4 po src test
+SUBDIRS = intl  m4 po src test
 
 ACLOCAL_AMFLAGS = -I m4
 

+ 31 - 11
Makefile.in

@@ -37,23 +37,29 @@ build_triplet = @build@
 host_triplet = @host@
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in $(srcdir)/config.h.in \
-	$(top_srcdir)/configure ABOUT-NLS AUTHORS COPYING ChangeLog \
-	INSTALL NEWS TODO config.guess config.rpath config.sub depcomp \
-	install-sh missing mkinstalldirs
+	$(top_srcdir)/configure $(top_srcdir)/intl/Makefile.in \
+	ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL NEWS TODO \
+	config.guess config.rpath config.sub depcomp install-sh \
+	missing mkinstalldirs
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
-	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
-	$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
-	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
-	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
+	$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
+	$(top_srcdir)/m4/inttypes-pri.m4 $(top_srcdir)/m4/inttypes.m4 \
+	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
+	$(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.in
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno configure.status.lineno
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = intl/Makefile
 SOURCES =
 DIST_SOURCES =
 RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -77,6 +83,7 @@ GZIP_ENV = --best
 distuninstallcheck_listfiles = find . -type f -print
 distcleancheck_listfiles = find . -type f -print
 ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
 AMDEP_FALSE = @AMDEP_FALSE@
 AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
@@ -84,6 +91,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -96,6 +105,7 @@ CXX = @CXX@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 ECHO_C = @ECHO_C@
@@ -103,12 +113,18 @@ ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
 GMSGFMT = @GMSGFMT@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
 INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
 LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
@@ -134,6 +150,7 @@ RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
@@ -179,7 +196,7 @@ sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
 target_alias = @target_alias@
-SUBDIRS = m4 po src test
+SUBDIRS = intl  m4 po src test
 ACLOCAL_AMFLAGS = -I m4
 EXTRA_DIST = config.rpath
 all: config.h
@@ -236,6 +253,8 @@ $(srcdir)/config.h.in:  $(am__configure_deps)
 
 distclean-hdr:
 	-rm -f config.h stamp-h1
+intl/Makefile: $(top_builddir)/config.status $(top_srcdir)/intl/Makefile.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
 uninstall-info-am:
 
 # This directory's subdirectories are mostly independent; you can cd
@@ -373,7 +392,7 @@ distclean-tags:
 distdir: $(DISTFILES)
 	$(am__remove_distdir)
 	mkdir $(distdir)
-	$(mkdir_p) $(distdir)/m4 $(distdir)/po
+	$(mkdir_p) $(distdir)/intl $(distdir)/m4 $(distdir)/po
 	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
 	list='$(DISTFILES)'; for file in $$list; do \
@@ -469,6 +488,7 @@ distcheck: dist
 	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
 	  && cd $(distdir)/_build \
 	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    --with-included-gettext \
 	    $(DISTCHECK_CONFIGURE_FLAGS) \
 	  && $(MAKE) $(AM_MAKEFLAGS) \
 	  && $(MAKE) $(AM_MAKEFLAGS) dvi \

+ 10 - 0
aclocal.m4

@@ -929,11 +929,21 @@ AC_SUBST([am__tar])
 AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
 
+m4_include([m4/codeset.m4])
 m4_include([m4/gettext.m4])
+m4_include([m4/glibc21.m4])
 m4_include([m4/iconv.m4])
+m4_include([m4/intdiv0.m4])
+m4_include([m4/inttypes-pri.m4])
+m4_include([m4/inttypes.m4])
+m4_include([m4/inttypes_h.m4])
+m4_include([m4/lcmessage.m4])
 m4_include([m4/lib-ld.m4])
 m4_include([m4/lib-link.m4])
 m4_include([m4/lib-prefix.m4])
 m4_include([m4/nls.m4])
 m4_include([m4/po.m4])
 m4_include([m4/progtest.m4])
+m4_include([m4/stdint_h.m4])
+m4_include([m4/uintmax_t.m4])
+m4_include([m4/ulonglong.m4])

+ 150 - 1
config.h.in

@@ -1,9 +1,27 @@
 /* config.h.in.  Generated from configure.in by autoheader.  */
 
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 #undef ENABLE_NLS
 
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #undef HAVE_ARPA_INET_H
 
@@ -17,6 +35,27 @@
 /* Define to 1 if you have the <fcntl.h> header file. */
 #undef HAVE_FCNTL_H
 
+/* Define to 1 if you have the `feof_unlocked' function. */
+#undef HAVE_FEOF_UNLOCKED
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+#undef HAVE_FGETS_UNLOCKED
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#undef HAVE_GETC_UNLOCKED
+
+/* Define to 1 if you have the `getegid' function. */
+#undef HAVE_GETEGID
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getgid' function. */
+#undef HAVE_GETGID
+
 /* Define to 1 if you have the `getpagesize' function. */
 #undef HAVE_GETPAGESIZE
 
@@ -26,42 +65,82 @@
 /* Define to 1 if you have the `gettimeofday' function. */
 #undef HAVE_GETTIMEOFDAY
 
+/* Define to 1 if you have the `getuid' function. */
+#undef HAVE_GETUID
+
 /* Define if you have the iconv() function. */
 #undef HAVE_ICONV
 
 /* Define to 1 if you have the `inet_ntoa' function. */
 #undef HAVE_INET_NTOA
 
-/* Define to 1 if you have the <inttypes.h> header file. */
+/* Define if <inttypes.h> exists and doesn't clash with <sys/types.h>. */
 #undef HAVE_INTTYPES_H
 
+/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
+   declares uintmax_t. */
+#undef HAVE_INTTYPES_H_WITH_UINTMAX
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#undef HAVE_LANGINFO_CODESET
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
 /* Define to 1 if you have the `ssl' library (-lssl). */
 #undef HAVE_LIBSSL
 
 /* Define to 1 if you have the <limits.h> header file. */
 #undef HAVE_LIMITS_H
 
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the `mempcpy' function. */
+#undef HAVE_MEMPCPY
+
 /* Define to 1 if you have the `memset' function. */
 #undef HAVE_MEMSET
 
 /* Define to 1 if you have the `mkdir' function. */
 #undef HAVE_MKDIR
 
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
 /* Define to 1 if you have the <netdb.h> header file. */
 #undef HAVE_NETDB_H
 
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
+/* Define to 1 if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define to 1 if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
 /* Define to 1 if you have the `rmdir' function. */
 #undef HAVE_RMDIR
 
 /* Define to 1 if you have the `select' function. */
 #undef HAVE_SELECT
 
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
 /* Define to 1 if you have the `socket' function. */
 #undef HAVE_SOCKET
 
@@ -72,15 +151,28 @@
 /* Define to 1 if stdbool.h conforms to C99. */
 #undef HAVE_STDBOOL_H
 
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
+/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
+   uintmax_t. */
+#undef HAVE_STDINT_H_WITH_UINTMAX
+
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
+/* Define to 1 if you have the `stpcpy' function. */
+#undef HAVE_STPCPY
+
 /* Define to 1 if you have the `strcasecmp' function. */
 #undef HAVE_STRCASECMP
 
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
 /* Define to 1 if you have the `strerror' function. */
 #undef HAVE_STRERROR
 
@@ -96,6 +188,12 @@
 /* Define to 1 if you have the `strtol' function. */
 #undef HAVE_STRTOL
 
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
 /* Define to 1 if you have the <sys/select.h> header file. */
 #undef HAVE_SYS_SELECT_H
 
@@ -111,15 +209,42 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
+/* Define to 1 if you have the `tsearch' function. */
+#undef HAVE_TSEARCH
+
+/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
+#undef HAVE_UINTMAX_T
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define if you have the unsigned long long type. */
+#undef HAVE_UNSIGNED_LONG_LONG
+
 /* Define to 1 if you have the `vprintf' function. */
 #undef HAVE_VPRINTF
 
 /* Define to 1 if the system has the type `_Bool'. */
 #undef HAVE__BOOL
 
+/* Define to 1 if you have the `__argz_count' function. */
+#undef HAVE___ARGZ_COUNT
+
+/* Define to 1 if you have the `__argz_next' function. */
+#undef HAVE___ARGZ_NEXT
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define to 1 if you have the `__fsetlocking' function. */
+#undef HAVE___FSETLOCKING
+
+/* Define as const if the declaration of iconv() needs const. */
+#undef ICONV_CONST
+
+/* Define if integer division by zero raises signal SIGFPE. */
+#undef INTDIV0_RAISES_SIGFPE
+
 /* Define to 1 if `lstat' dereferences a symlink specified with a trailing
    slash. */
 #undef LSTAT_FOLLOWS_SLASHED_SYMLINK
@@ -142,6 +267,9 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
+#undef PRI_MACROS_BROKEN
+
 /* Define to the type of arg 1 for `select'. */
 #undef SELECT_TYPE_ARG1
 
@@ -151,6 +279,14 @@
 /* Define to the type of arg 5 for `select'. */
 #undef SELECT_TYPE_ARG5
 
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
@@ -163,5 +299,18 @@
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `long' if <sys/types.h> does not define. */
+#undef off_t
+
 /* Define to `unsigned' if <sys/types.h> does not define. */
 #undef size_t
+
+/* Define to unsigned long or unsigned long long if <stdint.h> and
+   <inttypes.h> don't define. */
+#undef uintmax_t

Datei-Diff unterdrückt, da er zu groß ist
+ 2324 - 145
configure


+ 2 - 2
configure.in

@@ -8,7 +8,7 @@ AM_PATH_CPPUNIT(1.10.2)
 AC_CONFIG_SRCDIR([src/Socket.h])
 AC_CONFIG_HEADERS([config.h])
 AC_PROG_RANLIB
-AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT
 AM_GNU_GETTEXT_VERSION(0.12.1)
 
 # Set localedir
@@ -44,5 +44,5 @@ AC_FUNC_STAT
 AC_FUNC_VPRINTF
 AC_CHECK_FUNCS([getpagesize gettimeofday inet_ntoa memset mkdir rmdir select socket strcasecmp strerror strstr strtol])
 
-AC_CONFIG_FILES([Makefile src/Makefile test/Makefile po/Makefile.in m4/Makefile ])
+AC_CONFIG_FILES([Makefile src/Makefile test/Makefile po/Makefile.in m4/Makefile  intl/Makefile ])
 AC_OUTPUT

+ 4 - 0
intl/ChangeLog

@@ -0,0 +1,4 @@
+2003-05-22  GNU  <bug-gnu-gettext@gnu.org>
+
+	* Version 0.12.1 released.
+

+ 479 - 0
intl/Makefile.in

@@ -0,0 +1,479 @@
+# Makefile for directory with message catalog handling library of GNU gettext
+# Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ..
+VPATH = $(srcdir)
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+transform = @program_transform_name@
+libdir = @libdir@
+includedir = @includedir@
+datadir = @datadir@
+localedir = $(datadir)/locale
+gettextsrcdir = $(datadir)/gettext/intl
+aliaspath = $(localedir)
+subdir = intl
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+mkinstalldirs = $(SHELL) $(MKINSTALLDIRS)
+
+l = @INTL_LIBTOOL_SUFFIX_PREFIX@
+
+AR = ar
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+RANLIB = @RANLIB@
+YACC = @INTLBISON@ -y -d
+YFLAGS = --name-prefix=__gettext
+
+DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
+-DLIBDIR=\"$(libdir)\" -DIN_LIBINTL \
+-DENABLE_RELOCATABLE=1 -DIN_LIBRARY -DINSTALLDIR=\"$(libdir)\" -DNO_XMALLOC \
+-Dset_relocation_prefix=libintl_set_relocation_prefix \
+-Drelocate=libintl_relocate \
+-DDEPENDS_ON_LIBICONV=1 @DEFS@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+HEADERS = \
+  gmo.h \
+  gettextP.h \
+  hash-string.h \
+  loadinfo.h \
+  plural-exp.h \
+  eval-plural.h \
+  localcharset.h \
+  relocatable.h \
+  os2compat.h \
+  libgnuintl.h.in
+SOURCES = \
+  bindtextdom.c \
+  dcgettext.c \
+  dgettext.c \
+  gettext.c \
+  finddomain.c \
+  loadmsgcat.c \
+  localealias.c \
+  textdomain.c \
+  l10nflist.c \
+  explodename.c \
+  dcigettext.c \
+  dcngettext.c \
+  dngettext.c \
+  ngettext.c \
+  plural.y \
+  plural-exp.c \
+  localcharset.c \
+  relocatable.c \
+  localename.c \
+  log.c \
+  osdep.c \
+  os2compat.c \
+  intl-compat.c
+OBJECTS = \
+  bindtextdom.$lo \
+  dcgettext.$lo \
+  dgettext.$lo \
+  gettext.$lo \
+  finddomain.$lo \
+  loadmsgcat.$lo \
+  localealias.$lo \
+  textdomain.$lo \
+  l10nflist.$lo \
+  explodename.$lo \
+  dcigettext.$lo \
+  dcngettext.$lo \
+  dngettext.$lo \
+  ngettext.$lo \
+  plural.$lo \
+  plural-exp.$lo \
+  localcharset.$lo \
+  relocatable.$lo \
+  localename.$lo \
+  log.$lo \
+  osdep.$lo \
+  intl-compat.$lo
+DISTFILES.common = Makefile.in \
+config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES)
+DISTFILES.generated = plural.c
+DISTFILES.normal = VERSION
+DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc \
+Makefile.vms libgnuintl.h.msvc-shared README.woe32 Makefile.msvc
+DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \
+COPYING.LIB-2 gettext.h libgettext.h plural-eval.c libgnuintl.h
+
+all: all-@USE_INCLUDED_LIBINTL@
+all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed
+all-no: all-no-@BUILD_INCLUDED_LIBINTL@
+all-no-yes: libgnuintl.$la
+all-no-no:
+
+libintl.a libgnuintl.a: $(OBJECTS)
+	rm -f $@
+	$(AR) cru $@ $(OBJECTS)
+	$(RANLIB) $@
+
+libintl.la libgnuintl.la: $(OBJECTS)
+	$(LIBTOOL) --mode=link \
+	  $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \
+	  $(OBJECTS) @LTLIBICONV@ $(LIBS) -lc \
+	  -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
+	  -rpath $(libdir) \
+	  -no-undefined
+
+# Libtool's library version information for libintl.
+# Before making a gettext release, the gettext maintainer must change this
+# according to the libtool documentation, section "Library interface versions".
+# Maintainers of other packages that include the intl directory must *not*
+# change these values.
+LTV_CURRENT=5
+LTV_REVISION=0
+LTV_AGE=3
+
+.SUFFIXES:
+.SUFFIXES: .c .y .o .lo .sin .sed
+
+.c.o:
+	$(COMPILE) $<
+
+.y.c:
+	$(YACC) $(YFLAGS) --output $@ $<
+	rm -f $*.h
+
+bindtextdom.lo: $(srcdir)/bindtextdom.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/bindtextdom.c
+dcgettext.lo: $(srcdir)/dcgettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcgettext.c
+dgettext.lo: $(srcdir)/dgettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dgettext.c
+gettext.lo: $(srcdir)/gettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/gettext.c
+finddomain.lo: $(srcdir)/finddomain.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/finddomain.c
+loadmsgcat.lo: $(srcdir)/loadmsgcat.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/loadmsgcat.c
+localealias.lo: $(srcdir)/localealias.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localealias.c
+textdomain.lo: $(srcdir)/textdomain.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/textdomain.c
+l10nflist.lo: $(srcdir)/l10nflist.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/l10nflist.c
+explodename.lo: $(srcdir)/explodename.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/explodename.c
+dcigettext.lo: $(srcdir)/dcigettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcigettext.c
+dcngettext.lo: $(srcdir)/dcngettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcngettext.c
+dngettext.lo: $(srcdir)/dngettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dngettext.c
+ngettext.lo: $(srcdir)/ngettext.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/ngettext.c
+plural.lo: $(srcdir)/plural.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural.c
+plural-exp.lo: $(srcdir)/plural-exp.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural-exp.c
+localcharset.lo: $(srcdir)/localcharset.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localcharset.c
+relocatable.lo: $(srcdir)/relocatable.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/relocatable.c
+localename.lo: $(srcdir)/localename.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c
+log.lo: $(srcdir)/log.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c
+osdep.lo: $(srcdir)/osdep.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c
+intl-compat.lo: $(srcdir)/intl-compat.c
+	$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/intl-compat.c
+
+ref-add.sed: $(srcdir)/ref-add.sin
+	sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-add.sin > t-ref-add.sed
+	mv t-ref-add.sed ref-add.sed
+ref-del.sed: $(srcdir)/ref-del.sin
+	sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-del.sin > t-ref-del.sed
+	mv t-ref-del.sed ref-del.sed
+
+INCLUDES = -I. -I$(srcdir) -I..
+
+libgnuintl.h: $(srcdir)/libgnuintl.h.in
+	cp $(srcdir)/libgnuintl.h.in libgnuintl.h
+
+libintl.h: libgnuintl.h
+	cp libgnuintl.h libintl.h
+
+charset.alias: $(srcdir)/config.charset
+	$(SHELL) $(srcdir)/config.charset '@host@' > t-$@
+	mv t-$@ $@
+
+check: all
+
+# We must not install the libintl.h/libintl.a files if we are on a
+# system which has the GNU gettext() function in its C library or in a
+# separate library.
+# If you want to use the one which comes with this version of the
+# package, you have to use `configure --with-included-gettext'.
+install: install-exec install-data
+install-exec: all
+	if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
+	   && test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
+	  $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \
+	  $(LIBTOOL) --mode=install \
+	    $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \
+	  if test "@RELOCATABLE@" = yes; then \
+	    dependencies=`sed -n -e 's,^dependency_libs=\(.*\),\1,p' < $(DESTDIR)$(libdir)/libintl.la | sed -e "s,^',," -e "s,'\$$,,"`; \
+	    if test -n "$dependencies"; then \
+	      rm -f $(DESTDIR)$(libdir)/libintl.la; \
+	    fi; \
+	  fi; \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext-tools" \
+	   && test '@USE_INCLUDED_LIBINTL@' = no; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir); \
+	  $(LIBTOOL) --mode=install \
+	    $(INSTALL_DATA) libgnuintl.$la $(DESTDIR)$(libdir)/libgnuintl.$la; \
+	  rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+	  $(INSTALL_DATA) $(DESTDIR)$(libdir)/libgnuintl.so $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+	  $(LIBTOOL) --mode=uninstall \
+	    rm -f $(DESTDIR)$(libdir)/libgnuintl.$la; \
+	else \
+	  : ; \
+	fi
+	if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
+	  temp=$(DESTDIR)$(libdir)/t-charset.alias; \
+	  dest=$(DESTDIR)$(libdir)/charset.alias; \
+	  if test -f $(DESTDIR)$(libdir)/charset.alias; then \
+	    orig=$(DESTDIR)$(libdir)/charset.alias; \
+	    sed -f ref-add.sed $$orig > $$temp; \
+	    $(INSTALL_DATA) $$temp $$dest; \
+	    rm -f $$temp; \
+	  else \
+	    if test @GLIBC21@ = no; then \
+	      orig=charset.alias; \
+	      sed -f ref-add.sed $$orig > $$temp; \
+	      $(INSTALL_DATA) $$temp $$dest; \
+	      rm -f $$temp; \
+	    fi; \
+	  fi; \
+	  $(mkinstalldirs) $(DESTDIR)$(localedir); \
+	  test -f $(DESTDIR)$(localedir)/locale.alias \
+	    && orig=$(DESTDIR)$(localedir)/locale.alias \
+	    || orig=$(srcdir)/locale.alias; \
+	  temp=$(DESTDIR)$(localedir)/t-locale.alias; \
+	  dest=$(DESTDIR)$(localedir)/locale.alias; \
+	  sed -f ref-add.sed $$orig > $$temp; \
+	  $(INSTALL_DATA) $$temp $$dest; \
+	  rm -f $$temp; \
+	else \
+	  : ; \
+	fi
+install-data: all
+	if test "$(PACKAGE)" = "gettext-tools"; then \
+	  $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
+	  $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \
+	  $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \
+	  dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \
+	  for file in $$dists; do \
+	    $(INSTALL_DATA) $(srcdir)/$$file \
+			    $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	  chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \
+	  dists="$(DISTFILES.generated)"; \
+	  for file in $$dists; do \
+	    if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
+	    $(INSTALL_DATA) $$dir/$$file \
+			    $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	  dists="$(DISTFILES.obsolete)"; \
+	  for file in $$dists; do \
+	    rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	else \
+	  : ; \
+	fi
+
+install-strip: install
+
+installdirs:
+	if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
+	   && test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext-tools" \
+	   && test '@USE_INCLUDED_LIBINTL@' = no; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir); \
+	else \
+	  : ; \
+	fi
+	if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
+	  $(mkinstalldirs) $(DESTDIR)$(localedir); \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext-tools"; then \
+	  $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
+	else \
+	  : ; \
+	fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+	if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
+	   && test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  rm -f $(DESTDIR)$(includedir)/libintl.h; \
+	  $(LIBTOOL) --mode=uninstall \
+	    rm -f $(DESTDIR)$(libdir)/libintl.$la; \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext-tools" \
+	   && test '@USE_INCLUDED_LIBINTL@' = no; then \
+	  rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+	else \
+	  : ; \
+	fi
+	if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  if test -f $(DESTDIR)$(libdir)/charset.alias; then \
+	    temp=$(DESTDIR)$(libdir)/t-charset.alias; \
+	    dest=$(DESTDIR)$(libdir)/charset.alias; \
+	    sed -f ref-del.sed $$dest > $$temp; \
+	    if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
+	      rm -f $$dest; \
+	    else \
+	      $(INSTALL_DATA) $$temp $$dest; \
+	    fi; \
+	    rm -f $$temp; \
+	  fi; \
+	  if test -f $(DESTDIR)$(localedir)/locale.alias; then \
+	    temp=$(DESTDIR)$(localedir)/t-locale.alias; \
+	    dest=$(DESTDIR)$(localedir)/locale.alias; \
+	    sed -f ref-del.sed $$dest > $$temp; \
+	    if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
+	      rm -f $$dest; \
+	    else \
+	      $(INSTALL_DATA) $$temp $$dest; \
+	    fi; \
+	    rm -f $$temp; \
+	  fi; \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext-tools"; then \
+	  for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \
+	    rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	else \
+	  : ; \
+	fi
+
+info dvi ps pdf html:
+
+$(OBJECTS): ../config.h libgnuintl.h
+bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo textdomain.$lo: $(srcdir)/gettextP.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+dcigettext.$lo loadmsgcat.$lo: $(srcdir)/hash-string.h
+explodename.$lo l10nflist.$lo: $(srcdir)/loadinfo.h
+dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.h
+dcigettext.$lo: $(srcdir)/eval-plural.h
+localcharset.$lo: $(srcdir)/localcharset.h
+localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h
+
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES)
+	here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES)
+
+ctags: CTAGS
+
+CTAGS: $(HEADERS) $(SOURCES)
+	here=`pwd`; cd $(srcdir) && ctags -o $$here/CTAGS $(HEADERS) $(SOURCES)
+
+id: ID
+
+ID: $(HEADERS) $(SOURCES)
+	here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES)
+
+
+mostlyclean:
+	rm -f *.a *.la *.o *.obj *.lo core core.*
+	rm -f libgnuintl.h libintl.h charset.alias ref-add.sed ref-del.sed
+	rm -f -r .libs _libs
+
+clean: mostlyclean
+
+distclean: clean
+	rm -f Makefile ID TAGS
+	if test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; then \
+	  rm -f ChangeLog.inst $(DISTFILES.normal); \
+	else \
+	  : ; \
+	fi
+
+maintainer-clean: distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+
+# GNU gettext needs not contain the file `VERSION' but contains some
+# other files which should not be distributed in other packages.
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: Makefile
+	if test "$(PACKAGE)" = "gettext-tools"; then \
+	  : ; \
+	else \
+	  if test "$(PACKAGE)" = "gettext-runtime"; then \
+	    additional="$(DISTFILES.gettext)"; \
+	  else \
+	    additional="$(DISTFILES.normal)"; \
+	  fi; \
+	  $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \
+	  for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \
+	    if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
+	    cp -p $$dir/$$file $(distdir); \
+	  done; \
+	fi
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status
+# This would be more efficient, but doesn't work any more with autoconf-2.57,
+# when AC_CONFIG_FILES([intl/Makefile:somedir/Makefile.in]) is used.
+#	cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 1 - 0
intl/VERSION

@@ -0,0 +1 @@
+GNU gettext library from gettext-0.12.1

+ 374 - 0
intl/bindtextdom.c

@@ -0,0 +1,374 @@
+/* Implementation of the bindtextdomain(3) function
+   Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "gettextP.h"
+
+#ifdef _LIBC
+/* We have to handle multi-threaded applications.  */
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_rwlock_define(CLASS, NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#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
+
+/* 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 @@ */
+
+/* Contains the default location of the message catalogs.  */
+extern const char _nl_default_dirname[];
+#ifdef _LIBC
+extern const char _nl_default_dirname_internal[] attribute_hidden;
+#else
+# define INTUSE(name) name
+#endif
+
+/* List with bindings of specific domains.  */
+extern struct binding *_nl_domain_bindings;
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+__libc_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
+
+/* Prototypes for local functions.  */
+static void set_binding_values PARAMS ((const char *domainname,
+					const char **dirnamep,
+					const char **codesetp));
+
+/* 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 (domainname, dirnamep, codesetp)
+     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;
+    }
+
+  __libc_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, INTUSE(_nl_default_dirname)) == 0)
+		    result = (char *) INTUSE(_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 != INTUSE(_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))
+		    {
+		      if (binding->codeset != NULL)
+			free (binding->codeset);
+
+		      binding->codeset = result;
+		      binding->codeset_cntr++;
+		      modified = 1;
+		    }
+		}
+	      *codesetp = result;
+	    }
+	}
+    }
+  else if ((dirnamep == NULL || *dirnamep == NULL)
+	   && (codesetp == NULL || *codesetp == NULL))
+    {
+      /* Simply return the default values.  */
+      if (dirnamep)
+	*dirnamep = INTUSE(_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 = INTUSE(_nl_default_dirname);
+	  else
+	    {
+	      if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
+		dirname = INTUSE(_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 *) INTUSE(_nl_default_dirname);
+
+      new_binding->codeset_cntr = 0;
+
+      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;
+	      new_binding->codeset_cntr++;
+	    }
+	  *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 != INTUSE(_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;
+
+  __libc_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 (domainname, dirname)
+     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 (domainname, 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

+ 467 - 0
intl/config.charset

@@ -0,0 +1,467 @@
+#! /bin/sh
+# Output a system dependent table of character encoding aliases.
+#
+#   Copyright (C) 2000-2003 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Library 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
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#   USA.
+#
+# The table consists of lines of the form
+#    ALIAS  CANONICAL
+#
+# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
+# ALIAS is compared in a case sensitive way.
+#
+# CANONICAL is the GNU canonical name for this character encoding.
+# It must be an encoding supported by libiconv. Support by GNU libc is
+# also desirable. CANONICAL is case insensitive. Usually an upper case
+# MIME charset name is preferred.
+# The current list of GNU canonical charset names is as follows.
+#
+#       name                         used by which systems         a MIME name?
+#   ASCII, ANSI_X3.4-1968     glibc solaris freebsd
+#   ISO-8859-1                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-2                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-3                glibc solaris                             yes
+#   ISO-8859-4                osf solaris freebsd                       yes
+#   ISO-8859-5                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-6                glibc aix hpux solaris                    yes
+#   ISO-8859-7                glibc aix hpux irix osf solaris           yes
+#   ISO-8859-8                glibc aix hpux osf solaris                yes
+#   ISO-8859-9                glibc aix hpux irix osf solaris           yes
+#   ISO-8859-13               glibc
+#   ISO-8859-14               glibc
+#   ISO-8859-15               glibc aix osf solaris freebsd
+#   KOI8-R                    glibc solaris freebsd                     yes
+#   KOI8-U                    glibc freebsd                             yes
+#   KOI8-T                    glibc
+#   CP437                     dos
+#   CP775                     dos
+#   CP850                     aix osf dos
+#   CP852                     dos
+#   CP855                     dos
+#   CP856                     aix
+#   CP857                     dos
+#   CP861                     dos
+#   CP862                     dos
+#   CP864                     dos
+#   CP865                     dos
+#   CP866                     freebsd dos
+#   CP869                     dos
+#   CP874                     woe32 dos
+#   CP922                     aix
+#   CP932                     aix woe32 dos
+#   CP943                     aix
+#   CP949                     osf woe32 dos
+#   CP950                     woe32 dos
+#   CP1046                    aix
+#   CP1124                    aix
+#   CP1125                    dos
+#   CP1129                    aix
+#   CP1250                    woe32
+#   CP1251                    glibc solaris woe32
+#   CP1252                    aix woe32
+#   CP1253                    woe32
+#   CP1254                    woe32
+#   CP1255                    glibc woe32
+#   CP1256                    woe32
+#   CP1257                    woe32
+#   GB2312                    glibc aix hpux irix solaris freebsd       yes
+#   EUC-JP                    glibc aix hpux irix osf solaris freebsd   yes
+#   EUC-KR                    glibc aix hpux irix osf solaris freebsd   yes
+#   EUC-TW                    glibc aix hpux irix osf solaris
+#   BIG5                      glibc aix hpux osf solaris freebsd        yes
+#   BIG5-HKSCS                glibc solaris
+#   GBK                       glibc aix osf solaris woe32 dos
+#   GB18030                   glibc solaris
+#   SHIFT_JIS                 hpux osf solaris freebsd                  yes
+#   JOHAB                     glibc solaris woe32
+#   TIS-620                   glibc aix hpux osf solaris
+#   VISCII                    glibc                                     yes
+#   TCVN5712-1                glibc
+#   GEORGIAN-PS               glibc
+#   HP-ROMAN8                 hpux
+#   HP-ARABIC8                hpux
+#   HP-GREEK8                 hpux
+#   HP-HEBREW8                hpux
+#   HP-TURKISH8               hpux
+#   HP-KANA8                  hpux
+#   DEC-KANJI                 osf
+#   DEC-HANYU                 osf
+#   UTF-8                     glibc aix hpux osf solaris                yes
+#
+# Note: Names which are not marked as being a MIME name should not be used in
+# Internet protocols for information interchange (mail, news, etc.).
+#
+# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
+# must understand both names and treat them as equivalent.
+#
+# The first argument passed to this file is the canonical host specification,
+#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+
+host="$1"
+os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
+echo "# This file contains a table of character encoding aliases,"
+echo "# suitable for operating system '${os}'."
+echo "# It was automatically generated from config.charset."
+# List of references, updated during installation:
+echo "# Packages using this file: "
+case "$os" in
+    linux* | *-gnu*)
+	# With glibc-2.1 or newer, we don't need any canonicalization,
+	# because glibc has iconv and both glibc and libiconv support all
+	# GNU canonical names directly. Therefore, the Makefile does not
+	# need to install the alias file at all.
+	# The following applies only to glibc-2.0.x and older libcs.
+	echo "ISO_646.IRV:1983 ASCII"
+	;;
+    aix*)
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-6 ISO-8859-6"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-8 ISO-8859-8"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "IBM-850 CP850"
+	echo "IBM-856 CP856"
+	echo "IBM-921 ISO-8859-13"
+	echo "IBM-922 CP922"
+	echo "IBM-932 CP932"
+	echo "IBM-943 CP943"
+	echo "IBM-1046 CP1046"
+	echo "IBM-1124 CP1124"
+	echo "IBM-1129 CP1129"
+	echo "IBM-1252 CP1252"
+	echo "IBM-eucCN GB2312"
+	echo "IBM-eucJP EUC-JP"
+	echo "IBM-eucKR EUC-KR"
+	echo "IBM-eucTW EUC-TW"
+	echo "big5 BIG5"
+	echo "GBK GBK"
+	echo "TIS-620 TIS-620"
+	echo "UTF-8 UTF-8"
+	;;
+    hpux*)
+	echo "iso88591 ISO-8859-1"
+	echo "iso88592 ISO-8859-2"
+	echo "iso88595 ISO-8859-5"
+	echo "iso88596 ISO-8859-6"
+	echo "iso88597 ISO-8859-7"
+	echo "iso88598 ISO-8859-8"
+	echo "iso88599 ISO-8859-9"
+	echo "iso885915 ISO-8859-15"
+	echo "roman8 HP-ROMAN8"
+	echo "arabic8 HP-ARABIC8"
+	echo "greek8 HP-GREEK8"
+	echo "hebrew8 HP-HEBREW8"
+	echo "turkish8 HP-TURKISH8"
+	echo "kana8 HP-KANA8"
+	echo "tis620 TIS-620"
+	echo "big5 BIG5"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	echo "hp15CN GB2312"
+	#echo "ccdc ?" # what is this?
+	echo "SJIS SHIFT_JIS"
+	echo "utf8 UTF-8"
+	;;
+    irix*)
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "eucCN GB2312"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	;;
+    osf*)
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-4 ISO-8859-4"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-8 ISO-8859-8"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "cp850 CP850"
+	echo "big5 BIG5"
+	echo "dechanyu DEC-HANYU"
+	echo "dechanzi GB2312"
+	echo "deckanji DEC-KANJI"
+	echo "deckorean EUC-KR"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	echo "GBK GBK"
+	echo "KSC5601 CP949"
+	echo "sdeckanji EUC-JP"
+	echo "SJIS SHIFT_JIS"
+	echo "TACTIS TIS-620"
+	echo "UTF-8 UTF-8"
+	;;
+    solaris*)
+	echo "646 ASCII"
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-3 ISO-8859-3"
+	echo "ISO8859-4 ISO-8859-4"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-6 ISO-8859-6"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-8 ISO-8859-8"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "koi8-r KOI8-R"
+	echo "ansi-1251 CP1251"
+	echo "BIG5 BIG5"
+	echo "Big5-HKSCS BIG5-HKSCS"
+	echo "gb2312 GB2312"
+	echo "GBK GBK"
+	echo "GB18030 GB18030"
+	echo "cns11643 EUC-TW"
+	echo "5601 EUC-KR"
+	echo "ko_KR.johap92 JOHAB"
+	echo "eucJP EUC-JP"
+	echo "PCK SHIFT_JIS"
+	echo "TIS620.2533 TIS-620"
+	#echo "sun_eu_greek ?" # what is this?
+	echo "UTF-8 UTF-8"
+	;;
+    freebsd* | os2*)
+	# FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
+	# localcharset.c falls back to using the full locale name
+	# from the environment variables.
+	# Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just
+	# reuse FreeBSD's locale data for OS/2.
+	echo "C ASCII"
+	echo "US-ASCII ASCII"
+	for l in la_LN lt_LN; do
+	  echo "$l.ASCII ASCII"
+	done
+	for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+	         fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
+	         lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
+	  echo "$l.ISO_8859-1 ISO-8859-1"
+	  echo "$l.DIS_8859-15 ISO-8859-15"
+	done
+	for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
+	  echo "$l.ISO_8859-2 ISO-8859-2"
+	done
+	for l in la_LN lt_LT; do
+	  echo "$l.ISO_8859-4 ISO-8859-4"
+	done
+	for l in ru_RU ru_SU; do
+	  echo "$l.KOI8-R KOI8-R"
+	  echo "$l.ISO_8859-5 ISO-8859-5"
+	  echo "$l.CP866 CP866"
+	done
+	echo "uk_UA.KOI8-U KOI8-U"
+	echo "zh_TW.BIG5 BIG5"
+	echo "zh_TW.Big5 BIG5"
+	echo "zh_CN.EUC GB2312"
+	echo "ja_JP.EUC EUC-JP"
+	echo "ja_JP.SJIS SHIFT_JIS"
+	echo "ja_JP.Shift_JIS SHIFT_JIS"
+	echo "ko_KR.EUC EUC-KR"
+	;;
+    netbsd*)
+	echo "646 ASCII"
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-4 ISO-8859-4"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "eucCN GB2312"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	echo "BIG5 BIG5"
+	echo "SJIS SHIFT_JIS"
+	;;
+    beos*)
+	# BeOS has a single locale, and it has UTF-8 encoding.
+	echo "* UTF-8"
+	;;
+    msdosdjgpp*)
+	# DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
+	# localcharset.c falls back to using the full locale name
+	# from the environment variables.
+	echo "#"
+	echo "# The encodings given here may not all be correct."
+	echo "# If you find that the encoding given for your language and"
+	echo "# country is not the one your DOS machine actually uses, just"
+	echo "# correct it in this file, and send a mail to"
+	echo "# Juan Manuel Guerrero <st001906@hrz1.hrz.tu-darmstadt.de>"
+	echo "# and Bruno Haible <bruno@clisp.org>."
+	echo "#"
+	echo "C ASCII"
+	# ISO-8859-1 languages
+	echo "ca CP850"
+	echo "ca_ES CP850"
+	echo "da CP865"    # not CP850 ??
+	echo "da_DK CP865" # not CP850 ??
+	echo "de CP850"
+	echo "de_AT CP850"
+	echo "de_CH CP850"
+	echo "de_DE CP850"
+	echo "en CP850"
+	echo "en_AU CP850" # not CP437 ??
+	echo "en_CA CP850"
+	echo "en_GB CP850"
+	echo "en_NZ CP437"
+	echo "en_US CP437"
+	echo "en_ZA CP850" # not CP437 ??
+	echo "es CP850"
+	echo "es_AR CP850"
+	echo "es_BO CP850"
+	echo "es_CL CP850"
+	echo "es_CO CP850"
+	echo "es_CR CP850"
+	echo "es_CU CP850"
+	echo "es_DO CP850"
+	echo "es_EC CP850"
+	echo "es_ES CP850"
+	echo "es_GT CP850"
+	echo "es_HN CP850"
+	echo "es_MX CP850"
+	echo "es_NI CP850"
+	echo "es_PA CP850"
+	echo "es_PY CP850"
+	echo "es_PE CP850"
+	echo "es_SV CP850"
+	echo "es_UY CP850"
+	echo "es_VE CP850"
+	echo "et CP850"
+	echo "et_EE CP850"
+	echo "eu CP850"
+	echo "eu_ES CP850"
+	echo "fi CP850"
+	echo "fi_FI CP850"
+	echo "fr CP850"
+	echo "fr_BE CP850"
+	echo "fr_CA CP850"
+	echo "fr_CH CP850"
+	echo "fr_FR CP850"
+	echo "ga CP850"
+	echo "ga_IE CP850"
+	echo "gd CP850"
+	echo "gd_GB CP850"
+	echo "gl CP850"
+	echo "gl_ES CP850"
+	echo "id CP850"    # not CP437 ??
+	echo "id_ID CP850" # not CP437 ??
+	echo "is CP861"    # not CP850 ??
+	echo "is_IS CP861" # not CP850 ??
+	echo "it CP850"
+	echo "it_CH CP850"
+	echo "it_IT CP850"
+	echo "lt CP775"
+	echo "lt_LT CP775"
+	echo "lv CP775"
+	echo "lv_LV CP775"
+	echo "nb CP865"    # not CP850 ??
+	echo "nb_NO CP865" # not CP850 ??
+	echo "nl CP850"
+	echo "nl_BE CP850"
+	echo "nl_NL CP850"
+	echo "nn CP865"    # not CP850 ??
+	echo "nn_NO CP865" # not CP850 ??
+	echo "no CP865"    # not CP850 ??
+	echo "no_NO CP865" # not CP850 ??
+	echo "pt CP850"
+	echo "pt_BR CP850"
+	echo "pt_PT CP850"
+	echo "sv CP850"
+	echo "sv_SE CP850"
+	# ISO-8859-2 languages
+	echo "cs CP852"
+	echo "cs_CZ CP852"
+	echo "hr CP852"
+	echo "hr_HR CP852"
+	echo "hu CP852"
+	echo "hu_HU CP852"
+	echo "pl CP852"
+	echo "pl_PL CP852"
+	echo "ro CP852"
+	echo "ro_RO CP852"
+	echo "sk CP852"
+	echo "sk_SK CP852"
+	echo "sl CP852"
+	echo "sl_SI CP852"
+	echo "sq CP852"
+	echo "sq_AL CP852"
+	echo "sr CP852"    # CP852 or CP866 or CP855 ??
+	echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
+	# ISO-8859-3 languages
+	echo "mt CP850"
+	echo "mt_MT CP850"
+	# ISO-8859-5 languages
+	echo "be CP866"
+	echo "be_BE CP866"
+	echo "bg CP866"    # not CP855 ??
+	echo "bg_BG CP866" # not CP855 ??
+	echo "mk CP866"    # not CP855 ??
+	echo "mk_MK CP866" # not CP855 ??
+	echo "ru CP866"
+	echo "ru_RU CP866"
+	echo "uk CP1125"
+	echo "uk_UA CP1125"
+	# ISO-8859-6 languages
+	echo "ar CP864"
+	echo "ar_AE CP864"
+	echo "ar_DZ CP864"
+	echo "ar_EG CP864"
+	echo "ar_IQ CP864"
+	echo "ar_IR CP864"
+	echo "ar_JO CP864"
+	echo "ar_KW CP864"
+	echo "ar_MA CP864"
+	echo "ar_OM CP864"
+	echo "ar_QA CP864"
+	echo "ar_SA CP864"
+	echo "ar_SY CP864"
+	# ISO-8859-7 languages
+	echo "el CP869"
+	echo "el_GR CP869"
+	# ISO-8859-8 languages
+	echo "he CP862"
+	echo "he_IL CP862"
+	# ISO-8859-9 languages
+	echo "tr CP857"
+	echo "tr_TR CP857"
+	# Japanese
+	echo "ja CP932"
+	echo "ja_JP CP932"
+	# Chinese
+	echo "zh_CN GBK"
+	echo "zh_TW CP950" # not CP938 ??
+	# Korean
+	echo "kr CP949"    # not CP934 ??
+	echo "kr_KR CP949" # not CP934 ??
+	# Thai
+	echo "th CP874"
+	echo "th_TH CP874"
+	# Other
+	echo "eo CP850"
+	echo "eo_EO CP850"
+	;;
+esac

+ 59 - 0
intl/dcgettext.c

@@ -0,0 +1,59 @@
+/* Implementation of the dcgettext(3) function.
+   Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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 (domainname, msgid, category)
+     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.  */
+INTDEF(__dcgettext)
+weak_alias (__dcgettext, dcgettext);
+#endif

+ 1238 - 0
intl/dcigettext.c

@@ -0,0 +1,1238 @@
+/* Implementation of the internal dcigettext function.
+   Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* 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
+
+#include "gettextP.h"
+#include "plural-exp.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "hash-string.h"
+
+/* Thread safetyness.  */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_lock_define_initialized(CLASS, NAME)
+# define __libc_lock_lock(NAME)
+# define __libc_lock_unlock(NAME)
+# define __libc_rwlock_define_initialized(CLASS, NAME)
+# define __libc_rwlock_rdlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#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
+
+/* 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
+# define _nl_default_dirname libintl_nl_default_dirname
+# define _nl_domain_bindings libintl_nl_domain_bindings
+#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 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
+char *getcwd ();
+# endif
+# ifndef HAVE_STPCPY
+static char *stpcpy PARAMS ((char *dest, const char *src));
+# endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
+# endif
+#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 __EMX__ || defined __DJGPP__
+  /* Win32, 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
+
+/* This is the type used for the search tree where known translations
+   are stored.  */
+struct known_translation_t
+{
+  /* Domain in which to search.  */
+  char *domainname;
+
+  /* The category.  */
+  int category;
+
+  /* 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.  */
+  char msgid[ZERO];
+};
+
+/* Root of the search tree with known translations.  We can use this
+   only if the system provides the `tsearch' function family.  */
+#if defined HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+
+static void *root;
+
+# ifdef _LIBC
+#  define tsearch __tsearch
+# endif
+
+/* Function to compare two entries in the table of known translations.  */
+static int transcmp PARAMS ((const void *p1, const void *p2));
+static int
+transcmp (p1, p2)
+     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->msgid, s2->msgid);
+  if (result == 0)
+    {
+      result = strcmp (s1->domainname, s2->domainname);
+      if (result == 0)
+	/* 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;
+}
+#endif
+
+#ifndef INTVARDEF
+# define INTVARDEF(name)
+#endif
+#ifndef INTUSE
+# define INTUSE(name) name
+#endif
+
+/* 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";
+
+/* Value used as the default domain for gettext(3).  */
+const char *_nl_current_default_domain attribute_hidden
+     = _nl_default_default_domain;
+
+/* Contains the default location of the message catalogs.  */
+#if defined __EMX__
+extern const char _nl_default_dirname[];
+#else
+const char _nl_default_dirname[] = LOCALEDIR;
+INTVARDEF (_nl_default_dirname)
+#endif
+
+/* List with bindings of specific domains created by bindtextdomain()
+   calls.  */
+struct binding *_nl_domain_bindings;
+
+/* Prototypes for local functions.  */
+static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
+				    unsigned long int n,
+				    const char *translation,
+				    size_t translation_len))
+     internal_function;
+static const char *guess_category_value PARAMS ((int category,
+						 const char *categoryname))
+     internal_function;
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# define category_to_name(category)	_nl_category_names[category]
+#else
+static const char *category_to_name PARAMS ((int category)) internal_function;
+#endif
+
+
+/* For those loosing 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.  */
+#ifdef _LIBC
+__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
+#endif
+
+/* 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.  */
+char *
+DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     int plural;
+     unsigned long int n;
+     int category;
+{
+#ifndef HAVE_ALLOCA
+  struct block_list *block_list = NULL;
+#endif
+  struct loaded_l10nfile *domain;
+  struct binding *binding;
+  const char *categoryname;
+  const char *categoryvalue;
+  char *dirname, *xdomainname;
+  char *single_locale;
+  char *retval;
+  size_t retlen;
+  int saved_errno;
+#if defined HAVE_TSEARCH || defined _LIBC
+  struct known_translation_t *search;
+  struct known_translation_t **foundp = NULL;
+  size_t msgid_len;
+#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
+
+  __libc_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
+
+#if defined HAVE_TSEARCH || defined _LIBC
+  msgid_len = strlen (msgid1) + 1;
+
+  /* Try to find the translation among those which we found at
+     some time.  */
+  search = (struct known_translation_t *)
+	   alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
+  memcpy (search->msgid, msgid1, msgid_len);
+  search->domainname = (char *) domainname;
+  search->category = category;
+
+  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+  freea (search);
+  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;
+
+      __libc_rwlock_unlock (_nl_state_lock);
+      return retval;
+    }
+#endif
+
+  /* Preserve the `errno' value.  */
+  saved_errno = errno;
+
+  /* See whether this is a SUID binary or not.  */
+  DETERMINE_SECURE;
+
+  /* First find matching binding.  */
+  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 = (char *) INTUSE(_nl_default_dirname);
+  else if (IS_ABSOLUTE_PATH (binding->dirname))
+    dirname = binding->dirname;
+  else
+    {
+      /* We have a relative path.  Make it absolute now.  */
+      size_t dirname_len = strlen (binding->dirname) + 1;
+      size_t path_max;
+      char *ret;
+
+      path_max = (unsigned int) PATH_MAX;
+      path_max += 2;		/* The getcwd docs say to do this.  */
+
+      for (;;)
+	{
+	  dirname = (char *) alloca (path_max + dirname_len);
+	  ADD_BLOCK (block_list, dirname);
+
+	  __set_errno (0);
+	  ret = getcwd (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 (dirname, '\0'), "/"), binding->dirname);
+    }
+
+  /* Now determine the symbolic name of CATEGORY and its value.  */
+  categoryname = category_to_name (category);
+  categoryvalue = guess_category_value (category, categoryname);
+
+  domainname_len = strlen (domainname);
+  xdomainname = (char *) alloca (strlen (categoryname)
+				 + domainname_len + 5);
+  ADD_BLOCK (block_list, xdomainname);
+
+  stpcpy (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)
+	{
+	  retval = _nl_find_msg (domain, binding, msgid1, &retlen);
+
+	  if (retval == NULL)
+	    {
+	      int cnt;
+
+	      for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
+		{
+		  retval = _nl_find_msg (domain->successor[cnt], binding,
+					 msgid1, &retlen);
+
+		  if (retval != NULL)
+		    {
+		      domain = domain->successor[cnt];
+		      break;
+		    }
+		}
+	    }
+
+	  if (retval != NULL)
+	    {
+	      /* Found the translation of MSGID1 in domain DOMAIN:
+		 starting at RETVAL, RETLEN bytes.  */
+	      FREE_BLOCKS (block_list);
+#if defined HAVE_TSEARCH || defined _LIBC
+	      if (foundp == NULL)
+		{
+		  /* Create a new entry and add it to the search tree.  */
+		  struct known_translation_t *newp;
+
+		  newp = (struct known_translation_t *)
+		    malloc (offsetof (struct known_translation_t, msgid)
+			    + msgid_len + domainname_len + 1);
+		  if (newp != NULL)
+		    {
+		      newp->domainname =
+			mempcpy (newp->msgid, msgid1, msgid_len);
+		      memcpy (newp->domainname, domainname, domainname_len + 1);
+		      newp->category = category;
+		      newp->counter = _nl_msg_cat_cntr;
+		      newp->domain = domain;
+		      newp->translation = retval;
+		      newp->translation_length = retlen;
+
+		      /* Insert the entry in the search tree.  */
+		      foundp = (struct known_translation_t **)
+			tsearch (newp, &root, transcmp);
+		      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;
+		}
+#endif
+	      __set_errno (saved_errno);
+
+	      /* Now deal with plural.  */
+	      if (plural)
+		retval = plural_lookup (domain, n, retval, retlen);
+
+	      __libc_rwlock_unlock (_nl_state_lock);
+	      return retval;
+	    }
+	}
+    }
+
+ return_untranslated:
+  /* Return the untranslated MSGID.  */
+  FREE_BLOCKS (block_list);
+  __libc_rwlock_unlock (_nl_state_lock);
+#ifndef _LIBC
+  if (!ENABLE_SECURE)
+    {
+      extern void _nl_log_untranslated PARAMS ((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);
+}
+
+
+char *
+internal_function
+_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
+     struct loaded_l10nfile *domain_file;
+     struct binding *domainbinding;
+     const char *msgid;
+     size_t *lengthp;
+{
+  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
+  if (domain->codeset_cntr
+      != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
+    {
+      /* The domain's codeset has changed through bind_textdomain_codeset()
+	 since the message catalog was initialized or last accessed.  We
+	 have to reinitialize the converter.  */
+      _nl_free_domain_conv (domain);
+      _nl_init_domain_conv (domain_file, domain, domainbinding);
+    }
+
+  if (
+# ifdef _LIBC
+      domain->conv != (__gconv_t) -1
+# else
+#  if HAVE_ICONV
+      domain->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.  */
+
+      if (domain->conv_tab == NULL
+	  && ((domain->conv_tab =
+		 (char **) calloc (nstrings + domain->n_sysdep_strings,
+				   sizeof (char *)))
+	      == NULL))
+	/* Mark that we didn't succeed allocating a table.  */
+	domain->conv_tab = (char **) -1;
+
+      if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
+	/* Nothing we can do, no more memory.  */
+	goto converted;
+
+      if (domain->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.   */
+	  __libc_lock_define_initialized (static, lock)
+# 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 = NULL;
+# endif
+
+	  __libc_lock_lock (lock);
+
+	  inbuf = (const unsigned char *) result;
+	  outbuf = freemem + sizeof (size_t);
+
+	  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 (domain->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)
+		{
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+
+	      inbuf = 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 (domain->conv,
+			 (ICONV_CONST char **) &inptr, &inleft,
+			 &outptr, &outleft)
+		  != (size_t) (-1))
+		{
+		  outbuf = (unsigned char *) outptr;
+		  break;
+		}
+	      if (errno != E2BIG)
+		{
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+#  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 = transmem_list->next;
+		  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);
+		}
+	      if (__builtin_expect (newmem == NULL, 0))
+		{
+		  freemem = NULL;
+		  freemem_size = 0;
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+
+# ifdef _LIBC
+	      /* Add the block to the list of blocks we have to free
+                 at some point.  */
+	      newmem->next = transmem_list;
+	      transmem_list = newmem;
+
+	      freemem = 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);
+	  domain->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 domain->conv_tab[act] contains the translation of all
+	 the plural variants.  */
+      result = domain->conv_tab[act] + sizeof (size_t);
+      resultlen = *(size_t *) domain->conv_tab[act];
+    }
+
+ converted:
+  /* The result string is converted.  */
+
+#endif /* _LIBC || HAVE_ICONV */
+
+  *lengthp = resultlen;
+  return result;
+}
+
+
+/* Look up a plural variant.  */
+static char *
+internal_function
+plural_lookup (domain, n, translation, translation_len)
+     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 (category)
+     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.  */
+static const char *
+internal_function
+guess_category_value (category, categoryname)
+     int category;
+     const char *categoryname;
+{
+  const char *language;
+  const char *retval;
+
+  /* The highest priority value is the `LANGUAGE' environment
+     variable.  But we don't use the value if the currently selected
+     locale is the C locale.  This is a GNU extension.  */
+  language = getenv ("LANGUAGE");
+  if (language != NULL && language[0] == '\0')
+    language = NULL;
+
+  /* We have to proceed with the POSIX methods of looking to `LC_ALL',
+     `LC_xxx', and `LANG'.  On some systems this can be done by the
+     `setlocale' function itself.  */
+#ifdef _LIBC
+  retval = __current_locale_name (category);
+#else
+  retval = _nl_locale_name (category, categoryname);
+#endif
+
+  /* Ignore LANGUAGE 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".  We allow such programs to use gettext().  */
+  return language != NULL && strcmp (retval, "C") != 0 ? language : 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 (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif
+
+#if !_LIBC && !HAVE_MEMPCPY
+static void *
+mempcpy (dest, src, n)
+     void *dest;
+     const void *src;
+     size_t n;
+{
+  return (void *) ((char *) memcpy (dest, src, n) + n);
+}
+#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 != INTUSE(_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

+ 60 - 0
intl/dcngettext.c

@@ -0,0 +1,60 @@
+/* Implementation of the dcngettext(3) function.
+   Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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 (domainname, msgid1, msgid2, n, category)
+     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

+ 59 - 0
intl/dgettext.c

@@ -0,0 +1,59 @@
+/* Implementation of the dgettext(3) function.
+   Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <locale.h>
+
+#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 DGETTEXT __dgettext
+# define DCGETTEXT INTUSE(__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 (domainname, msgid)
+     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

+ 61 - 0
intl/dngettext.c

@@ -0,0 +1,61 @@
+/* Implementation of the dngettext(3) function.
+   Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <locale.h>
+
+#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 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 (domainname, msgid1, msgid2, n)
+     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

+ 114 - 0
intl/eval-plural.h

@@ -0,0 +1,114 @@
+/* Plural expression evaluation.
+   Copyright (C) 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+/* Evaluate the plural expression and return an index value.  */
+STATIC unsigned long int plural_eval PARAMS ((struct expression *pexp,
+					      unsigned long int n))
+     internal_function;
+
+STATIC
+unsigned long int
+internal_function
+plural_eval (pexp, n)
+     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;
+}

+ 192 - 0
intl/explodename.c

@@ -0,0 +1,192 @@
+/* Copyright (C) 1995-1998, 2000, 2001 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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 @@ */
+
+char *
+_nl_find_language (name)
+     const char *name;
+{
+  while (name[0] != '\0' && name[0] != '_' && name[0] != '@'
+	 && name[0] != '+' && name[0] != ',')
+    ++name;
+
+  return (char *) name;
+}
+
+
+int
+_nl_explode_name (name, language, modifier, territory, codeset,
+		  normalized_codeset, special, sponsor, revision)
+     char *name;
+     const char **language;
+     const char **modifier;
+     const char **territory;
+     const char **codeset;
+     const char **normalized_codeset;
+     const char **special;
+     const char **sponsor;
+     const char **revision;
+{
+  enum { undecided, xpg, cen } syntax;
+  char *cp;
+  int mask;
+
+  *modifier = NULL;
+  *territory = NULL;
+  *codeset = NULL;
+  *normalized_codeset = NULL;
+  *special = NULL;
+  *sponsor = NULL;
+  *revision = NULL;
+
+  /* Now we determine the single parts of the locale name.  First
+     look for the language.  Termination symbols are `_' and `@' if
+     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
+  mask = 0;
+  syntax = undecided;
+  *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[0] != '+' && cp[0] != ',' && cp[0] != '_')
+	++cp;
+
+      mask |= TERRITORY;
+
+      if (cp[0] == '.')
+	{
+	  /* Next is the codeset.  */
+	  syntax = xpg;
+	  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 (strcmp (*codeset, *normalized_codeset) == 0)
+		free ((char *) *normalized_codeset);
+	      else
+		mask |= XPG_NORM_CODESET;
+	    }
+	}
+    }
+
+  if (cp[0] == '@' || (syntax != xpg && cp[0] == '+'))
+    {
+      /* Next is the modifier.  */
+      syntax = cp[0] == '@' ? xpg : cen;
+      cp[0] = '\0';
+      *modifier = ++cp;
+
+      while (syntax == cen && cp[0] != '\0' && cp[0] != '+'
+	     && cp[0] != ',' && cp[0] != '_')
+	++cp;
+
+      mask |= XPG_MODIFIER | CEN_AUDIENCE;
+    }
+
+  if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_'))
+    {
+      syntax = cen;
+
+      if (cp[0] == '+')
+	{
+ 	  /* Next is special application (CEN syntax).  */
+	  cp[0] = '\0';
+	  *special = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_')
+	    ++cp;
+
+	  mask |= CEN_SPECIAL;
+	}
+
+      if (cp[0] == ',')
+	{
+ 	  /* Next is sponsor (CEN syntax).  */
+	  cp[0] = '\0';
+	  *sponsor = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != '_')
+	    ++cp;
+
+	  mask |= CEN_SPONSOR;
+	}
+
+      if (cp[0] == '_')
+	{
+ 	  /* Next is revision (CEN syntax).  */
+	  cp[0] = '\0';
+	  *revision = ++cp;
+
+	  mask |= CEN_REVISION;
+	}
+    }
+
+  /* For CEN syntax values it might be important to have the
+     separator character in the file name, not for XPG syntax.  */
+  if (syntax == xpg)
+    {
+      if (*territory != NULL && (*territory)[0] == '\0')
+	mask &= ~TERRITORY;
+
+      if (*codeset != NULL && (*codeset)[0] == '\0')
+	mask &= ~XPG_CODESET;
+
+      if (*modifier != NULL && (*modifier)[0] == '\0')
+	mask &= ~XPG_MODIFIER;
+    }
+
+  return mask;
+}

+ 195 - 0
intl/finddomain.c

@@ -0,0 +1,195 @@
+/* Handle list of needed message catalogs
+   Copyright (C) 1995-1999, 2000, 2001 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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
+
+/* @@ 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 (dirname, locale, domainname, domainbinding)
+     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 *special;
+  const char *sponsor;
+  const char *revision;
+  const char *alias_value;
+  int mask;
+
+  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
+
+		language[_territory[.codeset]][@modifier]
+
+     and six parts for the CEN syntax:
+
+	language[_territory][+audience][+special][,[sponsor][_revision]]
+
+     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) revision
+		(2) sponsor
+		(3) special
+		(4) codeset
+		(5) normalized codeset
+		(6) territory
+		(7) audience/modifier
+   */
+
+  /* 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, NULL, NULL, NULL, domainname, 0);
+  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 cnt >= 0 ? retval : NULL;
+      /* 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)
+    {
+#if defined _LIBC || defined HAVE_STRDUP
+      locale = strdup (alias_value);
+      if (locale == NULL)
+	return NULL;
+#else
+      size_t len = strlen (alias_value) + 1;
+      locale = (char *) malloc (len);
+      if (locale == NULL)
+	return NULL;
+
+      memcpy (locale, alias_value, len);
+#endif
+    }
+
+  /* Now we determine the single parts of the locale name.  First
+     look for the language.  Termination symbols are `_' and `@' if
+     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
+  mask = _nl_explode_name (locale, &language, &modifier, &territory,
+			   &codeset, &normalized_codeset, &special,
+			   &sponsor, &revision);
+
+  /* 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, special,
+			       sponsor, revision, domainname, 1);
+  if (retval == NULL)
+    /* This means we are out of core.  */
+    return NULL;
+
+  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);
+
+  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
+  if (mask & XPG_NORM_CODESET)
+    free ((void *) normalized_codeset);
+
+  return retval;
+}
+
+
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+  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

+ 64 - 0
intl/gettext.c

@@ -0,0 +1,64 @@
+/* Implementation of gettext(3) function.
+   Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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 INTUSE(__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 (msgid)
+     const char *msgid;
+{
+  return DCGETTEXT (NULL, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__gettext, gettext);
+#endif

+ 224 - 0
intl/gettextP.h

@@ -0,0 +1,224 @@
+/* Header describing internals of libintl library.
+   Copyright (C) 1995-1999, 2000-2003 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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
+
+#include "loadinfo.h"
+
+#include "gmo.h"		/* Get nls_uint32.  */
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#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
+SWAP (i)
+     nls_uint32 i;
+{
+  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;
+};
+
+/* 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;
+
+  int codeset_cntr;
+#ifdef _LIBC
+  __gconv_t conv;
+#else
+# if HAVE_ICONV
+  iconv_t conv;
+# endif
+#endif
+  char **conv_tab;
+
+  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;
+  int codeset_cntr;	/* Incremented each time codeset changes.  */
+  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.  */
+extern int _nl_msg_cat_cntr;
+
+#ifndef _LIBC
+const char *_nl_locale_name PARAMS ((int category, const char *categoryname));
+#endif
+
+struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
+						 char *__locale,
+						 const char *__domainname,
+					      struct binding *__domainbinding))
+     internal_function;
+void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain,
+			      struct binding *__domainbinding))
+     internal_function;
+void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
+     internal_function;
+const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file,
+					  struct loaded_domain *__domain,
+					  struct binding *__domainbinding))
+     internal_function;
+void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain))
+     internal_function;
+
+char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
+			    struct binding *domainbinding,
+			    const char *msgid, size_t *lengthp))
+     internal_function;
+
+#ifdef _LIBC
+extern char *__gettext PARAMS ((const char *__msgid));
+extern char *__dgettext PARAMS ((const char *__domainname,
+				 const char *__msgid));
+extern char *__dcgettext PARAMS ((const char *__domainname,
+				  const char *__msgid, int __category));
+extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2,
+				 unsigned long int __n));
+extern char *__dngettext PARAMS ((const char *__domainname,
+				  const char *__msgid1, const char *__msgid2,
+				  unsigned long int n));
+extern char *__dcngettext PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   unsigned long int __n, int __category));
+extern char *__dcigettext PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   int __plural, unsigned long int __n,
+				   int __category));
+extern char *__textdomain PARAMS ((const char *__domainname));
+extern char *__bindtextdomain PARAMS ((const char *__domainname,
+				       const char *__dirname));
+extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname,
+						const char *__codeset));
+#else
+/* Declare the exported libintl_* functions, in a way that allows us to
+   call them under their real name.  */
+# define _INTL_REDIRECT_MACROS
+# include "libgnuintl.h"
+extern char *libintl_dcigettext PARAMS ((const char *__domainname,
+					 const char *__msgid1,
+					 const char *__msgid2,
+					 int __plural, unsigned long int __n,
+					 int __category));
+#endif
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettextP.h  */

+ 148 - 0
intl/gmo.h

@@ -0,0 +1,148 @@
+/* Description of GNU message catalog format: general file layout.
+   Copyright (C) 1995, 1997, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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
+
+/* 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.  */
+
+  /* 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;
+};
+
+/* 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
+  {
+    /* Size of static segment.  */
+    nls_uint32 segsize;
+    /* Reference to system dependent string segment, or ~0 at the end.  */
+    nls_uint32 sysdepref;
+  } 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  */

+ 59 - 0
intl/hash-string.h

@@ -0,0 +1,59 @@
+/* Description of GNU message catalog format: string hashing function.
+   Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+#endif
+
+/* We assume to have `unsigned long int' value with at least 32 bits.  */
+#define HASHWORDBITS 32
+
+
+/* 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.]  */
+static unsigned long int hash_string PARAMS ((const char *__str_param));
+
+static inline unsigned long int
+hash_string (str_param)
+     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 long int) *str++;
+      g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+      if (g != 0)
+	{
+	  hval ^= g >> (HASHWORDBITS - 8);
+	  hval ^= g;
+	}
+    }
+  return hval;
+}

+ 151 - 0
intl/intl-compat.c

@@ -0,0 +1,151 @@
+/* intl-compat.c - Stub functions to call gettext functions from GNU gettext
+   Library.
+   Copyright (C) 1995, 2000-2003 Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+
+/* @@ end of prolog @@ */
+
+/* This file redirects the gettext functions (without prefix) to those
+   defined in the included GNU libintl library (with "libintl_" prefix).
+   It is compiled into libintl in order to make the AM_GNU_GETTEXT test
+   of gettext <= 0.11.2 work with the libintl library >= 0.11.3 which
+   has the redirections primarily in the <libintl.h> include file.
+   It is also compiled into libgnuintl so that libgnuintl.so can be used
+   as LD_PRELOADable library on glibc systems, to provide the extra
+   features that the functions in the libc don't have (namely, logging).  */
+
+
+#undef gettext
+#undef dgettext
+#undef dcgettext
+#undef ngettext
+#undef dngettext
+#undef dcngettext
+#undef textdomain
+#undef bindtextdomain
+#undef bind_textdomain_codeset
+
+
+/* When building a DLL, we must export some functions.  Note that because
+   the functions are only defined for binary backward compatibility, we
+   don't need to use __declspec(dllimport) in any case.  */
+#if defined _MSC_VER && BUILDING_DLL
+# define DLL_EXPORTED __declspec(dllexport)
+#else
+# define DLL_EXPORTED
+#endif
+
+
+DLL_EXPORTED
+char *
+gettext (msgid)
+     const char *msgid;
+{
+  return libintl_gettext (msgid);
+}
+
+
+DLL_EXPORTED
+char *
+dgettext (domainname, msgid)
+     const char *domainname;
+     const char *msgid;
+{
+  return libintl_dgettext (domainname, msgid);
+}
+
+
+DLL_EXPORTED
+char *
+dcgettext (domainname, msgid, category)
+     const char *domainname;
+     const char *msgid;
+     int category;
+{
+  return libintl_dcgettext (domainname, msgid, category);
+}
+
+
+DLL_EXPORTED
+char *
+ngettext (msgid1, msgid2, n)
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return libintl_ngettext (msgid1, msgid2, n);
+}
+
+
+DLL_EXPORTED
+char *
+dngettext (domainname, msgid1, msgid2, n)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return libintl_dngettext (domainname, msgid1, msgid2, n);
+}
+
+
+DLL_EXPORTED
+char *
+dcngettext (domainname, msgid1, msgid2, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+     int category;
+{
+  return libintl_dcngettext (domainname, msgid1, msgid2, n, category);
+}
+
+
+DLL_EXPORTED
+char *
+textdomain (domainname)
+     const char *domainname;
+{
+  return libintl_textdomain (domainname);
+}
+
+
+DLL_EXPORTED
+char *
+bindtextdomain (domainname, dirname)
+     const char *domainname;
+     const char *dirname;
+{
+  return libintl_bindtextdomain (domainname, dirname);
+}
+
+
+DLL_EXPORTED
+char *
+bind_textdomain_codeset (domainname, codeset)
+     const char *domainname;
+     const char *codeset;
+{
+  return libintl_bind_textdomain_codeset (domainname, codeset);
+}

+ 453 - 0
intl/l10nflist.c

@@ -0,0 +1,453 @@
+/* Copyright (C) 1995-1999, 2000, 2001, 2002 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* 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 PARAMS ((char *dest, const char *src));
+# endif
+#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.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, 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))
+#else
+  /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+#endif
+
+/* Define function which are usually not available.  */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
+/* Returns the number of strings in ARGZ.  */
+static size_t argz_count__ PARAMS ((const char *argz, size_t len));
+
+static size_t
+argz_count__ (argz, len)
+     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)
+#else
+# ifdef _LIBC
+#  define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
+# endif
+#endif	/* !_LIBC && !HAVE___ARGZ_COUNT */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+   except the last into the character SEP.  */
+static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
+
+static void
+argz_stringify__ (argz, len, sep)
+     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)
+#else
+# ifdef _LIBC
+#  define __argz_stringify(argz, len, sep) \
+  INTUSE(__argz_stringify) (argz, len, sep)
+# endif
+#endif	/* !_LIBC && !HAVE___ARGZ_STRINGIFY */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
+static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
+				  const char *entry));
+
+static char *
+argz_next__ (argz, argz_len, entry)
+     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.  */
+static int pop PARAMS ((int x));
+
+static inline int
+pop (x)
+     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;
+}
+
+
+struct loaded_l10nfile *
+_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
+		    territory, codeset, normalized_codeset, modifier, special,
+		    sponsor, revision, filename, do_allocate)
+     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 *special;
+     const char *sponsor;
+     const char *revision;
+     const char *filename;
+     int do_allocate;
+{
+  char *abs_filename;
+  struct loaded_l10nfile **lastp;
+  struct loaded_l10nfile *retval;
+  char *cp;
+  size_t dirlist_count;
+  size_t entries;
+  int cnt;
+
+  /* If LANGUAGE contains an absolute directory specification, we ignore
+     DIRLIST.  */
+  if (IS_ABSOLUTE_PATH (language))
+    dirlist_len = 0;
+
+  /* Allocate room for the full file name.  */
+  abs_filename = (char *) malloc (dirlist_len
+				  + strlen (language)
+				  + ((mask & 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
+				      || (mask & CEN_AUDIENCE) != 0)
+				     ? strlen (modifier) + 1 : 0)
+				  + ((mask & CEN_SPECIAL) != 0
+				     ? strlen (special) + 1 : 0)
+				  + (((mask & CEN_SPONSOR) != 0
+				      || (mask & CEN_REVISION) != 0)
+				     ? (1 + ((mask & CEN_SPONSOR) != 0
+					     ? strlen (sponsor) : 0)
+					+ ((mask & CEN_REVISION) != 0
+					   ? strlen (revision) + 1 : 0)) : 0)
+				  + 1 + strlen (filename) + 1);
+
+  if (abs_filename == NULL)
+    return NULL;
+
+  /* Construct file name.  */
+  cp = abs_filename;
+  if (dirlist_len > 0)
+    {
+      memcpy (cp, dirlist, dirlist_len);
+      __argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
+      cp += dirlist_len;
+      cp[-1] = '/';
+    }
+
+  cp = stpcpy (cp, language);
+
+  if ((mask & 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 | CEN_AUDIENCE)) != 0)
+    {
+      /* This component can be part of both syntaces but has different
+	 leading characters.  For CEN we use `+', else `@'.  */
+      *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
+      cp = stpcpy (cp, modifier);
+    }
+  if ((mask & CEN_SPECIAL) != 0)
+    {
+      *cp++ = '+';
+      cp = stpcpy (cp, special);
+    }
+  if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
+    {
+      *cp++ = ',';
+      if ((mask & CEN_SPONSOR) != 0)
+	cp = stpcpy (cp, sponsor);
+      if ((mask & CEN_REVISION) != 0)
+	{
+	  *cp++ = '_';
+	  cp = stpcpy (cp, revision);
+	}
+    }
+
+  *cp++ = '/';
+  stpcpy (cp, filename);
+
+  /* Look in list of already loaded domains whether it is already
+     available.  */
+  lastp = l10nfile_list;
+  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;
+	  }
+
+	lastp = &retval->next;
+      }
+
+  if (retval != NULL || do_allocate == 0)
+    {
+      free (abs_filename);
+      return retval;
+    }
+
+  dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
+
+  /* Allocate a new loaded_l10nfile.  */
+  retval =
+    (struct loaded_l10nfile *)
+    malloc (sizeof (*retval)
+	    + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
+	       * sizeof (struct loaded_l10nfile *)));
+  if (retval == NULL)
+    return NULL;
+
+  retval->filename = abs_filename;
+
+  /* We set retval->data to NULL here; it is filled in later.
+     Setting retval->decided to 1 here means that retval does not
+     correspond to a real file (dirlist_count > 1) or is not worth
+     looking up (if an unnormalized codeset was specified).  */
+  retval->decided = (dirlist_count > 1
+		     || ((mask & XPG_CODESET) != 0
+			 && (mask & XPG_NORM_CODESET) != 0));
+  retval->data = NULL;
+
+  retval->next = *lastp;
+  *lastp = retval;
+
+  entries = 0;
+  /* Recurse to fill the inheritance list of RETVAL.
+     If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL
+     entry does not correspond to a real file; retval->filename contains
+     colons.  In this case we loop across all elements of DIRLIST and
+     across all bit patterns dominated by MASK.
+     If the DIRLIST is a single directory or entirely redundant (i.e.
+     DIRLIST_COUNT == 1), we loop across all bit patterns dominated by
+     MASK, excluding MASK itself.
+     In either case, we loop down from MASK to 0.  This has the effect
+     that the extra bits in the locale name are dropped in this order:
+     first the modifier, then the territory, then the codeset, then the
+     normalized_codeset.  */
+  for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt)
+    if ((cnt & ~mask) == 0
+	&& ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
+	&& ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
+      {
+	if (dirlist_count > 1)
+	  {
+	    /* 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, special,
+				      sponsor, revision, filename, 1);
+	  }
+	else
+	  retval->successor[entries++]
+	    = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
+				  cnt, language, territory, codeset,
+				  normalized_codeset, modifier, special,
+				  sponsor, revision, 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 (codeset, name_len)
+     const char *codeset;
+     size_t name_len;
+{
+  int len = 0;
+  int only_digit = 1;
+  char *retval;
+  char *wp;
+  size_t cnt;
+
+  for (cnt = 0; cnt < name_len; ++cnt)
+    if (isalnum ((unsigned char) codeset[cnt]))
+      {
+	++len;
+
+	if (isalpha ((unsigned char) codeset[cnt]))
+	  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 ((unsigned char) codeset[cnt]))
+	  *wp++ = tolower ((unsigned char) codeset[cnt]);
+	else if (isdigit ((unsigned char) codeset[cnt]))
+	  *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 (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif

+ 309 - 0
intl/libgnuintl.h.in

@@ -0,0 +1,309 @@
+/* Message catalogs for internationalization.
+   Copyright (C) 1995-1997, 2000-2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef _LIBINTL_H
+#define _LIBINTL_H	1
+
+#include <locale.h>
+
+/* The LC_MESSAGES locale category is the category used by the functions
+   gettext() and dgettext().  It is specified in POSIX, but not in ANSI C.
+   On systems that don't define it, use an arbitrary value instead.
+   On Solaris, <locale.h> defines __LOCALE_H (or _LOCALE_H in Solaris 2.5)
+   then includes <libintl.h> (i.e. this file!) and then only defines
+   LC_MESSAGES.  To avoid a redefinition warning, don't define LC_MESSAGES
+   in this case.  */
+#if !defined LC_MESSAGES && !(defined __LOCALE_H || (defined _LOCALE_H && defined __sun))
+# define LC_MESSAGES 1729
+#endif
+
+/* 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)
+
+/* Resolve a platform specific conflict on DJGPP.  GNU gettext takes
+   precedence over _conio_gettext.  */
+#ifdef __DJGPP__
+# undef gettext
+#endif
+
+/* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers
+   used by programs.  Similarly, test __PROTOTYPES, not PROTOTYPES.  */
+#ifndef _INTL_PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define _INTL_PARAMS(args) args
+# else
+#  define _INTL_PARAMS(args) ()
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* We redirect the functions to those prefixed with "libintl_".  This is
+   necessary, because some systems define gettext/textdomain/... in the C
+   library (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer).
+   If we used the unprefixed names, there would be cases where the
+   definition in the C library would override the one in the libintl.so
+   shared library.  Recall that on ELF systems, the symbols are looked
+   up in the following order:
+     1. in the executable,
+     2. in the shared libraries specified on the link command line, in order,
+     3. in the dependencies of the shared libraries specified on the link
+        command line,
+     4. in the dlopen()ed shared libraries, in the order in which they were
+        dlopen()ed.
+   The definition in the C library would override the one in libintl.so if
+   either
+     * -lc is given on the link command line and -lintl isn't, or
+     * -lc is given on the link command line before -lintl, or
+     * libintl.so is a dependency of a dlopen()ed shared library but not
+       linked to the executable at link time.
+   Since Solaris gettext() behaves differently than GNU gettext(), this
+   would be unacceptable.
+
+   The redirection happens by default through macros in C, so that &gettext
+   is independent of the compilation unit, but through inline functions in
+   C++, in order not to interfere with the name mangling of class fields or
+   class methods called 'gettext'.  */
+
+/* The user can define _INTL_REDIRECT_INLINE or _INTL_REDIRECT_MACROS.
+   If he doesn't, we choose the method.  A third possible method is
+   _INTL_REDIRECT_ASM, supported only by GCC.  */
+#if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS)
+# if __GNUC__ >= 2 && !defined __APPLE_CC__ && (defined __STDC__ || defined __cplusplus)
+#  define _INTL_REDIRECT_ASM
+# else
+#  ifdef __cplusplus
+#   define _INTL_REDIRECT_INLINE
+#  else
+#   define _INTL_REDIRECT_MACROS
+#  endif
+# endif
+#endif
+/* Auxiliary macros.  */
+#ifdef _INTL_REDIRECT_ASM
+# define _INTL_ASM(cname) __asm__ (_INTL_ASMNAME (__USER_LABEL_PREFIX__, #cname))
+# define _INTL_ASMNAME(prefix,cnamestring) _INTL_STRINGIFY (prefix) cnamestring
+# define _INTL_STRINGIFY(prefix) #prefix
+#else
+# define _INTL_ASM(cname)
+#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).  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_gettext (const char *__msgid);
+static inline char *gettext (const char *__msgid)
+{
+  return libintl_gettext (__msgid);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define gettext libintl_gettext
+#endif
+extern char *gettext _INTL_PARAMS ((const char *__msgid))
+       _INTL_ASM (libintl_gettext);
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+   LC_MESSAGES locale.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dgettext (const char *__domainname, const char *__msgid);
+static inline char *dgettext (const char *__domainname, const char *__msgid)
+{
+  return libintl_dgettext (__domainname, __msgid);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dgettext libintl_dgettext
+#endif
+extern char *dgettext _INTL_PARAMS ((const char *__domainname,
+				     const char *__msgid))
+       _INTL_ASM (libintl_dgettext);
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dcgettext (const char *__domainname, const char *__msgid,
+				int __category);
+static inline char *dcgettext (const char *__domainname, const char *__msgid,
+			       int __category)
+{
+  return libintl_dcgettext (__domainname, __msgid, __category);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dcgettext libintl_dcgettext
+#endif
+extern char *dcgettext _INTL_PARAMS ((const char *__domainname,
+				      const char *__msgid,
+				      int __category))
+       _INTL_ASM (libintl_dcgettext);
+#endif
+
+
+/* Similar to `gettext' but select the plural form corresponding to the
+   number N.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_ngettext (const char *__msgid1, const char *__msgid2,
+			       unsigned long int __n);
+static inline char *ngettext (const char *__msgid1, const char *__msgid2,
+			      unsigned long int __n)
+{
+  return libintl_ngettext (__msgid1, __msgid2, __n);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define ngettext libintl_ngettext
+#endif
+extern char *ngettext _INTL_PARAMS ((const char *__msgid1,
+				     const char *__msgid2,
+				     unsigned long int __n))
+       _INTL_ASM (libintl_ngettext);
+#endif
+
+/* Similar to `dgettext' but select the plural form corresponding to the
+   number N.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dngettext (const char *__domainname, const char *__msgid1,
+				const char *__msgid2, unsigned long int __n);
+static inline char *dngettext (const char *__domainname, const char *__msgid1,
+			       const char *__msgid2, unsigned long int __n)
+{
+  return libintl_dngettext (__domainname, __msgid1, __msgid2, __n);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dngettext libintl_dngettext
+#endif
+extern char *dngettext _INTL_PARAMS ((const char *__domainname,
+				      const char *__msgid1,
+				      const char *__msgid2,
+				      unsigned long int __n))
+       _INTL_ASM (libintl_dngettext);
+#endif
+
+/* Similar to `dcgettext' but select the plural form corresponding to the
+   number N.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dcngettext (const char *__domainname,
+				 const char *__msgid1, const char *__msgid2,
+				 unsigned long int __n, int __category);
+static inline char *dcngettext (const char *__domainname,
+				const char *__msgid1, const char *__msgid2,
+				unsigned long int __n, int __category)
+{
+  return libintl_dcngettext (__domainname, __msgid1, __msgid2, __n, __category);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dcngettext libintl_dcngettext
+#endif
+extern char *dcngettext _INTL_PARAMS ((const char *__domainname,
+				       const char *__msgid1,
+				       const char *__msgid2,
+				       unsigned long int __n,
+				       int __category))
+       _INTL_ASM (libintl_dcngettext);
+#endif
+
+
+/* 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".  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_textdomain (const char *__domainname);
+static inline char *textdomain (const char *__domainname)
+{
+  return libintl_textdomain (__domainname);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define textdomain libintl_textdomain
+#endif
+extern char *textdomain _INTL_PARAMS ((const char *__domainname))
+       _INTL_ASM (libintl_textdomain);
+#endif
+
+/* Specify that the DOMAINNAME message catalog will be found
+   in DIRNAME rather than in the system locale data base.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_bindtextdomain (const char *__domainname,
+				     const char *__dirname);
+static inline char *bindtextdomain (const char *__domainname,
+				    const char *__dirname)
+{
+  return libintl_bindtextdomain (__domainname, __dirname);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define bindtextdomain libintl_bindtextdomain
+#endif
+extern char *bindtextdomain _INTL_PARAMS ((const char *__domainname,
+					   const char *__dirname))
+       _INTL_ASM (libintl_bindtextdomain);
+#endif
+
+/* Specify the character encoding in which the messages from the
+   DOMAINNAME message catalog will be returned.  */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_bind_textdomain_codeset (const char *__domainname,
+					      const char *__codeset);
+static inline char *bind_textdomain_codeset (const char *__domainname,
+					     const char *__codeset)
+{
+  return libintl_bind_textdomain_codeset (__domainname, __codeset);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define bind_textdomain_codeset libintl_bind_textdomain_codeset
+#endif
+extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname,
+						    const char *__codeset))
+       _INTL_ASM (libintl_bind_textdomain_codeset);
+#endif
+
+
+/* Support for relocatable packages.  */
+
+/* Sets the original and the current installation prefix of the package.
+   Relocation simply replaces a pathname starting with the original prefix
+   by the corresponding pathname with the current prefix instead.  Both
+   prefixes should be directory names without trailing slash (i.e. use ""
+   instead of "/").  */
+#define libintl_set_relocation_prefix libintl_set_relocation_prefix
+extern void
+       libintl_set_relocation_prefix _INTL_PARAMS ((const char *orig_prefix,
+						    const char *curr_prefix));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* libintl.h */

+ 156 - 0
intl/loadinfo.h

@@ -0,0 +1,156 @@
+/* Copyright (C) 1996-1999, 2000-2002 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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 PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#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 __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define PATH_SEPARATOR ';'
+#else
+  /* Unix */
+# define PATH_SEPARATOR ':'
+#endif
+
+/* Encoding of locale name parts.  */
+#define CEN_REVISION		1
+#define CEN_SPONSOR		2
+#define CEN_SPECIAL		4
+#define XPG_NORM_CODESET	8
+#define XPG_CODESET		16
+#define TERRITORY		32
+#define CEN_AUDIENCE		64
+#define XPG_MODIFIER		128
+
+#define CEN_SPECIFIC	(CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE)
+#define XPG_SPECIFIC	(XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER)
+
+
+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 PARAMS ((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,
+   SPECIAL, SPONSOR, REVISION 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 PARAMS ((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 *special,
+			    const char *sponsor, const char *revision,
+			    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.  */
+extern const char *_nl_expand_alias PARAMS ((const char *name));
+
+/* Split a locale name NAME into its pieces: language, modifier,
+   territory, codeset, special, sponsor, revision.
+   NAME gets destructively modified: NUL bytes are inserted here and
+   there.  *LANGUAGE gets assigned NAME.  Each of *MODIFIER, *TERRITORY,
+   *CODESET, *SPECIAL, *SPONSOR, *REVISION 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, CEN_AUDIENCE  for *MODIFIER,
+     TERRITORY                   for *TERRITORY,
+     XPG_CODESET                 for *CODESET,
+     XPG_NORM_CODESET            for *NORMALIZED_CODESET,
+     CEN_SPECIAL                 for *SPECIAL,
+     CEN_SPONSOR                 for *SPONSOR,
+     CEN_REVISION                for *REVISION.
+ */
+extern int _nl_explode_name PARAMS ((char *name, const char **language,
+				     const char **modifier,
+				     const char **territory,
+				     const char **codeset,
+				     const char **normalized_codeset,
+				     const char **special,
+				     const char **sponsor,
+				     const char **revision));
+
+/* 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.  */
+extern char *_nl_find_language PARAMS ((const char *name));
+
+#endif	/* loadinfo.h */

+ 1322 - 0
intl/loadmsgcat.c

@@ -0,0 +1,1322 @@
+/* Load needed message catalogs.
+   Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* 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 <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"
+#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   __open
+# define close  __close
+# define read   __read
+# define mmap   __mmap
+# define munmap __munmap
+#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
+
+
+/* Prototypes for local functions.  Needed to ensure compiler checking of
+   function argument counts despite of K&R C function definition syntax.  */
+static const char *get_sysdep_segment_value PARAMS ((const char *name));
+
+
+/* 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 (name)
+     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 ();
+	    }
+	}
+    }
+  /* Other system dependent strings are not valid.  */
+  return NULL;
+}
+
+/* Initialize the codeset dependent parts of an opened message catalog.
+   Return the header entry.  */
+const char *
+internal_function
+_nl_init_domain_conv (domain_file, domain, domainbinding)
+     struct loaded_l10nfile *domain_file;
+     struct loaded_domain *domain;
+     struct binding *domainbinding;
+{
+  /* 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.  */
+  char *nullentry;
+  size_t nullentrylen;
+
+  /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
+  domain->codeset_cntr =
+    (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
+#ifdef _LIBC
+  domain->conv = (__gconv_t) -1;
+#else
+# if HAVE_ICONV
+  domain->conv = (iconv_t) -1;
+# endif
+#endif
+  domain->conv_tab = NULL;
+
+  /* Get the header entry.  */
+  nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
+
+  if (nullentry != NULL)
+    {
+#if defined _LIBC || HAVE_ICONV
+      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
+
+	  /* 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.  Moreover, the value specified through
+	     bind_textdomain_codeset overrides both.  */
+	  if (domainbinding != NULL && domainbinding->codeset != NULL)
+	    outcharset = domainbinding->codeset;
+	  else
+	    {
+	      outcharset = getenv ("OUTPUT_CHARSET");
+	      if (outcharset == NULL || outcharset[0] == '\0')
+		{
+# ifdef _LIBC
+		  outcharset = _NL_CURRENT (LC_CTYPE, CODESET);
+# else
+#  if HAVE_ICONV
+		  extern const char *locale_charset PARAMS ((void));
+		  outcharset = locale_charset ();
+#  endif
+# endif
+		}
+	    }
+
+# ifdef _LIBC
+	  /* We always want to use transliteration.  */
+	  outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+	  charset = norm_add_slashes (charset, NULL);
+	  if (__gconv_open (outcharset, charset, &domain->conv,
+			    GCONV_AVOID_NOCONV)
+	      != __GCONV_OK)
+	    domain->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 \
+       || _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;
+
+	      domain->conv = iconv_open (outcharset, charset);
+
+	      freea (outcharset);
+	    }
+	  else
+#   endif
+	    domain->conv = iconv_open (outcharset, charset);
+#  endif
+# endif
+
+	  freea (charset);
+	}
+#endif /* _LIBC || HAVE_ICONV */
+    }
+
+  return nullentry;
+}
+
+/* Frees the codeset dependent parts of an opened message catalog.  */
+void
+internal_function
+_nl_free_domain_conv (domain)
+     struct loaded_domain *domain;
+{
+  if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
+    free (domain->conv_tab);
+
+#ifdef _LIBC
+  if (domain->conv != (__gconv_t) -1)
+    __gconv_close (domain->conv);
+#else
+# if HAVE_ICONV
+  if (domain->conv != (iconv_t) -1)
+    iconv_close (domain->conv);
+# endif
+#endif
+}
+
+/* Load the message catalogs specified by FILENAME.  If it is no valid
+   message catalog do nothing.  */
+void
+internal_function
+_nl_load_domain (domain_file, domainbinding)
+     struct loaded_l10nfile *domain_file;
+     struct binding *domainbinding;
+{
+  int fd;
+  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;
+
+  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)
+    return;
+
+  /* Try to open the addressed file.  */
+  fd = open (domain_file->filename, O_RDONLY | O_BINARY);
+  if (fd == -1)
+    return;
+
+  /* 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.  */
+      close (fd);
+      return;
+    }
+
+#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 != (struct mo_file_header *) -1, 1))
+    {
+      /* mmap() call was successful.  */
+      close (fd);
+      use_mmap = 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)
+	return;
+
+      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
+	      close (fd);
+	      return;
+	    }
+	  read_ptr += nb;
+	  to_read -= nb;
+	}
+      while (to_read > 0);
+
+      close (fd);
+    }
+
+  /* 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);
+      return;
+    }
+
+  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
+  if (domain == NULL)
+    return;
+  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 revision 0.  */
+  switch (revision >> 16)
+    {
+    case 0:
+      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;
+		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;
+
+		/* 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 =
+		  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.  */
+		memneed = 2 * n_sysdep_strings
+			  * sizeof (struct sysdep_string_desc)
+			  + domain->hash_size * sizeof (nls_uint32);
+		for (i = 0; i < 2 * n_sysdep_strings; i++)
+		  {
+		    const struct sysdep_string *sysdep_string =
+		      (const struct sysdep_string *)
+		      ((char *) data
+		       + W (domain->must_swap,
+			    i < n_sysdep_strings
+			    ? orig_sysdep_tab[i]
+			    : trans_sysdep_tab[i - n_sysdep_strings]));
+		    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;
+			    }
+
+			  need += strlen (sysdep_segment_values[sysdepref]);
+			}
+
+		    memneed += need;
+		  }
+
+		/* 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_sysdep_strings * sizeof (struct sysdep_string_desc);
+		inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
+		mem += n_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.  */
+		for (i = 0; i < 2 * n_sysdep_strings; i++)
+		  {
+		    const struct sysdep_string *sysdep_string =
+		      (const struct sysdep_string *)
+		      ((char *) data
+		       + W (domain->must_swap,
+			    i < n_sysdep_strings
+			    ? orig_sysdep_tab[i]
+			    : trans_sysdep_tab[i - n_sysdep_strings]));
+		    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[i] (for i < n_sysdep_strings) and
+		       inmem_trans_sysdep_tab[i-n_sysdep_strings] (for
+		       i >= n_sysdep_strings).  */
+
+		    if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END)
+		      {
+			/* Only one static segment.  */
+			inmem_orig_sysdep_tab[i].length =
+			  W (domain->must_swap, p->segsize);
+			inmem_orig_sysdep_tab[i].pointer = static_segments;
+		      }
+		    else
+		      {
+			inmem_orig_sysdep_tab[i].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_orig_sysdep_tab[i].length =
+			  mem - inmem_orig_sysdep_tab[i].pointer;
+		      }
+		  }
+
+		/* 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_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;
+		      }
+		  }
+
+		freea (sysdep_segment_values);
+
+		domain->n_sysdep_strings = n_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;
+	      }
+	  }
+	  break;
+	}
+      break;
+    default:
+      /* This is an invalid revision.  */
+    invalid:
+      /* This is an invalid .mo file.  */
+      if (domain->malloced)
+	free (domain->malloced);
+#ifdef HAVE_MMAP
+      if (use_mmap)
+	munmap ((caddr_t) data, size);
+      else
+#endif
+	free (data);
+      free (domain);
+      domain_file->data = NULL;
+      return;
+    }
+
+  /* Now initialize the character set converter from the character set
+     the file is encoded with (found in the header entry) to the domain's
+     specified character set or the locale's character set.  */
+  nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
+
+  /* Also look for a plural specification.  */
+  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+}
+
+
+#ifdef _LIBC
+void
+internal_function
+_nl_unload_domain (domain)
+     struct loaded_domain *domain;
+{
+  if (domain->plural != &__gettext_germanic_plural)
+    __gettext_free_exp (domain->plural);
+
+  _nl_free_domain_conv (domain);
+
+  if (domain->malloced)
+    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

+ 398 - 0
intl/localcharset.c

@@ -0,0 +1,398 @@
+/* Determine a canonical name for the current locale's character encoding.
+
+   Copyright (C) 2000-2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  */
+#include "localcharset.h"
+
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#if defined __EMX__
+/* Assume EMX program runs on OS/2, even if compiled under DOS.  */
+# define OS2
+#endif
+
+#if !defined WIN32
+# if HAVE_LANGINFO_CODESET
+#  include <langinfo.h>
+# else
+#  if HAVE_SETLOCALE
+#   include <locale.h>
+#  endif
+# endif
+#elif defined WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+#if defined OS2
+# define INCL_DOS
+# include <os2.h>
+#endif
+
+#if ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#endif
+
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
+
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
+
+#ifdef HAVE_GETC_UNLOCKED
+# undef getc
+# define getc getc_unlocked
+#endif
+
+/* The following static variable is declared 'volatile' to avoid a
+   possible multithread problem in the function get_charset_aliases. If we
+   are running in a threaded environment, and if two threads initialize
+   'charset_aliases' simultaneously, both will produce the same value,
+   and everything will be ok if the two assignments to 'charset_aliases'
+   are atomic. But I don't know what will happen if the two assignments mix.  */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+   read, else NULL.  Its format is:
+   ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
+static const char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file.  */
+static const char *
+get_charset_aliases ()
+{
+  const char *cp;
+
+  cp = charset_aliases;
+  if (cp == NULL)
+    {
+#if !(defined VMS || defined WIN32)
+      FILE *fp;
+      const char *dir = relocate (LIBDIR);
+      const char *base = "charset.alias";
+      char *file_name;
+
+      /* Concatenate dir and base into freshly allocated file_name.  */
+      {
+	size_t dir_len = strlen (dir);
+	size_t base_len = strlen (base);
+	int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+	file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+	if (file_name != NULL)
+	  {
+	    memcpy (file_name, dir, dir_len);
+	    if (add_slash)
+	      file_name[dir_len] = DIRECTORY_SEPARATOR;
+	    memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+	  }
+      }
+
+      if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
+	/* Out of memory or file not found, treat it as empty.  */
+	cp = "";
+      else
+	{
+	  /* Parse the file's contents.  */
+	  int c;
+	  char buf1[50+1];
+	  char buf2[50+1];
+	  char *res_ptr = NULL;
+	  size_t res_size = 0;
+	  size_t l1, l2;
+
+	  for (;;)
+	    {
+	      c = getc (fp);
+	      if (c == EOF)
+		break;
+	      if (c == '\n' || c == ' ' || c == '\t')
+		continue;
+	      if (c == '#')
+		{
+		  /* Skip comment, to end of line.  */
+		  do
+		    c = getc (fp);
+		  while (!(c == EOF || c == '\n'));
+		  if (c == EOF)
+		    break;
+		  continue;
+		}
+	      ungetc (c, fp);
+	      if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
+		break;
+	      l1 = strlen (buf1);
+	      l2 = strlen (buf2);
+	      if (res_size == 0)
+		{
+		  res_size = l1 + 1 + l2 + 1;
+		  res_ptr = (char *) malloc (res_size + 1);
+		}
+	      else
+		{
+		  res_size += l1 + 1 + l2 + 1;
+		  res_ptr = (char *) realloc (res_ptr, res_size + 1);
+		}
+	      if (res_ptr == NULL)
+		{
+		  /* Out of memory. */
+		  res_size = 0;
+		  break;
+		}
+	      strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+	      strcpy (res_ptr + res_size - (l2 + 1), buf2);
+	    }
+	  fclose (fp);
+	  if (res_size == 0)
+	    cp = "";
+	  else
+	    {
+	      *(res_ptr + res_size) = '\0';
+	      cp = res_ptr;
+	    }
+	}
+
+      if (file_name != NULL)
+	free (file_name);
+
+#else
+
+# if defined VMS
+      /* To avoid the troubles of an extra file charset.alias_vms in the
+	 sources of many GNU packages, simply inline the aliases here.  */
+      /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
+	 "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
+	 section 10.7 "Handling Different Character Sets".  */
+      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+	   "ISO8859-2" "\0" "ISO-8859-2" "\0"
+	   "ISO8859-5" "\0" "ISO-8859-5" "\0"
+	   "ISO8859-7" "\0" "ISO-8859-7" "\0"
+	   "ISO8859-8" "\0" "ISO-8859-8" "\0"
+	   "ISO8859-9" "\0" "ISO-8859-9" "\0"
+	   /* Japanese */
+	   "eucJP" "\0" "EUC-JP" "\0"
+	   "SJIS" "\0" "SHIFT_JIS" "\0"
+	   "DECKANJI" "\0" "DEC-KANJI" "\0"
+	   "SDECKANJI" "\0" "EUC-JP" "\0"
+	   /* Chinese */
+	   "eucTW" "\0" "EUC-TW" "\0"
+	   "DECHANYU" "\0" "DEC-HANYU" "\0"
+	   "DECHANZI" "\0" "GB2312" "\0"
+	   /* Korean */
+	   "DECKOREAN" "\0" "EUC-KR" "\0";
+# endif
+
+# if defined WIN32
+      /* To avoid the troubles of installing a separate file in the same
+	 directory as the DLL and of retrieving the DLL's directory at
+	 runtime, simply inline the aliases here.  */
+
+      cp = "CP936" "\0" "GBK" "\0"
+	   "CP1361" "\0" "JOHAB" "\0"
+	   "CP20127" "\0" "ASCII" "\0"
+	   "CP20866" "\0" "KOI8-R" "\0"
+	   "CP21866" "\0" "KOI8-RU" "\0"
+	   "CP28591" "\0" "ISO-8859-1" "\0"
+	   "CP28592" "\0" "ISO-8859-2" "\0"
+	   "CP28593" "\0" "ISO-8859-3" "\0"
+	   "CP28594" "\0" "ISO-8859-4" "\0"
+	   "CP28595" "\0" "ISO-8859-5" "\0"
+	   "CP28596" "\0" "ISO-8859-6" "\0"
+	   "CP28597" "\0" "ISO-8859-7" "\0"
+	   "CP28598" "\0" "ISO-8859-8" "\0"
+	   "CP28599" "\0" "ISO-8859-9" "\0"
+	   "CP28605" "\0" "ISO-8859-15" "\0";
+# endif
+#endif
+
+      charset_aliases = cp;
+    }
+
+  return cp;
+}
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+
+#ifdef STATIC
+STATIC
+#endif
+const char *
+locale_charset ()
+{
+  const char *codeset;
+  const char *aliases;
+
+#if !(defined WIN32 || defined OS2)
+
+# if HAVE_LANGINFO_CODESET
+
+  /* Most systems support nl_langinfo (CODESET) nowadays.  */
+  codeset = nl_langinfo (CODESET);
+
+# else
+
+  /* On old systems which lack it, use setlocale or getenv.  */
+  const char *locale = NULL;
+
+  /* But most old systems don't have a complete set of locales.  Some
+     (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
+     use setlocale here; it would return "C" when it doesn't support the
+     locale name the user has set.  */
+#  if HAVE_SETLOCALE && 0
+  locale = setlocale (LC_CTYPE, NULL);
+#  endif
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+	{
+	  locale = getenv ("LC_CTYPE");
+	  if (locale == NULL || locale[0] == '\0')
+	    locale = getenv ("LANG");
+	}
+    }
+
+  /* On some old systems, one used to set locale = "iso8859_1". On others,
+     you set it to "language_COUNTRY.charset". In any case, we resolve it
+     through the charset.alias file.  */
+  codeset = locale;
+
+# endif
+
+#elif defined WIN32
+
+  static char buf[2 + 10 + 1];
+
+  /* Woe32 has a function returning the locale's codepage as a number.  */
+  sprintf (buf, "CP%u", GetACP ());
+  codeset = buf;
+
+#elif defined OS2
+
+  const char *locale;
+  static char buf[2 + 10 + 1];
+  ULONG cp[3];
+  ULONG cplen;
+
+  /* Allow user to override the codeset, as set in the operating system,
+     with standard language environment variables.  */
+  locale = getenv ("LC_ALL");
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_CTYPE");
+      if (locale == NULL || locale[0] == '\0')
+	locale = getenv ("LANG");
+    }
+  if (locale != NULL && locale[0] != '\0')
+    {
+      /* If the locale name contains an encoding after the dot, return it.  */
+      const char *dot = strchr (locale, '.');
+
+      if (dot != NULL)
+	{
+	  const char *modifier;
+
+	  dot++;
+	  /* Look for the possible @... trailer and remove it, if any.  */
+	  modifier = strchr (dot, '@');
+	  if (modifier == NULL)
+	    return dot;
+	  if (modifier - dot < sizeof (buf))
+	    {
+	      memcpy (buf, dot, modifier - dot);
+	      buf [modifier - dot] = '\0';
+	      return buf;
+	    }
+	}
+
+      /* Resolve through the charset.alias file.  */
+      codeset = locale;
+    }
+  else
+    {
+      /* OS/2 has a function returning the locale's codepage as a number.  */
+      if (DosQueryCp (sizeof (cp), cp, &cplen))
+	codeset = "";
+      else
+	{
+	  sprintf (buf, "CP%u", cp[0]);
+	  codeset = buf;
+	}
+    }
+
+#endif
+
+  if (codeset == NULL)
+    /* The canonical name cannot be determined.  */
+    codeset = "";
+
+  /* Resolve alias. */
+  for (aliases = get_charset_aliases ();
+       *aliases != '\0';
+       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+    if (strcmp (codeset, aliases) == 0
+	|| (aliases[0] == '*' && aliases[1] == '\0'))
+      {
+	codeset = aliases + strlen (aliases) + 1;
+	break;
+      }
+
+  /* Don't return an empty string.  GNU libc and GNU libiconv interpret
+     the empty string as denoting "the locale's character encoding",
+     thus GNU libiconv would call this function a second time.  */
+  if (codeset[0] == '\0')
+    codeset = "ASCII";
+
+  return codeset;
+}

+ 42 - 0
intl/localcharset.h

@@ -0,0 +1,42 @@
+/* Determine a canonical name for the current locale's character encoding.
+   Copyright (C) 2000-2003 Free Software Foundation, Inc.
+   This file is part of the GNU CHARSET Library.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef _LOCALCHARSET_H
+#define _LOCALCHARSET_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+extern const char * locale_charset (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _LOCALCHARSET_H */

+ 78 - 0
intl/locale.alias

@@ -0,0 +1,78 @@
+# Locale name alias data base.
+# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# 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 far from being complete.  If you have a value for
+# your own site which you think might be useful for others too, share
+# it with the rest of us.  Send it using the `glibcbug' script to
+# bugs@gnu.org.
+
+# Packages using this file: 
+
+bokmal		no_NO.ISO-8859-1
+bokmål		no_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
+français	fr_FR.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
+nb_NO		no_NO.ISO-8859-1
+nb_NO.ISO-8859-1 no_NO.ISO-8859-1
+norwegian       no_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

+ 419 - 0
intl/localealias.c

@@ -0,0 +1,419 @@
+/* Handle aliases for locale names.
+   Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* 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"
+
+#if 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 __strcasecmp
+
+# ifndef mempcpy
+#  define mempcpy __mempcpy
+# endif
+# define HAVE_MEMPCPY	1
+# define HAVE___FSETLOCKING	1
+
+/* We need locking here since we can be called from different places.  */
+# include <bits/libc-lock.h>
+
+__libc_lock_define_initialized (static, lock);
+#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_FGETS_UNLOCKED
+# undef fgets
+# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
+#endif
+#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
+# undef feof
+# define feof(s) feof_unlocked (s)
+#endif
+
+
+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 PARAMS ((const char *fname, int fname_len))
+     internal_function;
+static int extend_alias_table PARAMS ((void));
+static int alias_compare PARAMS ((const struct alias_map *map1,
+				  const struct alias_map *map2));
+
+
+const char *
+_nl_expand_alias (name)
+    const char *name;
+{
+  static const char *locale_alias_path;
+  struct alias_map *retval;
+  const char *result = NULL;
+  size_t added;
+
+#ifdef _LIBC
+  __libc_lock_lock (lock);
+#endif
+
+  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 (*) PARAMS ((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);
+
+#ifdef _LIBC
+  __libc_lock_unlock (lock);
+#endif
+
+  return result;
+}
+
+
+static size_t
+internal_function
+read_alias_file (fname, fname_len)
+     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
+
+  fp = fopen (relocate (full_fname), "r");
+  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;
+
+      if (FGETS (buf, sizeof buf, fp) == NULL)
+	/* EOF reached.  */
+	break;
+
+      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')
+	    {
+	      size_t alias_len;
+	      size_t value_len;
+
+	      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';
+
+	      if (nmap >= maxmap)
+		if (__builtin_expect (extend_alias_table (), 0))
+		  return added;
+
+	      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)
+		    return added;
+
+		  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 = memcpy (&string_space[string_space_act],
+					alias, alias_len);
+	      string_space_act += alias_len;
+
+	      map[nmap].value = 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.  */
+      while (strchr (buf, '\n') == NULL)
+	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;
+    }
+
+  /* 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 (*) PARAMS ((const void *, const void *))) alias_compare);
+
+  return added;
+}
+
+
+static int
+extend_alias_table ()
+{
+  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 (map1, map2)
+     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
+}

+ 772 - 0
intl/localename.c

@@ -0,0 +1,772 @@
+/* Determine the current selected locale.
+   Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
+/* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <locale.h>
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* Mingw headers don't have latest language and sublanguage codes.  */
+# ifndef LANG_AFRIKAANS
+# define LANG_AFRIKAANS 0x36
+# endif
+# ifndef LANG_ALBANIAN
+# define LANG_ALBANIAN 0x1c
+# endif
+# ifndef LANG_ARABIC
+# define LANG_ARABIC 0x01
+# endif
+# ifndef LANG_ARMENIAN
+# define LANG_ARMENIAN 0x2b
+# endif
+# ifndef LANG_ASSAMESE
+# define LANG_ASSAMESE 0x4d
+# endif
+# ifndef LANG_AZERI
+# define LANG_AZERI 0x2c
+# endif
+# ifndef LANG_BASQUE
+# define LANG_BASQUE 0x2d
+# endif
+# ifndef LANG_BELARUSIAN
+# define LANG_BELARUSIAN 0x23
+# endif
+# ifndef LANG_BENGALI
+# define LANG_BENGALI 0x45
+# endif
+# ifndef LANG_CATALAN
+# define LANG_CATALAN 0x03
+# endif
+# ifndef LANG_DIVEHI
+# define LANG_DIVEHI 0x65
+# endif
+# ifndef LANG_ESTONIAN
+# define LANG_ESTONIAN 0x25
+# endif
+# ifndef LANG_FAEROESE
+# define LANG_FAEROESE 0x38
+# endif
+# ifndef LANG_FARSI
+# define LANG_FARSI 0x29
+# endif
+# ifndef LANG_GALICIAN
+# define LANG_GALICIAN 0x56
+# endif
+# ifndef LANG_GEORGIAN
+# define LANG_GEORGIAN 0x37
+# endif
+# ifndef LANG_GUJARATI
+# define LANG_GUJARATI 0x47
+# endif
+# ifndef LANG_HEBREW
+# define LANG_HEBREW 0x0d
+# endif
+# ifndef LANG_HINDI
+# define LANG_HINDI 0x39
+# endif
+# ifndef LANG_INDONESIAN
+# define LANG_INDONESIAN 0x21
+# endif
+# ifndef LANG_KANNADA
+# define LANG_KANNADA 0x4b
+# endif
+# ifndef LANG_KASHMIRI
+# define LANG_KASHMIRI 0x60
+# endif
+# ifndef LANG_KAZAK
+# define LANG_KAZAK 0x3f
+# endif
+# ifndef LANG_KONKANI
+# define LANG_KONKANI 0x57
+# endif
+# ifndef LANG_KYRGYZ
+# define LANG_KYRGYZ 0x40
+# endif
+# ifndef LANG_LATVIAN
+# define LANG_LATVIAN 0x26
+# endif
+# ifndef LANG_LITHUANIAN
+# define LANG_LITHUANIAN 0x27
+# endif
+# ifndef LANG_MACEDONIAN
+# define LANG_MACEDONIAN 0x2f
+# endif
+# ifndef LANG_MALAY
+# define LANG_MALAY 0x3e
+# endif
+# ifndef LANG_MALAYALAM
+# define LANG_MALAYALAM 0x4c
+# endif
+# ifndef LANG_MANIPURI
+# define LANG_MANIPURI 0x58
+# endif
+# ifndef LANG_MARATHI
+# define LANG_MARATHI 0x4e
+# endif
+# ifndef LANG_MONGOLIAN
+# define LANG_MONGOLIAN 0x50
+# endif
+# ifndef LANG_NEPALI
+# define LANG_NEPALI 0x61
+# endif
+# ifndef LANG_ORIYA
+# define LANG_ORIYA 0x48
+# endif
+# ifndef LANG_PUNJABI
+# define LANG_PUNJABI 0x46
+# endif
+# ifndef LANG_SANSKRIT
+# define LANG_SANSKRIT 0x4f
+# endif
+# ifndef LANG_SERBIAN
+# define LANG_SERBIAN 0x1a
+# endif
+# ifndef LANG_SINDHI
+# define LANG_SINDHI 0x59
+# endif
+# ifndef LANG_SLOVAK
+# define LANG_SLOVAK 0x1b
+# endif
+# ifndef LANG_SORBIAN
+# define LANG_SORBIAN 0x2e
+# endif
+# ifndef LANG_SWAHILI
+# define LANG_SWAHILI 0x41
+# endif
+# ifndef LANG_SYRIAC
+# define LANG_SYRIAC 0x5a
+# endif
+# ifndef LANG_TAMIL
+# define LANG_TAMIL 0x49
+# endif
+# ifndef LANG_TATAR
+# define LANG_TATAR 0x44
+# endif
+# ifndef LANG_TELUGU
+# define LANG_TELUGU 0x4a
+# endif
+# ifndef LANG_THAI
+# define LANG_THAI 0x1e
+# endif
+# ifndef LANG_UKRAINIAN
+# define LANG_UKRAINIAN 0x22
+# endif
+# ifndef LANG_URDU
+# define LANG_URDU 0x20
+# endif
+# ifndef LANG_UZBEK
+# define LANG_UZBEK 0x43
+# endif
+# ifndef LANG_VIETNAMESE
+# define LANG_VIETNAMESE 0x2a
+# endif
+# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
+# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_IRAQ
+# define SUBLANG_ARABIC_IRAQ 0x02
+# endif
+# ifndef SUBLANG_ARABIC_EGYPT
+# define SUBLANG_ARABIC_EGYPT 0x03
+# endif
+# ifndef SUBLANG_ARABIC_LIBYA
+# define SUBLANG_ARABIC_LIBYA 0x04
+# endif
+# ifndef SUBLANG_ARABIC_ALGERIA
+# define SUBLANG_ARABIC_ALGERIA 0x05
+# endif
+# ifndef SUBLANG_ARABIC_MOROCCO
+# define SUBLANG_ARABIC_MOROCCO 0x06
+# endif
+# ifndef SUBLANG_ARABIC_TUNISIA
+# define SUBLANG_ARABIC_TUNISIA 0x07
+# endif
+# ifndef SUBLANG_ARABIC_OMAN
+# define SUBLANG_ARABIC_OMAN 0x08
+# endif
+# ifndef SUBLANG_ARABIC_YEMEN
+# define SUBLANG_ARABIC_YEMEN 0x09
+# endif
+# ifndef SUBLANG_ARABIC_SYRIA
+# define SUBLANG_ARABIC_SYRIA 0x0a
+# endif
+# ifndef SUBLANG_ARABIC_JORDAN
+# define SUBLANG_ARABIC_JORDAN 0x0b
+# endif
+# ifndef SUBLANG_ARABIC_LEBANON
+# define SUBLANG_ARABIC_LEBANON 0x0c
+# endif
+# ifndef SUBLANG_ARABIC_KUWAIT
+# define SUBLANG_ARABIC_KUWAIT 0x0d
+# endif
+# ifndef SUBLANG_ARABIC_UAE
+# define SUBLANG_ARABIC_UAE 0x0e
+# endif
+# ifndef SUBLANG_ARABIC_BAHRAIN
+# define SUBLANG_ARABIC_BAHRAIN 0x0f
+# endif
+# ifndef SUBLANG_ARABIC_QATAR
+# define SUBLANG_ARABIC_QATAR 0x10
+# endif
+# ifndef SUBLANG_AZERI_LATIN
+# define SUBLANG_AZERI_LATIN 0x01
+# endif
+# ifndef SUBLANG_AZERI_CYRILLIC
+# define SUBLANG_AZERI_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_CHINESE_MACAU
+# define SUBLANG_CHINESE_MACAU 0x05
+# endif
+# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
+# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
+# endif
+# ifndef SUBLANG_ENGLISH_JAMAICA
+# define SUBLANG_ENGLISH_JAMAICA 0x08
+# endif
+# ifndef SUBLANG_ENGLISH_CARIBBEAN
+# define SUBLANG_ENGLISH_CARIBBEAN 0x09
+# endif
+# ifndef SUBLANG_ENGLISH_BELIZE
+# define SUBLANG_ENGLISH_BELIZE 0x0a
+# endif
+# ifndef SUBLANG_ENGLISH_TRINIDAD
+# define SUBLANG_ENGLISH_TRINIDAD 0x0b
+# endif
+# ifndef SUBLANG_ENGLISH_ZIMBABWE
+# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
+# endif
+# ifndef SUBLANG_ENGLISH_PHILIPPINES
+# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
+# endif
+# ifndef SUBLANG_FRENCH_LUXEMBOURG
+# define SUBLANG_FRENCH_LUXEMBOURG 0x05
+# endif
+# ifndef SUBLANG_FRENCH_MONACO
+# define SUBLANG_FRENCH_MONACO 0x06
+# endif
+# ifndef SUBLANG_GERMAN_LUXEMBOURG
+# define SUBLANG_GERMAN_LUXEMBOURG 0x04
+# endif
+# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
+# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
+# endif
+# ifndef SUBLANG_KASHMIRI_INDIA
+# define SUBLANG_KASHMIRI_INDIA 0x02
+# endif
+# ifndef SUBLANG_MALAY_MALAYSIA
+# define SUBLANG_MALAY_MALAYSIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
+# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
+# endif
+# ifndef SUBLANG_NEPALI_INDIA
+# define SUBLANG_NEPALI_INDIA 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_LATIN
+# define SUBLANG_SERBIAN_LATIN 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_CYRILLIC
+# define SUBLANG_SERBIAN_CYRILLIC 0x03
+# endif
+# ifndef SUBLANG_SPANISH_GUATEMALA
+# define SUBLANG_SPANISH_GUATEMALA 0x04
+# endif
+# ifndef SUBLANG_SPANISH_COSTA_RICA
+# define SUBLANG_SPANISH_COSTA_RICA 0x05
+# endif
+# ifndef SUBLANG_SPANISH_PANAMA
+# define SUBLANG_SPANISH_PANAMA 0x06
+# endif
+# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
+# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
+# endif
+# ifndef SUBLANG_SPANISH_VENEZUELA
+# define SUBLANG_SPANISH_VENEZUELA 0x08
+# endif
+# ifndef SUBLANG_SPANISH_COLOMBIA
+# define SUBLANG_SPANISH_COLOMBIA 0x09
+# endif
+# ifndef SUBLANG_SPANISH_PERU
+# define SUBLANG_SPANISH_PERU 0x0a
+# endif
+# ifndef SUBLANG_SPANISH_ARGENTINA
+# define SUBLANG_SPANISH_ARGENTINA 0x0b
+# endif
+# ifndef SUBLANG_SPANISH_ECUADOR
+# define SUBLANG_SPANISH_ECUADOR 0x0c
+# endif
+# ifndef SUBLANG_SPANISH_CHILE
+# define SUBLANG_SPANISH_CHILE 0x0d
+# endif
+# ifndef SUBLANG_SPANISH_URUGUAY
+# define SUBLANG_SPANISH_URUGUAY 0x0e
+# endif
+# ifndef SUBLANG_SPANISH_PARAGUAY
+# define SUBLANG_SPANISH_PARAGUAY 0x0f
+# endif
+# ifndef SUBLANG_SPANISH_BOLIVIA
+# define SUBLANG_SPANISH_BOLIVIA 0x10
+# endif
+# ifndef SUBLANG_SPANISH_EL_SALVADOR
+# define SUBLANG_SPANISH_EL_SALVADOR 0x11
+# endif
+# ifndef SUBLANG_SPANISH_HONDURAS
+# define SUBLANG_SPANISH_HONDURAS 0x12
+# endif
+# ifndef SUBLANG_SPANISH_NICARAGUA
+# define SUBLANG_SPANISH_NICARAGUA 0x13
+# endif
+# ifndef SUBLANG_SPANISH_PUERTO_RICO
+# define SUBLANG_SPANISH_PUERTO_RICO 0x14
+# endif
+# ifndef SUBLANG_SWEDISH_FINLAND
+# define SUBLANG_SWEDISH_FINLAND 0x02
+# endif
+# ifndef SUBLANG_URDU_PAKISTAN
+# define SUBLANG_URDU_PAKISTAN 0x01
+# endif
+# ifndef SUBLANG_URDU_INDIA
+# define SUBLANG_URDU_INDIA 0x02
+# endif
+# ifndef SUBLANG_UZBEK_LATIN
+# define SUBLANG_UZBEK_LATIN 0x01
+# endif
+# ifndef SUBLANG_UZBEK_CYRILLIC
+# define SUBLANG_UZBEK_CYRILLIC 0x02
+# endif
+#endif
+
+/* XPG3 defines the result of 'setlocale (category, NULL)' as:
+   "Directs 'setlocale()' to query 'category' and return the current
+    setting of 'local'."
+   However it does not specify the exact format.  Neither do SUSV2 and
+   ISO C 99.  So we can use this feature only on selected systems (e.g.
+   those using GNU C Library).  */
+#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
+# define HAVE_LOCALE_NULL
+#endif
+
+/* Determine the current locale's name, and canonicalize it into XPG syntax
+     language[_territory[.codeset]][@modifier]
+   The codeset part in the result is not reliable; the locale_charset()
+   should be used for codeset information instead.
+   The result must not be freed; it is statically allocated.  */
+
+const char *
+_nl_locale_name (category, categoryname)
+     int category;
+     const char *categoryname;
+{
+  const char *retval;
+
+#ifndef WIN32
+
+  /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
+     On some systems this can be done by the 'setlocale' function itself.  */
+# if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
+  retval = setlocale (category, NULL);
+# else
+  /* Setting of LC_ALL overwrites all other.  */
+  retval = getenv ("LC_ALL");
+  if (retval == NULL || retval[0] == '\0')
+    {
+      /* Next comes the name of the desired category.  */
+      retval = getenv (categoryname);
+      if (retval == NULL || retval[0] == '\0')
+	{
+	  /* Last possibility is the LANG environment variable.  */
+	  retval = getenv ("LANG");
+	  if (retval == NULL || retval[0] == '\0')
+	    /* We use C as the default domain.  POSIX says this is
+	       implementation defined.  */
+	    retval = "C";
+	}
+    }
+# endif
+
+  return retval;
+
+#else /* WIN32 */
+
+  /* Return an XPG style locale name language[_territory][@modifier].
+     Don't even bother determining the codeset; it's not useful in this
+     context, because message catalogs are not specific to a single
+     codeset.  */
+
+  LCID lcid;
+  LANGID langid;
+  int primary, sub;
+
+  /* Let the user override the system settings through environment
+     variables, as on POSIX systems.  */
+  retval = getenv ("LC_ALL");
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+  retval = getenv (categoryname);
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+  retval = getenv ("LANG");
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+
+  /* Use native Win32 API locale ID.  */
+  lcid = GetThreadLocale ();
+
+  /* Strip off the sorting rules, keep only the language part.  */
+  langid = LANGIDFROMLCID (lcid);
+
+  /* Split into language and territory part.  */
+  primary = PRIMARYLANGID (langid);
+  sub = SUBLANGID (langid);
+
+  /* Dispatch on language.
+     See also http://www.unicode.org/unicode/onlinedat/languages.html .
+     For details about languages, see http://www.ethnologue.com/ .  */
+  switch (primary)
+    {
+    case LANG_AFRIKAANS: return "af_ZA";
+    case LANG_ALBANIAN: return "sq_AL";
+    case 0x5e: /* AMHARIC */ return "am_ET";
+    case LANG_ARABIC:
+      switch (sub)
+	{
+	case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
+	case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
+	case SUBLANG_ARABIC_EGYPT: return "ar_EG";
+	case SUBLANG_ARABIC_LIBYA: return "ar_LY";
+	case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
+	case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
+	case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
+	case SUBLANG_ARABIC_OMAN: return "ar_OM";
+	case SUBLANG_ARABIC_YEMEN: return "ar_YE";
+	case SUBLANG_ARABIC_SYRIA: return "ar_SY";
+	case SUBLANG_ARABIC_JORDAN: return "ar_JO";
+	case SUBLANG_ARABIC_LEBANON: return "ar_LB";
+	case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
+	case SUBLANG_ARABIC_UAE: return "ar_AE";
+	case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
+	case SUBLANG_ARABIC_QATAR: return "ar_QA";
+	}
+      return "ar";
+    case LANG_ARMENIAN: return "hy_AM";
+    case LANG_ASSAMESE: return "as_IN";
+    case LANG_AZERI:
+      switch (sub)
+	{
+	/* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
+	case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
+	case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
+	}
+      return "az";
+    case LANG_BASQUE:
+      return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
+    case LANG_BELARUSIAN: return "be_BY";
+    case LANG_BENGALI: return "bn_IN";
+    case LANG_BULGARIAN: return "bg_BG";
+    case 0x55: /* BURMESE */ return "my_MM";
+    case 0x53: /* CAMBODIAN */ return "km_KH";
+    case LANG_CATALAN: return "ca_ES";
+    case 0x5c: /* CHEROKEE */ return "chr_US";
+    case LANG_CHINESE:
+      switch (sub)
+	{
+	case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
+	case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
+	case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
+	case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
+	case SUBLANG_CHINESE_MACAU: return "zh_MO";
+	}
+      return "zh";
+    case LANG_CROATIAN:		/* LANG_CROATIAN == LANG_SERBIAN
+				 * What used to be called Serbo-Croatian
+				 * should really now be two separate
+				 * languages because of political reasons.
+				 * (Says tml, who knows nothing about Serbian
+				 * or Croatian.)
+				 * (I can feel those flames coming already.)
+				 */
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "hr_HR";
+	case SUBLANG_SERBIAN_LATIN: return "sr_YU";
+	case SUBLANG_SERBIAN_CYRILLIC: return "sr_YU@cyrillic";
+	}
+      return "hr";
+    case LANG_CZECH: return "cs_CZ";
+    case LANG_DANISH: return "da_DK";
+    case LANG_DIVEHI: return "div_MV";
+    case LANG_DUTCH:
+      switch (sub)
+	{
+	case SUBLANG_DUTCH: return "nl_NL";
+	case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
+	}
+      return "nl";
+    case 0x66: /* EDO */ return "bin_NG";
+    case LANG_ENGLISH:
+      switch (sub)
+	{
+	/* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
+	 * English was the language spoken in England.
+	 * Oh well.
+	 */
+	case SUBLANG_ENGLISH_US: return "en_US";
+	case SUBLANG_ENGLISH_UK: return "en_GB";
+	case SUBLANG_ENGLISH_AUS: return "en_AU";
+	case SUBLANG_ENGLISH_CAN: return "en_CA";
+	case SUBLANG_ENGLISH_NZ: return "en_NZ";
+	case SUBLANG_ENGLISH_EIRE: return "en_IE";
+	case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
+	case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
+	case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
+	case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
+	case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
+	case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
+	case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
+	}
+      return "en";
+    case LANG_ESTONIAN: return "et_EE";
+    case LANG_FAEROESE: return "fo_FO";
+    case LANG_FARSI: return "fa_IR";
+    case LANG_FINNISH: return "fi_FI";
+    case LANG_FRENCH:
+      switch (sub)
+	{
+	case SUBLANG_FRENCH: return "fr_FR";
+	case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
+	case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
+	case SUBLANG_FRENCH_SWISS: return "fr_CH";
+	case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
+	case SUBLANG_FRENCH_MONACO: return "fr_MC";
+	}
+      return "fr";
+    case 0x62: /* FRISIAN */ return "fy_NL";
+    case 0x67: /* FULFULDE */ return "ful_NG";
+    case 0x3c: /* GAELIC */
+      switch (sub)
+	{
+	case 0x01: /* SCOTTISH */ return "gd_GB";
+	case 0x02: /* IRISH */ return "ga_IE";
+	}
+      return "C";
+    case LANG_GALICIAN: return "gl_ES";
+    case LANG_GEORGIAN: return "ka_GE";
+    case LANG_GERMAN:
+      switch (sub)
+	{
+	case SUBLANG_GERMAN: return "de_DE";
+	case SUBLANG_GERMAN_SWISS: return "de_CH";
+	case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
+	case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
+	case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
+	}
+      return "de";
+    case LANG_GREEK: return "el_GR";
+    case 0x74: /* GUARANI */ return "gn_PY";
+    case LANG_GUJARATI: return "gu_IN";
+    case 0x68: /* HAUSA */ return "ha_NG";
+    case 0x75: /* HAWAIIAN */
+      /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
+	 or Hawaii Creole English ("cpe_US", 600000 speakers)?  */
+      return "cpe_US";
+    case LANG_HEBREW: return "he_IL";
+    case LANG_HINDI: return "hi_IN";
+    case LANG_HUNGARIAN: return "hu_HU";
+    case 0x69: /* IBIBIO */ return "nic_NG";
+    case LANG_ICELANDIC: return "is_IS";
+    case 0x70: /* IGBO */ return "ibo_NG";
+    case LANG_INDONESIAN: return "id_ID";
+    case 0x5d: /* INUKTITUT */ return "iu_CA";
+    case LANG_ITALIAN:
+      switch (sub)
+	{
+	case SUBLANG_ITALIAN: return "it_IT";
+	case SUBLANG_ITALIAN_SWISS: return "it_CH";
+	}
+      return "it";
+    case LANG_JAPANESE: return "ja_JP";
+    case LANG_KANNADA: return "kn_IN";
+    case 0x71: /* KANURI */ return "kau_NG";
+    case LANG_KASHMIRI:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "ks_PK";
+	case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
+	}
+      return "ks";
+    case LANG_KAZAK: return "kk_KZ";
+    case LANG_KONKANI:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "kok_IN";
+    case LANG_KOREAN: return "ko_KR";
+    case LANG_KYRGYZ: return "ky_KG";
+    case 0x54: /* LAO */ return "lo_LA";
+    case 0x76: /* LATIN */ return "la_VA";
+    case LANG_LATVIAN: return "lv_LV";
+    case LANG_LITHUANIAN: return "lt_LT";
+    case LANG_MACEDONIAN: return "mk_MK";
+    case LANG_MALAY:
+      switch (sub)
+	{
+	case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
+	case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
+	}
+      return "ms";
+    case LANG_MALAYALAM: return "ml_IN";
+    case 0x3a: /* MALTESE */ return "mt_MT";
+    case LANG_MANIPURI:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "mni_IN";
+    case LANG_MARATHI: return "mr_IN";
+    case LANG_MONGOLIAN:
+      return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN".  */
+    case LANG_NEPALI:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "ne_NP";
+	case SUBLANG_NEPALI_INDIA: return "ne_IN";
+	}
+      return "ne";
+    case LANG_NORWEGIAN:
+      switch (sub)
+	{
+	case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
+	case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
+	}
+      return "no";
+    case LANG_ORIYA: return "or_IN";
+    case 0x72: /* OROMO */ return "om_ET";
+    case 0x79: /* PAPIAMENTU */ return "pap_AN";
+    case 0x63: /* PASHTO */
+      return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF".  */
+    case LANG_POLISH: return "pl_PL";
+    case LANG_PORTUGUESE:
+      switch (sub)
+	{
+	case SUBLANG_PORTUGUESE: return "pt_PT";
+	/* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
+	   Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
+	case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
+	}
+      return "pt";
+    case LANG_PUNJABI: return "pa_IN";
+    case 0x17: /* RHAETO-ROMANCE */ return "rm_CH";
+    case LANG_ROMANIAN: return "ro_RO";
+    case LANG_RUSSIAN:
+      return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA".  */
+    case 0x3b: /* SAMI */ return "se_NO";
+    case LANG_SANSKRIT: return "sa_IN";
+    case LANG_SINDHI: return "sd";
+    case 0x5b: /* SINHALESE */ return "si_LK";
+    case LANG_SLOVAK: return "sk_SK";
+    case LANG_SLOVENIAN: return "sl_SI";
+    case 0x77: /* SOMALI */ return "so_SO";
+    case LANG_SORBIAN:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "wen_DE";
+    case LANG_SPANISH:
+      switch (sub)
+	{
+	case SUBLANG_SPANISH: return "es_ES";
+	case SUBLANG_SPANISH_MEXICAN: return "es_MX";
+	case SUBLANG_SPANISH_MODERN:
+	  return "es_ES@modern";	/* not seen on Unix */
+	case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
+	case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
+	case SUBLANG_SPANISH_PANAMA: return "es_PA";
+	case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
+	case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
+	case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
+	case SUBLANG_SPANISH_PERU: return "es_PE";
+	case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
+	case SUBLANG_SPANISH_ECUADOR: return "es_EC";
+	case SUBLANG_SPANISH_CHILE: return "es_CL";
+	case SUBLANG_SPANISH_URUGUAY: return "es_UY";
+	case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
+	case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
+	case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
+	case SUBLANG_SPANISH_HONDURAS: return "es_HN";
+	case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
+	case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
+	}
+      return "es";
+    case 0x30: /* SUTU */ return "bnt_TZ";
+    case LANG_SWAHILI: return "sw_KE";
+    case LANG_SWEDISH:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "sv_SE";
+	case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
+	}
+      return "sv";
+    case LANG_SYRIAC: return "syr_TR"; /* An extinct language.  */
+    case 0x64: /* TAGALOG */ return "tl_PH";
+    case 0x28: /* TAJIK */ return "tg_TJ";
+    case 0x5f: /* TAMAZIGHT */ return "ber_MA";
+    case LANG_TAMIL:
+      return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG".  */
+    case LANG_TATAR: return "tt_RU";
+    case LANG_TELUGU: return "te_IN";
+    case LANG_THAI: return "th_TH";
+    case 0x51: /* TIBETAN */ return "bo_CN";
+    case 0x73: /* TIGRINYA */ return "ti_ET";
+    case 0x31: /* TSONGA */ return "ts_ZA";
+    case LANG_TURKISH: return "tr_TR";
+    case 0x42: /* TURKMEN */ return "tk_TM";
+    case LANG_UKRAINIAN: return "uk_UA";
+    case LANG_URDU:
+      switch (sub)
+	{
+	case SUBLANG_URDU_PAKISTAN: return "ur_PK";
+	case SUBLANG_URDU_INDIA: return "ur_IN";
+	}
+      return "ur";
+    case LANG_UZBEK:
+      switch (sub)
+	{
+	/* FIXME: Adjust this when Uzbek locales appear on Unix.  */
+	case SUBLANG_UZBEK_LATIN: return "uz_UZ@latin";
+	case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
+	}
+      return "uz";
+    case 0x33: /* VENDA */ return "ven_ZA";
+    case LANG_VIETNAMESE: return "vi_VN";
+    case 0x52: /* WELSH */ return "cy_GB";
+    case 0x34: /* XHOSA */ return "xh_ZA";
+    case 0x78: /* YI */ return "sit_CN";
+    case 0x3d: /* YIDDISH */ return "yi_IL";
+    case 0x6a: /* YORUBA */ return "yo_NG";
+    case 0x35: /* ZULU */ return "zu_ZA";
+    default: return "C";
+    }
+
+#endif
+}

+ 104 - 0
intl/log.c

@@ -0,0 +1,104 @@
+/* Log file output.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Print an ASCII string with quotes and escape sequences where needed.  */
+static void
+print_escaped (stream, str)
+     FILE *stream;
+     const char *str;
+{
+  putc ('"', stream);
+  for (; *str != '\0'; str++)
+    if (*str == '\n')
+      {
+	fputs ("\\n\"", stream);
+	if (str[1] == '\0')
+	  return;
+	fputs ("\n\"", stream);
+      }
+    else
+      {
+	if (*str == '"' || *str == '\\')
+	  putc ('\\', stream);
+	putc (*str, stream);
+      }
+  putc ('"', stream);
+}
+
+/* Add to the log file an entry denoting a failed translation.  */
+void
+_nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural)
+     const char *logfilename;
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     int plural;
+{
+  static char *last_logfilename = NULL;
+  static FILE *last_logfile = NULL;
+  FILE *logfile;
+
+  /* Can we reuse the last opened logfile?  */
+  if (last_logfilename == NULL || strcmp (logfilename, last_logfilename) != 0)
+    {
+      /* Close the last used logfile.  */
+      if (last_logfilename != NULL)
+	{
+	  if (last_logfile != NULL)
+	    {
+	      fclose (last_logfile);
+	      last_logfile = NULL;
+	    }
+	  free (last_logfilename);
+	  last_logfilename = NULL;
+	}
+      /* Open the logfile.  */
+      last_logfilename = (char *) malloc (strlen (logfilename) + 1);
+      if (last_logfilename == NULL)
+	return;
+      strcpy (last_logfilename, logfilename);
+      last_logfile = fopen (logfilename, "a");
+      if (last_logfile == NULL)
+	return;
+    }
+  logfile = last_logfile;
+
+  fprintf (logfile, "domain ");
+  print_escaped (logfile, domainname);
+  fprintf (logfile, "\nmsgid ");
+  print_escaped (logfile, msgid1);
+  if (plural)
+    {
+      fprintf (logfile, "\nmsgid_plural ");
+      print_escaped (logfile, msgid2);
+      fprintf (logfile, "\nmsgstr[0] \"\"\n");
+    }
+  else
+    fprintf (logfile, "\nmsgstr \"\"\n");
+  putc ('\n', logfile);
+}

+ 68 - 0
intl/ngettext.c

@@ -0,0 +1,68 @@
+/* Implementation of ngettext(3) function.
+   Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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 (msgid1, msgid2, n)
+     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

+ 98 - 0
intl/os2compat.c

@@ -0,0 +1,98 @@
+/* OS/2 compatibility functions.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#define OS2_AWARE
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+/* A version of getenv() that works from DLLs */
+extern unsigned long DosScanEnv (const unsigned char *pszName, unsigned char **ppszValue);
+
+char *
+_nl_getenv (const char *name)
+{
+  unsigned char *value;
+  if (DosScanEnv (name, &value))
+    return NULL;
+  else
+    return value;
+}
+
+/* A fixed size buffer.  */
+char libintl_nl_default_dirname[MAXPATHLEN+1];
+
+char *_nlos2_libdir = NULL;
+char *_nlos2_localealiaspath = NULL;
+char *_nlos2_localedir = NULL;
+
+static __attribute__((constructor)) void
+nlos2_initialize ()
+{
+  char *root = getenv ("UNIXROOT");
+  char *gnulocaledir = getenv ("GNULOCALEDIR");
+
+  _nlos2_libdir = gnulocaledir;
+  if (!_nlos2_libdir)
+    {
+      if (root)
+        {
+          size_t sl = strlen (root);
+          _nlos2_libdir = (char *) malloc (sl + strlen (LIBDIR) + 1);
+          memcpy (_nlos2_libdir, root, sl);
+          memcpy (_nlos2_libdir + sl, LIBDIR, strlen (LIBDIR) + 1);
+        }
+      else
+        _nlos2_libdir = LIBDIR;
+    }
+
+  _nlos2_localealiaspath = gnulocaledir;
+  if (!_nlos2_localealiaspath)
+    {
+      if (root)
+        {
+          size_t sl = strlen (root);
+          _nlos2_localealiaspath = (char *) malloc (sl + strlen (LOCALE_ALIAS_PATH) + 1);
+          memcpy (_nlos2_localealiaspath, root, sl);
+          memcpy (_nlos2_localealiaspath + sl, LOCALE_ALIAS_PATH, strlen (LOCALE_ALIAS_PATH) + 1);
+        }
+     else
+        _nlos2_localealiaspath = LOCALE_ALIAS_PATH;
+    }
+
+  _nlos2_localedir = gnulocaledir;
+  if (!_nlos2_localedir)
+    {
+      if (root)
+        {
+          size_t sl = strlen (root);
+          _nlos2_localedir = (char *) malloc (sl + strlen (LOCALEDIR) + 1);
+          memcpy (_nlos2_localedir, root, sl);
+          memcpy (_nlos2_localedir + sl, LOCALEDIR, strlen (LOCALEDIR) + 1);
+        }
+      else
+        _nlos2_localedir = LOCALEDIR;
+    }
+
+  if (strlen (_nlos2_localedir) <= MAXPATHLEN)
+    strcpy (libintl_nl_default_dirname, _nlos2_localedir);
+}

+ 46 - 0
intl/os2compat.h

@@ -0,0 +1,46 @@
+/* OS/2 compatibility defines.
+   This file is intended to be included from config.h
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* When included from os2compat.h we need all the original definitions */
+#ifndef OS2_AWARE
+
+#undef LIBDIR
+#define LIBDIR			_nlos2_libdir
+extern char *_nlos2_libdir;
+
+#undef LOCALEDIR
+#define LOCALEDIR		_nlos2_localedir
+extern char *_nlos2_localedir;
+
+#undef LOCALE_ALIAS_PATH
+#define LOCALE_ALIAS_PATH	_nlos2_localealiaspath
+extern char *_nlos2_localealiaspath;
+
+#endif
+
+#undef HAVE_STRCASECMP
+#define HAVE_STRCASECMP 1
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+
+/* We have our own getenv() which works even if library is compiled as DLL */
+#define getenv _nl_getenv
+
+/* Older versions of gettext used -1 as the value of LC_MESSAGES */
+#define LC_MESSAGES_COMPAT (-1)

+ 24 - 0
intl/osdep.c

@@ -0,0 +1,24 @@
+/* OS dependent parts of libintl.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#if defined __EMX__
+# include "os2compat.c"
+#else
+/* Avoid AIX compiler warning.  */
+typedef int dummy;
+#endif

+ 156 - 0
intl/plural-exp.c

@@ -0,0 +1,156 @@
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#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__) \
+    || (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
+  }
+};
+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 ()
+{
+  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 (nullentry, pluralp, npluralsp)
+     const char *nullentry;
+     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;
+    }
+}

+ 126 - 0
intl/plural-exp.h

@@ -0,0 +1,126 @@
+/* Expression parsing and evaluation for plural form selection.
+   Copyright (C) 2000, 2001, 2002 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef _PLURAL_EXP_H
+#define _PLURAL_EXP_H
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+
+/* This is the representation of the expressions to determine the
+   plural form.  */
+struct expression
+{
+  int nargs;			/* Number of arguments.  */
+  enum 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.  */
+  } 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 PARAMS ((struct expression *exp))
+     internal_function;
+extern int PLURAL_PARSE PARAMS ((void *arg));
+extern struct expression GERMANIC_PLURAL attribute_hidden;
+extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry,
+					       struct expression **pluralp,
+					       unsigned long int *npluralsp))
+     internal_function;
+
+#if !defined (_LIBC) && !defined (IN_LIBINTL)
+extern unsigned long int plural_eval PARAMS ((struct expression *pexp,
+					      unsigned long int n));
+#endif
+
+#endif /* _PLURAL_EXP_H */

+ 1518 - 0
intl/plural.c

@@ -0,0 +1,1518 @@
+/* A Bison parser, made from plural.y
+   by GNU bison 1.35.  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define yyparse __gettextparse
+#define yylex __gettextlex
+#define yyerror __gettexterror
+#define yylval __gettextlval
+#define yychar __gettextchar
+#define yydebug __gettextdebug
+#define yynerrs __gettextnerrs
+# define	EQUOP2	257
+# define	CMPOP2	258
+# define	ADDOP2	259
+# define	MULOP2	260
+# define	NUMBER	261
+
+#line 1 "plural.y"
+
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* 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.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.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
+
+#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM	arg
+
+#line 49 "plural.y"
+#ifndef YYSTYPE
+typedef union {
+  unsigned long int num;
+  enum operator op;
+  struct expression *exp;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+#line 55 "plural.y"
+
+/* Prototypes for local functions.  */
+static struct expression *new_exp PARAMS ((int nargs, enum operator op,
+					   struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline struct expression *new_exp_1 PARAMS ((enum operator op,
+						   struct expression *right));
+static struct expression *new_exp_2 PARAMS ((enum operator op,
+					     struct expression *left,
+					     struct expression *right));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+						   struct expression *bexp,
+						   struct expression *tbranch,
+						   struct expression *fbranch));
+static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
+static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum 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 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum 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 (op, bexp, tbranch, fbranch)
+     enum 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);
+}
+
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+
+
+#define	YYFINAL		27
+#define	YYFLAG		-32768
+#define	YYNTBASE	16
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char 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,     6,     7,     8,
+       9,    11
+};
+
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     2,     8,    12,    16,    20,    24,    28,    32,
+      35,    37,    39
+};
+static const short yyrhs[] =
+{
+      17,     0,    17,     3,    17,    12,    17,     0,    17,     4,
+      17,     0,    17,     5,    17,     0,    17,     6,    17,     0,
+      17,     7,    17,     0,    17,     8,    17,     0,    17,     9,
+      17,     0,    10,    17,     0,    13,     0,    11,     0,    14,
+      17,    15,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   174,   182,   186,   190,   194,   198,   202,   206,   210,
+     214,   218,   223
+};
+#endif
+
+
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2", 
+  "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'", 
+  "start", "exp", 0
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    16,    17,    17,    17,    17,    17,    17,    17,    17,
+      17,    17,    17
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     1,     5,     3,     3,     3,     3,     3,     3,     2,
+       1,     1,     3
+};
+
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+       0,     0,    11,    10,     0,     1,     9,     0,     0,     0,
+       0,     0,     0,     0,     0,    12,     0,     3,     4,     5,
+       6,     7,     8,     0,     2,     0,     0,     0
+};
+
+static const short yydefgoto[] =
+{
+      25,     5
+};
+
+static const short yypact[] =
+{
+      -9,    -9,-32768,-32768,    -9,    34,-32768,    11,    -9,    -9,
+      -9,    -9,    -9,    -9,    -9,-32768,    24,    39,    43,    16,
+      26,    -3,-32768,    -9,    34,    21,    53,-32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,    -1
+};
+
+
+#define	YYLAST		53
+
+
+static const short yytable[] =
+{
+       6,     1,     2,     7,     3,     4,    14,    16,    17,    18,
+      19,    20,    21,    22,     8,     9,    10,    11,    12,    13,
+      14,    26,    24,    12,    13,    14,    15,     8,     9,    10,
+      11,    12,    13,    14,    13,    14,    23,     8,     9,    10,
+      11,    12,    13,    14,    10,    11,    12,    13,    14,    11,
+      12,    13,    14,    27
+};
+
+static const short yycheck[] =
+{
+       1,    10,    11,     4,    13,    14,     9,     8,     9,    10,
+      11,    12,    13,    14,     3,     4,     5,     6,     7,     8,
+       9,     0,    23,     7,     8,     9,    15,     3,     4,     5,
+       6,     7,     8,     9,     8,     9,    12,     3,     4,     5,
+       6,     7,     8,     9,     5,     6,     7,     8,     9,     6,
+       7,     8,     9,     0
+};
+#define YYPURE 1
+
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/local/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* 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.  */
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+	 || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))	\
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  register YYSIZE_T yyi;		\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (0)
+#  endif
+# endif
+
+/* 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)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;	\
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (0)
+
+#endif
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#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 yyerrlab1
+/* 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.  */
+#define YYFAIL		goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { 								\
+      yyerror ("syntax error: cannot back up");			\
+      YYERROR;							\
+    }								\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)       	\
+   Current.last_line   = Rhs[N].last_line;	\
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX		yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX		yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX		yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX		yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX			yylex ()
+#endif /* !YYPURE */
+
+
+/* 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 (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#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
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  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.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+
+#line 315 "/usr/local/share/bison/bison.simple"
+
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES			\
+/* The lookahead symbol.  */				\
+int yychar;						\
+							\
+/* The semantic value of the lookahead symbol. */	\
+YYSTYPE yylval;						\
+							\
+/* Number of parse errors so far.  */			\
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES			\
+YY_DECL_NON_LSP_VARIABLES			\
+						\
+/* Location data for the lookahead symbol.  */	\
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES			\
+YY_DECL_NON_LSP_VARIABLES
+#endif
+
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack. */
+  short	yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+#endif
+
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+# define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+#if YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+  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 (yyssp >= yyss + yystacksize - 1)
+    {
+      /* 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;
+	short *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+	YYLTYPE *yyls1 = yyls;
+	/* This used to be a conditional around just the two extra args,
+	   but that might be undefined if yyoverflow is a macro.  */
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yyls1, yysize * sizeof (*yylsp),
+		    &yystacksize);
+	yyls = yyls1;
+# else
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+# endif
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	short *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyoverflowlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+# if YYLSP_NEEDED
+	YYSTACK_RELOCATE (yyls);
+# endif
+# undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
+#endif
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  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.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+	which are defined only if `YYDEBUG' is set.  */
+      if (yydebug)
+	{
+	  YYFPRINTF (stderr, "Next token is %d (%s",
+		     yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise
+	     meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+# endif
+	  YYFPRINTF (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+	      yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  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 the semantic value of
+     the lookahead token.  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];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+		 yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+	YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+  switch (yyn) {
+
+case 1:
+#line 175 "plural.y"
+{
+	    if (yyvsp[0].exp == NULL)
+	      YYABORT;
+	    ((struct parse_args *) arg)->res = yyvsp[0].exp;
+	  }
+    break;
+case 2:
+#line 183 "plural.y"
+{
+	    yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 3:
+#line 187 "plural.y"
+{
+	    yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 4:
+#line 191 "plural.y"
+{
+	    yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 5:
+#line 195 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 6:
+#line 199 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 7:
+#line 203 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 8:
+#line 207 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  }
+    break;
+case 9:
+#line 211 "plural.y"
+{
+	    yyval.exp = new_exp_1 (lnot, yyvsp[0].exp);
+	  }
+    break;
+case 10:
+#line 215 "plural.y"
+{
+	    yyval.exp = new_exp_0 (var);
+	  }
+    break;
+case 11:
+#line 219 "plural.y"
+{
+	    if ((yyval.exp = new_exp_0 (num)) != NULL)
+	      yyval.exp->val.num = yyvsp[0].num;
+	  }
+    break;
+case 12:
+#line 224 "plural.y"
+{
+	    yyval.exp = yyvsp[-1].exp;
+	  }
+    break;
+}
+
+#line 705 "/usr/local/share/bison/bison.simple"
+
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+	YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* 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 - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  YYSIZE_T yysize = 0;
+	  char *yymsg;
+	  int yyx, yycount;
+
+	  yycount = 0;
+	  /* Start YYX at -YYN if negative to avoid negative indexes in
+	     YYCHECK.  */
+	  for (yyx = yyn < 0 ? -yyn : 0;
+	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+	    if (yycheck[yyx + yyn] == yyx)
+	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+	  yysize += yystrlen ("parse error, unexpected ") + 1;
+	  yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+	  yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg != 0)
+	    {
+	      char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+	      yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+	      if (yycount < 5)
+		{
+		  yycount = 0;
+		  for (yyx = yyn < 0 ? -yyn : 0;
+		       yyx < (int) (sizeof (yytname) / sizeof (char *));
+		       yyx++)
+		    if (yycheck[yyx + yyn] == yyx)
+		      {
+			const char *yyq = ! yycount ? ", expecting " : " or ";
+			yyp = yystpcpy (yyp, yyq);
+			yyp = yystpcpy (yyp, yytname[yyx]);
+			yycount++;
+		      }
+		}
+	      yyerror (yymsg);
+	      YYSTACK_FREE (yymsg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exhausted");
+	}
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+	yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+		  yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+	YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 229 "plural.y"
+
+
+void
+internal_function
+FREE_EXPRESSION (exp)
+     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 (lval, pexp)
+     YYSTYPE *lval;
+     const char **pexp;
+{
+  const char *exp = *pexp;
+  int result;
+
+  while (1)
+    {
+      if (exp[0] == '\0')
+	{
+	  *pexp = 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;
+    }
+
+  *pexp = exp;
+
+  return result;
+}
+
+
+static void
+yyerror (str)
+     const char *str;
+{
+  /* Do nothing.  We don't print error messages here.  */
+}

+ 409 - 0
intl/plural.y

@@ -0,0 +1,409 @@
+%{
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 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 Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* 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.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.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
+
+#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM	arg
+%}
+%pure_parser
+%expect 7
+
+%union {
+  unsigned long int num;
+  enum operator op;
+  struct expression *exp;
+}
+
+%{
+/* Prototypes for local functions.  */
+static struct expression *new_exp PARAMS ((int nargs, enum operator op,
+					   struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline struct expression *new_exp_1 PARAMS ((enum operator op,
+						   struct expression *right));
+static struct expression *new_exp_2 PARAMS ((enum operator op,
+					     struct expression *left,
+					     struct expression *right));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+						   struct expression *bexp,
+						   struct expression *tbranch,
+						   struct expression *fbranch));
+static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
+static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum 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 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum 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 (op, bexp, tbranch, fbranch)
+     enum 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;
+	    ((struct parse_args *) 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 (exp)
+     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 (lval, pexp)
+     YYSTYPE *lval;
+     const char **pexp;
+{
+  const char *exp = *pexp;
+  int result;
+
+  while (1)
+    {
+      if (exp[0] == '\0')
+	{
+	  *pexp = 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;
+    }
+
+  *pexp = exp;
+
+  return result;
+}
+
+
+static void
+yyerror (str)
+     const char *str;
+{
+  /* Do nothing.  We don't print error messages here.  */
+}

+ 31 - 0
intl/ref-add.sin

@@ -0,0 +1,31 @@
+# Add this package to a list of references stored in a text file.
+#
+#   Copyright (C) 2000 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Library 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
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#   USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  ta
+  :a
+  s/ @PACKAGE@ / @PACKAGE@ /
+  tb
+  s/ $/ @PACKAGE@ /
+  :b
+  s/^/# Packages using this file:/
+}

+ 26 - 0
intl/ref-del.sin

@@ -0,0 +1,26 @@
+# Remove this package from a list of references stored in a text file.
+#
+#   Copyright (C) 2000 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Library 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
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#   USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  s/ @PACKAGE@ / /
+  s/^/# Packages using this file:/
+}

+ 439 - 0
intl/relocatable.c

@@ -0,0 +1,439 @@
+/* Provide relocatable packages.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+
+/* Tell glibc's <stdio.h> to provide a prototype for getline().
+   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
+
+/* Specification.  */
+#include "relocatable.h"
+
+#if ENABLE_RELOCATABLE
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NO_XMALLOC
+# define xmalloc malloc
+#else
+# include "xmalloc.h"
+#endif
+
+#if DEPENDS_ON_LIBCHARSET
+# include <libcharset.h>
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV
+# include <iconv.h>
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS
+# include <libintl.h>
+#endif
+
+/* Faked cheap 'bool'.  */
+#undef bool
+#undef false
+#undef true
+#define bool int
+#define false 0
+#define true 1
+
+/* Pathname support.
+   ISSLASH(C)           tests whether C is a directory separator character.
+   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, 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_PATH_WITH_DIR(P) \
+    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+# define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
+#else
+  /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+# define FILESYSTEM_PREFIX_LEN(P) 0
+#endif
+
+/* Original installation prefix.  */
+static char *orig_prefix;
+static size_t orig_prefix_len;
+/* Current installation prefix.  */
+static char *curr_prefix;
+static size_t curr_prefix_len;
+/* These prefixes do not end in a slash.  Anything that will be concatenated
+   to them must start with a slash.  */
+
+/* Sets the original and the current installation prefix of this module.
+   Relocation simply replaces a pathname starting with the original prefix
+   by the corresponding pathname with the current prefix instead.  Both
+   prefixes should be directory names without trailing slash (i.e. use ""
+   instead of "/").  */
+static void
+set_this_relocation_prefix (const char *orig_prefix_arg,
+			    const char *curr_prefix_arg)
+{
+  if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
+      /* Optimization: if orig_prefix and curr_prefix are equal, the
+	 relocation is a nop.  */
+      && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
+    {
+      /* Duplicate the argument strings.  */
+      char *memory;
+
+      orig_prefix_len = strlen (orig_prefix_arg);
+      curr_prefix_len = strlen (curr_prefix_arg);
+      memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
+#ifdef NO_XMALLOC
+      if (memory != NULL)
+#endif
+	{
+	  memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
+	  orig_prefix = memory;
+	  memory += orig_prefix_len + 1;
+	  memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
+	  curr_prefix = memory;
+	  return;
+	}
+    }
+  orig_prefix = NULL;
+  curr_prefix = NULL;
+  /* Don't worry about wasted memory here - this function is usually only
+     called once.  */
+}
+
+/* Sets the original and the current installation prefix of the package.
+   Relocation simply replaces a pathname starting with the original prefix
+   by the corresponding pathname with the current prefix instead.  Both
+   prefixes should be directory names without trailing slash (i.e. use ""
+   instead of "/").  */
+void
+set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
+{
+  set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+
+  /* Now notify all dependent libraries.  */
+#if DEPENDS_ON_LIBCHARSET
+  libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
+  libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
+  libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+}
+
+/* Convenience function:
+   Computes the current installation prefix, based on the original
+   installation prefix, the original installation directory of a particular
+   file, and the current pathname of this file.  Returns NULL upon failure.  */
+#ifdef IN_LIBRARY
+#define compute_curr_prefix local_compute_curr_prefix
+static
+#endif
+const char *
+compute_curr_prefix (const char *orig_installprefix,
+		     const char *orig_installdir,
+		     const char *curr_pathname)
+{
+  const char *curr_installdir;
+  const char *rel_installdir;
+
+  if (curr_pathname == NULL)
+    return NULL;
+
+  /* Determine the relative installation directory, relative to the prefix.
+     This is simply the difference between orig_installprefix and
+     orig_installdir.  */
+  if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
+      != 0)
+    /* Shouldn't happen - nothing should be installed outside $(prefix).  */
+    return NULL;
+  rel_installdir = orig_installdir + strlen (orig_installprefix);
+
+  /* Determine the current installation directory.  */
+  {
+    const char *p_base = curr_pathname + FILESYSTEM_PREFIX_LEN (curr_pathname);
+    const char *p = curr_pathname + strlen (curr_pathname);
+    char *q;
+
+    while (p > p_base)
+      {
+	p--;
+	if (ISSLASH (*p))
+	  break;
+      }
+
+    q = (char *) xmalloc (p - curr_pathname + 1);
+#ifdef NO_XMALLOC
+    if (q == NULL)
+      return NULL;
+#endif
+    memcpy (q, curr_pathname, p - curr_pathname);
+    q[p - curr_pathname] = '\0';
+    curr_installdir = q;
+  }
+
+  /* Compute the current installation prefix by removing the trailing
+     rel_installdir from it.  */
+  {
+    const char *rp = rel_installdir + strlen (rel_installdir);
+    const char *cp = curr_installdir + strlen (curr_installdir);
+    const char *cp_base =
+      curr_installdir + FILESYSTEM_PREFIX_LEN (curr_installdir);
+
+    while (rp > rel_installdir && cp > cp_base)
+      {
+	bool same = false;
+	const char *rpi = rp;
+	const char *cpi = cp;
+
+	while (rpi > rel_installdir && cpi > cp_base)
+	  {
+	    rpi--;
+	    cpi--;
+	    if (ISSLASH (*rpi) || ISSLASH (*cpi))
+	      {
+		if (ISSLASH (*rpi) && ISSLASH (*cpi))
+		  same = true;
+		break;
+	      }
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+	    /* Win32, OS/2, DOS - case insignificant filesystem */
+	    if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
+		!= (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
+	      break;
+#else
+	    if (*rpi != *cpi)
+	      break;
+#endif
+	  }
+	if (!same)
+	  break;
+	/* The last pathname component was the same.  opi and cpi now point
+	   to the slash before it.  */
+	rp = rpi;
+	cp = cpi;
+      }
+
+    if (rp > rel_installdir)
+      /* Unexpected: The curr_installdir does not end with rel_installdir.  */
+      return NULL;
+
+    {
+      size_t curr_prefix_len = cp - curr_installdir;
+      char *curr_prefix;
+
+      curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
+#ifdef NO_XMALLOC
+      if (curr_prefix == NULL)
+	return NULL;
+#endif
+      memcpy (curr_prefix, curr_installdir, curr_prefix_len);
+      curr_prefix[curr_prefix_len] = '\0';
+
+      return curr_prefix;
+    }
+  }
+}
+
+#if defined PIC && defined INSTALLDIR
+
+/* Full pathname of shared library, or NULL.  */
+static char *shared_library_fullname;
+
+#if defined _WIN32 || defined __WIN32__
+
+/* Determine the full pathname of the shared library when it is loaded.  */
+
+BOOL WINAPI
+DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
+{
+  (void) reserved;
+
+  if (event == DLL_PROCESS_ATTACH)
+    {
+      /* The DLL is being loaded into an application's address range.  */
+      static char location[MAX_PATH];
+
+      if (!GetModuleFileName (module_handle, location, sizeof (location)))
+	/* Shouldn't happen.  */
+	return FALSE;
+
+      if (!IS_PATH_WITH_DIR (location))
+	/* Shouldn't happen.  */
+	return FALSE;
+
+      shared_library_fullname = strdup (location);
+    }
+
+  return TRUE;
+}
+
+#else /* Unix */
+
+static void
+find_shared_library_fullname ()
+{
+#ifdef __linux__
+  FILE *fp;
+
+  /* Open the current process' maps file.  It describes one VMA per line.  */
+  fp = fopen ("/proc/self/maps", "r");
+  if (fp)
+    {
+      unsigned long address = (unsigned long) &find_shared_library_fullname;
+      for (;;)
+	{
+	  unsigned long start, end;
+	  int c;
+
+	  if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
+	    break;
+	  if (address >= start && address <= end - 1)
+	    {
+	      /* Found it.  Now see if this line contains a filename.  */
+	      while (c = getc (fp), c != EOF && c != '\n' && c != '/')
+		continue;
+	      if (c == '/')
+		{
+		  size_t size;
+		  int len;
+
+		  ungetc (c, fp);
+		  shared_library_fullname = NULL; size = 0;
+		  len = getline (&shared_library_fullname, &size, fp);
+		  if (len >= 0)
+		    {
+		      /* Success: filled shared_library_fullname.  */
+		      if (len > 0 && shared_library_fullname[len - 1] == '\n')
+			shared_library_fullname[len - 1] = '\0';
+		    }
+		}
+	      break;
+	    }
+	  while (c = getc (fp), c != EOF && c != '\n')
+	    continue;
+	}
+      fclose (fp);
+    }
+#endif
+}
+
+#endif /* WIN32 / Unix */
+
+/* Return the full pathname of the current shared library.
+   Return NULL if unknown.
+   Guaranteed to work only on Linux and Woe32.  */
+static char *
+get_shared_library_fullname ()
+{
+#if !(defined _WIN32 || defined __WIN32__)
+  static bool tried_find_shared_library_fullname;
+  if (!tried_find_shared_library_fullname)
+    {
+      find_shared_library_fullname ();
+      tried_find_shared_library_fullname = true;
+    }
+#endif
+  return shared_library_fullname;
+}
+
+#endif /* PIC */
+
+/* Returns the pathname, relocated according to the current installation
+   directory.  */
+const char *
+relocate (const char *pathname)
+{
+#if defined PIC && defined INSTALLDIR
+  static int initialized;
+
+  /* Initialization code for a shared library.  */
+  if (!initialized)
+    {
+      /* At this point, orig_prefix and curr_prefix likely have already been
+	 set through the main program's set_program_name_and_installdir
+	 function.  This is sufficient in the case that the library has
+	 initially been installed in the same orig_prefix.  But we can do
+	 better, to also cover the cases that 1. it has been installed
+	 in a different prefix before being moved to orig_prefix and (later)
+	 to curr_prefix, 2. unlike the program, it has not moved away from
+	 orig_prefix.  */
+      const char *orig_installprefix = INSTALLPREFIX;
+      const char *orig_installdir = INSTALLDIR;
+      const char *curr_prefix_better;
+
+      curr_prefix_better =
+	compute_curr_prefix (orig_installprefix, orig_installdir,
+			     get_shared_library_fullname ());
+      if (curr_prefix_better == NULL)
+	curr_prefix_better = curr_prefix;
+
+      set_relocation_prefix (orig_installprefix, curr_prefix_better);
+
+      initialized = 1;
+    }
+#endif
+
+  /* Note: It is not necessary to perform case insensitive comparison here,
+     even for DOS-like filesystems, because the pathname argument was
+     typically created from the same Makefile variable as orig_prefix came
+     from.  */
+  if (orig_prefix != NULL && curr_prefix != NULL
+      && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
+    {
+      if (pathname[orig_prefix_len] == '\0')
+	/* pathname equals orig_prefix.  */
+	return curr_prefix;
+      if (ISSLASH (pathname[orig_prefix_len]))
+	{
+	  /* pathname starts with orig_prefix.  */
+	  const char *pathname_tail = &pathname[orig_prefix_len];
+	  char *result =
+	    (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
+
+#ifdef NO_XMALLOC
+	  if (result != NULL)
+#endif
+	    {
+	      memcpy (result, curr_prefix, curr_prefix_len);
+	      strcpy (result + curr_prefix_len, pathname_tail);
+	      return result;
+	    }
+	}
+    }
+  /* Nothing to relocate.  */
+  return pathname;
+}
+
+#endif

+ 67 - 0
intl/relocatable.h

@@ -0,0 +1,67 @@
+/* Provide relocatable packages.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef _RELOCATABLE_H
+#define _RELOCATABLE_H
+
+/* This can be enabled through the configure --enable-relocatable option.  */
+#if ENABLE_RELOCATABLE
+
+/* When building a DLL, we must export some functions.  Note that because
+   this is a private .h file, we don't need to use __declspec(dllimport)
+   in any case.  */
+#if defined _MSC_VER && BUILDING_DLL
+# define RELOCATABLE_DLL_EXPORTED __declspec(dllexport)
+#else
+# define RELOCATABLE_DLL_EXPORTED
+#endif
+
+/* Sets the original and the current installation prefix of the package.
+   Relocation simply replaces a pathname starting with the original prefix
+   by the corresponding pathname with the current prefix instead.  Both
+   prefixes should be directory names without trailing slash (i.e. use ""
+   instead of "/").  */
+extern RELOCATABLE_DLL_EXPORTED void
+       set_relocation_prefix (const char *orig_prefix,
+			      const char *curr_prefix);
+
+/* Returns the pathname, relocated according to the current installation
+   directory.  */
+extern const char * relocate (const char *pathname);
+
+/* Memory management: relocate() leaks memory, because it has to construct
+   a fresh pathname.  If this is a problem because your program calls
+   relocate() frequently, think about caching the result.  */
+
+/* Convenience function:
+   Computes the current installation prefix, based on the original
+   installation prefix, the original installation directory of a particular
+   file, and the current pathname of this file.  Returns NULL upon failure.  */
+extern const char * compute_curr_prefix (const char *orig_installprefix,
+					 const char *orig_installdir,
+					 const char *curr_pathname);
+
+#else
+
+/* By default, we use the hardwired pathnames.  */
+#define relocate(pathname) (pathname)
+
+#endif
+
+#endif /* _RELOCATABLE_H */

+ 142 - 0
intl/textdomain.c

@@ -0,0 +1,142 @@
+/* Implementation of the textdomain(3) function.
+   Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "gettextP.h"
+
+#ifdef _LIBC
+/* We have to handle multi-threaded applications.  */
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_rwlock_define(CLASS, NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#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_default_domain libintl_nl_default_default_domain
+# define _nl_current_default_domain libintl_nl_current_default_domain
+#endif
+
+/* @@ end of prolog @@ */
+
+/* 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;
+
+
+/* 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.  */
+__libc_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 (domainname)
+     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;
+
+  __libc_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);
+    }
+
+  __libc_rwlock_unlock (_nl_state_lock);
+
+  return new_domain;
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__textdomain, textdomain);
+#endif

+ 21 - 5
m4/Makefile.in

@@ -38,11 +38,16 @@ host_triplet = @host@
 subdir = m4
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
-	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
-	$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
-	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
-	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
+	$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
+	$(top_srcdir)/m4/inttypes-pri.m4 $(top_srcdir)/m4/inttypes.m4 \
+	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
+	$(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.in
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -52,6 +57,7 @@ SOURCES =
 DIST_SOURCES =
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
 AMDEP_FALSE = @AMDEP_FALSE@
 AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
@@ -59,6 +65,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -71,6 +79,7 @@ CXX = @CXX@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 ECHO_C = @ECHO_C@
@@ -78,12 +87,18 @@ ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
 GMSGFMT = @GMSGFMT@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
 INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
 LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
@@ -109,6 +124,7 @@ RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@

+ 4 - 2
src/Makefile.am

@@ -48,7 +48,9 @@ SRCS =  Socket.cc Socket.h\
 	CookieBox.cc CookieBox.h
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
-aria2c_LDADD = libaria2c.a
-FLAGS =  -I../lib -Wall -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\"
+aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@
+FLAGS =  -Wall
+INCLUDES = -I../lib -I../intl -I$(top_srcdir)/intl
+DEFS = -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@
 libaria2c_a_CXXFLAGS = $(FLAGS)
 aria2c_CXXFLAGS = $(FLAGS)

+ 30 - 12
src/Makefile.in

@@ -39,13 +39,18 @@ build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = aria2c$(EXEEXT)
 subdir = src
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
-	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
-	$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
-	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
-	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
+	$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
+	$(top_srcdir)/m4/inttypes-pri.m4 $(top_srcdir)/m4/inttypes.m4 \
+	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
+	$(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.in
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -96,7 +101,7 @@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
 am_aria2c_OBJECTS = aria2c-main.$(OBJEXT)
 aria2c_OBJECTS = $(am_aria2c_OBJECTS)
-aria2c_DEPENDENCIES = libaria2c.a
+aria2c_DEPENDENCIES = libaria2c.a @ALLOCA@
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -115,6 +120,7 @@ ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
 AMDEP_FALSE = @AMDEP_FALSE@
 AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
@@ -122,6 +128,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -134,19 +142,26 @@ CXX = @CXX@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
+DATADIRNAME = @DATADIRNAME@
+DEFS = -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@
 DEPDIR = @DEPDIR@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
 GMSGFMT = @GMSGFMT@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
 INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
 LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
@@ -172,6 +187,7 @@ RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
@@ -267,8 +283,9 @@ SRCS = Socket.cc Socket.h\
 
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
-aria2c_LDADD = libaria2c.a
-FLAGS = -I../lib -Wall -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\"
+aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@
+FLAGS = -Wall
+INCLUDES = -I../lib -I../intl -I$(top_srcdir)/intl
 libaria2c_a_CXXFLAGS = $(FLAGS)
 aria2c_CXXFLAGS = $(FLAGS)
 all: all-am
@@ -344,6 +361,7 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-AbstractCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-AbstractDiskWriter.Po@am__quote@
@@ -1027,7 +1045,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \
 	mostlyclean-am
 
 distclean: distclean-am
-	-rm -rf ./$(DEPDIR)
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
@@ -1053,7 +1071,7 @@ install-man:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-am
-	-rm -rf ./$(DEPDIR)
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 

+ 504 - 0
src/alloca.c

@@ -0,0 +1,504 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+   J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef emacs
+# include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed.  */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+   there must be some other way alloca is supposed to work.  */
+# ifndef alloca
+
+#  ifdef emacs
+#   ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#    ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#    endif /* STACK_DIRECTION undefined */
+#   endif /* static */
+#  endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+   provide an "address metric" ADDRESS_FUNCTION macro.  */
+
+#  if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#   define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#  else
+#   define ADDRESS_FUNCTION(arg) &(arg)
+#  endif
+
+#  if __STDC__
+typedef void *pointer;
+#  else
+typedef char *pointer;
+#  endif
+
+#  ifndef NULL
+#   define NULL 0
+#  endif
+
+/* Different portions of Emacs need to call different versions of
+   malloc.  The Emacs executable needs alloca to call xmalloc, because
+   ordinary malloc isn't protected from input signals.  On the other
+   hand, the utilities in lib-src need alloca to call malloc; some of
+   them are very simple, and don't have an xmalloc routine.
+
+   Non-Emacs programs expect this to call xmalloc.
+
+   Callers below should use malloc.  */
+
+#  ifndef emacs
+#   undef malloc
+#   define malloc xmalloc
+#  endif
+extern pointer malloc ();
+
+/* Define STACK_DIRECTION if you know the direction of stack
+   growth for your system; otherwise it will be automatically
+   deduced at run-time.
+
+   STACK_DIRECTION > 0 => grows toward higher addresses
+   STACK_DIRECTION < 0 => grows toward lower addresses
+   STACK_DIRECTION = 0 => direction of growth unknown  */
+
+#  ifndef STACK_DIRECTION
+#   define STACK_DIRECTION	0	/* Direction unknown.  */
+#  endif
+
+#  if STACK_DIRECTION != 0
+
+#   define STACK_DIR	STACK_DIRECTION	/* Known at compile-time.  */
+
+#  else /* STACK_DIRECTION == 0; need run-time code.  */
+
+static int stack_dir;		/* 1 or -1 once known.  */
+#   define STACK_DIR	stack_dir
+
+static void
+find_stack_direction ()
+{
+  static char *addr = NULL;	/* Address of first `dummy', once known.  */
+  auto char dummy;		/* To get stack address.  */
+
+  if (addr == NULL)
+    {				/* Initial entry.  */
+      addr = ADDRESS_FUNCTION (dummy);
+
+      find_stack_direction ();	/* Recurse once.  */
+    }
+  else
+    {
+      /* Second entry.  */
+      if (ADDRESS_FUNCTION (dummy) > addr)
+	stack_dir = 1;		/* Stack grew upward.  */
+      else
+	stack_dir = -1;		/* Stack grew downward.  */
+    }
+}
+
+#  endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+   (a) chain together all alloca'ed blocks;
+   (b) keep track of stack depth.
+
+   It is very important that sizeof(header) agree with malloc
+   alignment chunk size.  The following default should work okay.  */
+
+#  ifndef	ALIGN_SIZE
+#   define ALIGN_SIZE	sizeof(double)
+#  endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];	/* To force sizeof(header).  */
+  struct
+    {
+      union hdr *next;		/* For chaining headers.  */
+      char *deep;		/* For stack depth measure.  */
+    } h;
+} header;
+
+static header *last_alloca_header = NULL;	/* -> last alloca header.  */
+
+/* Return a pointer to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+pointer
+alloca (size_t size)
+{
+  auto char probe;		/* Probes stack depth: */
+  register char *depth = ADDRESS_FUNCTION (probe);
+
+#  if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)		/* Unknown growth direction.  */
+    find_stack_direction ();
+#  endif
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently.  */
+
+  {
+    register header *hp;	/* Traverses linked list.  */
+
+#  ifdef emacs
+    BLOCK_INPUT;
+#  endif
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+	  || (STACK_DIR < 0 && hp->h.deep < depth))
+	{
+	  register header *np = hp->h.next;
+
+	  free ((pointer) hp);	/* Collect garbage.  */
+
+	  hp = np;		/* -> next header.  */
+	}
+      else
+	break;			/* Rest are not deeper.  */
+
+    last_alloca_header = hp;	/* -> last valid storage.  */
+
+#  ifdef emacs
+    UNBLOCK_INPUT;
+#  endif
+  }
+
+  if (size == 0)
+    return NULL;		/* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    register pointer new = malloc (sizeof (header) + size);
+    /* Address of header.  */
+
+    if (new == 0)
+      abort();
+
+    ((header *) new)->h.next = last_alloca_header;
+    ((header *) new)->h.deep = depth;
+
+    last_alloca_header = (header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (pointer) ((char *) new + sizeof (header));
+  }
+}
+
+#  if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#   ifdef DEBUG_I00AFUNC
+#    include <stdio.h>
+#   endif
+
+#   ifndef CRAY_STACK
+#    define CRAY_STACK
+#    ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+  {
+    long shgrow:32;		/* Number of times stack has grown.  */
+    long shaseg:32;		/* Size of increments to stack.  */
+    long shhwm:32;		/* High water mark of stack.  */
+    long shsize:32;		/* Current size of stack (all segments).  */
+  };
+
+/* The stack segment linkage control information occurs at
+   the high-address end of a stack segment.  (The stack
+   grows from low addresses to high addresses.)  The initial
+   part of the stack segment linkage control information is
+   0200 (octal) words.  This provides for register storage
+   for the routine which overflows the stack.  */
+
+struct stack_segment_linkage
+  {
+    long ss[0200];		/* 0200 overflow words.  */
+    long sssize:32;		/* Number of words in this segment.  */
+    long ssbase:32;		/* Offset to stack base.  */
+    long:32;
+    long sspseg:32;		/* Offset to linkage control of previous
+				   segment of stack.  */
+    long:32;
+    long sstcpt:32;		/* Pointer to task common address block.  */
+    long sscsnm;		/* Private control structure number for
+				   microtasking.  */
+    long ssusr1;		/* Reserved for user.  */
+    long ssusr2;		/* Reserved for user.  */
+    long sstpid;		/* Process ID for pid based multi-tasking.  */
+    long ssgvup;		/* Pointer to multitasking thread giveup.  */
+    long sscray[7];		/* Reserved for Cray Research.  */
+    long ssa0;
+    long ssa1;
+    long ssa2;
+    long ssa3;
+    long ssa4;
+    long ssa5;
+    long ssa6;
+    long ssa7;
+    long sss0;
+    long sss1;
+    long sss2;
+    long sss3;
+    long sss4;
+    long sss5;
+    long sss6;
+    long sss7;
+  };
+
+#    else /* CRAY2 */
+/* The following structure defines the vector of words
+   returned by the STKSTAT library routine.  */
+struct stk_stat
+  {
+    long now;			/* Current total stack size.  */
+    long maxc;			/* Amount of contiguous space which would
+				   be required to satisfy the maximum
+				   stack demand to date.  */
+    long high_water;		/* Stack high-water mark.  */
+    long overflows;		/* Number of stack overflow ($STKOFEN) calls.  */
+    long hits;			/* Number of internal buffer hits.  */
+    long extends;		/* Number of block extensions.  */
+    long stko_mallocs;		/* Block allocations by $STKOFEN.  */
+    long underflows;		/* Number of stack underflow calls ($STKRETN).  */
+    long stko_free;		/* Number of deallocations by $STKRETN.  */
+    long stkm_free;		/* Number of deallocations by $STKMRET.  */
+    long segments;		/* Current number of stack segments.  */
+    long maxs;			/* Maximum number of stack segments so far.  */
+    long pad_size;		/* Stack pad size.  */
+    long current_address;	/* Current stack segment address.  */
+    long current_size;		/* Current stack segment size.  This
+				   number is actually corrupted by STKSTAT to
+				   include the fifteen word trailer area.  */
+    long initial_address;	/* Address of initial segment.  */
+    long initial_size;		/* Size of initial segment.  */
+  };
+
+/* The following structure describes the data structure which trails
+   any stack segment.  I think that the description in 'asdef' is
+   out of date.  I only describe the parts that I am sure about.  */
+
+struct stk_trailer
+  {
+    long this_address;		/* Address of this block.  */
+    long this_size;		/* Size of this block (does not include
+				   this trailer).  */
+    long unknown2;
+    long unknown3;
+    long link;			/* Address of trailer block of previous
+				   segment.  */
+    long unknown5;
+    long unknown6;
+    long unknown7;
+    long unknown8;
+    long unknown9;
+    long unknown10;
+    long unknown11;
+    long unknown12;
+    long unknown13;
+    long unknown14;
+  };
+
+#    endif /* CRAY2 */
+#   endif /* not CRAY_STACK */
+
+#   ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+   I doubt that "lint" will like this much.  */
+
+static long
+i00afunc (long *address)
+{
+  struct stk_stat status;
+  struct stk_trailer *trailer;
+  long *block, size;
+  long result = 0;
+
+  /* We want to iterate through all of the segments.  The first
+     step is to get the stack status structure.  We could do this
+     more quickly and more directly, perhaps, by referencing the
+     $LM00 common block, but I know that this works.  */
+
+  STKSTAT (&status);
+
+  /* Set up the iteration.  */
+
+  trailer = (struct stk_trailer *) (status.current_address
+				    + status.current_size
+				    - 15);
+
+  /* There must be at least one stack segment.  Therefore it is
+     a fatal error if "trailer" is null.  */
+
+  if (trailer == 0)
+    abort ();
+
+  /* Discard segments that do not contain our argument address.  */
+
+  while (trailer != 0)
+    {
+      block = (long *) trailer->this_address;
+      size = trailer->this_size;
+      if (block == 0 || size == 0)
+	abort ();
+      trailer = (struct stk_trailer *) trailer->link;
+      if ((block <= address) && (address < (block + size)))
+	break;
+    }
+
+  /* Set the result to the offset in this segment and add the sizes
+     of all predecessor segments.  */
+
+  result = address - block;
+
+  if (trailer == 0)
+    {
+      return result;
+    }
+
+  do
+    {
+      if (trailer->this_size <= 0)
+	abort ();
+      result += trailer->this_size;
+      trailer = (struct stk_trailer *) trailer->link;
+    }
+  while (trailer != 0);
+
+  /* We are done.  Note that if you present a bogus address (one
+     not in any segment), you will get a different number back, formed
+     from subtracting the address of the first block.  This is probably
+     not what you want.  */
+
+  return (result);
+}
+
+#   else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+   Determine the number of the cell within the stack,
+   given the address of the cell.  The purpose of this
+   routine is to linearize, in some sense, stack addresses
+   for alloca.  */
+
+static long
+i00afunc (long address)
+{
+  long stkl = 0;
+
+  long size, pseg, this_segment, stack;
+  long result = 0;
+
+  struct stack_segment_linkage *ssptr;
+
+  /* Register B67 contains the address of the end of the
+     current stack segment.  If you (as a subprogram) store
+     your registers on the stack and find that you are past
+     the contents of B67, you have overflowed the segment.
+
+     B67 also points to the stack segment linkage control
+     area, which is what we are really interested in.  */
+
+  stkl = CRAY_STACKSEG_END ();
+  ssptr = (struct stack_segment_linkage *) stkl;
+
+  /* If one subtracts 'size' from the end of the segment,
+     one has the address of the first word of the segment.
+
+     If this is not the first segment, 'pseg' will be
+     nonzero.  */
+
+  pseg = ssptr->sspseg;
+  size = ssptr->sssize;
+
+  this_segment = stkl - size;
+
+  /* It is possible that calling this routine itself caused
+     a stack overflow.  Discard stack segments which do not
+     contain the target address.  */
+
+  while (!(this_segment <= address && address <= stkl))
+    {
+#    ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#    endif
+      if (pseg == 0)
+	break;
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      this_segment = stkl - size;
+    }
+
+  result = address - this_segment;
+
+  /* If you subtract pseg from the current end of the stack,
+     you get the address of the previous stack segment's end.
+     This seems a little convoluted to me, but I'll bet you save
+     a cycle somewhere.  */
+
+  while (pseg != 0)
+    {
+#    ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o\n", pseg, size);
+#    endif
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      result += size;
+    }
+  return (result);
+}
+
+#   endif /* not CRAY2 */
+#  endif /* CRAY */
+
+# endif /* no alloca */
+#endif /* not GCC version 2 */

+ 21 - 5
test/Makefile.in

@@ -39,11 +39,16 @@ check_PROGRAMS = $(am__EXEEXT_1)
 subdir = test
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
-	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
-	$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
-	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
-	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
+	$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
+	$(top_srcdir)/m4/inttypes-pri.m4 $(top_srcdir)/m4/inttypes.m4 \
+	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
+	$(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.in
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -71,6 +76,7 @@ ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
 AMDEP_FALSE = @AMDEP_FALSE@
 AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
@@ -78,6 +84,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -90,6 +98,7 @@ CXX = @CXX@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 ECHO_C = @ECHO_C@
@@ -97,12 +106,18 @@ ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
 GMSGFMT = @GMSGFMT@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
 INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
 LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
@@ -128,6 +143,7 @@ RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.