Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Approved by: TBD

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>
       36 +#include "libc.h"
  32   37  #include "ldpart.h"
  33   38  #include "lmonetary.h"
       39 +#include "localeimpl.h"
  34   40  
  35      -extern int __mlocale_changed;
  36   41  extern const char *__fix_locale_grouping_str(const char *);
  37   42  
  38      -#define LCMONETARY_SIZE_FULL (sizeof (struct lc_monetary_T) / sizeof (char *))
       43 +#define LCMONETARY_SIZE_FULL (sizeof (struct lc_monetary) / sizeof (char *))
  39   44  #define LCMONETARY_SIZE_MIN \
  40      -        (offsetof(struct lc_monetary_T, int_p_cs_precedes) / sizeof (char *))
       45 +        (offsetof(struct lc_monetary, int_p_cs_precedes) / sizeof (char *))
  41   46  
  42   47  static char     empty[] = "";
  43   48  static char     numempty[] = { CHAR_MAX, '\0' };
  44   49  
  45      -static const struct lc_monetary_T _C_monetary_locale = {
       50 +struct lc_monetary lc_monetary_posix = {
  46   51          empty,          /* int_curr_symbol */
  47   52          empty,          /* currency_symbol */
  48   53          empty,          /* mon_decimal_point */
  49   54          empty,          /* mon_thousands_sep */
  50   55          numempty,       /* mon_grouping */
  51   56          empty,          /* positive_sign */
  52   57          empty,          /* negative_sign */
  53   58          numempty,       /* int_frac_digits */
  54   59          numempty,       /* frac_digits */
  55   60          numempty,       /* p_cs_precedes */
  56   61          numempty,       /* p_sep_by_space */
  57   62          numempty,       /* n_cs_precedes */
  58   63          numempty,       /* n_sep_by_space */
  59   64          numempty,       /* p_sign_posn */
  60   65          numempty,       /* n_sign_posn */
  61   66          numempty,       /* int_p_cs_precedes */
  62   67          numempty,       /* int_n_cs_precedes */
  63   68          numempty,       /* int_p_sep_by_space */
  64   69          numempty,       /* int_n_sep_by_space */
  65   70          numempty,       /* int_p_sign_posn */
  66      -        numempty        /* int_n_sign_posn */
       71 +        numempty,       /* int_n_sign_posn */
       72 +        empty           /* crncystr */
  67   73  };
  68   74  
  69      -static struct lc_monetary_T _monetary_locale;
  70      -static int      _monetary_using_locale;
  71      -static char     *_monetary_locale_buf;
       75 +struct locdata __posix_monetary_locdata = {
       76 +        .l_lname = "C",
       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_free(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] = libc_malloc(clen);
      116 +        lmon->crncystr = ldata->l_data[2];
      117 +
      118 +        lmon->mon_grouping = __fix_locale_grouping_str(lmon->mon_grouping);
      119 +
  98  120  #define M_ASSIGN_CHAR(NAME) \
  99      -                (((char *)_monetary_locale.NAME)[0] = \
 100      -                        cnv(_monetary_locale.NAME))
      121 +        (((char *)lmon->NAME)[0] = cnv(lmon->NAME))
 101  122  
 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);
      123 +        M_ASSIGN_CHAR(int_frac_digits);
      124 +        M_ASSIGN_CHAR(frac_digits);
      125 +        M_ASSIGN_CHAR(p_cs_precedes);
      126 +        M_ASSIGN_CHAR(p_sep_by_space);
      127 +        M_ASSIGN_CHAR(n_cs_precedes);
      128 +        M_ASSIGN_CHAR(n_sep_by_space);
      129 +        M_ASSIGN_CHAR(p_sign_posn);
      130 +        M_ASSIGN_CHAR(n_sign_posn);
 110  131  
 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);
      132 +        /*
      133 +         * The six additional C99 international monetary formatting
      134 +         * parameters default to the national parameters when
      135 +         * reading FreeBSD LC_MONETARY data files.
      136 +         */
      137 +#define M_ASSIGN_ICHAR(NAME)                            \
      138 +        if (lmon->int_##NAME == NULL)                   \
      139 +                lmon->int_##NAME = lmon->NAME;          \
      140 +        else                                            \
      141 +                M_ASSIGN_CHAR(int_##NAME);
 122  142  
 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);
      143 +        M_ASSIGN_ICHAR(p_cs_precedes);
      144 +        M_ASSIGN_ICHAR(n_cs_precedes);
      145 +        M_ASSIGN_ICHAR(p_sep_by_space);
      146 +        M_ASSIGN_ICHAR(n_sep_by_space);
      147 +        M_ASSIGN_ICHAR(p_sign_posn);
      148 +        M_ASSIGN_ICHAR(n_sign_posn);
      149 +
      150 +        /*
      151 +         * Now calculate the currency string (CRNCYSTR) for nl_langinfo.
      152 +         * This is a legacy SUSv2 interface.
      153 +         */
      154 +        if ((lmon->p_cs_precedes[0] == lmon->n_cs_precedes[0]) &&
      155 +            (lmon->currency_symbol[0] != '\0')) {
      156 +                char sign = '\0';
      157 +                switch (lmon->p_cs_precedes[0]) {
      158 +                case 0:
      159 +                        sign = '-';
      160 +                        break;
      161 +                case 1:
      162 +                        sign = '+';
      163 +                        break;
      164 +                case CHAR_MAX:
      165 +                        /*
      166 +                         * Substitute currency string for radix character.
      167 +                         * To the best of my knowledge, no locale uses this.
      168 +                         */
      169 +                        if (strcmp(lmon->mon_decimal_point,
      170 +                            lmon->currency_symbol) == 0)
      171 +                                sign = '.';
      172 +                        break;
      173 +                }
      174 +                (void) snprintf(lmon->crncystr, clen, "%c%s", sign,
      175 +                    lmon->currency_symbol);
 129  176          }
 130      -        return (ret);
 131      -}
 132  177  
 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);
      178 +        return (ldata);
 138  179  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX