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 }