e7618b8001804443e906ba1501cde961b1516d19
1 /* Duplicate a locale object.
2 Copyright (C) 2009 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 Lesser 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
28 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
30 See <http://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
31 #undef _NL_LOCALE_NAME
32 #define _NL_LOCALE_NAME(category) _NL_ITEM ((category), _NL_ITEM_INDEX (-1))
34 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
39 rpl_duplocale (locale_t locale
)
41 /* Work around crash in the duplocale function in glibc < 2.12.
42 See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>. */
43 if (locale
== LC_GLOBAL_LOCALE
)
45 /* Create a copy of the locale by fetching the name of each locale
46 category, starting with LC_CTYPE. */
47 static struct { int cat
; int mask
; } categories
[] =
49 { LC_NUMERIC
, LC_NUMERIC_MASK
},
50 { LC_TIME
, LC_TIME_MASK
},
51 { LC_COLLATE
, LC_COLLATE_MASK
},
52 { LC_MONETARY
, LC_MONETARY_MASK
},
53 { LC_MESSAGES
, LC_MESSAGES_MASK
}
55 , { LC_PAPER
, LC_PAPER_MASK
}
58 , { LC_NAME
, LC_NAME_MASK
}
61 , { LC_ADDRESS
, LC_ADDRESS_MASK
}
64 , { LC_TELEPHONE
, LC_TELEPHONE_MASK
}
67 , { LC_MEASUREMENT
, LC_MEASUREMENT_MASK
}
69 #ifdef LC_IDENTIFICATION
70 , { LC_IDENTIFICATION
, LC_IDENTIFICATION_MASK
}
73 const char *base_name
;
77 base_name
= nl_langinfo (_NL_LOCALE_NAME (LC_CTYPE
));
78 if (base_name
[0] == '\0')
79 /* Fallback code for glibc < 2.4, which did not implement
80 nl_langinfo (_NL_LOCALE_NAME (category)). */
81 base_name
= setlocale (LC_CTYPE
, NULL
);
82 base_copy
= newlocale (LC_ALL_MASK
, base_name
, NULL
);
83 if (base_copy
== NULL
)
86 for (i
= 0; i
< SIZEOF (categories
); i
++)
88 int category
= categories
[i
].cat
;
89 int category_mask
= categories
[i
].mask
;
90 const char *name
= nl_langinfo (_NL_LOCALE_NAME (category
));
92 /* Fallback code for glibc < 2.4, which did not implement
93 nl_langinfo (_NL_LOCALE_NAME (category)). */
94 name
= setlocale (category
, NULL
);
95 if (strcmp (name
, base_name
) != 0)
97 locale_t copy
= newlocale (category_mask
, name
, base_copy
);
100 int saved_errno
= errno
;
101 freelocale (base_copy
);
105 /* No need to call freelocale (base_copy) if copy != base_copy;
106 the newlocale function already takes care of doing it. */
114 return duplocale (locale
);