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 } 197