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