3 * Silicon Graphics Computer Systems, Inc.
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.
18 #ifdef _POSIX_MAPPED_FILES
19 # include <sys/mman.h>
22 #include <stl/c_locale.h>
25 /* #include <libc-lock.h> */
29 #include "gcc_localeinfo.h"
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);
46 typedef struct _Locale_ctype {
47 const struct locale_data* gcc_data;
50 _Locale_mask_t* __class;
53 typedef struct _Locale_numeric {
54 const struct locale_data* gcc_data;
57 typedef struct _Locale_time {
58 const struct locale_data* gcc_data;
61 typedef struct _Locale_collate {
62 const struct locale_data* gcc_data;
65 typedef struct _Locale_monetary {
66 const struct locale_data* gcc_data;
69 typedef struct _Locale_messages {
70 const struct locale_data* gcc_data;
73 struct _Locale_name_hint* _Locale_get_ctype_hint(struct _Locale_ctype* ctype)
75 struct _Locale_name_hint* _Locale_get_numeric_hint(struct _Locale_numeric* numeric)
77 struct _Locale_name_hint* _Locale_get_time_hint(struct _Locale_time* time)
79 struct _Locale_name_hint* _Locale_get_collate_hint(struct _Locale_collate* collate)
81 struct _Locale_name_hint* _Locale_get_monetary_hint(struct _Locale_monetary* monetary)
83 struct _Locale_name_hint* _Locale_get_messages_hint(struct _Locale_messages* messages)
87 _Locale_extract_name ( const char *cname, char *into, int category )
92 if ( cname[0] != '/' )
93 return strcpy(into, cname); /* simple locale name */
95 for ( i = 0; i <= category; i ++ ) {
96 while ( *cname != '\0' && *cname != '/' )
103 if ( *cname == '\0' )
107 while ( *end != '\0' && *end != '/' )
110 strncpy ( into, cname, end - cname );
111 into [ end - cname ] = '\0';
116 char const* _Locale_name(const struct locale_data* gcc_data,
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';
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
132 const struct locale_data *
133 _Find_locale (char *locale_path, size_t locale_path_len,
134 int category, char **name)
136 return __nl_find_locale(locale_path, locale_path_len, category, name);
141 _Remove_locale (int locale, struct locale_data *data)
143 /* this should eventually call _nl_remove_locale() in glibc 2.1 */
144 /* _nl_remove_locale( locale, data ); */
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"
151 const struct locale_data*
152 _Category_create(const char * name, int category)
154 /* JGS, where should this path come from? */
156 char* locale_path = NULL;
157 size_t locale_path_len = 0;
159 locpath_var = __secure_getenv("LOCPATH");
161 if (locpath_var != NULL && locpath_var[0] != '\0')
162 if (argz_create_sep (locpath_var, ':',
163 &locale_path, &locale_path_len) != 0)
166 if (argz_add_sep (&locale_path, &locale_path_len, __LOCALE_PATH, ':') != 0)
169 return _Find_locale(locale_path, locale_path_len,
170 category, (char**)&name);
175 static const char* get_default_locale(char* buf) {
176 char* lang = getenv("LANG");
177 if (lang == NULL || lang[0] == '\0') {
187 const char* _Locale_ctype_default(char* buf) {
188 char fullname[_Locale_MAX_COMPOSITE_NAME];
189 if (get_default_locale(fullname) == NULL)
192 return _Locale_extract_ctype_name(fullname, buf, 0);
195 const char* _Locale_numeric_default(char* buf) {
196 char fullname[_Locale_MAX_COMPOSITE_NAME];
197 if (get_default_locale(fullname) == NULL)
200 return _Locale_extract_numeric_name(fullname, buf, 0);
203 const char* _Locale_time_default(char* buf) {
204 char fullname[_Locale_MAX_COMPOSITE_NAME];
205 if (get_default_locale(fullname) == NULL)
208 return _Locale_extract_time_name(fullname, buf, 0);
211 const char* _Locale_collate_default(char* buf) {
212 char fullname[_Locale_MAX_COMPOSITE_NAME];
213 if (get_default_locale(fullname) == NULL)
216 return _Locale_extract_collate_name(fullname, buf, 0);
219 const char* _Locale_monetary_default(char* buf) {
220 char fullname[_Locale_MAX_COMPOSITE_NAME];
221 if (get_default_locale(fullname) == NULL)
224 return _Locale_extract_monetary_name(fullname, buf, 0);
227 const char* _Locale_messages_default(char* buf) {
228 char fullname[_Locale_MAX_COMPOSITE_NAME];
229 if (get_default_locale(fullname) == NULL)
232 return _Locale_extract_messages_name(fullname, buf, 0);
236 /****** Numeric Category ******/
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);
246 char const* _Locale_numeric_name(const void* lnum,
248 return _Locale_name(((struct _Locale_ctype*)lnum)->gcc_data, buf);
250 void _Locale_numeric_destroy(void* lnum)
252 _Remove_locale(LC_NUMERIC, (struct locale_data *)((struct _Locale_ctype*)lnum)->gcc_data);
255 char const* _Locale_extract_numeric_name(const char* cname, char* buf, struct _Locale_name_hint* hint)
257 return _Locale_extract_name(cname, buf, LC_NUMERIC);
259 char _Locale_decimal_point(struct _Locale_numeric* lnum)
261 return lnum->gcc_data->values[_NL_ITEM_INDEX(DECIMAL_POINT)].string[0];
263 char _Locale_thousands_sep(struct _Locale_numeric* lnum)
265 return lnum->gcc_data->values[_NL_ITEM_INDEX(THOUSANDS_SEP)].string[0];
267 const char* _Locale_grouping(struct _Locale_numeric * lnum)
269 return lnum->gcc_data->values[_NL_ITEM_INDEX(GROUPING)].string;
272 /* JGS: gcc/linux does not provide true/false names in their
276 static const char* __true_name = "true";
277 static const char* __false_name = "false";
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; }
285 /****** Monetary Category ******/
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);
293 char const* _Locale_monetary_name(const void* lmon,
295 return _Locale_name(((struct _Locale_monetary*)lmon)->gcc_data, buf);
298 void _Locale_monetary_destroy(void*lmon) {
299 _Remove_locale(LC_MONETARY, (struct locale_data *)((struct _Locale_monetary*)lmon)->gcc_data);
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);
307 const char* _Locale_int_curr_symbol(struct _Locale_monetary* lmon) {
308 return lmon->gcc_data->values[_NL_ITEM_INDEX(INT_CURR_SYMBOL)].string;
310 const char* _Locale_currency_symbol(struct _Locale_monetary* lmon) {
311 return lmon->gcc_data->values[_NL_ITEM_INDEX(CURRENCY_SYMBOL)].string;
313 char _Locale_mon_decimal_point(struct _Locale_monetary* lmon) {
314 return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_DECIMAL_POINT)].string[0];
316 char _Locale_mon_thousands_sep(struct _Locale_monetary* lmon) {
317 return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_THOUSANDS_SEP)].string[0];
319 const char* _Locale_mon_grouping(struct _Locale_monetary* lmon) {
320 return lmon->gcc_data->values[_NL_ITEM_INDEX(MON_GROUPING)].string;
322 const char* _Locale_positive_sign(struct _Locale_monetary* lmon) {
323 return lmon->gcc_data->values[_NL_ITEM_INDEX(POSITIVE_SIGN)].string;
325 const char* _Locale_negative_sign(struct _Locale_monetary* lmon) {
326 return lmon->gcc_data->values[_NL_ITEM_INDEX(NEGATIVE_SIGN)].string;
328 char _Locale_int_frac_digits(struct _Locale_monetary* lmon) {
329 return lmon->gcc_data->values[_NL_ITEM_INDEX(INT_FRAC_DIGITS)].string[0];
331 char _Locale_frac_digits(struct _Locale_monetary* lmon) {
332 return lmon->gcc_data->values[_NL_ITEM_INDEX(FRAC_DIGITS)].string[0];
334 int _Locale_p_cs_precedes(struct _Locale_monetary* lmon) {
335 return lmon->gcc_data->values[_NL_ITEM_INDEX(P_CS_PRECEDES)].word;
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;
340 int _Locale_p_sign_posn(struct _Locale_monetary* lmon) {
341 return lmon->gcc_data->values[_NL_ITEM_INDEX(P_SIGN_POSN)].word;
343 int _Locale_n_cs_precedes(struct _Locale_monetary* lmon) {
344 return lmon->gcc_data->values[_NL_ITEM_INDEX(N_CS_PRECEDES)].word;
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;
349 int _Locale_n_sign_posn(struct _Locale_monetary* lmon) {
350 return lmon->gcc_data->values[_NL_ITEM_INDEX(N_SIGN_POSN)].word;
353 /****** Time Category ******/
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);
361 char const* _Locale_time_name(const void* ltime,
363 return _Locale_name(((struct _Locale_time*)ltime)->gcc_data, buf);
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);
368 void _Locale_time_destroy(void* ltime) {
369 _Remove_locale(LC_TIME, (struct locale_data *)((struct _Locale_time*)ltime)->gcc_data);
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)]);
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)]);
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)]);
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)]);
388 const char* _Locale_d_t_fmt(struct _Locale_time* ltime) {
389 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_T_FMT)].string;
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;
394 const char* _Locale_d_fmt(struct _Locale_time* ltime)
396 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_FMT)].string;
398 const char* _Locale_long_d_fmt(struct _Locale_time* ltime)
400 return ltime->gcc_data->values[_NL_ITEM_INDEX(D_FMT)].string;
402 const char* _Locale_t_fmt(struct _Locale_time* ltime) {
403 return ltime->gcc_data->values[_NL_ITEM_INDEX(T_FMT)].string;
405 const char* _Locale_am_str(struct _Locale_time* ltime) {
406 return ltime->gcc_data->values[_NL_ITEM_INDEX(AM_STR)].string;
408 const char* _Locale_pm_str(struct _Locale_time* ltime) {
409 return ltime->gcc_data->values[_NL_ITEM_INDEX(PM_STR)].string;
411 const char* _Locale_t_fmt_ampm(struct _Locale_time* ltime)
413 return ltime->gcc_data->values[_NL_ITEM_INDEX(T_FMT_AMPM)].string;
417 /****** Messages Category ******/
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);
425 char const* _Locale_messages_name(const void* lmsg, char* buf) {
426 return _Locale_name(((struct _Locale_messages*)lmsg)->gcc_data, buf);
429 void _Locale_messages_destroy(void* lmsg) {
430 _Remove_locale(LC_MESSAGES, (struct locale_data *)((struct _Locale_messages*)lmsg)->gcc_data);
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);
440 Could not find support for locale specific messages in glibc
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.
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 */
452 void _Locale_catclose(struct _Locale_messages*l, int catalog) {
453 catclose((nl_catd)catalog);
455 const char* _Locale_catgets(struct _Locale_messages*l, int catalog,
456 int set_num, int msg_num,
458 return catgets((nl_catd)catalog, set_num, msg_num, dfault);
462 /****** ctype Category ******/
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
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;
487 void* _Locale_ctype_create(const char * name, struct _Locale_name_hint* hint) {
488 const union locale_data_value *ctypes;
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;
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;
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;
514 # error bizarre byte order
516 #endif /* _STLP_GLIBC_LOCALE_2 */
519 char const* _Locale_ctype_name(const void* lctype,
521 return _Locale_name(((struct _Locale_ctype*)lctype)->gcc_data, buf);
523 void _Locale_ctype_destroy(void* lctype) {
524 _Remove_locale(LC_CTYPE, (struct locale_data *)((struct _Locale_ctype*)lctype)->gcc_data);
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);
530 const _Locale_mask_t* _Locale_ctype_table(struct _Locale_ctype* lctype) {
531 return lctype->__class;
533 int _Locale_toupper(struct _Locale_ctype* lctype, int c) {
534 return lctype->__toupper[c];
536 int _Locale_tolower(struct _Locale_ctype* lctype, int c) {
537 return lctype->__tolower[c];
540 /* Wide Character Functions */
543 cname_lookup (wint_t wc, const struct locale_data* loc)
545 #ifdef _STLP_GLIBC_LOCALE_2
546 printf( "******** Fix me: %s:%d", __FILE__, __LINE__ );
547 return ~((size_t) 0);
549 unsigned int *__nl_ctype_names;
550 unsigned int hash_size, hash_layers;
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;
558 # error bizarre byte order
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;
564 result = wc % hash_size;
565 for (cnt = 0; cnt < hash_layers; ++cnt) {
566 if (__nl_ctype_names[result] == wc)
570 return cnt < hash_layers ? result : ~((size_t) 0);
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;
583 idx = cname_lookup (wc, locale);
584 if (idx == ~((size_t) 0))
587 class32_b = (u_int32_t *)
588 locale->values[_NL_ITEM_INDEX (_NL_CTYPE_CLASS32)].string;
590 return _Map_wchar_mask_to_char_mask( class32_b[idx] ) & which_bits;
596 __towctrans_ld (wint_t wc, wctrans_t desc, const struct locale_data* locale)
600 idx = cname_lookup (wc, locale);
601 if (idx == ~((size_t) 0))
602 /* Character is not known. Default action is to simply return it. */
605 return (wint_t) desc[idx];
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);
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);
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;
620 int _Locale_mb_cur_min (struct _Locale_ctype *l) {
621 return 1; /* JGS just a guess */
624 int _Locale_is_stateless (struct _Locale_ctype *l) { return 1; }
626 wint_t _Locale_btowc(struct _Locale_ctype *l, int c) {
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
639 int _Locale_wctob(struct _Locale_ctype *l, wint_t c) {
643 size_t _Locale_mbtowc(struct _Locale_ctype *l,
645 const char *from, size_t n,
646 mbstate_t *shift_state)
650 ret = mbrtowc(to, from, n, shift_state);
652 ret = mbrlen(from, n, shift_state);
656 size_t _Locale_wctomb(struct _Locale_ctype *l,
659 mbstate_t *shift_state)
661 char buf [MB_LEN_MAX];
664 ret = wcrtomb(mb, c, shift_state);
678 size_t _Locale_unshift(struct _Locale_ctype *l,
680 char *buf, size_t n, char **next) {
681 *next = buf; /* JGS stateless, so don't need to do anything? */
686 /****** Collate Category ******/
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);
694 char const* _Locale_collate_name(const void* lcollate, char* buf) {
695 return _Locale_name(((struct _Locale_collate*)lcollate)->gcc_data, buf);
698 void _Locale_collate_destroy(void* lcollate) {
699 _Remove_locale(LC_COLLATE, (struct locale_data *)((struct _Locale_collate*)lcollate)->gcc_data);
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);
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)
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 );
724 strcat ( buf, ctype );
727 strcat ( buf, numeric );
730 strcat ( buf, time );
733 strcat ( buf, collate );
736 strcat ( buf, monetary );
739 strcat ( buf, messages );
747 glibc doesn't have a locale specific strcmp
748 This doesn't ignore null chars the way it should
751 _Locale_strcmp(struct _Locale_collate * l,
752 const char *s1, size_t n1,
753 const char *s2, size_t n2)
756 int minN = n1 < n2 ? n1 : n2;
757 ret = strncmp(s1, s2, minN);
759 if (n1 < n2) return -1;
760 else if (n1 > n2) return 1;
767 int _Locale_strwcmp(struct _Locale_collate*l,
768 const wchar_t*s1, size_t n1,
769 const wchar_t*s2, size_t n2)
772 int minN = n1 < n2 ? n1 : n2;
773 ret = wcsncmp(s1, s2, minN);
775 if (n1 < n2) return -1;
776 else if (n1 > n2) return 1;
781 size_t _Locale_strxfrm(struct _Locale_collate *lcollate,
782 char *dest, size_t dest_n,
783 const char *src, size_t src_n )
787 if (dest != NULL) dest[0] = 0;
790 const char *real_src;
792 if (src[src_n] != 0) {
793 buf = malloc(src_n + 1);
794 strncpy(buf, src, src_n);
800 size_t result = strxfrm(dest, real_src, dest_n);
801 if (buf != NULL) free(buf);
805 # ifndef _STLP_NO_WCHAR_T
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)
813 if (dest != NULL) dest[0] = 0;
816 const wchar_t *real_src;
818 if (src[src_n] != 0) {
819 buf = malloc((src_n + 1) * sizeof(wchar_t));
820 wcsncpy(buf, src, src_n);
826 size_t result = wcsxfrm(dest, real_src, dest_n, (__c_locale)__loc);
827 if (buf != NULL) free(buf);