home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / src / c_locale_glibc / c_locale_glibc.c next >
C/C++ Source or Header  |  2002-01-18  |  22KB  |  767 lines

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