root/maint/gnulib/lib/duplocale.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rpl_duplocale

   1 /* Duplicate a locale object.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 3 of the
   7    License, or (at your option) any later version.
   8 
   9    This file is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include <locale.h>
  23 
  24 #include <errno.h>
  25 #include <string.h>
  26 
  27 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
  28 
  29 #undef duplocale
  30 
  31 locale_t
  32 rpl_duplocale (locale_t locale)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34   /* Work around crash in the duplocale function in glibc < 2.12.
  35      See <https://sourceware.org/bugzilla/show_bug.cgi?id=10969>.
  36      Also, on AIX 7.1, duplocale(LC_GLOBAL_LOCALE) returns (locale_t)0 with
  37      errno set to EINVAL.
  38      Also, on NetBSD 7.0, duplocale(LC_GLOBAL_LOCALE) returns a locale that
  39      corresponds to the C locale.  */
  40   if (locale == LC_GLOBAL_LOCALE)
  41     {
  42       /* Create a copy of the locale by fetching the name of each locale
  43          category, starting with LC_CTYPE.  */
  44       static struct { int cat; int mask; } const categories[] =
  45         {
  46             { LC_NUMERIC,        LC_NUMERIC_MASK },
  47             { LC_TIME,           LC_TIME_MASK },
  48             { LC_COLLATE,        LC_COLLATE_MASK },
  49             { LC_MONETARY,       LC_MONETARY_MASK },
  50             { LC_MESSAGES,       LC_MESSAGES_MASK }
  51 #ifdef LC_PAPER
  52           , { LC_PAPER,          LC_PAPER_MASK }
  53 #endif
  54 #ifdef LC_NAME
  55           , { LC_NAME,           LC_NAME_MASK }
  56 #endif
  57 #ifdef LC_ADDRESS
  58           , { LC_ADDRESS,        LC_ADDRESS_MASK }
  59 #endif
  60 #ifdef LC_TELEPHONE
  61           , { LC_TELEPHONE,      LC_TELEPHONE_MASK }
  62 #endif
  63 #ifdef LC_MEASUREMENT
  64           , { LC_MEASUREMENT,    LC_MEASUREMENT_MASK }
  65 #endif
  66 #ifdef LC_IDENTIFICATION
  67           , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK }
  68 #endif
  69         };
  70       char base_name[SETLOCALE_NULL_MAX];
  71       int err;
  72       locale_t base_copy;
  73       unsigned int i;
  74 
  75       err = setlocale_null_r (LC_CTYPE, base_name, sizeof (base_name));
  76       if (err)
  77         {
  78           errno = err;
  79           return NULL;
  80         }
  81       base_copy = newlocale (LC_ALL_MASK, base_name, NULL);
  82       if (base_copy == NULL)
  83         return NULL;
  84 
  85       for (i = 0; i < SIZEOF (categories); i++)
  86         {
  87           int category = categories[i].cat;
  88           int category_mask = categories[i].mask;
  89           char name[SETLOCALE_NULL_MAX];
  90 
  91           err = setlocale_null_r (category, name, sizeof (name));
  92           if (err)
  93             {
  94               errno = err;
  95               return NULL;
  96             }
  97           if (strcmp (name, base_name) != 0)
  98             {
  99               locale_t copy = newlocale (category_mask, name, base_copy);
 100               if (copy == NULL)
 101                 {
 102                   int saved_errno = errno;
 103                   freelocale (base_copy);
 104                   errno = saved_errno;
 105                   return NULL;
 106                 }
 107               /* No need to call freelocale (base_copy) if copy != base_copy;
 108                  the newlocale function already takes care of doing it.  */
 109               base_copy = copy;
 110             }
 111         }
 112 
 113       return base_copy;
 114     }
 115 
 116   return duplocale (locale);
 117 }

/* [previous][next][first][last][top][bottom][index][help] */