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
   1 /*

   2  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   3  * Copyright (c) 2001, 2003 Alexey Zelkin <phantom@FreeBSD.org>
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice, this list of conditions and the following disclaimer.
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25  * SUCH DAMAGE.
  26  */
  27 
  28 #include "lint.h"
  29 #include <langinfo.h>
  30 #include <limits.h>
  31 #include <locale.h>
  32 #include <stdlib.h>
  33 #include <string.h>
  34 
  35 #include "lnumeric.h"
  36 #include "lmessages.h"
  37 #include "lmonetary.h"
  38 #include "timelocal.h"

  39 
  40 #define _REL(BASE) ((int)item-BASE)
  41 
  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 #pragma weak _nl_langinfo = nl_langinfo
  48 
  49 char *
  50 nl_langinfo(nl_item item)
  51 {
  52         char *ret, *s, *cs;
  53         static char *csym = NULL;




  54 
  55         switch (item) {
  56         case CODESET:
  57                 ret = "";
  58                 /*
  59                  * 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                  * not supported.  Note also that although FreeBSD uses
  62                  * US-ASCII, Solaris historically has reported "646" for the
  63                  * C locale.



  64                  */
  65                 if ((s = setlocale(LC_CTYPE, NULL)) != NULL) {


  66                         if ((cs = strchr(s, '.')) != NULL)
  67                                 ret = cs + 1;
  68                         else if (strcmp(s, "C") == 0 || strcmp(s, "POSIX") == 0)
  69                                 ret = "646";
  70                 }
  71                 break;
  72         case D_T_FMT:
  73                 ret = (char *)TIME->c_fmt;
  74                 break;
  75         case D_FMT:
  76                 ret = (char *)TIME->x_fmt;
  77                 break;
  78         case T_FMT:
  79                 ret = (char *)TIME->X_fmt;
  80                 break;
  81         case T_FMT_AMPM:
  82                 ret = (char *)TIME->ampm_fmt;
  83                 break;
  84         case AM_STR:
  85                 ret = (char *)TIME->am;
  86                 break;
  87         case PM_STR:
  88                 ret = (char *)TIME->pm;
  89                 break;
  90         case DAY_1: case DAY_2: case DAY_3:
  91         case DAY_4: case DAY_5: case DAY_6: case DAY_7:
  92                 ret = (char *)TIME->weekday[_REL(DAY_1)];
  93                 break;
  94         case ABDAY_1: case ABDAY_2: case ABDAY_3:
  95         case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
  96                 ret = (char *)TIME->wday[_REL(ABDAY_1)];
  97                 break;
  98         case MON_1: case MON_2: case MON_3: case MON_4:
  99         case MON_5: case MON_6: case MON_7: case MON_8:
 100         case MON_9: case MON_10: case MON_11: case MON_12:
 101                 ret = (char *)TIME->month[_REL(MON_1)];
 102                 break;
 103         case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
 104         case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
 105         case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
 106                 ret = (char *)TIME->mon[_REL(ABMON_1)];
 107                 break;
 108         case ERA:
 109                 /* XXX: need to be implemented  */
 110                 ret = "";
 111                 break;
 112         case ERA_D_FMT:
 113                 /* XXX: need to be implemented  */
 114                 ret = "";
 115                 break;
 116         case ERA_D_T_FMT:
 117                 /* XXX: need to be implemented  */
 118                 ret = "";
 119                 break;
 120         case ERA_T_FMT:
 121                 /* XXX: need to be implemented  */
 122                 ret = "";
 123                 break;
 124         case ALT_DIGITS:
 125                 /* XXX: need to be implemented  */
 126                 ret = "";
 127                 break;
 128         case RADIXCHAR:
 129                 ret = (char *)NUMERIC->decimal_point;
 130                 break;
 131         case THOUSEP:
 132                 ret = (char *)NUMERIC->thousands_sep;
 133                 break;
 134         case YESEXPR:
 135                 ret = (char *)MESSAGES->yesexpr;
 136                 break;
 137         case NOEXPR:
 138                 ret = (char *)MESSAGES->noexpr;
 139                 break;
 140         /*
 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.
 144          */
 145         case YESSTR:    /* LEGACY  */
 146                 ret = (char *)MESSAGES->yesstr;
 147                 break;
 148         case NOSTR:     /* LEGACY  */
 149                 ret = (char *)MESSAGES->nostr;
 150                 break;
 151         /*
 152          * SUSv2 special formatted currency string
 153          */
 154         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                 }
 184                 break;

 185         case _DATE_FMT:         /* Solaris specific extension */
 186                 ret = (char *)TIME->date_fmt;
 187                 break;
 188         /*
 189          * Note that FreeBSD also had a private D_MD_ORDER, but that appears
 190          * to have been specific to FreeBSD, so we have not included it here.
 191          */
 192         default:
 193                 ret = "";
 194         }
 195         return (ret);






 196 }
   1 /*
   2  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
   3  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   4  * Copyright (c) 2001, 2003 Alexey Zelkin <phantom@FreeBSD.org>
   5  * All rights reserved.
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  * 2. Redistributions in binary form must reproduce the above copyright
  13  *    notice, this list of conditions and the following disclaimer in the
  14  *    documentation and/or other materials provided with the distribution.
  15  *
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  */
  28 
  29 #include "lint.h"
  30 #include <langinfo.h>
  31 #include <limits.h>
  32 #include <locale.h>
  33 #include <stdlib.h>
  34 #include <string.h>
  35 
  36 #include "lnumeric.h"
  37 #include "lmessages.h"
  38 #include "lmonetary.h"
  39 #include "timelocal.h"
  40 #include "localeimpl.h"
  41 
  42 #define _REL(BASE) ((int)item-BASE)
  43 





  44 #pragma weak _nl_langinfo = nl_langinfo
  45 
  46 char *
  47 nl_langinfo_l(nl_item item, locale_t loc)
  48 {
  49         char *ret, *s, *cs;
  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;
  55 
  56         switch (item) {
  57         case CODESET:
  58                 ret = "";
  59                 /*
  60                  * The codeset is the suffix of a locale, for most it will
  61                  * will be UTF-8, as in "en_US.UTF-8".  Short form locales are
  62                  * not supported.  Note also that although FreeBSD uses
  63                  * US-ASCII, Solaris historically has reported "646" for the
  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)
  68                  */
  69                 ldata = loc->locdata[LC_CTYPE];
  70                 s = ldata ? ldata->l_lname : NULL;
  71                 if (s != NULL) {
  72                         if ((cs = strchr(s, '.')) != NULL)
  73                                 ret = cs + 1;
  74                         else if (strcmp(s, "C") == 0 || strcmp(s, "POSIX") == 0)
  75                                 ret = "646";
  76                 }
  77                 break;
  78         case D_T_FMT:
  79                 ret = (char *)ltime->c_fmt;
  80                 break;
  81         case D_FMT:
  82                 ret = (char *)ltime->x_fmt;
  83                 break;
  84         case T_FMT:
  85                 ret = (char *)ltime->X_fmt;
  86                 break;
  87         case T_FMT_AMPM:
  88                 ret = (char *)ltime->ampm_fmt;
  89                 break;
  90         case AM_STR:
  91                 ret = (char *)ltime->am;
  92                 break;
  93         case PM_STR:
  94                 ret = (char *)ltime->pm;
  95                 break;
  96         case DAY_1: case DAY_2: case DAY_3:
  97         case DAY_4: case DAY_5: case DAY_6: case DAY_7:
  98                 ret = (char *)ltime->weekday[_REL(DAY_1)];
  99                 break;
 100         case ABDAY_1: case ABDAY_2: case ABDAY_3:
 101         case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
 102                 ret = (char *)ltime->wday[_REL(ABDAY_1)];
 103                 break;
 104         case MON_1: case MON_2: case MON_3: case MON_4:
 105         case MON_5: case MON_6: case MON_7: case MON_8:
 106         case MON_9: case MON_10: case MON_11: case MON_12:
 107                 ret = (char *)ltime->month[_REL(MON_1)];
 108                 break;
 109         case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
 110         case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
 111         case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
 112                 ret = (char *)ltime->mon[_REL(ABMON_1)];
 113                 break;
 114         case ERA:
 115                 /* XXX: need to be implemented  */
 116                 ret = "";
 117                 break;
 118         case ERA_D_FMT:
 119                 /* XXX: need to be implemented  */
 120                 ret = "";
 121                 break;
 122         case ERA_D_T_FMT:
 123                 /* XXX: need to be implemented  */
 124                 ret = "";
 125                 break;
 126         case ERA_T_FMT:
 127                 /* XXX: need to be implemented  */
 128                 ret = "";
 129                 break;
 130         case ALT_DIGITS:
 131                 /* XXX: need to be implemented  */
 132                 ret = "";
 133                 break;
 134         case RADIXCHAR:
 135                 ret = (char *)lnum->decimal_point;
 136                 break;
 137         case THOUSEP:
 138                 ret = (char *)lnum->thousands_sep;
 139                 break;
 140         case YESEXPR:
 141                 ret = (char *)lmsgs->yesexpr;
 142                 break;
 143         case NOEXPR:
 144                 ret = (char *)lmsgs->noexpr;
 145                 break;
 146         /*
 147          * YESSTR and NOSTR items were removed from Issue 7.  But
 148          * older applications might still need them.  Their use is
 149          * discouraged.
 150          */
 151         case YESSTR:    /* LEGACY  */
 152                 ret = (char *)lmsgs->yesstr;
 153                 break;
 154         case NOSTR:     /* LEGACY  */
 155                 ret = (char *)lmsgs->nostr;
 156                 break;
 157         /*
 158          * SUSv2 special formatted currency string
 159          */
 160         case CRNCYSTR:
 161                 ret = lmon->crncystr;




























 162                 break;
 163 
 164         case _DATE_FMT:         /* Solaris specific extension */
 165                 ret = (char *)ltime->date_fmt;
 166                 break;
 167         /*
 168          * Note that FreeBSD also had a private D_MD_ORDER, but that appears
 169          * to have been specific to FreeBSD, so we have not included it here.
 170          */
 171         default:
 172                 ret = "";
 173         }
 174         return (ret);
 175 }
 176 
 177 char *
 178 nl_langinfo(nl_item item)
 179 {
 180         return (nl_langinfo_l(item, uselocale(NULL)));
 181 }