]> git.buserror.net Git - polintos/scott/priv.git/blob - lib/c++/stlport/c_locale_glibc/c_locale_glibc.c
Add STLport 5.1.4
[polintos/scott/priv.git] / lib / c++ / stlport / c_locale_glibc / c_locale_glibc.c
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
40 void _Locale_init()
41 {}
42
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
73 struct _Locale_name_hint* _Locale_get_ctype_hint(struct _Locale_ctype* ctype)
74 { return 0; }
75 struct _Locale_name_hint* _Locale_get_numeric_hint(struct _Locale_numeric* numeric)
76 { return 0; }
77 struct _Locale_name_hint* _Locale_get_time_hint(struct _Locale_time* time)
78 { return 0; }
79 struct _Locale_name_hint* _Locale_get_collate_hint(struct _Locale_collate* collate)
80 { return 0; }
81 struct _Locale_name_hint* _Locale_get_monetary_hint(struct _Locale_monetary* monetary)
82 { return 0; }
83 struct _Locale_name_hint* _Locale_get_messages_hint(struct _Locale_messages* messages)
84 { return 0; }
85
86 static char const*
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
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 *
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
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*
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
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
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
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
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
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
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
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*
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
246 char const* _Locale_numeric_name(const void* lnum,
247               char* buf) {
248   return _Locale_name(((struct _Locale_ctype*)lnum)->gcc_data, buf);
249 }
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 }
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 }
259 char _Locale_decimal_point(struct _Locale_numeric* lnum)
260 {
261   return lnum->gcc_data->values[_NL_ITEM_INDEX(DECIMAL_POINT)].string[0];
262 }
263 char _Locale_thousands_sep(struct _Locale_numeric* lnum)
264 {
265   return lnum->gcc_data->values[_NL_ITEM_INDEX(THOUSANDS_SEP)].string[0];
266 }
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
279 const char * _Locale_true(struct _Locale_numeric *l)
280 { return __true_name; }
281 const char * _Locale_false(struct _Locale_numeric *l)
282 { return __false_name; }
283
284
285 /****** Monetary Category ******/
286
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
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
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
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
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 }
310 const char* _Locale_currency_symbol(struct _Locale_monetary* lmon) {
311   return lmon->gcc_data->values[_NL_ITEM_INDEX(CURRENCY_SYMBOL)].string;
312 }
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 }
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 }
319 const char* _Locale_mon_grouping(struct _Locale_monetary* lmon) {
320   return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_GROUPING)].string;
321 }
322 const char* _Locale_positive_sign(struct _Locale_monetary* lmon) {
323   return lmon->gcc_data->values[_NL_ITEM_INDEX(POSITIVE_SIGN)].string;
324 }
325 const char* _Locale_negative_sign(struct _Locale_monetary* lmon) {
326   return lmon->gcc_data->values[_NL_ITEM_INDEX(NEGATIVE_SIGN)].string;
327 }
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 }
331 char        _Locale_frac_digits(struct _Locale_monetary* lmon) {
332   return lmon->gcc_data->values[_NL_ITEM_INDEX(FRAC_DIGITS)].string[0];
333 }
334 int         _Locale_p_cs_precedes(struct _Locale_monetary* lmon) {
335   return lmon->gcc_data->values[_NL_ITEM_INDEX(P_CS_PRECEDES)].word;
336 }
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 }
340 int         _Locale_p_sign_posn(struct _Locale_monetary* lmon) {
341   return lmon->gcc_data->values[_NL_ITEM_INDEX(P_SIGN_POSN)].word;
342 }
343 int         _Locale_n_cs_precedes(struct _Locale_monetary* lmon) {
344   return lmon->gcc_data->values[_NL_ITEM_INDEX(N_CS_PRECEDES)].word;
345 }
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 }
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
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
361 char const* _Locale_time_name(const void* ltime,
362       char* buf) {
363   return _Locale_name(((struct _Locale_time*)ltime)->gcc_data, buf);
364 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
394 const char* _Locale_d_fmt(struct _Locale_time* ltime)
395 {
396   return ltime->gcc_data->values[_NL_ITEM_INDEX(D_FMT)].string;
397 }
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 }
402 const char* _Locale_t_fmt(struct _Locale_time* ltime) {
403   return ltime->gcc_data->values[_NL_ITEM_INDEX(T_FMT)].string;
404 }
405 const char* _Locale_am_str(struct _Locale_time* ltime) {
406   return ltime->gcc_data->values[_NL_ITEM_INDEX(AM_STR)].string;
407 }
408 const char* _Locale_pm_str(struct _Locale_time* ltime) {
409   return ltime->gcc_data->values[_NL_ITEM_INDEX(PM_STR)].string;
410 }
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
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
425 char const* _Locale_messages_name(const void* lmsg, char* buf) {
426   return _Locale_name(((struct _Locale_messages*)lmsg)->gcc_data, buf);
427 }
428
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
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
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 }
452 void _Locale_catclose(struct _Locale_messages*l, int catalog) {
453   catclose((nl_catd)catalog);
454 }
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  */
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
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 }
519 char const* _Locale_ctype_name(const void* lctype,
520        char* buf) {
521   return _Locale_name(((struct _Locale_ctype*)lctype)->gcc_data, buf);
522 }
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 }
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 }
530 const _Locale_mask_t* _Locale_ctype_table(struct _Locale_ctype* lctype) {
531   return lctype->__class;
532 }
533 int _Locale_toupper(struct _Locale_ctype* lctype, int c) {
534   return lctype->__toupper[c];
535 }
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
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
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
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
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 }
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
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
620 int _Locale_mb_cur_min (struct _Locale_ctype *l) {
621   return 1;  /* JGS just a guess */
622 }
623
624 int _Locale_is_stateless (struct _Locale_ctype *l) { return 1; }
625
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
639 int _Locale_wctob(struct _Locale_ctype *l, wint_t c) {
640   return wctob(c);
641 }
642
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
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
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
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
694 char const* _Locale_collate_name(const void* lcollate, char* buf) {
695   return _Locale_name(((struct _Locale_collate*)lcollate)->gcc_data, buf);
696 }
697
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
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 */
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
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
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 }
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
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