code:
/* Optimized case-insensitive string comparison in C locale.
   Copyright (C) 2001-2002, 2007, 2009-2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published
   by the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <bruno@clisp.org>.  */

#include "c-strcase.h"
#include "c-ctype.h"

/* STRCASEEQ allows to optimize string comparison with a small literal string.
     STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
   is semantically equivalent to
     c_strcasecmp (s, "UTF-8") == 0
   just faster.  */

/* Help GCC to generate good code for string comparisons with
   immediate strings. */
#if defined (__GNUC__) && defined (__OPTIMIZE__)

/* Case insensitive comparison of ASCII characters.  */
# if C_CTYPE_ASCII
#  define CASEEQ(other,upper) \
     (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
# elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
#  define CASEEQ(other,upper) \
     (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' : (other) == (upper))
# else
#  define CASEEQ(other,upper) \
     (c_toupper (other) == (upper))
# endif

static inline int
strcaseeq9 (const char *s1, const char *s2)
{
  return c_strcasecmp (s1 + 9, s2 + 9) == 0;
}

static inline int
strcaseeq8 (const char *s1, const char *s2, char s28)
{
  if (CASEEQ (s1[8], s28))
    {
      if (s28 == 0)
        return 1;
      else
        return strcaseeq9 (s1, s2);
    }
  else
    return 0;
}

static inline int
strcaseeq7 (const char *s1, const char *s2, char s27, char s28)
{
  if (CASEEQ (s1[7], s27))
    {
      if (s27 == 0)
        return 1;
      else
        return strcaseeq8 (s1, s2, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
{
  if (CASEEQ (s1[6], s26))
    {
      if (s26 == 0)
        return 1;
      else
        return strcaseeq7 (s1, s2, s27, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
{
  if (CASEEQ (s1[5], s25))
    {
      if (s25 == 0)
        return 1;
      else
        return strcaseeq6 (s1, s2, s26, s27, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
{
  if (CASEEQ (s1[4], s24))
    {
      if (s24 == 0)
        return 1;
      else
        return strcaseeq5 (s1, s2, s25, s26, s27, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
{
  if (CASEEQ (s1[3], s23))
    {
      if (s23 == 0)
        return 1;
      else
        return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
  if (CASEEQ (s1[2], s22))
    {
      if (s22 == 0)
        return 1;
      else
        return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
  if (CASEEQ (s1[1], s21))
    {
      if (s21 == 0)
        return 1;
      else
        return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
    }
  else
    return 0;
}

static inline int
strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
  if (CASEEQ (s1[0], s20))
    {
      if (s20 == 0)
        return 1;
      else
        return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
    }
  else
    return 0;
}

#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
  strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)

#else

#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
  (c_strcasecmp (s1, s2) == 0)

#endif


code:
/* c-strncasecmp.c -- case insensitive string comparator in C locale
   Copyright (C) 1998-1999, 2005-2006, 2009-2010 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

/* Specification.  */
#include "c-strcase.h"

#include <limits.h>

#include "c-ctype.h"

int
c_strncasecmp (const char *s1, const char *s2, size_t n)
{
  register const unsigned char *p1 = (const unsigned char *) s1;
  register const unsigned char *p2 = (const unsigned char *) s2;
  unsigned char c1, c2;

  if (p1 == p2 || n == 0)
    return 0;

  do
    {
      c1 = c_tolower (*p1);
      c2 = c_tolower (*p2);

      if (--n == 0 || c1 == '\0')
        break;

      ++p1;
      ++p2;
    }
  while (c1 == c2);

  if (UCHAR_MAX <= INT_MAX)
    return c1 - c2;
  else
    /* On machines where 'char' and 'int' are types of the same size, the
       difference of two 'unsigned char' values - including the sign bit -
       doesn't fit in an 'int'.  */
    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
}

license: mit


code:
/* Return the canonical absolute name of a given file.
   Copyright (C) 1996-2010 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef _LIBC
# include <config.h>
#endif

#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC

/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
   optimizes away the name == NULL test below.  */
#define _GL_ARG_NONNULL(params)

/* Specification.  */
#include <stdlib.h>

#include <alloca.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#if HAVE_SYS_PARAM_H || defined _LIBC
# include <sys/param.h>
#endif
#include <sys/stat.h>
#include <errno.h>
#include <stddef.h>

#ifdef _LIBC
# include <shlib-compat.h>
#else
# define SHLIB_COMPAT(lib, introduced, obsoleted) 0
# define versioned_symbol(lib, local, symbol, version) extern int dummy
# define compat_symbol(lib, local, symbol, version)
# define weak_alias(local, symbol)
# define __canonicalize_file_name canonicalize_file_name
# define __realpath realpath
# include "pathmax.h"
# include "malloca.h"
# if HAVE_GETCWD
#  ifdef VMS
    /* We want the directory in Unix syntax, not in VMS syntax.  */
#   define __getcwd(buf, max) getcwd (buf, max, 0)
#  else
#   define __getcwd getcwd
#  endif
# else
#  define __getcwd(buf, max) getwd (buf)
# endif
# define __readlink readlink
# define __set_errno(e) errno = (e)
# ifndef MAXSYMLINKS
#  ifdef SYMLOOP_MAX
#   define MAXSYMLINKS SYMLOOP_MAX
#  else
#   define MAXSYMLINKS 20
#  endif
# endif
#endif

#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
#endif

#if !FUNC_REALPATH_WORKS || defined _LIBC
/* Return the canonical absolute name of file NAME.  A canonical name
   does not contain any `.', `..' components nor any repeated path
   separators ('/') or symlinks.  All path components must exist.  If
   RESOLVED is null, the result is malloc'd; otherwise, if the
   canonical name is PATH_MAX chars or more, returns null with `errno'
   set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
   returns the name in RESOLVED.  If the name cannot be resolved and
   RESOLVED is non-NULL, it contains the path of the first component
   that cannot be resolved.  If the path can be resolved, RESOLVED
   holds the same value as the value returned.  */

char *
__realpath (const char *name, char *resolved)
{
  char *rpath, *dest, *extra_buf = NULL;
  const char *start, *end, *rpath_limit;
  long int path_max;
  int num_links = 0;

  if (name == NULL)
    {
      /* As per Single Unix Specification V2 we must return an error if
         either parameter is a null pointer.  We extend this to allow
         the RESOLVED parameter to be NULL in case the we are expected to
         allocate the room for the return value.  */
      __set_errno (EINVAL);
      return NULL;
    }

  if (name[0] == '\0')
    {
      /* As per Single Unix Specification V2 we must return an error if
         the name argument points to an empty string.  */
      __set_errno (ENOENT);
      return NULL;
    }

#ifdef PATH_MAX
  path_max = PATH_MAX;
#else
  path_max = pathconf (name, _PC_PATH_MAX);
  if (path_max <= 0)
    path_max = 1024;
#endif

  if (resolved == NULL)
    {
      rpath = malloc (path_max);
      if (rpath == NULL)
        {
          /* It's easier to set errno to ENOMEM than to rely on the
             'malloc-posix' gnulib module.  */
          errno = ENOMEM;
          return NULL;
        }
    }
  else
    rpath = resolved;
  rpath_limit = rpath + path_max;

  if (name[0] != '/')
    {
      if (!__getcwd (rpath, path_max))
        {
          rpath[0] = '\0';
          goto error;
        }
      dest = strchr (rpath, '\0');
    }
  else
    {
      rpath[0] = '/';
      dest = rpath + 1;
      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
        *dest++ = '/';
    }

  for (start = end = name; *start; start = end)
    {
#ifdef _LIBC
      struct stat64 st;
#else
      struct stat st;
#endif
      int n;

      /* Skip sequence of multiple path-separators.  */
      while (*start == '/')
        ++start;

      /* Find end of path component.  */
      for (end = start; *end && *end != '/'; ++end)
        /* Nothing.  */;

      if (end - start == 0)
        break;
      else if (end - start == 1 && start[0] == '.')
        /* nothing */;
      else if (end - start == 2 && start[0] == '.' && start[1] == '.')
        {
          /* Back up to previous component, ignore if at root already.  */
          if (dest > rpath + 1)
            while ((--dest)[-1] != '/');
          if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
              && *dest == '/')
            dest++;
        }
      else
        {
          size_t new_size;

          if (dest[-1] != '/')
            *dest++ = '/';

          if (dest + (end - start) >= rpath_limit)
            {
              ptrdiff_t dest_offset = dest - rpath;
              char *new_rpath;

              if (resolved)
                {
                  __set_errno (ENAMETOOLONG);
                  if (dest > rpath + 1)
                    dest--;
                  *dest = '\0';
                  goto error;
                }
              new_size = rpath_limit - rpath;
              if (end - start + 1 > path_max)
                new_size += end - start + 1;
              else
                new_size += path_max;
              new_rpath = (char *) realloc (rpath, new_size);
              if (new_rpath == NULL)
                {
                  /* It's easier to set errno to ENOMEM than to rely on the
                     'realloc-posix' gnulib module.  */
                  errno = ENOMEM;
                  goto error;
                }
              rpath = new_rpath;
              rpath_limit = rpath + new_size;

              dest = rpath + dest_offset;
            }

#ifdef _LIBC
          dest = __mempcpy (dest, start, end - start);
#else
          memcpy (dest, start, end - start);
          dest += end - start;
#endif
          *dest = '\0';

#ifdef _LIBC
          if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
#else
          if (lstat (rpath, &st) < 0)
#endif
            goto error;

          if (S_ISLNK (st.st_mode))
            {
              char *buf;
              size_t len;

              if (++num_links > MAXSYMLINKS)
                {
                  __set_errno (ELOOP);
                  goto error;
                }

              buf = malloca (path_max);
              if (!buf)
                {
                  errno = ENOMEM;
                  goto error;
                }

              n = __readlink (rpath, buf, path_max - 1);
              if (n < 0)
                {
                  int saved_errno = errno;
                  freea (buf);
                  errno = saved_errno;
                  goto error;
                }
              buf[n] = '\0';

              if (!extra_buf)
                {
                  extra_buf = malloca (path_max);
                  if (!extra_buf)
                    {
                      freea (buf);
                      errno = ENOMEM;
                      goto error;
                    }
                }

              len = strlen (end);
              if ((long int) (n + len) >= path_max)
                {
                  freea (buf);
                  __set_errno (ENAMETOOLONG);
                  goto error;
                }

              /* Careful here, end may be a pointer into extra_buf... */
              memmove (&extra_buf[n], end, len + 1);
              name = end = memcpy (extra_buf, buf, n);

              if (buf[0] == '/')
                {
                  dest = rpath + 1;     /* It's an absolute symlink */
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
                    *dest++ = '/';
                }
              else
                {
                  /* Back up to previous component, ignore if at root
                     already: */
                  if (dest > rpath + 1)
                    while ((--dest)[-1] != '/');
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
                      && *dest == '/')
                    dest++;
                }
            }
          else if (!S_ISDIR (st.st_mode) && *end != '\0')
            {
              __set_errno (ENOTDIR);
              goto error;
            }
        }
    }
  if (dest > rpath + 1 && dest[-1] == '/')
    --dest;
  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')
    dest++;
  *dest = '\0';

  if (extra_buf)
    freea (extra_buf);

  return rpath;

error:
  {
    int saved_errno = errno;
    if (extra_buf)
      freea (extra_buf);
    if (resolved == NULL)
      free (rpath);
    errno = saved_errno;
  }
  return NULL;
}
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */

#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
char *
attribute_compat_text_section
__old_realpath (const char *name, char *resolved)
{
  if (resolved == NULL)
    {
      __set_errno (EINVAL);
      return NULL;
    }

  return __realpath (name, resolved);
}
compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
#endif

char *
__canonicalize_file_name (const char *name)
{
  return __realpath (name, NULL);
}
weak_alias (__canonicalize_file_name, canonicalize_file_name)

#else

/* This declaration is solely to ensure that after preprocessing
   this file is never empty.  */
typedef int dummy;

#endif


code:
#! /bin/sh
# Output a system dependent table of character encoding aliases.
#
#   Copyright (C) 2000-2004, 2006-2010 Free Software Foundation, Inc.
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU Lesser General Public License as published by
#   the Free Software Foundation; either version 2, or (at your option)
#   any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public License along
#   with this program; if not, write to the Free Software Foundation,
#   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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              MIME?             used by which systems
#   ASCII, ANSI_X3.4-1968       glibc solaris freebsd netbsd darwin cygwin
#   ISO-8859-1              Y   glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
#   ISO-8859-2              Y   glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
#   ISO-8859-3              Y   glibc solaris cygwin
#   ISO-8859-4              Y   osf solaris freebsd netbsd openbsd darwin
#   ISO-8859-5              Y   glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
#   ISO-8859-6              Y   glibc aix hpux solaris cygwin
#   ISO-8859-7              Y   glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin
#   ISO-8859-8              Y   glibc aix hpux osf solaris cygwin
#   ISO-8859-9              Y   glibc aix hpux irix osf solaris darwin cygwin
#   ISO-8859-13                 glibc netbsd openbsd darwin cygwin
#   ISO-8859-14                 glibc cygwin
#   ISO-8859-15                 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin
#   KOI8-R                  Y   glibc solaris freebsd netbsd openbsd darwin
#   KOI8-U                  Y   glibc freebsd netbsd openbsd darwin cygwin
#   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 netbsd openbsd darwin dos
#   CP869                       dos
#   CP874                       woe32 dos
#   CP922                       aix
#   CP932                       aix cygwin woe32 dos
#   CP943                       aix
#   CP949                       osf darwin woe32 dos
#   CP950                       woe32 dos
#   CP1046                      aix
#   CP1124                      aix
#   CP1125                      dos
#   CP1129                      aix
#   CP1131                      darwin
#   CP1250                      woe32
#   CP1251                      glibc solaris netbsd openbsd darwin cygwin woe32
#   CP1252                      aix woe32
#   CP1253                      woe32
#   CP1254                      woe32
#   CP1255                      glibc woe32
#   CP1256                      woe32
#   CP1257                      woe32
#   GB2312                  Y   glibc aix hpux irix solaris freebsd netbsd darwin
#   EUC-JP                  Y   glibc aix hpux irix osf solaris freebsd netbsd darwin
#   EUC-KR                  Y   glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
#   EUC-TW                      glibc aix hpux irix osf solaris netbsd
#   BIG5                    Y   glibc aix hpux osf solaris freebsd netbsd darwin cygwin
#   BIG5-HKSCS                  glibc solaris darwin
#   GBK                         glibc aix osf solaris darwin cygwin woe32 dos
#   GB18030                     glibc solaris netbsd darwin
#   SHIFT_JIS               Y   hpux osf solaris freebsd netbsd darwin
#   JOHAB                       glibc solaris woe32
#   TIS-620                     glibc aix hpux osf solaris cygwin
#   VISCII                  Y   glibc
#   TCVN5712-1                  glibc
#   ARMSCII-8                   glibc darwin
#   GEORGIAN-PS                 glibc cygwin
#   PT154                       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                   Y   glibc aix hpux osf solaris netbsd darwin cygwin
#
# 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-gnulibc1*)
    # Linux libc5 doesn't have nl_langinfo(CODESET); therefore
    # localcharset.c falls back to using the full locale name
    # from the environment variables.
    echo "C ASCII"
    echo "POSIX ASCII"
    for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \
             en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \
             en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \
             es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \
             et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \
             fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \
             it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \
             sv_FI sv_SE; do
      echo "$l ISO-8859-1"
      echo "$l.iso-8859-1 ISO-8859-1"
      echo "$l.iso-8859-15 ISO-8859-15"
      echo "$l.iso-8859-15@euro ISO-8859-15"
      echo "$l@euro ISO-8859-15"
      echo "$l.cp-437 CP437"
      echo "$l.cp-850 CP850"
      echo "$l.cp-1252 CP1252"
      echo "$l.cp-1252@euro CP1252"
      #echo "$l.atari-st ATARI-ST" # not a commonly used encoding
      echo "$l.utf-8 UTF-8"
      echo "$l.utf-8@euro UTF-8"
    done
    for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \
             sl_SI sr sr_CS sr_YU; do
      echo "$l ISO-8859-2"
      echo "$l.iso-8859-2 ISO-8859-2"
      echo "$l.cp-852 CP852"
      echo "$l.cp-1250 CP1250"
      echo "$l.utf-8 UTF-8"
    done
    for l in mk mk_MK ru ru_RU; do
      echo "$l ISO-8859-5"
      echo "$l.iso-8859-5 ISO-8859-5"
      echo "$l.koi8-r KOI8-R"
      echo "$l.cp-866 CP866"
      echo "$l.cp-1251 CP1251"
      echo "$l.utf-8 UTF-8"
    done
    for l in ar ar_SA; do
      echo "$l ISO-8859-6"
      echo "$l.iso-8859-6 ISO-8859-6"
      echo "$l.cp-864 CP864"
      #echo "$l.cp-868 CP868" # not a commonly used encoding
      echo "$l.cp-1256 CP1256"
      echo "$l.utf-8 UTF-8"
    done
    for l in el el_GR gr gr_GR; do
      echo "$l ISO-8859-7"
      echo "$l.iso-8859-7 ISO-8859-7"
      echo "$l.cp-869 CP869"
      echo "$l.cp-1253 CP1253"
      echo "$l.cp-1253@euro CP1253"
      echo "$l.utf-8 UTF-8"
      echo "$l.utf-8@euro UTF-8"
    done
    for l in he he_IL iw iw_IL; do
      echo "$l ISO-8859-8"
      echo "$l.iso-8859-8 ISO-8859-8"
      echo "$l.cp-862 CP862"
      echo "$l.cp-1255 CP1255"
      echo "$l.utf-8 UTF-8"
    done
    for l in tr tr_TR; do
      echo "$l ISO-8859-9"
      echo "$l.iso-8859-9 ISO-8859-9"
      echo "$l.cp-857 CP857"
      echo "$l.cp-1254 CP1254"
      echo "$l.utf-8 UTF-8"
    done
    for l in lt lt_LT lv lv_LV; do
      #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name
      echo "$l ISO-8859-13"
    done
    for l in ru_UA uk uk_UA; do
      echo "$l KOI8-U"
    done
    for l in zh zh_CN; do
      #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name
      echo "$l GB2312"
    done
    for l in ja ja_JP ja_JP.EUC; do
      echo "$l EUC-JP"
    done
    for l in ko ko_KR; do
      echo "$l EUC-KR"
    done
    for l in th th_TH; do
      echo "$l TIS-620"
    done
    for l in fa fa_IR; do
      #echo "$l ISIRI-3342" # a broken encoding
      echo "$l.utf-8 UTF-8"
    done
    ;;
  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-7 ISO-8859-7"
    echo "ISO8859-13 ISO-8859-13"
    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"
    ;;
  openbsd*)
    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-7 ISO-8859-7"
    echo "ISO8859-13 ISO-8859-13"
    echo "ISO8859-15 ISO-8859-15"
    ;;
  darwin[56]*)
    # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore
    # localcharset.c falls back to using the full locale name
    # from the environment variables.
    echo "C ASCII"
    for l in en_AU en_CA en_GB en_US la_LN; do
      echo "$l.US-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 nl_BE \
             nl_NL no_NO pt_PT sv_SE; do
      echo "$l ISO-8859-1"
      echo "$l.ISO8859-1 ISO-8859-1"
      echo "$l.ISO8859-15 ISO-8859-15"
    done
    for l in la_LN; do
      echo "$l.ISO8859-1 ISO-8859-1"
      echo "$l.ISO8859-15 ISO-8859-15"
    done
    for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do
      echo "$l.ISO8859-2 ISO-8859-2"
    done
    for l in la_LN lt_LT; do
      echo "$l.ISO8859-4 ISO-8859-4"
    done
    for l in ru_RU; do
      echo "$l.KOI8-R KOI8-R"
      echo "$l.ISO8859-5 ISO-8859-5"
      echo "$l.CP866 CP866"
    done
    for l in bg_BG; do
      echo "$l.CP1251 CP1251"
    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 "ko_KR.EUC EUC-KR"
    ;;
  darwin*)
    # Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
    # useless:
    # - It returns the empty string when LANG is set to a locale of the
    #   form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
    #   LC_CTYPE file.
    # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
    #   the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
    # - The documentation says:
    #     "... all code that calls BSD system routines should ensure
    #      that the const *char parameters of these routines are in UTF-8
    #      encoding. All BSD system functions expect their string
    #      parameters to be in UTF-8 encoding and nothing else."
    #   It also says
    #     "An additional caveat is that string parameters for files,
    #      paths, and other file-system entities must be in canonical
    #      UTF-8. In a canonical UTF-8 Unicode string, all decomposable
    #      characters are decomposed ..."
    #   but this is not true: You can pass non-decomposed UTF-8 strings
    #   to file system functions, and it is the OS which will convert
    #   them to decomposed UTF-8 before accessing the file system.
    # - The Apple Terminal application displays UTF-8 by default.
    # - However, other applications are free to use different encodings:
    #   - xterm uses ISO-8859-1 by default.
    #   - TextEdit uses MacRoman by default.
    # We prefer UTF-8 over decomposed UTF-8-MAC because one should
    # minimize the use of decomposed Unicode. Unfortunately, through the
    # Darwin file system, decomposed UTF-8 strings are leaked into user
    # space nevertheless.
    # Then there are also the locales with encodings other than US-ASCII
    # and UTF-8. These locales can be occasionally useful to users (e.g.
    # when grepping through ISO-8859-1 encoded text files), when all their
    # file names are in US-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-7 ISO-8859-7"
    echo "ISO8859-9 ISO-8859-9"
    echo "ISO8859-13 ISO-8859-13"
    echo "ISO8859-15 ISO-8859-15"
    echo "KOI8-R KOI8-R"
    echo "KOI8-U KOI8-U"
    echo "CP866 CP866"
    echo "CP949 CP949"
    echo "CP1131 CP1131"
    echo "CP1251 CP1251"
    echo "eucCN GB2312"
    echo "GB2312 GB2312"
    echo "eucJP EUC-JP"
    echo "eucKR EUC-KR"
    echo "Big5 BIG5"
    echo "Big5HKSCS BIG5-HKSCS"
    echo "GBK GBK"
    echo "GB18030 GB18030"
    echo "SJIS SHIFT_JIS"
    echo "ARMSCII-8 ARMSCII-8"
    echo "PT154 PT154"
    #echo "ISCII-DEV ?"
    echo "* UTF-8"
    ;;
  beos* | haiku*)
    # BeOS and Haiku have 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 <juan.guerrero@gmx.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_CS 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


code:
/* Duplicate a locale object.
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <bruno@clisp.org>, 2007.  */

#include <config.h>

/* Specification.  */
#include <locale.h>

#include <errno.h>
#include <string.h>

#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))

#undef duplocale

locale_t
rpl_duplocale (locale_t locale)
{
  /* Work around crash in the duplocale function in glibc < 2.12.
     See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>.  */
  if (locale == LC_GLOBAL_LOCALE)
    {
      /* Create a copy of the locale by fetching the name of each locale
         category, starting with LC_CTYPE.  */
      static struct { int cat; int mask; } const categories[] =
        {
            { LC_NUMERIC,        LC_NUMERIC_MASK },
            { LC_TIME,           LC_TIME_MASK },
            { LC_COLLATE,        LC_COLLATE_MASK },
            { LC_MONETARY,       LC_MONETARY_MASK },
            { LC_MESSAGES,       LC_MESSAGES_MASK }
#ifdef LC_PAPER
          , { LC_PAPER,          LC_PAPER_MASK }
#endif
#ifdef LC_NAME
          , { LC_NAME,           LC_NAME_MASK }
#endif
#ifdef LC_ADDRESS
          , { LC_ADDRESS,        LC_ADDRESS_MASK }
#endif
#ifdef LC_TELEPHONE
          , { LC_TELEPHONE,      LC_TELEPHONE_MASK }
#endif
#ifdef LC_MEASUREMENT
          , { LC_MEASUREMENT,    LC_MEASUREMENT_MASK }
#endif
#ifdef LC_IDENTIFICATION
          , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK }
#endif
        };
      const char *base_name;
      locale_t base_copy;
      unsigned int i;

      base_name = setlocale (LC_CTYPE, NULL);
      base_copy = newlocale (LC_ALL_MASK, base_name, NULL);
      if (base_copy == NULL)
        return NULL;

      for (i = 0; i < SIZEOF (categories); i++)
        {
          int category = categories[i].cat;
          int category_mask = categories[i].mask;
          const char *name = setlocale (category, NULL);
          if (strcmp (name, base_name) != 0)
            {
              locale_t copy = newlocale (category_mask, name, base_copy);
              if (copy == NULL)
                {
                  int saved_errno = errno;
                  freelocale (base_copy);
                  errno = saved_errno;
                  return NULL;
                }
              /* No need to call freelocale (base_copy) if copy != base_copy;
                 the newlocale function already takes care of doing it.  */
              base_copy = copy;
            }
        }

      return base_copy;
    }

  return duplocale (locale);
}


code:
/* A POSIX-like <errno.h>.

   Copyright (C) 2008-2010 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _GL_ERRNO_H

#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif

/* The include_next requires a split double-inclusion guard.  */
#@INCLUDE_NEXT@ @NEXT_ERRNO_H@

#ifndef _GL_ERRNO_H
#define _GL_ERRNO_H

/* On native Windows platforms, many macros are not defined.  */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__

/* POSIX says that EAGAIN and EWOULDBLOCK may have the same value.  */
#  define EWOULDBLOCK     EAGAIN

/* Values >= 100 seem safe to use.  */
#  define ETXTBSY   100
#  define GNULIB_defined_ETXTBSY 1

/* These are intentionally the same values as the WSA* error numbers, defined
   in <winsock2.h>.  */
#  define EINPROGRESS     10036
#  define EALREADY        10037
#  define ENOTSOCK        10038
#  define EDESTADDRREQ    10039
#  define EMSGSIZE        10040
#  define EPROTOTYPE      10041
#  define ENOPROTOOPT     10042
#  define EPROTONOSUPPORT 10043
#  define ESOCKTNOSUPPORT 10044  /* not required by POSIX */
#  define EOPNOTSUPP      10045
#  define EPFNOSUPPORT    10046  /* not required by POSIX */
#  define EAFNOSUPPORT    10047
#  define EADDRINUSE      10048
#  define EADDRNOTAVAIL   10049
#  define ENETDOWN        10050
#  define ENETUNREACH     10051
#  define ENETRESET       10052
#  define ECONNABORTED    10053
#  define ECONNRESET      10054
#  define ENOBUFS         10055
#  define EISCONN         10056
#  define ENOTCONN        10057
#  define ESHUTDOWN       10058  /* not required by POSIX */
#  define ETOOMANYREFS    10059  /* not required by POSIX */
#  define ETIMEDOUT       10060
#  define ECONNREFUSED    10061
#  define ELOOP           10062
#  define EHOSTDOWN       10064  /* not required by POSIX */
#  define EHOSTUNREACH    10065
#  define EPROCLIM        10067  /* not required by POSIX */
#  define EUSERS          10068  /* not required by POSIX */
#  define EDQUOT          10069
#  define ESTALE          10070
#  define EREMOTE         10071  /* not required by POSIX */
#  define GNULIB_defined_ESOCK 1

# endif

/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros
   EMULTIHOP, ENOLINK, EOVERFLOW are not defined.  */
# if @EMULTIHOP_HIDDEN@
#  define EMULTIHOP @EMULTIHOP_VALUE@
#  define GNULIB_defined_EMULTIHOP 1
# endif
# if @ENOLINK_HIDDEN@
#  define ENOLINK   @ENOLINK_VALUE@
#  define GNULIB_defined_ENOLINK 1
# endif
# if @EOVERFLOW_HIDDEN@
#  define EOVERFLOW @EOVERFLOW_VALUE@
#  define GNULIB_defined_EOVERFLOW 1
# endif

/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK,
   EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined.
   Define them here.  Values >= 2000 seem safe to use: Solaris ESTALE = 151,
   HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133.

   Note: When one of these systems defines some of these macros some day,
   binaries will have to be recompiled so that they recognizes the new
   errno values from the system.  */

# ifndef ENOMSG
#  define ENOMSG    2000
#  define GNULIB_defined_ENOMSG 1
# endif

# ifndef EIDRM
#  define EIDRM     2001
#  define GNULIB_defined_EIDRM 1
# endif

# ifndef ENOLINK
#  define ENOLINK   2002
#  define GNULIB_defined_ENOLINK 1
# endif

# ifndef EPROTO
#  define EPROTO    2003
#  define GNULIB_defined_EPROTO 1
# endif

# ifndef EMULTIHOP
#  define EMULTIHOP 2004
#  define GNULIB_defined_EMULTIHOP 1
# endif

# ifndef EBADMSG
#  define EBADMSG   2005
#  define GNULIB_defined_EBADMSG 1
# endif

# ifndef EOVERFLOW
#  define EOVERFLOW 2006
#  define GNULIB_defined_EOVERFLOW 1
# endif

# ifndef ENOTSUP
#  define ENOTSUP   2007
#  define GNULIB_defined_ENOTSUP 1
# endif

# ifndef ESTALE
#  define ESTALE    2009
#  define GNULIB_defined_ESTALE 1
# endif

# ifndef ECANCELED
#  define ECANCELED 2008
#  define GNULIB_defined_ECANCELED 1
# endif

#endif /* _GL_ERRNO_H */
#endif /* _GL_ERRNO_H */


code:
/* Supplemental information about the floating-point formats.
   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2007.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _FLOATPLUS_H
#define _FLOATPLUS_H

#include <float.h>
#include <limits.h>

/* Number of bits in the mantissa of a floating-point number, including the
   "hidden bit".  */
#if FLT_RADIX == 2
# define FLT_MANT_BIT FLT_MANT_DIG
# define DBL_MANT_BIT DBL_MANT_DIG
# define LDBL_MANT_BIT LDBL_MANT_DIG
#elif FLT_RADIX == 4
# define FLT_MANT_BIT (FLT_MANT_DIG * 2)
# define DBL_MANT_BIT (DBL_MANT_DIG * 2)
# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2)
#elif FLT_RADIX == 16
# define FLT_MANT_BIT (FLT_MANT_DIG * 4)
# define DBL_MANT_BIT (DBL_MANT_DIG * 4)
# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4)
#endif

/* Bit mask that can be used to mask the exponent, as an unsigned number.  */
#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7)
#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7)

/* Number of bits used for the exponent of a floating-point number, including
   the exponent's sign.  */
#define FLT_EXP_BIT \
  (FLT_EXP_MASK < 0x100 ? 8 : \
   FLT_EXP_MASK < 0x200 ? 9 : \
   FLT_EXP_MASK < 0x400 ? 10 : \
   FLT_EXP_MASK < 0x800 ? 11 : \
   FLT_EXP_MASK < 0x1000 ? 12 : \
   FLT_EXP_MASK < 0x2000 ? 13 : \
   FLT_EXP_MASK < 0x4000 ? 14 : \
   FLT_EXP_MASK < 0x8000 ? 15 : \
   FLT_EXP_MASK < 0x10000 ? 16 : \
   FLT_EXP_MASK < 0x20000 ? 17 : \
   FLT_EXP_MASK < 0x40000 ? 18 : \
   FLT_EXP_MASK < 0x80000 ? 19 : \
   FLT_EXP_MASK < 0x100000 ? 20 : \
   FLT_EXP_MASK < 0x200000 ? 21 : \
   FLT_EXP_MASK < 0x400000 ? 22 : \
   FLT_EXP_MASK < 0x800000 ? 23 : \
   FLT_EXP_MASK < 0x1000000 ? 24 : \
   FLT_EXP_MASK < 0x2000000 ? 25 : \
   FLT_EXP_MASK < 0x4000000 ? 26 : \
   FLT_EXP_MASK < 0x8000000 ? 27 : \
   FLT_EXP_MASK < 0x10000000 ? 28 : \
   FLT_EXP_MASK < 0x20000000 ? 29 : \
   FLT_EXP_MASK < 0x40000000 ? 30 : \
   FLT_EXP_MASK <= 0x7fffffff ? 31 : \
   32)
#define DBL_EXP_BIT \
  (DBL_EXP_MASK < 0x100 ? 8 : \
   DBL_EXP_MASK < 0x200 ? 9 : \
   DBL_EXP_MASK < 0x400 ? 10 : \
   DBL_EXP_MASK < 0x800 ? 11 : \
   DBL_EXP_MASK < 0x1000 ? 12 : \
   DBL_EXP_MASK < 0x2000 ? 13 : \
   DBL_EXP_MASK < 0x4000 ? 14 : \
   DBL_EXP_MASK < 0x8000 ? 15 : \
   DBL_EXP_MASK < 0x10000 ? 16 : \
   DBL_EXP_MASK < 0x20000 ? 17 : \
   DBL_EXP_MASK < 0x40000 ? 18 : \
   DBL_EXP_MASK < 0x80000 ? 19 : \
   DBL_EXP_MASK < 0x100000 ? 20 : \
   DBL_EXP_MASK < 0x200000 ? 21 : \
   DBL_EXP_MASK < 0x400000 ? 22 : \
   DBL_EXP_MASK < 0x800000 ? 23 : \
   DBL_EXP_MASK < 0x1000000 ? 24 : \
   DBL_EXP_MASK < 0x2000000 ? 25 : \
   DBL_EXP_MASK < 0x4000000 ? 26 : \
   DBL_EXP_MASK < 0x8000000 ? 27 : \
   DBL_EXP_MASK < 0x10000000 ? 28 : \
   DBL_EXP_MASK < 0x20000000 ? 29 : \
   DBL_EXP_MASK < 0x40000000 ? 30 : \
   DBL_EXP_MASK <= 0x7fffffff ? 31 : \
   32)
#define LDBL_EXP_BIT \
  (LDBL_EXP_MASK < 0x100 ? 8 : \
   LDBL_EXP_MASK < 0x200 ? 9 : \
   LDBL_EXP_MASK < 0x400 ? 10 : \
   LDBL_EXP_MASK < 0x800 ? 11 : \
   LDBL_EXP_MASK < 0x1000 ? 12 : \
   LDBL_EXP_MASK < 0x2000 ? 13 : \
   LDBL_EXP_MASK < 0x4000 ? 14 : \
   LDBL_EXP_MASK < 0x8000 ? 15 : \
   LDBL_EXP_MASK < 0x10000 ? 16 : \
   LDBL_EXP_MASK < 0x20000 ? 17 : \
   LDBL_EXP_MASK < 0x40000 ? 18 : \
   LDBL_EXP_MASK < 0x80000 ? 19 : \
   LDBL_EXP_MASK < 0x100000 ? 20 : \
   LDBL_EXP_MASK < 0x200000 ? 21 : \
   LDBL_EXP_MASK < 0x400000 ? 22 : \
   LDBL_EXP_MASK < 0x800000 ? 23 : \
   LDBL_EXP_MASK < 0x1000000 ? 24 : \
   LDBL_EXP_MASK < 0x2000000 ? 25 : \
   LDBL_EXP_MASK < 0x4000000 ? 26 : \
   LDBL_EXP_MASK < 0x8000000 ? 27 : \
   LDBL_EXP_MASK < 0x10000000 ? 28 : \
   LDBL_EXP_MASK < 0x20000000 ? 29 : \
   LDBL_EXP_MASK < 0x40000000 ? 30 : \
   LDBL_EXP_MASK <= 0x7fffffff ? 31 : \
   32)

/* Number of bits used for a floating-point number: the mantissa (not
   counting the "hidden bit", since it may or may not be explicit), the
   exponent, and the sign.  */
#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1)
#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1)
#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1)

/* Number of bytes used for a floating-point number.
   This can be smaller than the 'sizeof'.  For example, on i386 systems,
   'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence
   LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but
   sizeof (long double) = 12 or = 16.  */
#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)

/* Verify that SIZEOF_FLT <= sizeof (float) etc.  */
typedef int verify_sizeof_flt[2 * (SIZEOF_FLT <= sizeof (float)) - 1];
typedef int verify_sizeof_dbl[2 * (SIZEOF_DBL <= sizeof (double)) - 1];
typedef int verify_sizeof_ldbl[2 * (SIZEOF_LDBL <= sizeof (long double)) - 1];

#endif /* _FLOATPLUS_H */


code:
/* A correct <float.h>.

   Copyright (C) 2007-2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef _GL_FLOAT_H

#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif

/* The include_next requires a split double-inclusion guard.  */
#@INCLUDE_NEXT@ @NEXT_FLOAT_H@

#ifndef _GL_FLOAT_H
#define _GL_FLOAT_H

/* 'long double' properties.  */
#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
/* Number of mantissa units, in base FLT_RADIX.  */
# undef LDBL_MANT_DIG
# define LDBL_MANT_DIG   64
/* Number of decimal digits that is sufficient for representing a number.  */
# undef LDBL_DIG
# define LDBL_DIG        18
/* x-1 where x is the smallest representable number > 1.  */
# undef LDBL_EPSILON
# define LDBL_EPSILON    1.0842021724855044340E-19L
/* Minimum e such that FLT_RADIX^(e-1) is a normalized number.  */
# undef LDBL_MIN_EXP
# define LDBL_MIN_EXP    (-16381)
/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number.  */
# undef LDBL_MAX_EXP
# define LDBL_MAX_EXP    16384
/* Minimum positive normalized number.  */
# undef LDBL_MIN
# define LDBL_MIN        3.3621031431120935063E-4932L
/* Maximum representable finite number.  */
# undef LDBL_MAX
# define LDBL_MAX        1.1897314953572317650E+4932L
/* Minimum e such that 10^e is in the range of normalized numbers.  */
# undef LDBL_MIN_10_EXP
# define LDBL_MIN_10_EXP (-4931)
/* Maximum e such that 10^e is in the range of representable finite numbers.  */
# undef LDBL_MAX_10_EXP
# define LDBL_MAX_10_EXP 4932
#endif

#endif /* _GL_FLOAT_H */
#endif /* _GL_FLOAT_H */


code:
/* Emulate flock on platforms that lack it, primarily Windows and MinGW.

   This is derived from sqlite3 sources.
   http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
   http://www.sqlite.org/copyright.html

   Written by Richard W.M. Jones <rjones.at.redhat.com>

   Copyright (C) 2008-2010 Free Software Foundation, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>
#include <sys/file.h>

#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__

/* _get_osfhandle */
#include <io.h>

/* LockFileEx */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <errno.h>

/* Determine the current size of a file.  Because the other braindead
 * APIs we'll call need lower/upper 32 bit pairs, keep the file size
 * like that too.
 */
static BOOL
file_size (HANDLE h, DWORD * lower, DWORD * upper)
{
  *lower = GetFileSize (h, upper);
  return 1;
}

/* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
#ifndef LOCKFILE_FAIL_IMMEDIATELY
# define LOCKFILE_FAIL_IMMEDIATELY 1
#endif

/* Acquire a lock. */
static BOOL
do_lock (HANDLE h, int non_blocking, int exclusive)
{
  BOOL res;
  DWORD size_lower, size_upper;
  OVERLAPPED ovlp;
  int flags = 0;

  /* We're going to lock the whole file, so get the file size. */
  res = file_size (h, &size_lower, &size_upper);
  if (!res)
    return 0;

  /* Start offset is 0, and also zero the remaining members of this struct. */
  memset (&ovlp, 0, sizeof ovlp);

  if (non_blocking)
    flags |= LOCKFILE_FAIL_IMMEDIATELY;
  if (exclusive)
    flags |= LOCKFILE_EXCLUSIVE_LOCK;

  return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
}

/* Unlock reader or exclusive lock. */
static BOOL
do_unlock (HANDLE h)
{
  int res;
  DWORD size_lower, size_upper;

  res = file_size (h, &size_lower, &size_upper);
  if (!res)
    return 0;

  return UnlockFile (h, 0, 0, size_lower, size_upper);
}

/* Now our BSD-like flock operation. */
int
flock (int fd, int operation)
{
  HANDLE h = (HANDLE) _get_osfhandle (fd);
  DWORD res;
  int non_blocking;

  if (h == INVALID_HANDLE_VALUE)
    {
      errno = EBADF;
      return -1;
    }

  non_blocking = operation & LOCK_NB;
  operation &= ~LOCK_NB;

  switch (operation)
    {
    case LOCK_SH:
      res = do_lock (h, non_blocking, 0);
      break;
    case LOCK_EX:
      res = do_lock (h, non_blocking, 1);
      break;
    case LOCK_UN:
      res = do_unlock (h);
      break;
    default:
      errno = EINVAL;
      return -1;
    }

  /* Map Windows errors into Unix errnos.  As usual MSDN fails to
   * document the permissible error codes.
   */
  if (!res)
    {
      DWORD err = GetLastError ();
      switch (err)
        {
          /* This means someone else is holding a lock. */
        case ERROR_LOCK_VIOLATION:
          errno = EAGAIN;
          break;

          /* Out of memory. */
        case ERROR_NOT_ENOUGH_MEMORY:
          errno = ENOMEM;
          break;

        case ERROR_BAD_COMMAND:
          errno = EINVAL;
          break;

          /* Unlikely to be other errors, but at least don't lose the
           * error code.
           */
        default:
          errno = err;
        }

      return -1;
    }

  return 0;
}

#else /* !Windows */

#ifdef HAVE_STRUCT_FLOCK_L_TYPE
/* We know how to implement flock in terms of fcntl. */

#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <errno.h>
#include <string.h>

int
flock (int fd, int operation)
{
  int cmd, r;
  struct flock fl;

  if (operation & LOCK_NB)
    cmd = F_SETLK;
  else
    cmd = F_SETLKW;
  operation &= ~LOCK_NB;

  memset (&fl, 0, sizeof fl);
  fl.l_whence = SEEK_SET;
  /* l_start & l_len are 0, which as a special case means "whole file". */

  switch (operation)
    {
    case LOCK_SH:
      fl.l_type = F_RDLCK;
      break;
    case LOCK_EX:
      fl.l_type = F_WRLCK;
      break;
    case LOCK_UN:
      fl.l_type = F_UNLCK;
      break;
    default:
      errno = EINVAL;
      return -1;
    }

  r = fcntl (fd, cmd, &fl);
  if (r == -1 && errno == EACCES)
    errno = EAGAIN;

  return r;
}

#else /* !HAVE_STRUCT_FLOCK_L_TYPE */

#error "This platform lacks flock function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."

#endif /* !HAVE_STRUCT_FLOCK_L_TYPE */

#endif /* !Windows */


code:
/* An interface to read that retries after partial reads and interrupts.
   Copyright (C) 2002-2003, 2009-2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#define FULL_READ
#include "full-write.c"


code:
/* An interface to read() that reads all it is asked to read.

   Copyright (C) 2002, 2009-2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, read to the Free Software Foundation,
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <stddef.h>

/* Read COUNT bytes at BUF to descriptor FD, retrying if interrupted
   or if partial reads occur.  Return the number of bytes successfully
   read, setting errno if that is less than COUNT.  errno = 0 means EOF.  */
extern size_t full_read (int fd, void *buf, size_t count);


code:
/* An interface to read and write that retries (if necessary) until complete.

   Copyright (C) 1993-1994, 1997-2006, 2009-2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>

/* Specification.  */
#ifdef FULL_READ
# include "full-read.h"
#else
# include "full-write.h"
#endif

#include <errno.h>

#ifdef FULL_READ
# include "safe-read.h"
# define safe_rw safe_read
# define full_rw full_read
# undef const
# define const /* empty */
#else
# include "safe-write.h"
# define safe_rw safe_write
# define full_rw full_write
#endif

#ifdef FULL_READ
/* Set errno to zero upon EOF.  */
# define ZERO_BYTE_TRANSFER_ERRNO 0
#else
/* Some buggy drivers return 0 when one tries to write beyond
   a device's end.  (Example: Linux 1.2.13 on /dev/fd0.)
   Set errno to ENOSPC so they get a sensible diagnostic.  */
# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
#endif

/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
   interrupted or if a partial write(read) occurs.  Return the number
   of bytes transferred.
   When writing, set errno if fewer than COUNT bytes are written.
   When reading, if fewer than COUNT bytes are read, you must examine
   errno to distinguish failure from EOF (errno == 0).  */
size_t
full_rw (int fd, const void *buf, size_t count)
{
  size_t total = 0;
  const char *ptr = (const char *) buf;

  while (count > 0)
    {
      size_t n_rw = safe_rw (fd, ptr, count);
      if (n_rw == (size_t) -1)
        break;
      if (n_rw == 0)
        {
          errno = ZERO_BYTE_TRANSFER_ERRNO;
          break;
        }
      total += n_rw;
      ptr += n_rw;
      count -= n_rw;
    }

  return total;
}


code:
/* An interface to write() that writes all it is asked to write.

   Copyright (C) 2002-2003, 2009-2010 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
   or if partial writes occur.  Return the number of bytes successfully
   written, setting errno if that is less than COUNT.  */
extern size_t full_write (int fd, const void *buf, size_t count);

#ifdef __cplusplus
}
#endif


code:
/* Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 Free
   Software Foundation, Inc.
   This file is part of the GNU C Library.
   Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _LIBC
# include <config.h>
#endif

#include <stdio.h>
#include <netdb.h>

#ifdef _LIBC
# include <libintl.h>
#else
# include "gettext.h"
# define _(String) gettext (String)
# define N_(String) String
#endif

static struct
  {
    int code;
    const char *msg;
  }
values[] =
  {
    { EAI_ADDRFAMILY, N_("Address family for hostname not supported") },
    { EAI_AGAIN, N_("Temporary failure in name resolution") },
    { EAI_BADFLAGS, N_("Bad value for ai_flags") },
    { EAI_FAIL, N_("Non-recoverable failure in name resolution") },
    { EAI_FAMILY, N_("ai_family not supported") },
    { EAI_MEMORY, N_("Memory allocation failure") },
    { EAI_NODATA, N_("No address associated with hostname") },
    { EAI_NONAME, N_("Name or service not known") },
    { EAI_SERVICE, N_("Servname not supported for ai_socktype") },
    { EAI_SOCKTYPE, N_("ai_socktype not supported") },
    { EAI_SYSTEM, N_("System error") },
    { EAI_OVERFLOW, N_("Argument buffer too small") },
#ifdef EAI_INPROGRESS
    { EAI_INPROGRESS, N_("Processing request in progress") },
    { EAI_CANCELED, N_("Request canceled") },
    { EAI_NOTCANCELED, N_("Request not canceled") },
    { EAI_ALLDONE, N_("All requests done") },
    { EAI_INTR, N_("Interrupted by a signal") },
    { EAI_IDN_ENCODE, N_("Parameter string not correctly encoded") }
#endif
  };

const char *
gai_strerror (int code)
{
  size_t i;
  for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
    if (values[i].code == code)
      return _(values[i].msg);

  return _("Unknown error");
}
#ifdef _LIBC
libc_hidden_def (gai_strerror)
#endif


code:
/* Get address information (partial implementation).
   Copyright (C) 1997, 2001-2002, 2004-2010 Free Software Foundation, Inc.
   Contributed by Simon Josefsson <simon@josefsson.org>.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
   optimizes away the sa == NULL test below.  */
#define _GL_ARG_NONNULL(params)

#include <netdb.h>

#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif

/* Get inet_ntop.  */
#include <arpa/inet.h>

/* Get calloc. */
#include <stdlib.h>

/* Get memcpy, strdup. */
#include <string.h>

/* Get snprintf. */
#include <stdio.h>

#include <stdbool.h>

#include "gettext.h"
#define _(String) gettext (String)
#define N_(String) String

/* BeOS has AF_INET, but not PF_INET.  */
#ifndef PF_INET
# define PF_INET AF_INET
#endif
/* BeOS also lacks PF_UNSPEC.  */
#ifndef PF_UNSPEC
# define PF_UNSPEC 0
#endif

#if defined _WIN32 || defined __WIN32__
# define WIN32_NATIVE
#endif

#ifdef WIN32_NATIVE
typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
                                        const struct addrinfo*,
                                        struct addrinfo**);
typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*);
typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*,
                                        socklen_t, char*, DWORD,
                                        char*, DWORD, int);

static getaddrinfo_func getaddrinfo_ptr = NULL;
static freeaddrinfo_func freeaddrinfo_ptr = NULL;
static getnameinfo_func getnameinfo_ptr = NULL;

static int
use_win32_p (void)
{
  static int done = 0;
  HMODULE h;

  if (done)
    return getaddrinfo_ptr ? 1 : 0;

  done = 1;

  h = GetModuleHandle ("ws2_32.dll");

  if (h)
    {
      getaddrinfo_ptr = (getaddrinfo_func) GetProcAddress (h, "getaddrinfo");
      freeaddrinfo_ptr = (freeaddrinfo_func) GetProcAddress (h, "freeaddrinfo");
      getnameinfo_ptr = (getnameinfo_func) GetProcAddress (h, "getnameinfo");
    }

  /* If either is missing, something is odd. */
  if (!getaddrinfo_ptr || !freeaddrinfo_ptr || !getnameinfo_ptr)
    {
      getaddrinfo_ptr = NULL;
      freeaddrinfo_ptr = NULL;
      getnameinfo_ptr = NULL;
      return 0;
    }

  return 1;
}
#endif

static inline bool
validate_family (int family)
{
  /* FIXME: Support more families. */
#if HAVE_IPV4
     if (family == PF_INET)
       return true;
#endif
#if HAVE_IPV6
     if (family == PF_INET6)
       return true;
#endif
     if (family == PF_UNSPEC)
       return true;
     return false;
}

/* Translate name of a service location and/or a service name to set of
   socket addresses. */
int
getaddrinfo (const char *restrict nodename,
             const char *restrict servname,
             const struct addrinfo *restrict hints,
             struct addrinfo **restrict res)
{
  struct addrinfo *tmp;
  int port = 0;
  struct hostent *he;
  void *storage;
  size_t size;
#if HAVE_IPV6
  struct v6_pair {
    struct addrinfo addrinfo;
    struct sockaddr_in6 sockaddr_in6;
  };
#endif
#if HAVE_IPV4
  struct v4_pair {
    struct addrinfo addrinfo;
    struct sockaddr_in sockaddr_in;
  };
#endif

#ifdef WIN32_NATIVE
  if (use_win32_p ())
    return getaddrinfo_ptr (nodename, servname, hints, res);
#endif

  if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
    /* FIXME: Support more flags. */
    return EAI_BADFLAGS;

  if (hints && !validate_family (hints->ai_family))
    return EAI_FAMILY;

  if (hints &&
      hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM)
    /* FIXME: Support other socktype. */
    return EAI_SOCKTYPE; /* FIXME: Better return code? */

  if (!nodename)
    {
      if (!(hints->ai_flags & AI_PASSIVE))
        return EAI_NONAME;

#ifdef HAVE_IPV6
      nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
#else
      nodename = "0.0.0.0";
#endif
    }

  if (servname)
    {
      struct servent *se = NULL;
      const char *proto =
        (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";

      if (hints == NULL || !(hints->ai_flags & AI_NUMERICSERV))
        /* FIXME: Use getservbyname_r if available. */
        se = getservbyname (servname, proto);

      if (!se)
        {
          char *c;
          if (!(*servname >= '0' && *servname <= '9'))
            return EAI_NONAME;
          port = strtoul (servname, &c, 10);
          if (*c || port > 0xffff)
            return EAI_NONAME;
          port = htons (port);
        }
      else
        port = se->s_port;
    }

  /* FIXME: Use gethostbyname_r if available. */
  he = gethostbyname (nodename);
  if (!he || he->h_addr_list[0] == NULL)
    return EAI_NONAME;

  switch (he->h_addrtype)
    {
#if HAVE_IPV6
    case PF_INET6:
      size = sizeof (struct v6_pair);
      break;
#endif

#if HAVE_IPV4
    case PF_INET:
      size = sizeof (struct v4_pair);
      break;
#endif

    default:
      return EAI_NODATA;
    }

  storage = calloc (1, size);
  if (!storage)
    return EAI_MEMORY;

  switch (he->h_addrtype)
    {
#if HAVE_IPV6
    case PF_INET6:
      {
        struct v6_pair *p = storage;
        struct sockaddr_in6 *sinp = &p->sockaddr_in6;
        tmp = &p->addrinfo;

        if (port)
          sinp->sin6_port = port;

        if (he->h_length != sizeof (sinp->sin6_addr))
          {
            free (storage);
            return EAI_SYSTEM; /* FIXME: Better return code?  Set errno? */
          }

        memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr);

        tmp->ai_addr = (struct sockaddr *) sinp;
        tmp->ai_addrlen = sizeof *sinp;
      }
      break;
#endif

#if HAVE_IPV4
    case PF_INET:
      {
        struct v4_pair *p = storage;
        struct sockaddr_in *sinp = &p->sockaddr_in;
        tmp = &p->addrinfo;

        if (port)
          sinp->sin_port = port;

        if (he->h_length != sizeof (sinp->sin_addr))
          {
            free (storage);
            return EAI_SYSTEM; /* FIXME: Better return code?  Set errno? */
          }

        memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr);

        tmp->ai_addr = (struct sockaddr *) sinp;
        tmp->ai_addrlen = sizeof *sinp;
      }
      break;
#endif

    default:
      free (storage);
      return EAI_NODATA;
    }

  if (hints && hints->ai_flags & AI_CANONNAME)
    {
      const char *cn;
      if (he->h_name)
        cn = he->h_name;
      else
        cn = nodename;

      tmp->ai_canonname = strdup (cn);
      if (!tmp->ai_canonname)
        {
          free (storage);
          return EAI_MEMORY;
        }
    }

  tmp->ai_protocol = (hints) ? hints->ai_protocol : 0;
  tmp->ai_socktype = (hints) ? hints->ai_socktype : 0;
  tmp->ai_addr->sa_family = he->h_addrtype;
  tmp->ai_family = he->h_addrtype;

#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
  switch (he->h_addrtype)
    {
#if HAVE_IPV4
    case AF_INET:
      tmp->ai_addr->sa_len = sizeof (struct sockaddr_in);
      break;
#endif
#if HAVE_IPV6
    case AF_INET6:
      tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6);
      break;
#endif
    }
#endif

  /* FIXME: If more than one address, create linked list of addrinfo's. */

  *res = tmp;

  return 0;
}

/* Free `addrinfo' structure AI including associated storage.  */
void
freeaddrinfo (struct addrinfo *ai)
{
#ifdef WIN32_NATIVE
  if (use_win32_p ())
    {
      freeaddrinfo_ptr (ai);
      return;
    }
#endif

  while (ai)
    {
      struct addrinfo *cur;

      cur = ai;
      ai = ai->ai_next;

      free (cur->ai_canonname);
      free (cur);
    }
}

int
getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
             char *restrict node, socklen_t nodelen,
             char *restrict service, socklen_t servicelen,
             int flags)
{
#ifdef WIN32_NATIVE
  if (use_win32_p ())
    return getnameinfo_ptr (sa, salen, node, nodelen,
                            service, servicelen, flags);
#endif

  /* FIXME: Support other flags. */
  if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) ||
      (service && servicelen > 0 && !(flags & NI_NUMERICHOST)) ||
      (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV)))
    return EAI_BADFLAGS;

  if (sa == NULL || salen < sizeof (sa->sa_family))
    return EAI_FAMILY;

  switch (sa->sa_family)
    {
#if HAVE_IPV4
    case AF_INET:
      if (salen < sizeof (struct sockaddr_in))
        return EAI_FAMILY;
      break;
#endif
#if HAVE_IPV6
    case AF_INET6:
      if (salen < sizeof (struct sockaddr_in6))
        return EAI_FAMILY;
      break;
#endif
    default:
      return EAI_FAMILY;
    }

  if (node && nodelen > 0 && flags & NI_NUMERICHOST)
    {
      switch (sa->sa_family)
        {
#if HAVE_IPV4
        case AF_INET:
          if (!inet_ntop (AF_INET,
                          &(((const struct sockaddr_in *) sa)->sin_addr),
                          node, nodelen))
            return EAI_SYSTEM;
          break;
#endif

#if HAVE_IPV6
        case AF_INET6:
          if (!inet_ntop (AF_INET6,
                          &(((const struct sockaddr_in6 *) sa)->sin6_addr),
                          node, nodelen))
            return EAI_SYSTEM;
          break;
#endif

        default:
          return EAI_FAMILY;
        }
    }

  if (service && servicelen > 0 && flags & NI_NUMERICSERV)
    switch (sa->sa_family)
      {
#if HAVE_IPV4
      case AF_INET:
#endif
#if HAVE_IPV6
      case AF_INET6:
#endif
        {
          unsigned short int port
            = ntohs (((const struct sockaddr_in *) sa)->sin_port);
          if (servicelen <= snprintf (service, servicelen, "%u", port))
            return EAI_OVERFLOW;
        }
        break;
      }

  return 0;
}


