Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/port/locale/nl_langinfo.c
          +++ new/usr/src/lib/libc/port/locale/nl_langinfo.c
   1    1  /*
        2 + * Copyright 2013 Garrett D'Amore <garrett@damore.org>
   2    3   * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   3    4   * Copyright (c) 2001, 2003 Alexey Zelkin <phantom@FreeBSD.org>
   4    5   * All rights reserved.
   5    6   *
   6    7   * Redistribution and use in source and binary forms, with or without
   7    8   * modification, are permitted provided that the following conditions
   8    9   * are met:
   9   10   * 1. Redistributions of source code must retain the above copyright
  10   11   *    notice, this list of conditions and the following disclaimer.
  11   12   * 2. Redistributions in binary form must reproduce the above copyright
↓ open down ↓ 17 lines elided ↑ open up ↑
  29   30  #include <langinfo.h>
  30   31  #include <limits.h>
  31   32  #include <locale.h>
  32   33  #include <stdlib.h>
  33   34  #include <string.h>
  34   35  
  35   36  #include "lnumeric.h"
  36   37  #include "lmessages.h"
  37   38  #include "lmonetary.h"
  38   39  #include "timelocal.h"
       40 +#include "localeimpl.h"
  39   41  
  40   42  #define _REL(BASE) ((int)item-BASE)
  41   43  
  42      -#define MONETARY        (__get_current_monetary_locale())
  43      -#define TIME            (__get_current_time_locale())
  44      -#define MESSAGES        (__get_current_messages_locale())
  45      -#define NUMERIC         (__get_current_numeric_locale())
  46      -
  47   44  #pragma weak _nl_langinfo = nl_langinfo
  48   45  
  49   46  char *
  50      -nl_langinfo(nl_item item)
       47 +nl_langinfo_l(nl_item item, locale_t loc)
  51   48  {
  52   49          char *ret, *s, *cs;
  53      -        static char *csym = NULL;
       50 +        struct locdata *ldata;
       51 +        const struct lc_monetary *lmon = loc->monetary;
       52 +        const struct lc_numeric *lnum = loc->numeric;
       53 +        const struct lc_messages *lmsgs = loc->messages;
       54 +        const struct lc_time *ltime = loc->time;
  54   55  
  55   56          switch (item) {
  56   57          case CODESET:
  57   58                  ret = "";
  58   59                  /*
  59   60                   * The codeset is the suffix of a locale, for most it will
  60      -                 * will be UTF-8, as in "en.UTF-8".  Short form locales are
       61 +                 * will be UTF-8, as in "en_US.UTF-8".  Short form locales are
  61   62                   * not supported.  Note also that although FreeBSD uses
  62   63                   * US-ASCII, Solaris historically has reported "646" for the
  63   64                   * C locale.
       65 +                 *
       66 +                 * Note that this code will need to change if we ever support
       67 +                 * POSIX defined locale variants (suffixes with an @ sign)
  64   68                   */
  65      -                if ((s = setlocale(LC_CTYPE, NULL)) != NULL) {
       69 +                ldata = loc->locdata[LC_CTYPE];
       70 +                s = ldata ? ldata->l_lname : NULL;
       71 +                if (s != NULL) {
  66   72                          if ((cs = strchr(s, '.')) != NULL)
  67   73                                  ret = cs + 1;
  68   74                          else if (strcmp(s, "C") == 0 || strcmp(s, "POSIX") == 0)
  69   75                                  ret = "646";
  70   76                  }
  71   77                  break;
  72   78          case D_T_FMT:
  73      -                ret = (char *)TIME->c_fmt;
       79 +                ret = (char *)ltime->c_fmt;
  74   80                  break;
  75   81          case D_FMT:
  76      -                ret = (char *)TIME->x_fmt;
       82 +                ret = (char *)ltime->x_fmt;
  77   83                  break;
  78   84          case T_FMT:
  79      -                ret = (char *)TIME->X_fmt;
       85 +                ret = (char *)ltime->X_fmt;
  80   86                  break;
  81   87          case T_FMT_AMPM:
  82      -                ret = (char *)TIME->ampm_fmt;
       88 +                ret = (char *)ltime->ampm_fmt;
  83   89                  break;
  84   90          case AM_STR:
  85      -                ret = (char *)TIME->am;
       91 +                ret = (char *)ltime->am;
  86   92                  break;
  87   93          case PM_STR:
  88      -                ret = (char *)TIME->pm;
       94 +                ret = (char *)ltime->pm;
  89   95                  break;
  90   96          case DAY_1: case DAY_2: case DAY_3:
  91   97          case DAY_4: case DAY_5: case DAY_6: case DAY_7:
  92      -                ret = (char *)TIME->weekday[_REL(DAY_1)];
       98 +                ret = (char *)ltime->weekday[_REL(DAY_1)];
  93   99                  break;
  94  100          case ABDAY_1: case ABDAY_2: case ABDAY_3:
  95  101          case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
  96      -                ret = (char *)TIME->wday[_REL(ABDAY_1)];
      102 +                ret = (char *)ltime->wday[_REL(ABDAY_1)];
  97  103                  break;
  98  104          case MON_1: case MON_2: case MON_3: case MON_4:
  99  105          case MON_5: case MON_6: case MON_7: case MON_8:
 100  106          case MON_9: case MON_10: case MON_11: case MON_12:
 101      -                ret = (char *)TIME->month[_REL(MON_1)];
      107 +                ret = (char *)ltime->month[_REL(MON_1)];
 102  108                  break;
 103  109          case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
 104  110          case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
 105  111          case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
 106      -                ret = (char *)TIME->mon[_REL(ABMON_1)];
      112 +                ret = (char *)ltime->mon[_REL(ABMON_1)];
 107  113                  break;
 108  114          case ERA:
 109  115                  /* XXX: need to be implemented  */
 110  116                  ret = "";
 111  117                  break;
 112  118          case ERA_D_FMT:
 113  119                  /* XXX: need to be implemented  */
 114  120                  ret = "";
 115  121                  break;
 116  122          case ERA_D_T_FMT:
↓ open down ↓ 2 lines elided ↑ open up ↑
 119  125                  break;
 120  126          case ERA_T_FMT:
 121  127                  /* XXX: need to be implemented  */
 122  128                  ret = "";
 123  129                  break;
 124  130          case ALT_DIGITS:
 125  131                  /* XXX: need to be implemented  */
 126  132                  ret = "";
 127  133                  break;
 128  134          case RADIXCHAR:
 129      -                ret = (char *)NUMERIC->decimal_point;
      135 +                ret = (char *)lnum->decimal_point;
 130  136                  break;
 131  137          case THOUSEP:
 132      -                ret = (char *)NUMERIC->thousands_sep;
      138 +                ret = (char *)lnum->thousands_sep;
 133  139                  break;
 134  140          case YESEXPR:
 135      -                ret = (char *)MESSAGES->yesexpr;
      141 +                ret = (char *)lmsgs->yesexpr;
 136  142                  break;
 137  143          case NOEXPR:
 138      -                ret = (char *)MESSAGES->noexpr;
      144 +                ret = (char *)lmsgs->noexpr;
 139  145                  break;
 140  146          /*
 141      -         * YESSTR and NOSTR items marked with LEGACY are available, but not
 142      -         * recomended by SUSv2 to be used in portable applications since
 143      -         * they're subject to remove in future specification editions.
      147 +         * YESSTR and NOSTR items were removed from Issue 7.  But
      148 +         * older applications might still need them.  Their use is
      149 +         * discouraged.
 144  150           */
 145  151          case YESSTR:    /* LEGACY  */
 146      -                ret = (char *)MESSAGES->yesstr;
      152 +                ret = (char *)lmsgs->yesstr;
 147  153                  break;
 148  154          case NOSTR:     /* LEGACY  */
 149      -                ret = (char *)MESSAGES->nostr;
      155 +                ret = (char *)lmsgs->nostr;
 150  156                  break;
 151  157          /*
 152  158           * SUSv2 special formatted currency string
 153  159           */
 154  160          case CRNCYSTR:
 155      -                ret = "";
 156      -                cs = (char *)MONETARY->currency_symbol;
 157      -                if (*cs != '\0') {
 158      -                        char pos = localeconv()->p_cs_precedes;
 159      -
 160      -                        if (pos == localeconv()->n_cs_precedes) {
 161      -                                char psn = '\0';
 162      -
 163      -                                if (pos == CHAR_MAX) {
 164      -                                        if (strcmp(cs,
 165      -                                            MONETARY->mon_decimal_point) == 0)
 166      -                                                psn = '.';
 167      -                                } else
 168      -                                        psn = pos ? '-' : '+';
 169      -                                if (psn != '\0') {
 170      -                                        int clen = strlen(cs);
 171      -                                        char *newc;
 172      -
 173      -                                        newc = realloc(csym, clen + 2);
 174      -                                        if (newc != NULL) {
 175      -                                                free(csym);
 176      -                                                csym = newc;
 177      -                                                *csym = psn;
 178      -                                                (void) strcpy(csym + 1, cs);
 179      -                                                ret = csym;
 180      -                                        }
 181      -                                }
 182      -                        }
 183      -                }
      161 +                ret = lmon->crncystr;
 184  162                  break;
      163 +
 185  164          case _DATE_FMT:         /* Solaris specific extension */
 186      -                ret = (char *)TIME->date_fmt;
      165 +                ret = (char *)ltime->date_fmt;
 187  166                  break;
 188  167          /*
 189  168           * Note that FreeBSD also had a private D_MD_ORDER, but that appears
 190  169           * to have been specific to FreeBSD, so we have not included it here.
 191  170           */
 192  171          default:
 193  172                  ret = "";
 194  173          }
 195  174          return (ret);
      175 +}
      176 +
      177 +char *
      178 +nl_langinfo(nl_item item)
      179 +{
      180 +        return (nl_langinfo_l(item, uselocale(NULL)));
 196  181  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX