]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - intl/localealias.c
Sync move-if-change from Gnulib, updating copyright
[thirdparty/glibc.git] / intl / localealias.c
index 324f2fe6624069d532ab0201643ce5304b58df13..3ae360f40d202fc3ff3d1eca89e501742737bd0e 100644 (file)
@@ -1,21 +1,18 @@
 /* Handle aliases for locale names.
-   Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   Copyright (C) 1995-2022 Free Software Foundation, Inc.
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
 
-   The GNU C Library is distributed in the hope that it will be useful,
+   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.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
    This must come before <config.h> because <config.h> may include
 # define alloca __builtin_alloca
 # define HAVE_ALLOCA 1
 #else
-# if defined HAVE_ALLOCA_H || defined _LIBC
-#  include <alloca.h>
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
 # else
-#  ifdef _AIX
- #pragma alloca
+#  if defined HAVE_ALLOCA_H || defined _LIBC
+#   include <alloca.h>
 #  else
-#   ifndef alloca
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca
 char *alloca ();
+#    endif
 #   endif
 #  endif
 # endif
@@ -58,34 +60,38 @@ char *alloca ();
 
 #include "gettextP.h"
 
+#ifdef ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
 /* @@ end of prolog @@ */
 
 #ifdef _LIBC
 /* Rename the non ANSI C functions.  This is required by the standard
    because some ANSI C functions will require linking with this object
    file and the name space must not be polluted.  */
-# define strcasecmp __strcasecmp
+# define strcasecmp(s1, s2) __strcasecmp_l (s1, s2, _nl_C_locobj_ptr)
 
 # ifndef mempcpy
 #  define mempcpy __mempcpy
 # endif
 # define HAVE_MEMPCPY  1
 # define HAVE___FSETLOCKING    1
-
-/* 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
+/* Handle multi-threaded applications.  */
+#ifdef _LIBC
+# include <libc-lock.h>
+#else
+# include "lock.h"
 #endif
 
 /* Some optimizations for glibc.  */
 #ifdef _LIBC
-# define FEOF(fp)              feof_unlocked (fp)
-# define FGETS(buf, n, fp)     fgets_unlocked (buf, n, fp)
+# 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)
@@ -100,16 +106,19 @@ __libc_lock_define_initialized (static, lock);
 # define freea(p) free (p)
 #endif
 
-#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
+#if defined _LIBC_REENTRANT || defined HAVE_DECL_FGETS_UNLOCKED
 # undef fgets
 # define fgets(buf, len, s) fgets_unlocked (buf, len, s)
 #endif
-#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
+#if defined _LIBC_REENTRANT || defined HAVE_DECL_FEOF_UNLOCKED
 # undef feof
 # define feof(s) feof_unlocked (s)
 #endif
 
 
+__libc_lock_define_initialized (static, lock)
+
+
 struct alias_map
 {
   const char *alias;
@@ -130,25 +139,24 @@ 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));
+static size_t read_alias_file (const char *fname, int fname_len);
+static int extend_alias_table (void);
+static int alias_compare (const struct alias_map *map1,
+                         const struct alias_map *map2);
 
 
 const char *
