1 /* Return a reference to locale information record.
2 Copyright (C) 1996, 1997 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_ALL
];
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_ALL
) - 1;
56 /* Sanity check for CATEGORY argument. */
57 if ((category_mask
& ~((1 << LC_ALL
) - 1)) != 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_ALL
; ++cnt
)
76 result
.__locales
[cnt
] = _nl_C
[cnt
];
78 /* If no category is to be set we return BASE if available or a
79 dataset using the C locale data. */
80 if (category_mask
== 0)
82 result_ptr
= (__locale_t
) malloc (sizeof (struct __locale_struct
));
89 /* We perhaps really have to load some data. So we determine the
90 path in which to look for the data now. The environment variable
91 `LOCPATH' must only be used when the binary has no SUID or SGID
96 locpath_var
= __secure_getenv ("LOCPATH");
97 if (locpath_var
!= NULL
&& locpath_var
[0] != '\0')
98 if (__argz_create_sep (locpath_var
, ':',
99 &locale_path
, &locale_path_len
) != 0)
102 if (__argz_append (&locale_path
, &locale_path_len
,
103 LOCALE_PATH
, sizeof (LOCALE_PATH
)) != 0)
106 /* Get the names for the locales we are interested in. We either
107 allow a composite name or a single name. */
108 for (cnt
= 0; cnt
< LC_ALL
; ++cnt
)
109 newnames
[cnt
] = locale
;
110 if (strchr (locale
, ';') != NULL
)
112 /* This is a composite name. Make a copy and split it up. */
113 char *np
= strdupa (locale
);
116 while ((cp
= strchr (np
, '=')) != NULL
)
118 for (cnt
= 0; cnt
< LC_ALL
; ++cnt
)
119 if ((size_t) (cp
- np
) == _nl_category_name_sizes
[cnt
]
120 && memcmp (np
, _nl_category_names
[cnt
], cp
- np
) == 0)
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_ALL
; ++cnt
)
142 if ((category_mask
& 1 << cnt
) != 0 && newnames
[cnt
] == locale
)
143 /* The composite name did not specify the category we need. */
147 /* Now process all categories we are interested in. */
148 for (cnt
= 0; cnt
< LC_ALL
; ++cnt
)
149 if ((category_mask
& 1 << cnt
) != 0)
151 result
.__locales
[cnt
] = _nl_find_locale (locale_path
, locale_path_len
,
152 cnt
, &newnames
[cnt
]);
153 if (result
.__locales
[cnt
] == NULL
)
157 /* We successfully loaded all required data. */
160 /* Allocate new structure. */
161 result_ptr
= (__locale_t
) malloc (sizeof (struct __locale_struct
));
162 if (result_ptr
== NULL
)
165 *result_ptr
= result
;
168 *(result_ptr
= base
) = result
;
170 /* Update the special members. */
173 union locale_data_value
*ctypes
= result_ptr
->__locales
[LC_CTYPE
]->values
;
174 result_ptr
->__ctype_b
= (const unsigned short int *)
175 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_CLASS
)] .string
);
176 #if BYTE_ORDER == BIG_ENDIAN
177 result_ptr
->__ctype_tolower
= (const int *)
178 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER_EB
)].string
);
179 result_ptr
->__ctype_toupper
= (const int *)
180 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER_EB
)].string
);
181 #elif BYTE_ORDER == LITTLE_ENDIAN
182 result_ptr
->__ctype_tolower
= (const int *)
183 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER_EL
)].string
);
184 result_ptr
->__ctype_toupper
= (const int *)
185 (ctypes
[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER_EL
)].string
);
187 #error bizarre byte order