code:
/* Convenience header for conditional use of GNU <libintl.h>.
   Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2010 Free Software
   Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License along
   with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1

/* NLS can be disabled through the configure --disable-nls option.  */
#if ENABLE_NLS

/* Get declarations of GNU message catalog functions.  */
# include <libintl.h>

/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
   the gettext() and ngettext() macros.  This is an alternative to calling
   textdomain(), and is useful for libraries.  */
# ifdef DEFAULT_TEXT_DOMAIN
#  undef gettext
#  define gettext(Msgid) \
     dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
#  undef ngettext
#  define ngettext(Msgid1, Msgid2, N) \
     dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
# endif

#else

/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
   chokes if dcgettext is defined as a macro.  So include it now, to make
   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
   as well because people using "gettext.h" will not include <libintl.h>,
   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
   is OK.  */
#if defined(__sun)
# include <locale.h>
#endif

/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
   <libintl.h>, which chokes if dcgettext is defined as a macro.  So include
   it now, to make later inclusions of <libintl.h> a NOP.  */
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
# include <cstdlib>
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
#  include <libintl.h>
# endif
#endif

/* Disabled NLS.
   The casts to 'const char *' serve the purpose of producing warnings
   for invalid uses of the value returned from these functions.
   On pre-ANSI systems without 'const', the config.h file is supposed to
   contain "#define const".  */
