1 /* Duplicate a locale object.
2 Copyright (C) 2009-2018 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program 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 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
27 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
32 rpl_duplocale (locale_t locale
)
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
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
)
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
[] =
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
}
52 , { LC_PAPER
, LC_PAPER_MASK
}
55 , { LC_NAME
, LC_NAME_MASK
}
58 , { LC_ADDRESS
, LC_ADDRESS_MASK
}
61 , { LC_TELEPHONE
, LC_TELEPHONE_MASK
}
64 , { LC_MEASUREMENT
, LC_MEASUREMENT_MASK
}
66 #ifdef LC_IDENTIFICATION
67 , { LC_IDENTIFICATION
, LC_IDENTIFICATION_MASK
}
70 const char *base_name
;
74 base_name
= setlocale (LC_CTYPE
, NULL
);
75 base_copy
= newlocale (LC_ALL_MASK
, base_name
, NULL
);
76 if (base_copy
== NULL
)
79 for (i
= 0; i
< SIZEOF (categories
); i
++)
81 int category
= categories
[i
].cat
;
82 int category_mask
= categories
[i
].mask
;
83 const char *name
= setlocale (category
, NULL
);
84 if (strcmp (name
, base_name
) != 0)
86 locale_t copy
= newlocale (category_mask
, name
, base_copy
);
89 int saved_errno
= errno
;
90 freelocale (base_copy
);
94 /* No need to call freelocale (base_copy) if copy != base_copy;
95 the newlocale function already takes care of doing it. */
103 return duplocale (locale
);