1 /* Return a reference to locale information record.
2 Copyright (C) 1996, 1997, 1999, 2000, 2001 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
== 1 << LC_ALL
)
54 category_mask
= (1 << __LC_LAST
) - 1 - (1 << LC_ALL
);
56 /* Sanity check for CATEGORY argument. */
57 if ((category_mask
& ~((1 << __LC_LAST
) - 1 - (1 << LC_ALL
))) != 0)
60 /* `newlocale' does not support asking for the locale name. */
64 /* Allocate memory for the result. */
69 /* Fill with pointers to C locale data. */
70 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
72 result
.__locales
[cnt
] = _nl_C
[cnt
];
75 /* If no category is to be set we return BASE if available or a
76 dataset using the C locale data. */
77 if (category_mask
== 0)
79 result_ptr
= (__locale_t
) malloc (sizeof (struct __locale_struct
));
80 if (result_ptr
== NULL
)
87 /* We perhaps really have to load some data. So we determine the
88 path in which to look for the data now. The environment variable
89 `LOCPATH' must only be used when the binary has no SUID or SGID
94 locpath_var
= getenv ("LOCPATH");
95 if (locpath_var
!= NULL
&& locpath_var
[0] != '\0')
96 if (__argz_create_sep (locpath_var
, ':',
97 &locale_path
, &locale_path_len
) != 0)
100 if (__argz_append (&locale_path
, &locale_path_len
,
101 LOCALEDIR
, sizeof (LOCALEDIR
)) != 0)
104 /* Get the names for the locales we are interested in. We either
105 allow a composite name or a single name. */
106 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
108 newnames
[cnt
] = locale
;
109 if (strchr (locale
, ';') != NULL
)
111 /* This is a composite name. Make a copy and split it up. */
112 char *np
= strdupa (locale
);
115 while ((cp
= strchr (np
, '=')) != NULL
)
117 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
119 && (size_t) (cp
- np
) == _nl_category_name_sizes
[cnt
]
120 && memcmp (np
, _nl_category_names
[cnt
], cp
- np
) == 0)
123 if (cnt
== __LC_LAST
)
124 /* Bogus category name. */
127 /* Found the category this clause sets. */
128 newnames
[cnt
] = ++cp
;
129 cp
= strchr (cp
, ';');
132 /* Examine the next clause. */
137 /* This was the last clause. We are done. */
141 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
143 && (category_mask
& 1 << cnt
) != 0 && newnames
[cnt
] == locale
)
144 /* The composite name did not specify the category we need. */
148 /* Now process all categories we are interested in. */
149 for (cnt
= 0; cnt
< __LC_LAST
; ++cnt
)
150 if (cnt
!= LC_ALL
&& (category_mask
& 1 << cnt
) != 0)
152 result
.__locales
[cnt
] = _nl_find_locale (locale_path
, locale_path_len
,
153 cnt
, &newnames
[cnt
]);
154 if (result
.__locales
[cnt
] == NULL
)
158 /* We successfully loaded all required data. */
161 /* Allocate new structure. */
162 result_ptr
= (__locale_t
) malloc (sizeof (struct __locale_struct
));
163 if (result_ptr
== NULL
)
166 *result_ptr
= result
;
169 *(result_ptr
= base
) = result
;
171 /* Update the special members. */
174 union locale_data_value
*ctypes
= result_ptr
->__locales
[LC_CTYPE
]->values
;
175 result_ptr
->__ctype_b
= (const unsigned short int *)
176 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_CLASS
)].string
);
177 result_ptr
->__ctype_tolower
= (const int *)
178 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER
)].string
);
179 result_ptr
->__ctype_toupper
= (const int *)
180 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER
)].string
);