# undef gettext
# define gettext(Msgid) ((const char *) (Msgid))
# undef dgettext
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
# undef dcgettext
# define dcgettext(Domainname, Msgid, Category) \
    ((void) (Category), dgettext (Domainname, Msgid))
# undef ngettext
# define ngettext(Msgid1, Msgid2, N) \
    ((N) == 1 \
     ? ((void) (Msgid2), (const char *) (Msgid1)) \
     : ((void) (Msgid1), (const char *) (Msgid2)))
# undef dngettext
# define dngettext(Domainname, Msgid1, Msgid2, N) \
    ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
# undef dcngettext
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
    ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
# undef textdomain
# define textdomain(Domainname) ((const char *) (Domainname))
# undef bindtextdomain
# define bindtextdomain(Domainname, Dirname) \
    ((void) (Domainname), (const char *) (Dirname))
# undef bind_textdomain_codeset
# define bind_textdomain_codeset(Domainname, Codeset) \
    ((void) (Domainname), (const char *) (Codeset))

#endif

/* A pseudo function call that serves as a marker for the automated
   extraction of messages, but does not call gettext().  The run-time
   translation is done at a different place in the code.
   The argument, String, should be a literal string.  Concatenated strings
   and other string expressions won't work.
   The macro's expansion is not parenthesized, so that it is suitable as
   initializer for static 'char[]' or 'const char[]' variables.  */
#define gettext_noop(String) String

/* The separator between msgctxt and msgid in a .mo file.  */
#define GETTEXT_CONTEXT_GLUE "\004"

/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
   MSGID.  MSGCTXT and MSGID must be string literals.  MSGCTXT should be
   short and rarely need to change.
   The letter 'p' stands for 'particular' or 'special'.  */
#ifdef DEFAULT_TEXT_DOMAIN
# define pgettext(Msgctxt, Msgid) \
   pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#else
# define pgettext(Msgctxt, Msgid) \
   pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#endif
#define dpgettext(Domainname, Msgctxt, Msgid) \
  pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
  pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
#ifdef DEFAULT_TEXT_DOMAIN
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
   npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#else
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
   npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#endif
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
  npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
  npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
pgettext_aux (const char *domain,
              const char *msg_ctxt_id, const char *msgid,
              int category)
{
  const char *translation = dcgettext (domain, msg_ctxt_id, category);
  if (translation == msg_ctxt_id)
    return msgid;
  else
    return translation;
}

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
npgettext_aux (const char *domain,
               const char *msg_ctxt_id, const char *msgid,
               const char *msgid_plural, unsigned long int n,
               int category)
{
  const char *translation =
    dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
  if (translation == msg_ctxt_id || translation == msgid_plural)
    return (n == 1 ? msgid : msgid_plural);
  else
    return translation;
}

