1 /* Return a reference to locale information record.
2 Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
26 #include "localeinfo.h"
29 /* Constant data defined in setlocale.c. */
30 extern struct locale_data
*const _nl_C
[];
32 /* Use this when we come along an error. */
33 #define ERROR_RETURN \
35 __set_errno (EINVAL); \
41 __newlocale (int category_mask
, const char *locale
, __locale_t base
)
43 /* Intermediate memory for result. */
44 const char *newnames
[__LC_LAST
];
45 struct __locale_struct result
;
46 __locale_t result_ptr
;
48 size_t locale_path_len
;
49 const char *locpath_var
;
52 /* We treat LC_ALL in the same way as if all bits were set. */
53 if (category_mask
== LC_ALL
)
54 category_mask
= (1 << __LC_LAST
) - 1 - (1 << LC_ALL
);
56 /* Sanity check for CATEGORY argument. */
57 if ((category_mask
& ~((1 << LC_ALL
) - 1 - (1 << LC_ALL
))) != 0)
60 /* `newlocale' does not support asking for the locale name. */
64 /* Allocate memory for the result. */
74 /* Fill with pointers to C locale data to . */
75 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
77 result
.__locales
[cnt
] = _nl_C
[cnt
];
79 /* If no category is to be set we return BASE if available or a
80 dataset using the C locale data. */
81 if (category_mask
== 0)
83 result_ptr
= (__locale_t
) malloc (sizeof (struct __locale_struct
));
90 /* We perhaps really have to load some data. So we determine the
91 path in which to look for the data now. The environment variable
92 `LOCPATH' must only be used when the binary has no SUID or SGID
97 locpath_var
= __secure_getenv ("LOCPATH");
98 if (locpath_var
!= NULL
&& locpath_var
[0] != '\0')
99 if (__argz_create_sep (locpath_var
, ':',
100 &locale_path
, &locale_path_len
) != 0)
103 if (__argz_append (&locale_path
, &locale_path_len
,
104 LOCALE_PATH
, sizeof (LOCALE_PATH
)) != 0)
107 /* Get the names for the locales we are interested in. We either
108 allow a composite name or a single name. */
109 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
111 newnames
[cnt
] = locale
;
112 if (strchr (locale
, ';') != NULL
)
114 /* This is a composite name. Make a copy and split it up. */
115 char *np
= strdupa (locale
);
118 while ((cp
= strchr (np
, '=')) != NULL
)
120 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
122 && (size_t) (cp
- np
) == _nl_category_name_sizes
[cnt
]
123 && memcmp (np
, _nl_category_names
[cnt
], cp
- np
) == 0)
126 if (cnt
== __LC_LAST
)
127 /* Bogus category name. */
130 /* Found the category this clause sets. */
131 newnames
[cnt
] = ++cp
;
132 cp
= strchr (cp
, ';');
135 /* Examine the next clause. */
140 /* This was the last clause. We are done. */
144 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
146 && (category_mask
& 1 << cnt
) != 0 && newnames
[cnt
] == locale
)
147 /* The composite name did not specify the category we need. */
151 /* Now process all categories we are interested in. */
152 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
153 if (cnt
!= LC_ALL
&& (category_mask
& 1 << cnt
) != 0)
155 result
.__locales
[cnt
] = _nl_find_locale (locale_path
, locale_path_len
,
156 cnt
, &newnames
[cnt
]);
157 if (result
.__locales
[cnt
] == NULL
)
161 /* We successfully loaded all required data. */
164 /* Allocate new structure. */
165 result_ptr
= (__locale_t
) malloc (sizeof (struct __locale_struct
));
166 if (result_ptr
== NULL
)
169 *result_ptr
= result
;
172 *(result_ptr
= base
) = result
;
174 /* Update the special members. */
177 union locale_data_value
*ctypes
= result_ptr
->__locales
[LC_CTYPE
]->values
;
178 result_ptr
->__ctype_b
= (const unsigned short int *)
179 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_CLASS
)] .string
);
180 result_ptr
->__ctype_tolower
= (const int *)
181 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER
)].string
);
182 result_ptr
->__ctype_toupper
= (const int *)
183 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER
)].string
);