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/lmonetary.c
          +++ new/usr/src/lib/libc/port/locale/lmonetary.c
   1    1  /*
        2 + * Copyright 2014 Garrett D'Amore <garrett@damore.org>
   2    3   * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   3    4   * Copyright (c) 2000, 2001 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 ↓ 10 lines elided ↑ open up ↑
  22   23   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23   24   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24   25   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25   26   * SUCH DAMAGE.
  26   27   */
  27   28  
  28   29  #include "lint.h"
  29   30  #include <limits.h>
  30   31  #include <stddef.h>
  31   32  #include <stdlib.h>
       33 +#include <stdio.h>
       34 +#include <string.h>
       35 +#include <errno.h>
  32   36  #include "ldpart.h"
  33   37  #include "lmonetary.h"
       38 +#include "localeimpl.h"
  34   39  
  35      -extern int __mlocale_changed;
  36   40  extern const char *__fix_locale_grouping_str(const char *);
  37   41  
  38      -#define LCMONETARY_SIZE_FULL (sizeof (struct lc_monetary_T) / sizeof (char *))
       42 +#define LCMONETARY_SIZE_FULL (sizeof (struct lc_monetary) / sizeof (char *))
  39   43  #define LCMONETARY_SIZE_MIN \
  40      -        (offsetof(struct lc_monetary_T, int_p_cs_precedes) / sizeof (char *))
       44 +        (offsetof(struct lc_monetary, int_p_cs_precedes) / sizeof (char *))
  41   45  
  42   46  static char     empty[] = "";
  43   47  static char     numempty[] = { CHAR_MAX, '\0' };
  44   48  
  45      -static const struct lc_monetary_T _C_monetary_locale = {
       49 +struct lc_monetary lc_monetary_posix = {
  46   50          empty,          /* int_curr_symbol */
  47   51          empty,          /* currency_symbol */
  48   52          empty,          /* mon_decimal_point */
  49   53          empty,          /* mon_thousands_sep */
  50   54          numempty,       /* mon_grouping */
  51   55          empty,          /* positive_sign */
  52   56          empty,          /* negative_sign */
  53   57          numempty,       /* int_frac_digits */
  54   58          numempty,       /* frac_digits */
  55   59          numempty,       /* p_cs_precedes */
  56   60          numempty,       /* p_sep_by_space */
  57   61          numempty,       /* n_cs_precedes */
  58   62          numempty,       /* n_sep_by_space */
  59   63          numempty,       /* p_sign_posn */
  60   64          numempty,       /* n_sign_posn */
  61   65          numempty,       /* int_p_cs_precedes */
  62   66          numempty,       /* int_n_cs_precedes */
  63   67          numempty,       /* int_p_sep_by_space */
  64   68          numempty,       /* int_n_sep_by_space */
  65   69          numempty,       /* int_p_sign_posn */
  66      -        numempty        /* int_n_sign_posn */
       70 +        numempty,       /* int_n_sign_posn */
       71 +        empty           /* crncystr */
  67   72  };
  68   73  
  69      -static struct lc_monetary_T _monetary_locale;
  70      -static int      _monetary_using_locale;
  71      -static char     *_monetary_locale_buf;
       74 +struct locdata __posix_monetary_locdata = {
       75 +        .l_lname = "C",
       76 +        .l_refcnt = (uint32_t)-1,
       77 +        .l_data = { &lc_monetary_posix }
       78 +};
  72   79  
  73   80  static char
  74   81  cnv(const char *str)
  75   82  {
  76   83          int i = strtol(str, NULL, 10);
  77   84  
  78   85          if (i == -1)
  79   86                  i = CHAR_MAX;
  80   87          return ((char)i);
  81   88  }
  82   89  
  83      -int
  84      -__monetary_load_locale(const char *name)
       90 +struct locdata *
       91 +__lc_monetary_load(const char *name)
  85   92  {
  86   93          int ret;
       94 +        int clen;
       95 +        struct lc_monetary      *lmon;
       96 +        struct locdata          *ldata;
  87   97  
  88      -        ret = __part_load_locale(name, &_monetary_using_locale,
  89      -            &_monetary_locale_buf, "LC_MONETARY",
  90      -            LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
  91      -            (const char **)&_monetary_locale);
  92      -        if (ret != _LDP_ERROR)
  93      -                __mlocale_changed = 1;
  94      -        if (ret == _LDP_LOADED) {
  95      -                _monetary_locale.mon_grouping =
  96      -                    __fix_locale_grouping_str(_monetary_locale.mon_grouping);
       98 +        if ((ldata = __locdata_alloc(name, sizeof (*lmon))) == NULL) {
       99 +                return (NULL);
      100 +        }
      101 +        lmon = ldata->l_data[0];
  97  102  
      103 +        ret = __part_load_locale(name, (char **)&ldata->l_data[1],
      104 +            "LC_MONETARY", LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
      105 +            (const char **)lmon);
      106 +
      107 +        if (ret != _LDP_LOADED) {
      108 +                __locdata_release(ldata);
      109 +                errno = EINVAL;
      110 +                return (NULL);
      111 +        }
      112 +
      113 +        /* special storage for currency string */
      114 +        clen = strlen(lmon->currency_symbol) + 2;
      115 +        ldata->l_data[2] = malloc(clen);
      116 +        lmon->crncystr = ldata->l_data[2];
      117 +        lmon->crncystr[0] = '\0';
      118 +
      119 +        lmon->mon_grouping = __fix_locale_grouping_str(lmon->mon_grouping);
      120 +
  98  121  #define M_ASSIGN_CHAR(NAME) \
  99      -                (((char *)_monetary_locale.NAME)[0] = \
 100      -                        cnv(_monetary_locale.NAME))
      122 +        (((char *)lmon->NAME)[0] = cnv(lmon->NAME))
 101  123  
 102      -                M_ASSIGN_CHAR(int_frac_digits);
 103      -                M_ASSIGN_CHAR(frac_digits);
 104      -                M_ASSIGN_CHAR(p_cs_precedes);
 105      -                M_ASSIGN_CHAR(p_sep_by_space);
 106      -                M_ASSIGN_CHAR(n_cs_precedes);
 107      -                M_ASSIGN_CHAR(n_sep_by_space);
 108      -                M_ASSIGN_CHAR(p_sign_posn);
 109      -                M_ASSIGN_CHAR(n_sign_posn);
      124 +        M_ASSIGN_CHAR(int_frac_digits);
      125 +        M_ASSIGN_CHAR(frac_digits);
      126 +        M_ASSIGN_CHAR(p_cs_precedes);
      127 +        M_ASSIGN_CHAR(p_sep_by_space);
      128 +        M_ASSIGN_CHAR(n_cs_precedes);
      129 +        M_ASSIGN_CHAR(n_sep_by_space);
      130 +        M_ASSIGN_CHAR(p_sign_posn);
      131 +        M_ASSIGN_CHAR(n_sign_posn);
 110  132  
 111      -                /*
 112      -                 * The six additional C99 international monetary formatting
 113      -                 * parameters default to the national parameters when
 114      -                 * reading FreeBSD LC_MONETARY data files.
 115      -                 */
 116      -#define M_ASSIGN_ICHAR(NAME)                                    \
 117      -                if (_monetary_locale.int_##NAME == NULL)        \
 118      -                        _monetary_locale.int_##NAME =           \
 119      -                            _monetary_locale.NAME;              \
 120      -                else                                            \
 121      -                        M_ASSIGN_CHAR(int_##NAME);
      133 +        /*
      134 +         * The six additional C99 international monetary formatting
      135 +         * parameters default to the national parameters when
      136 +         * reading FreeBSD LC_MONETARY data files.
      137 +         */
      138 +#define M_ASSIGN_ICHAR(NAME)                            \
      139 +        if (lmon->int_##NAME == NULL)                   \
      140 +                lmon->int_##NAME = lmon->NAME;          \
      141 +        else                                            \
      142 +                M_ASSIGN_CHAR(int_##NAME);
 122  143  
 123      -                M_ASSIGN_ICHAR(p_cs_precedes);
 124      -                M_ASSIGN_ICHAR(n_cs_precedes);
 125      -                M_ASSIGN_ICHAR(p_sep_by_space);
 126      -                M_ASSIGN_ICHAR(n_sep_by_space);
 127      -                M_ASSIGN_ICHAR(p_sign_posn);
 128      -                M_ASSIGN_ICHAR(n_sign_posn);
      144 +        M_ASSIGN_ICHAR(p_cs_precedes);
      145 +        M_ASSIGN_ICHAR(n_cs_precedes);
      146 +        M_ASSIGN_ICHAR(p_sep_by_space);
      147 +        M_ASSIGN_ICHAR(n_sep_by_space);
      148 +        M_ASSIGN_ICHAR(p_sign_posn);
      149 +        M_ASSIGN_ICHAR(n_sign_posn);
      150 +
      151 +        /*
      152 +         * Now calculate the currency string (CRNCYSTR) for nl_langinfo.
      153 +         * This is a legacy SUSv2 interface.
      154 +         */
      155 +        if ((lmon->p_cs_precedes[0] == lmon->n_cs_precedes[0]) &&
      156 +            (lmon->currency_symbol[0] != '\0')) {
      157 +                char sign = '\0';
      158 +                switch (lmon->p_cs_precedes[0]) {
      159 +                case 0:
      160 +                        sign = '-';
      161 +                        break;
      162 +                case 1:
      163 +                        sign = '+';
      164 +                        break;
      165 +                case CHAR_MAX:
      166 +                        /*
      167 +                         * Substitute currency string for radix character.
      168 +                         * To the best of my knowledge, no locale uses this.
      169 +                         */
      170 +                        if (strcmp(lmon->mon_decimal_point,
      171 +                            lmon->currency_symbol) == 0)
      172 +                                sign = '.';
      173 +                        break;
      174 +                }
      175 +                (void) snprintf(lmon->crncystr, clen, "%c%s", sign,
      176 +                    lmon->currency_symbol);
 129  177          }
 130      -        return (ret);
 131      -}
 132  178  
 133      -struct lc_monetary_T *
 134      -__get_current_monetary_locale(void)
 135      -{
 136      -        return (_monetary_using_locale ? &_monetary_locale :
 137      -            (struct lc_monetary_T *)&_C_monetary_locale);
      179 +        return (ldata);
 138  180  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX