1 /* Duplicate a locale object.
2 Copyright (C) 2009, 2010 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. */
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 <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>. */
36 if (locale
== LC_GLOBAL_LOCALE
)
38 /* Create a copy of the locale by fetching the name of each locale
39 category, starting with LC_CTYPE. */
40 static struct { int cat
; int mask
; } const categories
[] =
42 { LC_NUMERIC
, LC_NUMERIC_MASK
},
43 { LC_TIME
, LC_TIME_MASK
},
44 { LC_COLLATE
, LC_COLLATE_MASK
},
45 { LC_MONETARY
, LC_MONETARY_MASK
},
46 { LC_MESSAGES
, LC_MESSAGES_MASK
}
48 , { LC_PAPER
, LC_PAPER_MASK
}
51 , { LC_NAME
, LC_NAME_MASK
}
54 , { LC_ADDRESS
, LC_ADDRESS_MASK
}
57 , { LC_TELEPHONE
, LC_TELEPHONE_MASK
}
60 , { LC_MEASUREMENT
, LC_MEASUREMENT_MASK
}
62 #ifdef LC_IDENTIFICATION
63 , { LC_IDENTIFICATION
, LC_IDENTIFICATION_MASK
}
66 const char *base_name
;
70 base_name
= setlocale (LC_CTYPE
, NULL
);
71 base_copy
= newlocale (LC_ALL_MASK
, base_name
, NULL
);
72 if (base_copy
== NULL
)
75 for (i
= 0; i
< SIZEOF (categories
); i
++)
77 int category
= categories
[i
].cat
;
78 int category_mask
= categories
[i
].mask
;
79 const char *name
= setlocale (category
, NULL
);
80 if (strcmp (name
, base_name
) != 0)
82 locale_t copy
= newlocale (category_mask
, name
, base_copy
);
85 int saved_errno
= errno
;
86 freelocale (base_copy
);
90 /* No need to call freelocale (base_copy) if copy != base_copy;
91 the newlocale function already takes care of doing it. */
99 return duplocale (locale
);