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 _DEFAULT_SOURCE
71 #include <newlib.h>
72 #include <stdlib.h>
73 #include "setlocale.h"
74 
75 struct __locale_t *
duplocale(struct __locale_t * locobj)76 duplocale (struct __locale_t *locobj)
77 {
78   struct __locale_t tmp_locale, *new_locale;
79   int i;
80 
81   (void) locobj;
82   (void) i;
83   (void) new_locale;
84   (void) tmp_locale;
85 #ifndef _MB_CAPABLE
86   return __get_C_locale ();
87 #else /* _MB_CAPABLE */
88   /* LC_GLOBAL_LOCALE denotes the global locale. */
89   if (locobj == LC_GLOBAL_LOCALE)
90     locobj = __get_global_locale ();
91   /* The "C" locale is used statically, never copied. */
92   else if (locobj == __get_C_locale ())
93     return __get_C_locale ();
94   /* Copy locale content. */
95   tmp_locale = *locobj;
96 #ifdef __HAVE_LOCALE_INFO__
97   for (i = 1; i < _LC_LAST; ++i)
98     if (locobj->lc_cat[i].buf)
99       {
100 	/* If the object is not a "C" locale category, copy it.  Just call
101 	   __loadlocale.  It knows what to do to replicate the category. */
102 	tmp_locale.lc_cat[i].ptr = NULL;
103 	tmp_locale.lc_cat[i].buf = NULL;
104 	tmp_locale.categories[i][0] = '\0';	/* __loadlocale tests this! */
105 	if (!__loadlocale (&tmp_locale, i, locobj->categories[i]))
106 	  goto error;
107       }
108 #endif /* __HAVE_LOCALE_INFO__ */
109   /* Allocate new locale_t. */
110   new_locale = (struct __locale_t *) calloc (1, sizeof *new_locale);
111   if (!new_locale)
112     goto error;
113 
114   *new_locale = tmp_locale;
115   return new_locale;
116 
117 error:
118   /* An error occured while we had already (potentially) allocated memory.
119      Free memory and return NULL.  errno is supposed to be set already. */
120 #ifdef __HAVE_LOCALE_INFO__
121   while (--i > 0)
122     if (tmp_locale.lc_cat[i].buf)
123       {
124 	free ((void *) tmp_locale.lc_cat[i].ptr);
125 	free (tmp_locale.lc_cat[i].buf);
126       }
127 #endif /* __HAVE_LOCALE_INFO__ */
128 
129   return NULL;
130 #endif /* _MB_CAPABLE */
131 }
132