1 /*
2 * Copyright (c) 1999
3 * Silicon Graphics Computer Systems, Inc.
4 *
5 * Permission to use, copy, modify, distribute and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appear in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation. Silicon Graphics makes no
10 * representations about the suitability of this software for any
11 * purpose. It is provided "as is" without express or implied warranty.
12 */
13
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #ifdef _POSIX_MAPPED_FILES
19 # include <sys/mman.h>
20 #endif
21
22 #include <stl/c_locale.h>
23 #include <limits.h>
24 #include <wctype.h>
25 /* #include <libc-lock.h> */
26
27 #include <locale.h>
28 #include <argz.h>
29 #include "gcc_localeinfo.h"
30
31 wint_t btowc(int c);
32 int wctob (wint_t c);
33
34 size_t mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps);
35 size_t wcrtomb (char *s, wchar_t wc, mbstate_t *ps);
36 size_t mbrlen (const char* s, size_t n, mbstate_t *ps);
37
38 #include <nl_types.h>
39
_Locale_init()40 void _Locale_init()
41 {}
42
_Locale_final()43 void _Locale_final()
44 {}
45
46 typedef struct _Locale_ctype {
47 const struct locale_data* gcc_data;
48 const int* __tolower;
49 const int* __toupper;
50 _Locale_mask_t* __class;
51 } L_ctype_t;
52
53 typedef struct _Locale_numeric {
54 const struct locale_data* gcc_data;
55 } L_numeric_t;
56
57 typedef struct _Locale_time {
58 const struct locale_data* gcc_data;
59 } L_time_t;
60
61 typedef struct _Locale_collate {
62 const struct locale_data* gcc_data;
63 } L_collate_t;
64
65 typedef struct _Locale_monetary {
66 const struct locale_data* gcc_data;
67 } L_monetary_t;
68
69 typedef struct _Locale_messages {
70 const struct locale_data* gcc_data;
71 } L_messages_t;
72
_Locale_get_ctype_hint(struct _Locale_ctype * ctype)73 struct _Locale_name_hint* _Locale_get_ctype_hint(struct _Locale_ctype* ctype)
74 { return 0; }
_Locale_get_numeric_hint(struct _Locale_numeric * numeric)75 struct _Locale_name_hint* _Locale_get_numeric_hint(struct _Locale_numeric* numeric)
76 { return 0; }
_Locale_get_time_hint(struct _Locale_time * time)77 struct _Locale_name_hint* _Locale_get_time_hint(struct _Locale_time* time)
78 { return 0; }
_Locale_get_collate_hint(struct _Locale_collate * collate)79 struct _Locale_name_hint* _Locale_get_collate_hint(struct _Locale_collate* collate)
80 { return 0; }
_Locale_get_monetary_hint(struct _Locale_monetary * monetary)81 struct _Locale_name_hint* _Locale_get_monetary_hint(struct _Locale_monetary* monetary)
82 { return 0; }
_Locale_get_messages_hint(struct _Locale_messages * messages)83 struct _Locale_name_hint* _Locale_get_messages_hint(struct _Locale_messages* messages)
84 { return 0; }
85
86 static char const*
_Locale_extract_name(const char * cname,char * into,int category)87 _Locale_extract_name ( const char *cname, char *into, int category )
88 {
89 int i = 0;
90 const char * end;
91
92 if ( cname[0] != '/' )
93 return strcpy(into, cname); /* simple locale name */
94
95 for ( i = 0; i <= category; i ++ ) {
96 while ( *cname != '\0' && *cname != '/' )
97 cname++;
98 if ( *cname == '\0' )
99 return into;
100 cname++;
101 }
102
103 if ( *cname == '\0' )
104 return into;
105
106 end = cname;
107 while ( *end != '\0' && *end != '/' )
108 end++;
109
110 strncpy ( into, cname, end - cname );
111 into [ end - cname ] = '\0';
112
113 return into;
114 }
115
_Locale_name(const struct locale_data * gcc_data,char * buf)116 char const* _Locale_name(const struct locale_data* gcc_data,
117 char* buf)
118 {
119 if (!(gcc_data && gcc_data->name)) return 0;
120 strncpy(buf, gcc_data->name, _Locale_MAX_SIMPLE_NAME);
121 buf [ _Locale_MAX_SIMPLE_NAME - 1 ] = '\0';
122 return buf;
123 }
124
125
126 /* calls _nl_find_locale which is a function internal to the glibc
127 locale implementation that loads locale data in from the data
128 files. The locale_data struct has information for all categories.
129 In the following implementation we use a locale_data struct for
130 each category for simplicity, though there is an obvious waste in
131 doing that. */
132 const struct locale_data *
_Find_locale(char * locale_path,size_t locale_path_len,int category,char ** name)133 _Find_locale (char *locale_path, size_t locale_path_len,
134 int category, char **name)
135 {
136 return __nl_find_locale(locale_path, locale_path_len, category, name);
137 }
138
139
140 static void
_Remove_locale(int locale,struct locale_data * data)141 _Remove_locale (int locale, struct locale_data *data)
142 {
143 /* this should eventually call _nl_remove_locale() in glibc 2.1 */
144 /* _nl_remove_locale( locale, data ); */
145 }
146
147 /* couldn't find where LOCALE_PATH was defined in glibc,
148 but this is the directory it is defined to -JGS */
149 #define __LOCALE_PATH "/usr/share/locale"
150
151 const struct locale_data*
_Category_create(const char * name,int category)152 _Category_create(const char * name, int category)
153 {
154 /* JGS, where should this path come from? */
155 char* locpath_var;
156 char* locale_path = NULL;
157 size_t locale_path_len = 0;
158
159 locpath_var = __secure_getenv("LOCPATH");
160
161 if (locpath_var != NULL && locpath_var[0] != '\0')
162 if (argz_create_sep (locpath_var, ':',
163 &locale_path, &locale_path_len) != 0)
164 return NULL;
165
166 if (argz_add_sep (&locale_path, &locale_path_len, __LOCALE_PATH, ':') != 0)
167 return NULL;
168
169 return _Find_locale(locale_path, locale_path_len,
170 category, (char**)&name);
171 }
172
173
174
get_default_locale(char * buf)175 static const char* get_default_locale(char* buf) {
176 char* lang = getenv("LANG");
177 if (lang == NULL || lang[0] == '\0') {
178 buf[0] = '\0';
179 return NULL;
180 }
181 else {
182 strcpy(buf, lang);
183 return buf;
184 }
185 }
186
_Locale_ctype_default(char * buf)187 const char* _Locale_ctype_default(char* buf) {
188 char fullname[_Locale_MAX_COMPOSITE_NAME];
189 if (get_default_locale(fullname) == NULL)
190 return NULL;
191 else
192 return _Locale_extract_ctype_name(fullname, buf, 0);
193 }
194
_Locale_numeric_default(char * buf)195 const char* _Locale_numeric_default(char* buf) {
196 char fullname[_Locale_MAX_COMPOSITE_NAME];
197 if (get_default_locale(fullname) == NULL)
198 return NULL;
199 else
200 return _Locale_extract_numeric_name(fullname, buf, 0);
201 }
202
_Locale_time_default(char * buf)203 const char* _Locale_time_default(char* buf) {
204 char fullname[_Locale_MAX_COMPOSITE_NAME];
205 if (get_default_locale(fullname) == NULL)
206 return NULL;
207 else
208 return _Locale_extract_time_name(fullname, buf, 0);
209 }
210
_Locale_collate_default(char * buf)211 const char* _Locale_collate_default(char* buf) {
212 char fullname[_Locale_MAX_COMPOSITE_NAME];
213 if (get_default_locale(fullname) == NULL)
214 return NULL;
215 else
216 return _Locale_extract_collate_name(fullname, buf, 0);
217 }
218
_Locale_monetary_default(char * buf)219 const char* _Locale_monetary_default(char* buf) {
220 char fullname[_Locale_MAX_COMPOSITE_NAME];
221 if (get_default_locale(fullname) == NULL)
222 return NULL;
223 else
224 return _Locale_extract_monetary_name(fullname, buf, 0);
225 }
226
_Locale_messages_default(char * buf)227 const char* _Locale_messages_default(char* buf) {
228 char fullname[_Locale_MAX_COMPOSITE_NAME];
229 if (get_default_locale(fullname) == NULL)
230 return NULL;
231 else
232 return _Locale_extract_messages_name(fullname, buf, 0);
233 }
234
235
236 /****** Numeric Category ******/
237
238 void*
_Locale_numeric_create(const char * name,struct _Locale_name_hint * hint)239 _Locale_numeric_create(const char * name, struct _Locale_name_hint* hint) {
240 L_numeric_t* lnum = (L_numeric_t*)malloc(sizeof(L_numeric_t));
241 lnum->gcc_data = _Category_create(name, LC_NUMERIC);
242 return (void*)lnum;
243 }
244
245
_Locale_numeric_name(const void * lnum,char * buf)246 char const* _Locale_numeric_name(const void* lnum,
247 char* buf) {
248 return _Locale_name(((struct _Locale_ctype*)lnum)->gcc_data, buf);
249 }
_Locale_numeric_destroy(void * lnum)250 void _Locale_numeric_destroy(void* lnum)
251 {
252 _Remove_locale(LC_NUMERIC, (struct locale_data *)((struct _Locale_ctype*)lnum)->gcc_data);
253 free(lnum);
254 }
_Locale_extract_numeric_name(const char * cname,char * buf,struct _Locale_name_hint * hint)255 char const* _Locale_extract_numeric_name(const char* cname, char* buf, struct _Locale_name_hint* hint)
256 {
257 return _Locale_extract_name(cname, buf, LC_NUMERIC);
258 }
_Locale_decimal_point(struct _Locale_numeric * lnum)259 char _Locale_decimal_point(struct _Locale_numeric* lnum)
260 {
261 return lnum->gcc_data->values[_NL_ITEM_INDEX(DECIMAL_POINT)].string[0];
262 }
_Locale_thousands_sep(struct _Locale_numeric * lnum)263 char _Locale_thousands_sep(struct _Locale_numeric* lnum)
264 {
265 return lnum->gcc_data->values[_NL_ITEM_INDEX(THOUSANDS_SEP)].string[0];
266 }
_Locale_grouping(struct _Locale_numeric * lnum)267 const char* _Locale_grouping(struct _Locale_numeric * lnum)
268 {
269 return lnum->gcc_data->values[_NL_ITEM_INDEX(GROUPING)].string;
270 }
271
272 /* JGS: gcc/linux does not provide true/false names in their
273 * locale data files
274 */
275
276 static const char* __true_name = "true";
277 static const char* __false_name = "false";
278
_Locale_true(struct _Locale_numeric * l)279 const char * _Locale_true(struct _Locale_numeric *l)
280 { return __true_name; }
_Locale_false(struct _Locale_numeric * l)281 const char * _Locale_false(struct _Locale_numeric *l)
282 { return __false_name; }
283
284
285 /****** Monetary Category ******/
286
_Locale_monetary_create(const char * name,struct _Locale_name_hint * hint)287 void* _Locale_monetary_create(const char* name, struct _Locale_name_hint* hint) {
288 L_monetary_t* lmon = (L_monetary_t*)malloc(sizeof(L_monetary_t));
289 lmon->gcc_data = _Category_create(name, LC_MONETARY);
290 return lmon;
291 }
292
_Locale_monetary_name(const void * lmon,char * buf)293 char const* _Locale_monetary_name(const void* lmon,
294 char* buf) {
295 return _Locale_name(((struct _Locale_monetary*)lmon)->gcc_data, buf);
296 }
297
_Locale_monetary_destroy(void * lmon)298 void _Locale_monetary_destroy(void*lmon) {
299 _Remove_locale(LC_MONETARY, (struct locale_data *)((struct _Locale_monetary*)lmon)->gcc_data);
300 free(lmon);
301 }
302
_Locale_extract_monetary_name(const char * cname,char * buf,struct _Locale_name_hint * hint)303 char const* _Locale_extract_monetary_name(const char* cname, char* buf, struct _Locale_name_hint* hint) {
304 return _Locale_extract_name(cname, buf, LC_MONETARY);
305 }
306
_Locale_int_curr_symbol(struct _Locale_monetary * lmon)307 const char* _Locale_int_curr_symbol(struct _Locale_monetary* lmon) {
308 return lmon->gcc_data->values[_NL_ITEM_INDEX(INT_CURR_SYMBOL)].string;
309 }
_Locale_currency_symbol(struct _Locale_monetary * lmon)310 const char* _Locale_currency_symbol(struct _Locale_monetary* lmon) {
311 return lmon->gcc_data->values[_NL_ITEM_INDEX(CURRENCY_SYMBOL)].string;
312 }
_Locale_mon_decimal_point(struct _Locale_monetary * lmon)313 char _Locale_mon_decimal_point(struct _Locale_monetary* lmon) {
314 return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_DECIMAL_POINT)].string[0];
315 }
_Locale_mon_thousands_sep(struct _Locale_monetary * lmon)316 char _Locale_mon_thousands_sep(struct _Locale_monetary* lmon) {
317 return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_THOUSANDS_SEP)].string[0];
318 }
_Locale_mon_grouping(struct _Locale_monetary * lmon)319 const char* _Locale_mon_grouping(struct _Locale_monetary* lmon) {
320 return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_GROUPING)].string;
321 }
_Locale_positive_sign(struct _Locale_monetary * lmon)322 const char* _Locale_positive_sign(struct _Locale_monetary* lmon) {
323 return lmon->gcc_data->values[_NL_ITEM_INDEX(POSITIVE_SIGN)].string;
324 }
_Locale_negative_sign(struct _Locale_monetary * lmon)325 const char* _Locale_negative_sign(struct _Locale_monetary* lmon) {
326 return lmon->gcc_data->values[_NL_ITEM_INDEX(NEGATIVE_SIGN)].string;
327 }
_Locale_int_frac_digits(struct _Locale_monetary * lmon)328 char _Locale_int_frac_digits(struct _Locale_monetary* lmon) {
329 return lmon->gcc_data->values[_NL_ITEM_INDEX(INT_FRAC_DIGITS)].string[0];
330 }
_Locale_frac_digits(struct _Locale_monetary * lmon)331 char _Locale_frac_digits(struct _Locale_monetary* lmon) {
332 return lmon->gcc_data->values[_NL_ITEM_INDEX(FRAC_DIGITS)].string[0];
333 }
_Locale_p_cs_precedes(struct _Locale_monetary * lmon)334 int _Locale_p_cs_precedes(struct _Locale_monetary* lmon) {
335 return lmon->gcc_data->values[_NL_ITEM_INDEX(P_CS_PRECEDES)].word;
336 }
_Locale_p_sep_by_space(struct _Locale_monetary * lmon)337 int _Locale_p_sep_by_space(struct _Locale_monetary* lmon) {
338 return lmon->gcc_data->values[_NL_ITEM_INDEX(P_SEP_BY_SPACE)].word;
339 }
_Locale_p_sign_posn(struct _Locale_monetary * lmon)340 int _Locale_p_sign_posn(struct _Locale_monetary* lmon) {
341 return lmon->gcc_data->values[_NL_ITEM_INDEX(P_SIGN_POSN)].word;
342 }
_Locale_n_cs_precedes(struct _Locale_monetary * lmon)343 int _Locale_n_cs_precedes(struct _Locale_monetary* lmon) {
344 return lmon->gcc_data->values[_NL_ITEM_INDEX(N_CS_PRECEDES)].word;
345 }
_Locale_n_sep_by_space(struct _Locale_monetary * lmon)346 int _Locale_n_sep_by_space(struct _Locale_monetary* lmon) {
347 return lmon->gcc_data->values[_NL_ITEM_INDEX(N_SEP_BY_SPACE)].word;
348 }
_Locale_n_sign_posn(struct _Locale_monetary * lmon)349 int _Locale_n_sign_posn(struct _Locale_monetary* lmon) {
350 return lmon->gcc_data->values[_NL_ITEM_INDEX(N_SIGN_POSN)].word;
351 }
352
353 /****** Time Category ******/
354
_Locale_time_create(const char * name,struct _Locale_name_hint * hint)355 void* _Locale_time_create(const char * name, struct _Locale_name_hint* hint) {
356 L_time_t* ltime = (L_time_t*)malloc(sizeof(L_time_t));
357 ltime->gcc_data = _Category_create(name, LC_TIME);
358 return ltime;
359 }
360
_Locale_time_name(const void * ltime,char * buf)361 char const* _Locale_time_name(const void* ltime,
362 char* buf) {
363 return _Locale_name(((struct _Locale_time*)ltime)->gcc_data, buf);
364 }
_Locale_extract_time_name(const char * cname,char * buf,struct _Locale_name_hint * hint)365 char const* _Locale_extract_time_name(const char* cname, char* buf, struct _Locale_name_hint* hint) {
366 return _Locale_extract_name(cname, buf, LC_TIME);
367 }
_Locale_time_destroy(void * ltime)368 void _Locale_time_destroy(void* ltime) {
369 _Remove_locale(LC_TIME, (struct locale_data *)((struct _Locale_time*)ltime)->gcc_data);
370 free(ltime);
371 }
_Locale_full_monthname(struct _Locale_time * ltime,int month)372 const char * _Locale_full_monthname(struct _Locale_time *ltime, int month) {
373 const char **names = (const char **)&(ltime->gcc_data->values[_NL_ITEM_INDEX(MON_1)]);
374 return names[month];
375 }
_Locale_abbrev_monthname(struct _Locale_time * ltime,int month)376 const char * _Locale_abbrev_monthname(struct _Locale_time *ltime, int month) {
377 const char **names = (const char **)&(ltime->gcc_data->values[_NL_ITEM_INDEX(ABMON_1)]);
378 return names[month];
379 }
_Locale_full_dayofweek(struct _Locale_time * ltime,int day)380 const char * _Locale_full_dayofweek(struct _Locale_time *ltime, int day) {
381 const char **names = (const char **)&(ltime->gcc_data->values[_NL_ITEM_INDEX(DAY_1)]);
382 return names[day];
383 }
_Locale_abbrev_dayofweek(struct _Locale_time * ltime,int day)384 const char * _Locale_abbrev_dayofweek(struct _Locale_time *ltime, int day) {
385 const char **names = (const char **)&(ltime->gcc_data->values[_NL_ITEM_INDEX(ABDAY_1)]);
386 return names[day];
387 }
_Locale_d_t_fmt(struct _Locale_time * ltime)388 const char* _Locale_d_t_fmt(struct _Locale_time* ltime) {
389 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_T_FMT)].string;
390 }
_Locale_long_d_t_fmt(struct _Locale_time * ltime)391 const char* _Locale_long_d_t_fmt(struct _Locale_time* ltime) {
392 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_T_FMT)].string;
393 }
_Locale_d_fmt(struct _Locale_time * ltime)394 const char* _Locale_d_fmt(struct _Locale_time* ltime)
395 {
396 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_FMT)].string;
397 }
_Locale_long_d_fmt(struct _Locale_time * ltime)398 const char* _Locale_long_d_fmt(struct _Locale_time* ltime)
399 {
400 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_FMT)].string;
401 }
_Locale_t_fmt(struct _Locale_time * ltime)402 const char* _Locale_t_fmt(struct _Locale_time* ltime) {
403 return ltime->gcc_data->values[_NL_ITEM_INDEX(T_FMT)].string;
404 }
_Locale_am_str(struct _Locale_time * ltime)405 const char* _Locale_am_str(struct _Locale_time* ltime) {
406 return ltime->gcc_data->values[_NL_ITEM_INDEX(AM_STR)].string;
407 }
_Locale_pm_str(struct _Locale_time * ltime)408 const char* _Locale_pm_str(struct _Locale_time* ltime) {
409 return ltime->gcc_data->values[_NL_ITEM_INDEX(PM_STR)].string;
410 }
_Locale_t_fmt_ampm(struct _Locale_time * ltime)411 const char* _Locale_t_fmt_ampm(struct _Locale_time* ltime)
412 {
413 return ltime->gcc_data->values[_NL_ITEM_INDEX(T_FMT_AMPM)].string;
414 }
415
416
417 /****** Messages Category ******/
418
_Locale_messages_create(const char * name,struct _Locale_name_hint * hint)419 void* _Locale_messages_create(const char * name, struct _Locale_name_hint* hint) {
420 L_messages_t* lmsg = (L_messages_t*)malloc(sizeof(L_messages_t));
421 lmsg->gcc_data = _Category_create(name, LC_MESSAGES);
422 return lmsg;
423 }
424
_Locale_messages_name(const void * lmsg,char * buf)425 char const* _Locale_messages_name(const void* lmsg, char* buf) {
426 return _Locale_name(((struct _Locale_messages*)lmsg)->gcc_data, buf);
427 }
428
_Locale_messages_destroy(void * lmsg)429 void _Locale_messages_destroy(void* lmsg) {
430 _Remove_locale(LC_MESSAGES, (struct locale_data *)((struct _Locale_messages*)lmsg)->gcc_data);
431 free(lmsg);
432 }
433
_Locale_extract_messages_name(const char * cname,char * buf,struct _Locale_name_hint * hint)434 char const* _Locale_extract_messages_name(const char* cname, char* buf, struct _Locale_name_hint* hint) {
435 return _Locale_extract_name(cname, buf, LC_MESSAGES);
436 }
437
438
439 /*
440 Could not find support for locale specific messages in glibc
441
442 Also, this C locale interface should use a typedef for the catalog
443 instead of just an int. Currently I'm casting a void* (nl_catd)
444 back and forth to and int.
445
446 -JGS
447 */
448
_Locale_catopen(struct _Locale_messages * l,const char * cat_name)449 int _Locale_catopen(struct _Locale_messages*l, const char* cat_name) {
450 return (int)catopen(cat_name, 0); /* JGS, don't know about the flag */
451 }
_Locale_catclose(struct _Locale_messages * l,int catalog)452 void _Locale_catclose(struct _Locale_messages*l, int catalog) {
453 catclose((nl_catd)catalog);
454 }
_Locale_catgets(struct _Locale_messages * l,int catalog,int set_num,int msg_num,const char * dfault)455 const char* _Locale_catgets(struct _Locale_messages*l, int catalog,
456 int set_num, int msg_num,
457 const char *dfault){
458 return catgets((nl_catd)catalog, set_num, msg_num, dfault);
459 }
460
461
462 /****** ctype Category ******/
463
464
465 /*
466 gcc uses a different set of masks for wide characters than for
467 normal characters. However, the C++ standard requires there
468 to be only one set of masks for both. Therefore we must
469 translate the mask values from the wide characters to the
470 mask values for the normal characters. -JGS
471 */
_Map_wchar_mask_to_char_mask(wctype_t m)472 static _Locale_mask_t _Map_wchar_mask_to_char_mask(wctype_t m) {
473 _Locale_mask_t ret = 0;
474 if (m & _ISwcntrl) ret |= _Locale_CNTRL;
475 if (m & _ISwupper) ret |= _Locale_UPPER;
476 if (m & _ISwlower) ret |= _Locale_LOWER;
477 if (m & _ISwdigit) ret |= _Locale_DIGIT;
478 if (m & _ISwxdigit) ret |= _Locale_XDIGIT;
479 if (m & _ISwpunct) ret |= _Locale_PUNCT;
480 if (m & _ISwspace) ret |= _Locale_SPACE;
481 if (m & _ISwprint) ret |= _Locale_PRINT;
482 if (m & _ISwalpha) ret |= _Locale_ALPHA;
483 return ret;
484 }
485
486
_Locale_ctype_create(const char * name,struct _Locale_name_hint * hint)487 void* _Locale_ctype_create(const char * name, struct _Locale_name_hint* hint) {
488 const union locale_data_value *ctypes;
489 L_ctype_t* lctype;
490
491 lctype = (L_ctype_t*)malloc(sizeof(L_ctype_t));
492 lctype->gcc_data = _Category_create(name, LC_CTYPE);
493 ctypes = lctype->gcc_data->values;
494
495 lctype->__class = (_Locale_mask_t *)
496 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_CLASS)] .string) + 128;
497 #ifdef _STLP_GLIBC_LOCALE_2
498 lctype->__tolower = (const int *)
499 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER)].string) + 128;
500 lctype->__toupper = (const int *)
501 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER)].string) + 128;
502 #else
503 # if BYTE_ORDER == BIG_ENDIAN
504 lctype->__tolower = (const int *)
505 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER_EB)].string) + 128;
506 lctype->__toupper = (const int *)
507 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER_EB)].string) + 128;
508 # elif BYTE_ORDER == LITTLE_ENDIAN
509 lctype->__tolower = (const int *)
510 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER_EL)].string) + 128;
511 lctype->__toupper = (const int *)
512 (ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER_EL)].string) + 128;
513 # else
514 # error bizarre byte order
515 # endif
516 #endif /* _STLP_GLIBC_LOCALE_2 */
517 return lctype;
518 }
_Locale_ctype_name(const void * lctype,char * buf)519 char const* _Locale_ctype_name(const void* lctype,
520 char* buf) {
521 return _Locale_name(((struct _Locale_ctype*)lctype)->gcc_data, buf);
522 }
_Locale_ctype_destroy(void * lctype)523 void _Locale_ctype_destroy(void* lctype) {
524 _Remove_locale(LC_CTYPE, (struct locale_data *)((struct _Locale_ctype*)lctype)->gcc_data);
525 free(lctype);
526 }
_Locale_extract_ctype_name(const char * cname,char * buf,struct _Locale_name_hint * hint)527 char const* _Locale_extract_ctype_name(const char* cname, char* buf, struct _Locale_name_hint* hint) {
528 return _Locale_extract_name(cname, buf, LC_CTYPE);
529 }
_Locale_ctype_table(struct _Locale_ctype * lctype)530 const _Locale_mask_t* _Locale_ctype_table(struct _Locale_ctype* lctype) {
531 return lctype->__class;
532 }
_Locale_toupper(struct _Locale_ctype * lctype,int c)533 int _Locale_toupper(struct _Locale_ctype* lctype, int c) {
534 return lctype->__toupper[c];
535 }
_Locale_tolower(struct _Locale_ctype * lctype,int c)536 int _Locale_tolower(struct _Locale_ctype* lctype, int c) {
537 return lctype->__tolower[c];
538 }
539
540 /* Wide Character Functions */
541
542 static inline size_t
cname_lookup(wint_t wc,const struct locale_data * loc)543 cname_lookup (wint_t wc, const struct locale_data* loc)
544 {
545 #ifdef _STLP_GLIBC_LOCALE_2
546 printf( "******** Fix me: %s:%d", __FILE__, __LINE__ );
547 return ~((size_t) 0);
548 #else
549 unsigned int *__nl_ctype_names;
550 unsigned int hash_size, hash_layers;
551 size_t result, cnt;
552
553 # if BYTE_ORDER == BIG_ENDIAN
554 __nl_ctype_names = (unsigned int*)loc->values[_NL_ITEM_INDEX(_NL_CTYPE_NAMES_EB)].string;
555 # elif BYTE_ORDER == LITTLE_ENDIAN
556 __nl_ctype_names = (unsigned int*)loc->values[_NL_ITEM_INDEX(_NL_CTYPE_NAMES_EL)].string;
557 # else
558 # error bizarre byte order
559 # endif
560
561 hash_size = loc->values[_NL_ITEM_INDEX(_NL_CTYPE_HASH_SIZE)].word;
562 hash_layers = loc->values[_NL_ITEM_INDEX(_NL_CTYPE_HASH_LAYERS)].word;
563
564 result = wc % hash_size;
565 for (cnt = 0; cnt < hash_layers; ++cnt) {
566 if (__nl_ctype_names[result] == wc)
567 break;
568 result += hash_size;
569 }
570 return cnt < hash_layers ? result : ~((size_t) 0);
571 #endif
572 }
573
574
575
576
_Locale_wchar_ctype(struct _Locale_ctype * loc,wint_t wc,_Locale_mask_t which_bits)577 _Locale_mask_t _Locale_wchar_ctype(struct _Locale_ctype* loc, wint_t wc,
578 _Locale_mask_t which_bits) {
579 const struct locale_data* locale = loc->gcc_data;
580 const unsigned int *class32_b;
581 size_t idx;
582
583 idx = cname_lookup (wc, locale);
584 if (idx == ~((size_t) 0))
585 return 0;
586
587 class32_b = (u_int32_t *)
588 locale->values[_NL_ITEM_INDEX (_NL_CTYPE_CLASS32)].string;
589
590 return _Map_wchar_mask_to_char_mask( class32_b[idx] ) & which_bits;
591 }
592
593
594
595 wint_t
__towctrans_ld(wint_t wc,wctrans_t desc,const struct locale_data * locale)596 __towctrans_ld (wint_t wc, wctrans_t desc, const struct locale_data* locale)
597 {
598 size_t idx;
599
600 idx = cname_lookup (wc, locale);
601 if (idx == ~((size_t) 0))
602 /* Character is not known. Default action is to simply return it. */
603 return wc;
604
605 return (wint_t) desc[idx];
606 }
607
_Locale_wchar_tolower(struct _Locale_ctype * locale,wint_t wc)608 wint_t _Locale_wchar_tolower(struct _Locale_ctype* locale, wint_t wc) {
609 return __towctrans_ld (wc, (const unsigned int *)locale->__tolower, locale->gcc_data);
610 }
_Locale_wchar_toupper(struct _Locale_ctype * locale,wint_t wc)611 wint_t _Locale_wchar_toupper(struct _Locale_ctype* locale, wint_t wc) {
612 return __towctrans_ld (wc, (const unsigned int *)locale->__toupper, locale->gcc_data);
613 }
614
615
_Locale_mb_cur_max(struct _Locale_ctype * lctype)616 int _Locale_mb_cur_max (struct _Locale_ctype *lctype) {
617 return lctype->gcc_data->values[_NL_ITEM_INDEX(_NL_CTYPE_MB_CUR_MAX)].word;
618 }
619
_Locale_mb_cur_min(struct _Locale_ctype * l)620 int _Locale_mb_cur_min (struct _Locale_ctype *l) {
621 return 1; /* JGS just a guess */
622 }
623
_Locale_is_stateless(struct _Locale_ctype * l)624 int _Locale_is_stateless (struct _Locale_ctype *l) { return 1; }
625
_Locale_btowc(struct _Locale_ctype * l,int c)626 wint_t _Locale_btowc(struct _Locale_ctype *l, int c) {
627 return btowc(c);
628 }
629
630 /*
631 glibc currently doesn't support locale dependent conversion,
632 which affects the following functions. When it does, then
633 these functions will need to change. Hopeully, the
634 just the calls to the glibc functions will need to be
635 replaced.
636 -JGS
637 */
638
_Locale_wctob(struct _Locale_ctype * l,wint_t c)639 int _Locale_wctob(struct _Locale_ctype *l, wint_t c) {
640 return wctob(c);
641 }
642
_Locale_mbtowc(struct _Locale_ctype * l,wchar_t * to,const char * from,size_t n,mbstate_t * shift_state)643 size_t _Locale_mbtowc(struct _Locale_ctype *l,
644 wchar_t *to,
645 const char *from, size_t n,
646 mbstate_t *shift_state)
647 {
648 int ret;
649 if (to)
650 ret = mbrtowc(to, from, n, shift_state);
651 else
652 ret = mbrlen(from, n, shift_state);
653 return ret;
654 }
655
_Locale_wctomb(struct _Locale_ctype * l,char * to,size_t n,const wchar_t c,mbstate_t * shift_state)656 size_t _Locale_wctomb(struct _Locale_ctype *l,
657 char *to, size_t n,
658 const wchar_t c,
659 mbstate_t *shift_state)
660 {
661 char buf [MB_LEN_MAX];
662 int ret;
663 char* mb = buf;
664 ret = wcrtomb(mb, c, shift_state);
665
666 if (ret > n)
667 return (size_t)-2;
668 else if (ret <= 0)
669 return ret;
670
671 n = ret;
672 while (n--)
673 *to++ = *mb++;
674
675 return ret;
676 }
677
_Locale_unshift(struct _Locale_ctype * l,mbstate_t * st,char * buf,size_t n,char ** next)678 size_t _Locale_unshift(struct _Locale_ctype *l,
679 mbstate_t * st,
680 char *buf, size_t n, char **next) {
681 *next = buf; /* JGS stateless, so don't need to do anything? */
682 return 0;
683 }
684
685
686 /****** Collate Category ******/
687
_Locale_collate_create(const char * name,struct _Locale_name_hint * hint)688 void* _Locale_collate_create(const char * name, struct _Locale_name_hint* hint) {
689 L_collate_t* lcollate = (L_collate_t*)malloc(sizeof(L_collate_t));
690 lcollate->gcc_data = _Category_create(name, LC_COLLATE);
691 return lcollate;
692 }
693
_Locale_collate_name(const void * lcollate,char * buf)694 char const* _Locale_collate_name(const void* lcollate, char* buf) {
695 return _Locale_name(((struct _Locale_collate*)lcollate)->gcc_data, buf);
696 }
697
_Locale_collate_destroy(void * lcollate)698 void _Locale_collate_destroy(void* lcollate) {
699 _Remove_locale(LC_COLLATE, (struct locale_data *)((struct _Locale_collate*)lcollate)->gcc_data);
700 free(lcollate);
701 }
702
_Locale_extract_collate_name(const char * cname,char * buf,struct _Locale_name_hint * hint)703 char const* _Locale_extract_collate_name(const char* cname, char* buf, struct _Locale_name_hint* hint) {
704 return _Locale_extract_name(cname, buf, LC_COLLATE);
705 }
706
707 /* copied from the IRIX version -JGS */
_Locale_compose_name(char * buf,const char * ctype,const char * numeric,const char * time,const char * collate,const char * monetary,const char * messages,const char * default_name)708 char const* _Locale_compose_name(char* buf,
709 const char* ctype, const char* numeric,
710 const char* time, const char* collate,
711 const char* monetary, const char* messages,
712 const char *default_name)
713 {
714 (void) default_name;
715
716 if ( !strcmp ( ctype, numeric ) &&
717 !strcmp ( ctype, time ) &&
718 !strcmp ( ctype, collate ) &&
719 !strcmp ( ctype, monetary ) &&
720 !strcmp ( ctype, messages ) )
721 return strcpy ( buf, ctype );
722
723 strcpy ( buf, "/" );
724 strcat ( buf, ctype );
725
726 strcat ( buf, "/" );
727 strcat ( buf, numeric );
728
729 strcat ( buf, "/" );
730 strcat ( buf, time );
731
732 strcat ( buf, "/" );
733 strcat ( buf, collate );
734
735 strcat ( buf, "/" );
736 strcat ( buf, monetary );
737
738 strcat ( buf, "/" );
739 strcat ( buf, messages );
740
741 return buf;
742 }
743
744
745
746 /*
747 glibc doesn't have a locale specific strcmp
748 This doesn't ignore null chars the way it should
749 */
750 int
_Locale_strcmp(struct _Locale_collate * l,const char * s1,size_t n1,const char * s2,size_t n2)751 _Locale_strcmp(struct _Locale_collate * l,
752 const char *s1, size_t n1,
753 const char *s2, size_t n2)
754 {
755 int ret;
756 int minN = n1 < n2 ? n1 : n2;
757 ret = strncmp(s1, s2, minN);
758 if (ret == 0) {
759 if (n1 < n2) return -1;
760 else if (n1 > n2) return 1;
761 else return 0;
762 } else
763 return ret;
764 }
765
766
_Locale_strwcmp(struct _Locale_collate * l,const wchar_t * s1,size_t n1,const wchar_t * s2,size_t n2)767 int _Locale_strwcmp(struct _Locale_collate*l,
768 const wchar_t*s1, size_t n1,
769 const wchar_t*s2, size_t n2)
770 {
771 int ret;
772 int minN = n1 < n2 ? n1 : n2;
773 ret = wcsncmp(s1, s2, minN);
774 if (ret == 0) {
775 if (n1 < n2) return -1;
776 else if (n1 > n2) return 1;
777 else return 0;
778 } else
779 return ret;
780 }
_Locale_strxfrm(struct _Locale_collate * lcollate,char * dest,size_t dest_n,const char * src,size_t src_n)781 size_t _Locale_strxfrm(struct _Locale_collate *lcollate,
782 char *dest, size_t dest_n,
783 const char *src, size_t src_n )
784 {
785 if (src_n == 0)
786 {
787 if (dest != NULL) dest[0] = 0;
788 return 0;
789 }
790 const char *real_src;
791 char *buf = NULL;
792 if (src[src_n] != 0) {
793 buf = malloc(src_n + 1);
794 strncpy(buf, src, src_n);
795 buf[src_n] = 0;
796 real_src = buf;
797 }
798 else
799 real_src = src;
800 size_t result = strxfrm(dest, real_src, dest_n);
801 if (buf != NULL) free(buf);
802 return result;
803 }
804
805 # ifndef _STLP_NO_WCHAR_T
806
_Locale_strwxfrm(struct _Locale_collate * lcollate,wchar_t * dest,size_t dest_n,const wchar_t * src,size_t src_n)807 size_t _Locale_strwxfrm(struct _Locale_collate *lcollate,
808 wchar_t *dest, size_t dest_n,
809 const wchar_t *src, size_t src_n)
810 {
811 if (src_n == 0)
812 {
813 if (dest != NULL) dest[0] = 0;
814 return 0;
815 }
816 const wchar_t *real_src;
817 wchar_t *buf = NULL;
818 if (src[src_n] != 0) {
819 buf = malloc((src_n + 1) * sizeof(wchar_t));
820 wcsncpy(buf, src, src_n);
821 buf[src_n] = 0;
822 real_src = buf;
823 }
824 else
825 real_src = src;
826 size_t result = wcsxfrm(dest, real_src, dest_n, (__c_locale)__loc);
827 if (buf != NULL) free(buf);
828 return result;
829 }
830
831 #endif
832