1 /* Parts of this code are originally taken from FreeBSD. */
2 /*
3 * Copyright (c) 1996 - 2002 FreeBSD Project
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Paul Borman at Krystal Technologies.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34 /*
35 FUNCTION
36 <<duplocale>>---duplicate a locale object
37
38 INDEX
39 duplocale
40
41 INDEX
42 _duplocale_r
43
44 SYNOPSIS
45 #include <locale.h>
46 locale_t duplocale(locale_t <[locobj]>);
47
48 locale_t _duplocale_r(void *<[reent]>, locale_t <[locobj]>);
49
50 DESCRIPTION
51 The <<duplocale>> function shall create a duplicate copy of the locale
52 object referenced by the <[locobj]> argument.
53
54 If the <[locobj]> argument is LC_GLOBAL_LOCALE, duplocale() shall create
55 a new locale object containing a copy of the global locale determined by
56 the setlocale() function.
57
58 The behavior is undefined if the <[locobj]> argument is not a valid locale
59 object handle.
60
61 RETURNS
62 Upon successful completion, the <<duplocale>> function shall return a
63 handle for a new locale object. Otherwise <<duplocale>> shall return
64 (locale_t) <<0>> and set errno to indicate the error.
65
66 PORTABILITY
67 <<duplocale>> is POSIX-1.2008.
68 */
69
70 #define _GNU_SOURCE
71 #include <stdlib.h>
72 #include "setlocale.h"
73
74 struct __locale_t *
duplocale(struct __locale_t * locobj)75 duplocale (struct __locale_t *locobj)
76 {
77 struct __locale_t tmp_locale, *new_locale;
78 int i;
79
80 (void) locobj;
81 (void) i;
82 (void) new_locale;
83 (void) tmp_locale;
84 #ifndef _MB_CAPABLE
85 return __get_C_locale ();
86 #else /* _MB_CAPABLE */
87 /* LC_GLOBAL_LOCALE denotes the global locale. */
88 if (locobj == LC_GLOBAL_LOCALE)
89 locobj = __get_global_locale ();
90 /* The "C" locale is used statically, never copied. */
91 else if (locobj == __get_C_locale ())
92 return __get_C_locale ();
93 /* Copy locale content. */
94 tmp_locale = *locobj;
95 #ifdef __HAVE_LOCALE_INFO__
96 for (i = 1; i < _LC_LAST; ++i)
97 if (locobj->lc_cat[i].buf)
98 {
99 /* If the object is not a "C" locale category, copy it. Just call
100 __loadlocale. It knows what to do to replicate the category. */
101 tmp_locale.lc_cat[i].ptr = NULL;
102 tmp_locale.lc_cat[i].buf = NULL;
103 tmp_locale.categories[i][0] = '\0'; /* __loadlocale tests this! */
104 if (!__loadlocale (&tmp_locale, i, locobj->categories[i]))
105 goto error;
106 }
107 #endif /* __HAVE_LOCALE_INFO__ */
108 /* Allocate new locale_t. */
109 new_locale = (struct __locale_t *) calloc (1, sizeof *new_locale);
110 if (!new_locale)
111 goto error;
112
113 *new_locale = tmp_locale;
114 return new_locale;
115
116 error:
117 /* An error occured while we had already (potentially) allocated memory.
118 Free memory and return NULL. errno is supposed to be set already. */
119 #ifdef __HAVE_LOCALE_INFO__
120 while (--i > 0)
121 if (tmp_locale.lc_cat[i].buf)
122 {
123 free ((void *) tmp_locale.lc_cat[i].ptr);
124 free (tmp_locale.lc_cat[i].buf);
125 }
126 #endif /* __HAVE_LOCALE_INFO__ */
127
128 return NULL;
129 #endif /* _MB_CAPABLE */
130 }
131