1 
2 #include <locale.h>
3 #include <langinfo.h>
4 
5 #include <stl/c_locale.h>
6 #include <stdio.h>
7 #include <wctype.h>
8 #include <string.h>
9 
10 #include <stdint.h>
11 
12 /* Structure describing locale data in core for a category.  */
13 /* GLIBC internal, see <glibc catalog>/locale/localeinfo.h */
14 #if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ > 2))
15 
16 /* GLIBC 2.3.x */
17 struct locale_data
18 {
19   const char *name;
20   const char *filedata;         /* Region mapping the file data.  */
21   off_t filesize;               /* Size of the file (and the region).  */
22   enum                          /* Flavor of storage used for those.  */
23   {
24     ld_malloced,                /* Both are malloc'd.  */
25     ld_mapped,                  /* name is malloc'd, filedata mmap'd */
26     ld_archive                  /* Both point into mmap'd archive regions.  */
27   } alloc;
28 
29   /* This provides a slot for category-specific code to cache data computed
30    * about this locale.  That code can set a cleanup function to deallocate
31    * the data.
32   struct
33   {
34     void (*cleanup) (struct locale_data *);
35     union
36     {
37       void *data;
38       struct lc_time_data *time;
39       const struct gconv_fcts *ctype;
40     };
41   } private;
42    */
43 
44   unsigned int usage_count;     /* Counter for users.  */
45 
46   int use_translit;             /* Nonzero if the mb*towv*() and wc*tomb()
47                                    functions should use transliteration.  */
48 
49   unsigned int nstrings;        /* Number of strings below.  */
50   union locale_data_value
51   {
52     const uint32_t *wstr;
53     const char *string;
54     unsigned int word;          /* Note endian issues vs 64-bit pointers.  */
55   }
56   values[1];     /* Items, usually pointers into `filedata'.  */
57 };
58 
59 #else /* GLIBC 2.2.x */
60 
61 struct locale_data
62 {
63   const char *name;
64   const char *filedata;         /* Region mapping the file data.  */
65   off_t filesize;               /* Size of the file (and the region).  */
66   int mmaped;                   /* If nonzero the data is mmaped.  */
67 
68   unsigned int usage_count;     /* Counter for users.  */
69 
70   int use_translit;             /* Nonzero if the mb*towv*() and wc*tomb()
71                                    functions should use transliteration.  */
72   const char *options;          /* Extra options from the locale name,
73                                    not used in the path to the locale data.  */
74 
75   unsigned int nstrings;        /* Number of strings below.  */
76   union locale_data_value
77   {
78     const uint32_t *wstr;
79     const char *string;
80     unsigned int word;
81   }
82   values[1];     /* Items, usually pointers into `filedata'.  */
83 };
84 
85 #endif
86 
87 
88 typedef __locale_t __c_locale;
89 
90 #if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ > 2))
91 # define __nl_langinfo_l nl_langinfo_l
92 #endif
93 
94 #if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ > 2))
95 #  define __LOCALE_CREATE(nm,category) (void*)newlocale(1 << category, nm, NULL )
96 #  define __LOCALE_DESTROY(__loc)      freelocale((__c_locale)__loc)
97 #else
98 #  define __LOCALE_CREATE(nm,category) (void*)__newlocale(1 << category, nm, NULL )
99 #  define __LOCALE_DESTROY(__loc)      __freelocale((__c_locale)__loc)
100 #endif
101 
102 static const char *_empty_str = "";
103 static const char *_C_name = "C";
104 
105 
106 #if 0
107 struct _Locale_ctype
108 {
109   __c_locale __cloc;
110 };
111 
112 struct _Locale_numeric
113 {
114   __c_locale __cloc;
115 };
116 
117 struct _Locale_time
118 {
119   __c_locale __cloc;
120 };
121 
122 struct _Locale_collate
123 {
124   __c_locale __cloc;
125 };
126 
127 struct _Locale_monetary
128 {
129   __c_locale __cloc;
130 };
131 
132 struct _Locale_messages
133 {
134   __c_locale __cloc;
135 };
136 #endif
137 
_Locale_init()138 void _Locale_init()
139 {}
140 
_Locale_final()141 void _Locale_final()
142 {}
143 
_Locale_ctype_create(const char * nm,struct _Locale_name_hint * hint)144 void *_Locale_ctype_create( const char *nm, struct _Locale_name_hint* hint )
145 { return __LOCALE_CREATE( nm, LC_CTYPE ); }
146 
_Locale_numeric_create(const char * nm,struct _Locale_name_hint * hint)147 void* _Locale_numeric_create( const char *nm, struct _Locale_name_hint* hint )
148 { return __LOCALE_CREATE( nm, LC_NUMERIC ); }
149 
_Locale_time_create(const char * nm,struct _Locale_name_hint * hint)150 void* _Locale_time_create( const char *nm, struct _Locale_name_hint* hint )
151 { return __LOCALE_CREATE( nm, LC_TIME ); }
152 
_Locale_collate_create(const char * nm,struct _Locale_name_hint * hint)153 void *_Locale_collate_create( const char *nm, struct _Locale_name_hint* hint )
154 { return __LOCALE_CREATE( nm, LC_COLLATE ); }
155 
_Locale_monetary_create(const char * nm,struct _Locale_name_hint * hint)156 void *_Locale_monetary_create( const char *nm, struct _Locale_name_hint* hint )
157 { return __LOCALE_CREATE( nm, LC_MONETARY ); }
158 
_Locale_messages_create(const char * nm,struct _Locale_name_hint * hint)159 void *_Locale_messages_create( const char *nm, struct _Locale_name_hint* hint )
160 { return __LOCALE_CREATE( nm, LC_MESSAGES ); }
161 
162 /*
163   try to see locale category LC should be used from environment;
164   according POSIX, the order is
165   1. LC_ALL
166   2. category (LC_CTYPE, LC_NUMERIC, ... )
167   3. LANG
168   If set nothing, return "C" (this really implemetation-specific).
169 */
_Locale_aux_default(const char * LC,char * nm)170 const char *_Locale_aux_default( const char *LC, char *nm )
171 {
172   char *name = getenv( "LC_ALL" );
173 
174   if ( name != NULL && *name != 0 ) {
175     return strncpy( nm, name, _Locale_MAX_SIMPLE_NAME );
176   }
177   name = getenv( LC );
178   if ( name != NULL && *name != 0 ) {
179     return strncpy( nm, name, _Locale_MAX_SIMPLE_NAME );
180   }
181   name = getenv( "LANG" );
182   if ( name != NULL && *name != 0 ) {
183     return strncpy( nm, name, _Locale_MAX_SIMPLE_NAME );
184   }
185 
186   return strcpy( nm, "C" );
187 }
188 
_Locale_ctype_default(char * nm)189 const char *_Locale_ctype_default( char *nm )
190 {
191   return _Locale_aux_default( "LC_CTYPE", nm );
192 }
193 
_Locale_numeric_default(char * nm)194 const char *_Locale_numeric_default( char *nm )
195 {
196   return _Locale_aux_default( "LC_NUMERIC", nm );
197 }
198 
_Locale_time_default(char * nm)199 const char *_Locale_time_default( char *nm )
200 {
201   return _Locale_aux_default( "LC_TIME", nm );
202 }
203 
_Locale_collate_default(char * nm)204 const char *_Locale_collate_default( char *nm )
205 {
206   return _Locale_aux_default( "LC_COLLATE", nm );
207 }
208 
_Locale_monetary_default(char * nm)209 const char *_Locale_monetary_default( char *nm )
210 {
211   return _Locale_aux_default( "LC_MONETARY", nm );
212 }
213 
_Locale_messages_default(char * nm)214 const char *_Locale_messages_default( char *nm )
215 {
216   return _Locale_aux_default( "LC_MESSAGES", nm );
217 }
218 
_Locale_ctype_name(const void * __loc,char * buf)219 char const*_Locale_ctype_name( const void *__loc, char *buf )
220 {
221   return __loc != 0 ? strncpy( buf, ((__c_locale)__loc)->__locales[LC_CTYPE]->name, _Locale_MAX_SIMPLE_NAME ) : 0;
222 }
223 
_Locale_numeric_name(const void * __loc,char * buf)224 char const*_Locale_numeric_name( const void *__loc, char *buf )
225 {
226   return __loc != 0 ? strncpy( buf, ((__c_locale)__loc)->__locales[LC_NUMERIC]->name, _Locale_MAX_SIMPLE_NAME ) : 0;
227 }
228 
_Locale_time_name(const void * __loc,char * buf)229 char const*_Locale_time_name( const void *__loc, char *buf )
230 {
231   return __loc != 0 ? strncpy( buf, ((__c_locale)__loc)->__locales[LC_TIME]->name, _Locale_MAX_SIMPLE_NAME ) : 0;
232 }
233 
_Locale_collate_name(const void * __loc,char * buf)234 char const*_Locale_collate_name( const void *__loc, char *buf )
235 {
236   return __loc != 0 ? strncpy( buf, ((__c_locale)__loc)->__locales[LC_COLLATE]->name, _Locale_MAX_SIMPLE_NAME ) : 0;
237 }
238 
_Locale_monetary_name(const void * __loc,char * buf)239 char const*_Locale_monetary_name( const void *__loc, char *buf )
240 {
241   return __loc != 0 ? strncpy( buf, ((__c_locale)__loc)->__locales[LC_MONETARY]->name, _Locale_MAX_SIMPLE_NAME ) : 0;
242 }
243 
_Locale_messages_name(const void * __loc,char * buf)244 char const*_Locale_messages_name( const void *__loc, char *buf )
245 {
246   return __loc != 0 ? strncpy( buf, ((__c_locale)__loc)->__locales[LC_MESSAGES]->name, _Locale_MAX_SIMPLE_NAME ) : 0;
247 }
248 
_Locale_ctype_destroy(void * __loc)249 void _Locale_ctype_destroy( void *__loc )
250 { __LOCALE_DESTROY(__loc); }
251 
_Locale_numeric_destroy(void * __loc)252 void _Locale_numeric_destroy( void *__loc )
253 { __LOCALE_DESTROY(__loc); }
254 
_Locale_time_destroy(void * __loc)255 void _Locale_time_destroy( void *__loc )
256 { __LOCALE_DESTROY(__loc); }
257 
_Locale_collate_destroy(void * __loc)258 void _Locale_collate_destroy( void *__loc )
259 { __LOCALE_DESTROY(__loc); }
260 
_Locale_monetary_destroy(void * __loc)261 void _Locale_monetary_destroy( void *__loc )
262 { __LOCALE_DESTROY(__loc); }
263 
_Locale_messages_destroy(void * __loc)264 void _Locale_messages_destroy( void* __loc )
265 { __LOCALE_DESTROY(__loc); }
266 
267 /*
268  * locale loc expected either locale name indeed (platform-specific)
269  * or string like "LC_CTYPE=LocaleNameForCType;LC_NUMERIC=LocaleNameForNum;"
270  *
271  */
272 
__Extract_locale_name(const char * loc,const char * category,char * buf)273 char const*__Extract_locale_name( const char *loc, const char *category, char *buf )
274 {
275   char *expr;
276   size_t len_name;
277   buf[0] = 0;
278 
279   if( loc[0]=='L' && loc[1]=='C' && loc[2]=='_') {
280     expr = strstr( (char*)loc, category );
281     if ( expr == NULL )
282       return NULL; /* Category not found. */
283     ++expr;
284     len_name = strcspn( expr, ";" );
285     len_name = len_name >= _Locale_MAX_SIMPLE_NAME ? _Locale_MAX_SIMPLE_NAME - 1: len_name;
286     strncpy( buf, expr, len_name );
287     buf[len_name] = 0;
288     return buf;
289   }
290   return strncpy( buf, loc, _Locale_MAX_SIMPLE_NAME );
291 }
292 
_Locale_extract_ctype_name(const char * loc,char * buf,struct _Locale_name_hint * hint)293 char const*_Locale_extract_ctype_name( const char *loc, char *buf, struct _Locale_name_hint* hint )
294 { return __Extract_locale_name( loc, "LC_CTYPE=", buf ); }
295 
_Locale_extract_numeric_name(const char * loc,char * buf,struct _Locale_name_hint * hint)296 char const*_Locale_extract_numeric_name( const char *loc, char *buf, struct _Locale_name_hint* hint )
297 { return __Extract_locale_name( loc, "LC_NUMERIC=", buf ); }
298 
_Locale_extract_time_name(const char * loc,char * buf,struct _Locale_name_hint * hint)299 char const*_Locale_extract_time_name( const char *loc, char *buf, struct _Locale_name_hint* hint )
300 { return __Extract_locale_name( loc, "LC_TIME=", buf ); }
301 
_Locale_extract_collate_name(const char * loc,char * buf,struct _Locale_name_hint * hint)302 char const*_Locale_extract_collate_name( const char *loc, char *buf, struct _Locale_name_hint* hint )
303 { return __Extract_locale_name( loc, "LC_COLLATE=", buf ); }
304 
_Locale_extract_monetary_name(const char * loc,char * buf,struct _Locale_name_hint * hint)305 char const*_Locale_extract_monetary_name( const char *loc, char *buf, struct _Locale_name_hint* hint )
306 { return __Extract_locale_name( loc, "LC_MONETARY=", buf ); }
307 
_Locale_extract_messages_name(const char * loc,char * buf,struct _Locale_name_hint * hint)308 char const*_Locale_extract_messages_name( const char *loc, char *buf, struct _Locale_name_hint* hint )
309 { return __Extract_locale_name( loc, "LC_MESSAGES=", buf ); }
310 
_Locale_compose_name(char * __DUMMY_PAR1,const char * __DUMMY_PAR2,const char * __DUMMY_PAR3,const char * __DUMMY_PAR4,const char * __DUMMY_PAR5,const char * __DUMMY_PAR6,const char * __DUMMY_PAR7,const char * __DUMMY_PAR8)311 char const*_Locale_compose_name(char*__DUMMY_PAR1, const char*__DUMMY_PAR2, const char*__DUMMY_PAR3,
312                             const char*__DUMMY_PAR4,
313                             const char*__DUMMY_PAR5, const char*__DUMMY_PAR6, const char*__DUMMY_PAR7, const char*__DUMMY_PAR8) {
314   /* TODO: what's this? Is this a marker that this is not yet completely
315   implemented? Copy the implementation from c_locale_win32 perhaps? It seems
316   to complement the extract functions above. */
317   printf( "%s:%d\n", __FILE__, __LINE__ );
318   return 0;
319 }
320 
_Locale_get_ctype_hint(struct _Locale_ctype * ctype)321 struct _Locale_name_hint* _Locale_get_ctype_hint(struct _Locale_ctype* ctype)
322 { return 0; }
_Locale_get_numeric_hint(struct _Locale_numeric * numeric)323 struct _Locale_name_hint* _Locale_get_numeric_hint(struct _Locale_numeric* numeric)
324 { return 0; }
_Locale_get_time_hint(struct _Locale_time * time)325 struct _Locale_name_hint* _Locale_get_time_hint(struct _Locale_time* time)
326 { return 0; }
_Locale_get_collate_hint(struct _Locale_collate * collate)327 struct _Locale_name_hint* _Locale_get_collate_hint(struct _Locale_collate* collate)
328 { return 0; }
_Locale_get_monetary_hint(struct _Locale_monetary * monetary)329 struct _Locale_name_hint* _Locale_get_monetary_hint(struct _Locale_monetary* monetary)
330 { return 0; }
_Locale_get_messages_hint(struct _Locale_messages * messages)331 struct _Locale_name_hint* _Locale_get_messages_hint(struct _Locale_messages* messages)
332 { return 0; }
333 
334 /* ctype */
335 
_Locale_ctype_table(struct _Locale_ctype * __loc)336 const _Locale_mask_t *_Locale_ctype_table( struct _Locale_ctype *__loc )
337 {
338   /* return table with masks (upper, lower, alpha, etc.) */
339   /* return ((__c_locale)__loc)->__locales[LC_CTYPE]->values[_NL_ITEM_INDEX (_NL_CTYPE_CLASS)].string + 128; */
340   return ((__c_locale)__loc)->__ctype_b;
341 }
342 
_Locale_toupper(struct _Locale_ctype * __loc,int c)343 int _Locale_toupper( struct _Locale_ctype *__loc, int c )
344 { return ((__c_locale)__loc)->__ctype_toupper[c]; }
345 
_Locale_tolower(struct _Locale_ctype * __loc,int c)346 int _Locale_tolower( struct _Locale_ctype *__loc, int c )
347 { return ((__c_locale)__loc)->__ctype_tolower[c]; }
348 
349 #if !defined (_STLP_NO_WCHAR_T)
_Locale_wchar_ctype(struct _Locale_ctype * __DUMMY_PAR1,wint_t __DUMMY_PAR2,_Locale_mask_t __DUMMY_PAR3)350 _Locale_mask_t _Locale_wchar_ctype(struct _Locale_ctype*__DUMMY_PAR1, wint_t __DUMMY_PAR2, _Locale_mask_t __DUMMY_PAR3) {
351   printf( "%s:%d\n", __FILE__, __LINE__ );
352   return 0;
353 }
354 
_Locale_wchar_tolower(struct _Locale_ctype * __loc,wint_t c)355 wint_t _Locale_wchar_tolower( struct _Locale_ctype *__loc, wint_t c ) {
356   printf( "%s:%d\n", __FILE__, __LINE__ );
357   return __towlower_l( c, ((__c_locale)__loc) );
358 }
359 
_Locale_wchar_toupper(struct _Locale_ctype * __loc,wint_t c)360 wint_t _Locale_wchar_toupper( struct _Locale_ctype *__loc, wint_t c ) {
361   printf( "%s:%d\n", __FILE__, __LINE__ );
362   return __towupper_l( c, ((__c_locale)__loc) );
363 }
364 #endif
365 
366 #if !defined (_STLP_NO_MBSTATE_T)
367 
_Locale_mb_cur_max(struct _Locale_ctype * __DUMMY_PAR)368 int _Locale_mb_cur_max( struct _Locale_ctype * __DUMMY_PAR) {
369   printf( "%s:%d\n", __FILE__, __LINE__ );
370   return 0;
371 }
372 
_Locale_mb_cur_min(struct _Locale_ctype * __DUMMY_PAR)373 int _Locale_mb_cur_min( struct _Locale_ctype * __DUMMY_PAR) {
374   printf( "%s:%d\n", __FILE__, __LINE__ );
375   return 0;
376 }
377 
_Locale_is_stateless(struct _Locale_ctype * __DUMMY_PAR)378 int _Locale_is_stateless( struct _Locale_ctype * __DUMMY_PAR) {
379   printf( "%s:%d\n", __FILE__, __LINE__ );
380   return 1;
381 }
382 
383 #if !defined (_STLP_NO_WCHAR_T)
_Locale_btowc(struct _Locale_ctype * __loc,int c)384 wint_t _Locale_btowc(struct _Locale_ctype *__loc, int c) {
385   wint_t _c;
386   /* __c_locale __tmp = __uselocale( __loc ); */
387   _c = btowc( c );
388   /* __uselocale( __tmp ); */
389   return _c;
390 }
391 
_Locale_wctob(struct _Locale_ctype * __loc,wint_t c)392 int _Locale_wctob(struct _Locale_ctype *__loc, wint_t c) {
393   int _c;
394   /* __c_locale __tmp = __uselocale( __loc ); */
395   _c = wctob( c );
396   /* __uselocale( __tmp ); */
397   return _c;
398 }
399 
_Locale_mbtowc(struct _Locale_ctype * __DUMMY_PAR1,wchar_t * __DUMMY_PAR2,const char * __DUMMY_PAR3,size_t __DUMMY_PAR4,mbstate_t * __DUMMY_PAR5)400 size_t _Locale_mbtowc(struct _Locale_ctype *__DUMMY_PAR1,
401                       wchar_t *__DUMMY_PAR2,
402                       const char *__DUMMY_PAR3, size_t __DUMMY_PAR4,
403                       mbstate_t *__DUMMY_PAR5) {
404   printf( "%s:%d\n", __FILE__, __LINE__ );
405   return (size_t) -1;
406 }
407 
_Locale_wctomb(struct _Locale_ctype * __DUMMY_PAR1,char * __DUMMY_PAR2,size_t __DUMMY_PAR3,const wchar_t __DUMMY_PAR4,mbstate_t * __DUMMY_PAR5)408 size_t _Locale_wctomb(struct _Locale_ctype *__DUMMY_PAR1,
409                       char *__DUMMY_PAR2, size_t __DUMMY_PAR3,
410                       const wchar_t __DUMMY_PAR4,
411                       mbstate_t *__DUMMY_PAR5) {
412   printf( "%s:%d\n", __FILE__, __LINE__ );
413   return (size_t) -1;
414 }
415 #endif
416 
_Locale_unshift(struct _Locale_ctype * __DUMMY_PAR1,mbstate_t * __DUMMY_PAR2,char * __DUMMY_PAR3,size_t __DUMMY_PAR4,char ** __DUMMY_PAR5)417 size_t _Locale_unshift(struct _Locale_ctype *__DUMMY_PAR1,
418                        mbstate_t *__DUMMY_PAR2,
419                        char *__DUMMY_PAR3, size_t __DUMMY_PAR4, char ** __DUMMY_PAR5) {
420   printf( "%s:%d\n", __FILE__, __LINE__ );
421   return (size_t) -1;
422 }
423 
424 #endif /*  _STLP_NO_MBSTATE_T */
425 
426 /* Collate */
_Locale_strcmp(struct _Locale_collate * __loc,const char * s1,size_t n1,const char * s2,size_t n2)427 int _Locale_strcmp(struct _Locale_collate * __loc,
428                    const char *s1, size_t n1,
429 		   const char *s2, size_t n2) {
430   int ret;
431   char buf1[64], buf2[64];
432   while (n1 > 0 && n2 > 0) {
433     size_t bufsize1 = n1 < 63 ? n1 : 63;
434     size_t bufsize2 = n2 < 63 ? n2 : 63;
435     strncpy(buf1, s1, bufsize1); buf1[bufsize1] = 0;
436     strncpy(buf2, s2, bufsize2); buf2[bufsize2] = 0;
437 
438     ret = strcoll_l(buf1, buf2, (__c_locale)__loc);
439     if (ret != 0) return ret;
440     s1 += bufsize1; n1 -= bufsize1;
441     s2 += bufsize2; n2 -= bufsize2;
442   }
443   return ret;
444 }
445 
446 #if !defined (_STLP_NO_WCHAR_T)
_Locale_strwcmp(struct _Locale_collate * __loc,const wchar_t * s1,size_t n1,const wchar_t * s2,size_t n2)447 int _Locale_strwcmp(struct _Locale_collate *__loc,
448                     const wchar_t *s1, size_t n1,
449                     const wchar_t *s2, size_t n2) {
450   int ret;
451   wchar_t buf1[64], buf2[64];
452   while (n1 > 0 && n2 > 0) {
453     size_t bufsize1 = n1 < 63 ? n1 : 63;
454     size_t bufsize2 = n2 < 63 ? n2 : 63;
455     wcsncpy(buf1, s1, bufsize1); buf1[bufsize1] = 0;
456     wcsncpy(buf2, s2, bufsize2); buf2[bufsize2] = 0;
457 
458     ret = wcscoll_l(buf1, buf2, (__c_locale)__loc);
459     if (ret != 0) return ret;
460     s1 += bufsize1; n1 -= bufsize1;
461     s2 += bufsize2; n2 -= bufsize2;
462   }
463   return ret;
464 }
465 
466 #endif
467 
_Locale_strxfrm(struct _Locale_collate * __loc,char * dest,size_t dest_n,const char * src,size_t src_n)468 size_t _Locale_strxfrm(struct _Locale_collate *__loc,
469                        char *dest, size_t dest_n,
470                        const char *src, size_t src_n )
471 {
472   const char *real_src;
473   char *buf = NULL;
474   size_t result;
475 
476   if (src_n == 0)
477   {
478     if (dest != NULL) dest[0] = 0;
479     return 0;
480   }
481   if (src[src_n] != 0) {
482     buf = malloc(src_n + 1);
483     strncpy(buf, src, src_n);
484     buf[src_n] = 0;
485     real_src = buf;
486   }
487   else
488     real_src = src;
489   result = __strxfrm_l(dest, real_src, dest_n, (__c_locale)__loc);
490   if (buf != NULL) free(buf);
491   return result;
492 }
493 
494 # ifndef _STLP_NO_WCHAR_T
495 
_Locale_strwxfrm(struct _Locale_collate * __loc,wchar_t * dest,size_t dest_n,const wchar_t * src,size_t src_n)496 size_t _Locale_strwxfrm( struct _Locale_collate *__loc,
497                           wchar_t *dest, size_t dest_n,
498                           const wchar_t *src, size_t src_n )
499 {
500   const wchar_t *real_src;
501   wchar_t *buf = NULL;
502   size_t result;
503 
504   if (src_n == 0)
505   {
506     if (dest != NULL) dest[0] = 0;
507     return 0;
508   }
509   if (src[src_n] != 0) {
510     buf = malloc((src_n + 1) * sizeof(wchar_t));
511     wcsncpy(buf, src, src_n);
512     buf[src_n] = 0;
513     real_src = buf;
514   }
515   else
516     real_src = src;
517   result = __wcsxfrm_l(dest, real_src, dest_n, (__c_locale)__loc);
518   if (buf != NULL) free(buf);
519   return result;
520 }
521 
522 # endif
523 
524 /* Numeric */
525 
_Locale_decimal_point(struct _Locale_numeric * __loc)526 char _Locale_decimal_point(struct _Locale_numeric *__loc)
527 {
528   return (__loc != 0) ? *(__nl_langinfo_l(RADIXCHAR, (__c_locale)__loc)) : '.';
529 }
530 
_Locale_thousands_sep(struct _Locale_numeric * __loc)531 char _Locale_thousands_sep(struct _Locale_numeric *__loc)
532 {
533   return (__loc != 0) ? *(__nl_langinfo_l(THOUSEP, (__c_locale)__loc)) : ',';
534 }
535 
_Locale_grouping(struct _Locale_numeric * __loc)536 const char* _Locale_grouping(struct _Locale_numeric *__loc)
537 {
538   return (__loc != 0 && _Locale_thousands_sep(__loc) != '\0' ) ?
539     (__nl_langinfo_l(GROUPING, (__c_locale)__loc)) : "";
540 }
541 
_Locale_true(struct _Locale_numeric * __loc)542 const char *_Locale_true(struct _Locale_numeric *__loc)
543 {
544   return __loc != 0 ? __nl_langinfo_l(YESSTR, (__c_locale)__loc) : "true";
545 }
546 
_Locale_false(struct _Locale_numeric * __loc)547 const char *_Locale_false(struct _Locale_numeric *__loc)
548 {
549   return __loc != 0 ? __nl_langinfo_l(NOSTR, (__c_locale)__loc) : "false";
550 }
551 
552 
553 /* Monetary */
554 
_Locale_int_curr_symbol(struct _Locale_monetary * __loc)555 const char *_Locale_int_curr_symbol(struct _Locale_monetary *__loc)
556 {
557   return __loc != 0 ? __nl_langinfo_l(INT_CURR_SYMBOL, (__c_locale)__loc) : 0;
558 }
559 
_Locale_currency_symbol(struct _Locale_monetary * __loc)560 const char *_Locale_currency_symbol(struct _Locale_monetary *__loc)
561 {
562   return __loc != 0 ? __nl_langinfo_l(CURRENCY_SYMBOL, (__c_locale)__loc) : 0;
563 }
564 
_Locale_mon_decimal_point(struct _Locale_monetary * __loc)565 char _Locale_mon_decimal_point(struct _Locale_monetary * __loc)
566 {
567   return __loc != 0 ? *(__nl_langinfo_l(MON_DECIMAL_POINT,(__c_locale)__loc)) : '.';
568 }
569 
_Locale_mon_thousands_sep(struct _Locale_monetary * __loc)570 char _Locale_mon_thousands_sep(struct _Locale_monetary *__loc)
571 {
572   return __loc != 0 ? *(__nl_langinfo_l(MON_THOUSANDS_SEP, (__c_locale)__loc)) : ',';
573 }
574 
_Locale_mon_grouping(struct _Locale_monetary * __loc)575 const char *_Locale_mon_grouping(struct _Locale_monetary *__loc)
576 {
577   return (__loc != 0 && _Locale_mon_thousands_sep( __loc ) != '\0' ) ?
578     __nl_langinfo_l(MON_GROUPING, (__c_locale)__loc) : _empty_str;
579 }
580 
_Locale_positive_sign(struct _Locale_monetary * __loc)581 const char *_Locale_positive_sign(struct _Locale_monetary *__loc)
582 {
583   return __loc != 0 ? __nl_langinfo_l(POSITIVE_SIGN, (__c_locale)__loc) : _empty_str;
584 }
585 
_Locale_negative_sign(struct _Locale_monetary * __loc)586 const char *_Locale_negative_sign(struct _Locale_monetary *__loc)
587 {
588   return __loc != 0 ? __nl_langinfo_l(NEGATIVE_SIGN, (__c_locale)__loc) : _empty_str;
589 }
590 
_Locale_int_frac_digits(struct _Locale_monetary * __loc)591 char _Locale_int_frac_digits(struct _Locale_monetary *__loc)
592 {
593   return __loc != 0 ? *(__nl_langinfo_l(INT_FRAC_DIGITS, (__c_locale)__loc)) : CHAR_MAX;
594 }
595 
_Locale_frac_digits(struct _Locale_monetary * __loc)596 char _Locale_frac_digits(struct _Locale_monetary *__loc)
597 {
598   return __loc != 0 ? *(__nl_langinfo_l(FRAC_DIGITS, (__c_locale)__loc)) : CHAR_MAX;
599 }
600 
601 /* 1 if currency_symbol precedes a positive value, 0 if succeeds */
_Locale_p_cs_precedes(struct _Locale_monetary * __loc)602 int _Locale_p_cs_precedes(struct _Locale_monetary *__loc)
603 {
604   return __loc != 0 ? *(__nl_langinfo_l(P_CS_PRECEDES, (__c_locale)__loc)) : CHAR_MAX;
605 }
606 
607 /* 1 if a space separates currency_symbol from a positive value. */
_Locale_p_sep_by_space(struct _Locale_monetary * __loc)608 int _Locale_p_sep_by_space(struct _Locale_monetary *__loc)
609 {
610   return __loc != 0 ? *(__nl_langinfo_l(P_SEP_BY_SPACE, (__c_locale)__loc)) : CHAR_MAX;
611 }
612 
613 /*
614  * 0 Parentheses surround the quantity and currency_symbol
615  * 1 The sign string precedes the quantity and currency_symbol
616  * 2 The sign string succeeds the quantity and currency_symbol.
617  * 3 The sign string immediately precedes the currency_symbol.
618  * 4 The sign string immediately succeeds the currency_symbol.
619  */
_Locale_p_sign_posn(struct _Locale_monetary * __loc)620 int _Locale_p_sign_posn(struct _Locale_monetary *__loc)
621 {
622   return __loc != 0 ? *(__nl_langinfo_l(P_SIGN_POSN, (__c_locale)__loc)) : CHAR_MAX;
623 }
624 
625 /* 1 if currency_symbol precedes a negative value, 0 if succeeds */
_Locale_n_cs_precedes(struct _Locale_monetary * __loc)626 int _Locale_n_cs_precedes(struct _Locale_monetary *__loc)
627 {
628   return __loc != 0 ? *(__nl_langinfo_l(N_CS_PRECEDES, (__c_locale)__loc)) : CHAR_MAX;
629 }
630 
631 /* 1 if a space separates currency_symbol from a negative value. */
_Locale_n_sep_by_space(struct _Locale_monetary * __loc)632 int _Locale_n_sep_by_space(struct _Locale_monetary *__loc)
633 {
634   return __loc != 0 ? *(__nl_langinfo_l(N_SEP_BY_SPACE, (__c_locale)__loc)) : CHAR_MAX;
635 }
636 
637 /*
638  * 0 Parentheses surround the quantity and currency_symbol
639  * 1 The sign string precedes the quantity and currency_symbol
640  * 2 The sign string succeeds the quantity and currency_symbol.
641  * 3 The sign string immediately precedes the currency_symbol.
642  * 4 The sign string immediately succeeds the currency_symbol.
643  */
_Locale_n_sign_posn(struct _Locale_monetary * __loc)644 int _Locale_n_sign_posn(struct _Locale_monetary *__loc)
645 {
646   return __loc != 0 ? *(__nl_langinfo_l(N_SIGN_POSN, (__c_locale)__loc)) : CHAR_MAX;
647 }
648 
649 
650 /* Time */
_Locale_full_monthname(struct _Locale_time * __loc,int _m)651 const char *_Locale_full_monthname(struct _Locale_time *__loc, int _m )
652 {
653   return (__loc != 0 && _m >= 0 && _m < 12) ? __nl_langinfo_l(MON_1 + _m, (__c_locale)__loc) : 0;
654 }
655 
_Locale_abbrev_monthname(struct _Locale_time * __loc,int _m)656 const char *_Locale_abbrev_monthname(struct _Locale_time *__loc, int _m )
657 {
658   return (__loc != 0 && _m >= 0 && _m < 12) ? __nl_langinfo_l(ABMON_1 + _m, (__c_locale)__loc) : 0;
659 }
660 
_Locale_full_dayofweek(struct _Locale_time * __loc,int _d)661 const char *_Locale_full_dayofweek(struct _Locale_time *__loc, int _d )
662 {
663   return (__loc != 0 && _d >= 0 && _d < 7) ? __nl_langinfo_l(DAY_1 + _d, (__c_locale)__loc) : 0;
664 }
665 
_Locale_abbrev_dayofweek(struct _Locale_time * __loc,int _d)666 const char *_Locale_abbrev_dayofweek(struct _Locale_time *__loc, int _d )
667 {
668   return (__loc != 0 && _d >= 0 && _d < 7) ? __nl_langinfo_l(ABDAY_1 + _d, (__c_locale)__loc) : 0;
669 }
670 
_Locale_d_t_fmt(struct _Locale_time * __loc)671 const char *_Locale_d_t_fmt(struct _Locale_time *__loc)
672 {
673   return __loc != 0 ? __nl_langinfo_l(D_T_FMT, (__c_locale)__loc) : 0;
674 }
675 
_Locale_d_fmt(struct _Locale_time * __loc)676 const char *_Locale_d_fmt(struct _Locale_time *__loc )
677 {
678   return __loc != 0 ? __nl_langinfo_l(D_FMT, (__c_locale)__loc) : 0;
679 }
680 
_Locale_t_fmt(struct _Locale_time * __loc)681 const char *_Locale_t_fmt(struct _Locale_time *__loc )
682 {
683   return __loc != 0 ? __nl_langinfo_l(T_FMT, (__c_locale)__loc) : 0;
684 }
685 
_Locale_long_d_t_fmt(struct _Locale_time * __loc)686 const char *_Locale_long_d_t_fmt(struct _Locale_time *__loc )
687 {
688   return __loc != 0 ? __nl_langinfo_l(ERA_D_T_FMT, (__c_locale)__loc) : 0;
689 }
690 
_Locale_long_d_fmt(struct _Locale_time * __loc)691 const char *_Locale_long_d_fmt(struct _Locale_time *__loc )
692 {
693   return __loc != 0 ? __nl_langinfo_l(ERA_D_FMT, (__c_locale)__loc) : 0;
694 }
695 
_Locale_am_str(struct _Locale_time * __loc)696 const char *_Locale_am_str(struct _Locale_time *__loc )
697 {
698   return __loc != 0 ? __nl_langinfo_l(AM_STR, (__c_locale)__loc) : _empty_str;
699 }
700 
_Locale_pm_str(struct _Locale_time * __loc)701 const char *_Locale_pm_str(struct _Locale_time* __loc )
702 {
703   return __loc != 0 ? __nl_langinfo_l(PM_STR, (__c_locale)__loc) : _empty_str;
704 }
705 
_Locale_t_fmt_ampm(struct _Locale_time * __loc)706 const char *_Locale_t_fmt_ampm(struct _Locale_time *__loc )
707 {
708   return __loc != 0 ? __nl_langinfo_l(T_FMT_AMPM, (__c_locale)__loc) : 0;
709 }
710 
711 /* Messages */
712 
_Locale_catopen(struct _Locale_messages * __loc,const char * __cat_name)713 nl_catd_type _Locale_catopen(struct _Locale_messages *__loc, const char *__cat_name )
714 {
715   return catopen( __cat_name, NL_CAT_LOCALE );
716 }
717 
_Locale_catclose(struct _Locale_messages * __loc,nl_catd_type __cat)718 void _Locale_catclose(struct _Locale_messages *__loc, nl_catd_type __cat )
719 {
720   catclose( __cat );
721 }
722 
_Locale_catgets(struct _Locale_messages * __loc,nl_catd_type __cat,int __setid,int __msgid,const char * dfault)723 const char *_Locale_catgets(struct _Locale_messages *__loc, nl_catd_type __cat,
724                             int __setid, int __msgid, const char *dfault)
725 {
726   return catgets( __cat, __setid, __msgid, dfault );
727 }
728