-_nl_expand_alias (name)
-    const char *name;
+_nl_expand_alias (const char *name)
 {
-  static const char *locale_alias_path = LOCALE_ALIAS_PATH;
+  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
     {
@@ -159,8 +167,8 @@ _nl_expand_alias (name)
       if (nmap > 0)
        retval = (struct alias_map *) bsearch (&item, map, nmap,
                                               sizeof (struct alias_map),
-                                              (int (*) PARAMS ((const void *,
-                                                                const void *))
+                                              (int (*) (const void *,
+                                                        const void *)
                                                ) alias_compare);
       else
        retval = NULL;
@@ -178,11 +186,12 @@ _nl_expand_alias (name)
        {
          const char *start;
 
-         while (locale_alias_path[0] == ':')
+         while (locale_alias_path[0] == PATH_SEPARATOR)
            ++locale_alias_path;
          start = locale_alias_path;
 
-         while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':')
+         while (locale_alias_path[0] != '\0'
+                && locale_alias_path[0] != PATH_SEPARATOR)
            ++locale_alias_path;
 
          if (start < locale_alias_path)
@@ -191,19 +200,14 @@ _nl_expand_alias (name)
     }
   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;
+read_alias_file (const char *fname, int fname_len)
 {
   FILE *fp;
   char *full_fname;
@@ -219,7 +223,13 @@ read_alias_file (fname, fname_len)
   memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
 #endif
 
-  fp = fopen (full_fname, "r");
+#ifdef _LIBC
+  /* Note the file is opened with cancellation in the I/O functions
+     disabled.  */
+  fp = fopen (relocate (full_fname), "rce");
+#else
+  fp = fopen (relocate (full_fname), "r");
+#endif
   freea (full_fname);
   if (fp == NULL)
     return 0;
@@ -273,9 +283,6 @@ read_alias_file (fname, fname_len)
 
          if (cp[0] != '\0')
            {
-             size_t alias_len;
-             size_t value_len;
-
              value = cp++;
              while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
                ++cp;
@@ -291,48 +298,62 @@ read_alias_file (fname, fname_len)
              else if (cp[0] != '\0')
                *cp++ = '\0';
 
-             if (nmap >= maxmap)
-               if (__builtin_expect (extend_alias_table (), 0))
-                 return added;
+#ifdef IN_LIBGLOCALE
+             /* glibc's locale.alias contains entries for ja_JP and ko_KR
+                that make it impossible to use a Japanese or Korean UTF-8
+                locale under the name "ja_JP" or "ko_KR".  Ignore these
+                entries.  */
+             if (strchr (alias, '_') == NULL)
+#endif
+               {
+                 size_t alias_len;
+                 size_t value_len;
 
-             alias_len = strlen (alias) + 1;
-             value_len = strlen (value) + 1;
+                 if (nmap >= maxmap)
+                   if (__builtin_expect (extend_alias_table (), 0))
+                     goto out;
 
-             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;
+                 alias_len = strlen (alias) + 1;
+                 value_len = strlen (value) + 1;
 
-                     for (i = 0; i < nmap; i++)
+                 if (string_space_act + alias_len + value_len > string_space_max)
+                   {
+                     /* Increase size of memory pool.  */
+                     size_t new_size = (string_space_max
+                                        + (alias_len + value_len > 1024
+                                           ? alias_len + value_len : 1024));
+                     char *new_pool = (char *) realloc (string_space, new_size);
+                     if (new_pool == NULL)
+                       goto out;
+
+                     if (__builtin_expect (string_space != new_pool, 0))
                        {
-                         map[i].alias += new_pool - string_space;
-                         map[i].value += new_pool - string_space;
+                         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;
-               }
+                     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].alias =
+                   (const char *) 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;
+                 map[nmap].value =
+                   (const char *) memcpy (&string_space[string_space_act],
+                                          value, value_len);
+                 string_space_act += value_len;
 
-             ++nmap;
-             ++added;
+                 ++nmap;
+                 ++added;
+               }
            }
        }
 
@@ -344,23 +365,24 @@ read_alias_file (fname, fname_len)
            /* Make sure the inner loop will be left.  The outer loop
               will exit at the `feof' test.  */
            break;
-       while (strchr (buf, '\n') == NULL)
+       while (strchr (buf, '\n') == NULL);
     }
 
+ out:
   /* Should we test for ferror()?  I think we have to silently ignore
      errors.  --drepper  */
   fclose (fp);
 
   if (added > 0)
     qsort (map, nmap, sizeof (struct alias_map),
-          (int (*) PARAMS ((const void *, const void *))) alias_compare);
+          (int (*) (const void *, const void *)) alias_compare);
 
   return added;
 }
 
 
 static int
-extend_alias_table ()
+extend_alias_table (void)
 {
   size_t new_size;
   struct alias_map *new_map;
@@ -379,9 +401,7 @@ extend_alias_table ()
 
 
 static int
-alias_compare (map1, map2)
-     const struct alias_map *map1;
-     const struct alias_map *map2;
+alias_compare (const struct alias_map *map1, const struct alias_map *map2)
 {
 #if defined _LIBC || defined HAVE_STRCASECMP
   return strcasecmp (map1->alias, map2->alias);