/* The same thing extended for non-constant arguments.  Here MSGCTXT and MSGID
   can be arbitrary expressions.  But for string literals these macros are
   less efficient than those above.  */

#include <string.h>

#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
  (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
   /* || __STDC_VERSION__ >= 199901L */ )

#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
#include <stdlib.h>
#endif

#define pgettext_expr(Msgctxt, Msgid) \
  dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
  dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
dcpgettext_expr (const char *domain,
                 const char *msgctxt, const char *msgid,
                 int category)
{
  size_t msgctxt_len = strlen (msgctxt) + 1;
  size_t msgid_len = strlen (msgid) + 1;
  const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
  char msg_ctxt_id[msgctxt_len + msgid_len];
#else
  char buf[1024];
  char *msg_ctxt_id =
    (msgctxt_len + msgid_len <= sizeof (buf)
     ? buf
     : (char *) malloc (msgctxt_len + msgid_len));
  if (msg_ctxt_id != NULL)
#endif
    {
      memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
      msg_ctxt_id[msgctxt_len - 1] = '\004';
      memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
      translation = dcgettext (domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
      if (msg_ctxt_id != buf)
        free (msg_ctxt_id);
#endif
      if (translation != msg_ctxt_id)
        return translation;
    }
  return msgid;
}

#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
  dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
  dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)

#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
dcnpgettext_expr (const char *domain,
                  const char *msgctxt, const char *msgid,
                  const char *msgid_plural, unsigned long int n,
                  int category)
{
  size_t msgctxt_len = strlen (msgctxt) + 1;
  size_t msgid_len = strlen (msgid) + 1;
  const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
  char msg_ctxt_id[msgctxt_len + msgid_len];
#else
  char buf[1024];
  char *msg_ctxt_id =
    (msgctxt_len + msgid_len <= sizeof (buf)
     ? buf
     : (char *) malloc (msgctxt_len + msgid_len));
  if (msg_ctxt_id != NULL)
#endif
    {
      memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
      msg_ctxt_id[msgctxt_len - 1] = '\004';
      memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
      translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
      if (msg_ctxt_id != buf)
        free (msg_ctxt_id);
#endif
      if (!(translation == msg_ctxt_id || translation == msgid_plural))
        return translation;
    }
  return (n == 1 ? msgid : msgid_plural);
}

#endif /* _LIBGETTEXT_H */