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 * Copyright (c) 2011 The FreeBSD Foundation 7 * All rights reserved. 8 * Portions of this software were developed by David Chisnall 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include "lint.h" 34 #include <langinfo.h> 35 #include <limits.h> 36 #include <locale.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "lnumeric.h" 41 #include "lmessages.h" 42 #include "lmonetary.h" 43 #include "timelocal.h" 44 45 #define _REL(BASE) ((int)item-BASE) 46 47 #define MONETARY (__get_current_monetary_locale(loc)) 48 #define TIME (__get_current_time_locale()) 49 #define MESSAGES (__get_current_messages_locale(loc)) /* XXX */ 50 #define NUMERIC (__get_current_numeric_locale()) 51 52 #pragma weak _nl_langinfo = nl_langinfo 53 54 char * 55 nl_langinfo_l(nl_item item, locale_t loc) 56 { 57 char *ret, *s, *cs; 58 static char *csym = NULL; 59 60 switch (item) { 61 case CODESET: 62 ret = ""; 63 /* 64 * The codeset is the suffix of a locale, for most it will 65 * will be UTF-8, as in "en.UTF-8". Short form locales are 66 * not supported. Note also that although FreeBSD uses 67 * US-ASCII, Solaris historically has reported "646" for the 68 * C locale. 69 */ 70 if ((s = setlocale(LC_CTYPE, NULL)) != NULL) { 71 if ((cs = strchr(s, '.')) != NULL) 72 ret = cs + 1; 73 else if (strcmp(s, "C") == 0 || strcmp(s, "POSIX") == 0) 74 ret = "646"; 75 } 76 break; 77 case D_T_FMT: 78 ret = (char *)TIME->c_fmt; 79 break; 80 case D_FMT: 81 ret = (char *)TIME->x_fmt; 82 break; 83 case T_FMT: 84 ret = (char *)TIME->X_fmt; 85 break; 86 case T_FMT_AMPM: 87 ret = (char *)TIME->ampm_fmt; 88 break; 89 case AM_STR: 90 ret = (char *)TIME->am; 91 break; 92 case PM_STR: 93 ret = (char *)TIME->pm; 94 break; 95 case DAY_1: case DAY_2: case DAY_3: 96 case DAY_4: case DAY_5: case DAY_6: case DAY_7: 97 ret = (char *)TIME->weekday[_REL(DAY_1)]; 98 break; 99 case ABDAY_1: case ABDAY_2: case ABDAY_3: 100 case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7: 101 ret = (char *)TIME->wday[_REL(ABDAY_1)]; 102 break; 103 case MON_1: case MON_2: case MON_3: case MON_4: 104 case MON_5: case MON_6: case MON_7: case MON_8: 105 case MON_9: case MON_10: case MON_11: case MON_12: 106 ret = (char *)TIME->month[_REL(MON_1)]; 107 break; 108 case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: 109 case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8: 110 case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12: 111 ret = (char *)TIME->mon[_REL(ABMON_1)]; 112 break; 113 case ERA: 114 /* XXX: need to be implemented */ 115 ret = ""; 116 break; 117 case ERA_D_FMT: 118 /* XXX: need to be implemented */ 119 ret = ""; 120 break; 121 case ERA_D_T_FMT: 122 /* XXX: need to be implemented */ 123 ret = ""; 124 break; 125 case ERA_T_FMT: 126 /* XXX: need to be implemented */ 127 ret = ""; 128 break; 129 case ALT_DIGITS: 130 /* XXX: need to be implemented */ 131 ret = ""; 132 break; 133 case RADIXCHAR: 134 ret = (char *)NUMERIC->decimal_point; 135 break; 136 case THOUSEP: 137 ret = (char *)NUMERIC->thousands_sep; 138 break; 139 case YESEXPR: 140 ret = (char *)MESSAGES->yesexpr; 141 break; 142 case NOEXPR: 143 ret = (char *)MESSAGES->noexpr; 144 break; 145 /* 146 * YESSTR and NOSTR items marked with LEGACY are available, but not 147 * recomended by SUSv2 to be used in portable applications since 148 * they're subject to remove in future specification editions. 149 */ 150 case YESSTR: /* LEGACY */ 151 ret = (char *)MESSAGES->yesstr; 152 break; 153 case NOSTR: /* LEGACY */ 154 ret = (char *)MESSAGES->nostr; 155 break; 156 /* 157 * SUSv2 special formatted currency string 158 */ 159 case CRNCYSTR: 160 ret = ""; 161 cs = (char *)MONETARY->currency_symbol; 162 if (*cs != '\0') { 163 char pos = localeconv()->p_cs_precedes; 164 165 if (pos == localeconv()->n_cs_precedes) { 166 char psn = '\0'; 167 168 if (pos == CHAR_MAX) { 169 if (strcmp(cs, 170 MONETARY->mon_decimal_point) == 0) 171 psn = '.'; 172 } else 173 psn = pos ? '-' : '+'; 174 if (psn != '\0') { 175 int clen = strlen(cs); 176 char *newc; 177 178 newc = realloc(csym, clen + 2); 179 if (newc != NULL) { 180 free(csym); 181 csym = newc; 182 *csym = psn; 183 (void) strcpy(csym + 1, cs); 184 ret = csym; 185 } 186 } 187 } 188 } 189 break; 190 case _DATE_FMT: /* Solaris specific extension */ 191 ret = (char *)TIME->date_fmt; 192 break; 193 /* 194 * Note that FreeBSD also had a private D_MD_ORDER, but that appears 195 * to have been specific to FreeBSD, so we have not included it here. 196 */ 197 default: 198 ret = ""; 199 } 200 return (ret); 201 } 202 203 char * 204 nl_langinfo(nl_item item) 205 { 206 return (nl_langinfo_l(item, __get_locale())); 207 }