172169Sphantom/*-
2116875Sphantom * Copyright (c) 2001, 2003 Alexey Zelkin <phantom@FreeBSD.org>
372169Sphantom * All rights reserved.
472169Sphantom *
5227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation
6227753Stheraven * All rights reserved.
7227753Stheraven * Portions of this software were developed by David Chisnall
8227753Stheraven * under sponsorship from the FreeBSD Foundation.
9227753Stheraven *
1072169Sphantom * Redistribution and use in source and binary forms, with or without
1172169Sphantom * modification, are permitted provided that the following conditions
1272169Sphantom * are met:
1372169Sphantom * 1. Redistributions of source code must retain the above copyright
1472169Sphantom *    notice, this list of conditions and the following disclaimer.
1572169Sphantom * 2. Redistributions in binary form must reproduce the above copyright
1672169Sphantom *    notice, this list of conditions and the following disclaimer in the
1772169Sphantom *    documentation and/or other materials provided with the distribution.
1872169Sphantom *
1972169Sphantom * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2072169Sphantom * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2172169Sphantom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2272169Sphantom * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2372169Sphantom * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2472169Sphantom * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2572169Sphantom * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2672169Sphantom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2772169Sphantom * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2872169Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2972169Sphantom * SUCH DAMAGE.
3072169Sphantom */
3172169Sphantom
3292986Sobrien#include <sys/cdefs.h>
3392986Sobrien__FBSDID("$FreeBSD$");
3492986Sobrien
3572263Sache#include <langinfo.h>
3672561Sache#include <limits.h>
37116875Sphantom#include <locale.h>
3872561Sache#include <stdlib.h>
3972263Sache#include <string.h>
4087658Sphantom
4172169Sphantom#include "lnumeric.h"
42116875Sphantom#include "lmessages.h"
4372169Sphantom#include "lmonetary.h"
44116875Sphantom#include "../stdtime/timelocal.h"
4572169Sphantom
4672169Sphantom#define _REL(BASE) ((int)item-BASE)
4772169Sphantom
4872169Sphantomchar *
49227753Stheravennl_langinfo_l(nl_item item, locale_t loc)
50116875Sphantom{
51227753Stheraven   char *ret, *cs;
52227753Stheraven   const char *s;
53227753Stheraven   FIX_LOCALE(loc);
5472169Sphantom
5572169Sphantom   switch (item) {
5672169Sphantom	case CODESET:
5772263Sache		ret = "";
58227753Stheraven		if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) {
59116134Sache			if ((cs = strchr(s, '.')) != NULL)
6072263Sache				ret = cs + 1;
61116134Sache			else if (strcmp(s, "C") == 0 ||
62116134Sache				 strcmp(s, "POSIX") == 0)
6372263Sache				ret = "US-ASCII";
6472263Sache		}
6572169Sphantom		break;
6672169Sphantom	case D_T_FMT:
67227753Stheraven		ret = (char *) __get_current_time_locale(loc)->c_fmt;
6872169Sphantom		break;
6972169Sphantom	case D_FMT:
70227753Stheraven		ret = (char *) __get_current_time_locale(loc)->x_fmt;
7172169Sphantom		break;
7272169Sphantom	case T_FMT:
73227753Stheraven		ret = (char *) __get_current_time_locale(loc)->X_fmt;
7472169Sphantom		break;
7572169Sphantom	case T_FMT_AMPM:
76227753Stheraven		ret = (char *) __get_current_time_locale(loc)->ampm_fmt;
7772169Sphantom		break;
7872169Sphantom	case AM_STR:
79227753Stheraven		ret = (char *) __get_current_time_locale(loc)->am;
8072169Sphantom		break;
8172169Sphantom	case PM_STR:
82227753Stheraven		ret = (char *) __get_current_time_locale(loc)->pm;
8372169Sphantom		break;
8472169Sphantom	case DAY_1: case DAY_2: case DAY_3:
8572169Sphantom	case DAY_4: case DAY_5: case DAY_6: case DAY_7:
86227753Stheraven		ret = (char*) __get_current_time_locale(loc)->weekday[_REL(DAY_1)];
8772169Sphantom		break;
8872169Sphantom	case ABDAY_1: case ABDAY_2: case ABDAY_3:
8972169Sphantom	case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
90227753Stheraven		ret = (char*) __get_current_time_locale(loc)->wday[_REL(ABDAY_1)];
9172169Sphantom		break;
9272169Sphantom	case MON_1: case MON_2: case MON_3: case MON_4:
9372169Sphantom	case MON_5: case MON_6: case MON_7: case MON_8:
9472169Sphantom	case MON_9: case MON_10: case MON_11: case MON_12:
95227753Stheraven		ret = (char*) __get_current_time_locale(loc)->month[_REL(MON_1)];
9672169Sphantom		break;
9772169Sphantom	case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
9872169Sphantom	case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
9972169Sphantom	case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
100227753Stheraven		ret = (char*) __get_current_time_locale(loc)->mon[_REL(ABMON_1)];
10172169Sphantom		break;
102197765Sedwin	case ALTMON_1: case ALTMON_2: case ALTMON_3: case ALTMON_4:
103197765Sedwin	case ALTMON_5: case ALTMON_6: case ALTMON_7: case ALTMON_8:
104197765Sedwin	case ALTMON_9: case ALTMON_10: case ALTMON_11: case ALTMON_12:
105197765Sedwin		ret = (char*)
106227753Stheraven		    __get_current_time_locale(loc)->alt_month[_REL(ALTMON_1)];
107197765Sedwin		break;
10872169Sphantom	case ERA:
10972706Sphantom		/* XXX: need to be implemented  */
11072169Sphantom		ret = "";
11172169Sphantom		break;
11272169Sphantom	case ERA_D_FMT:
11372706Sphantom		/* XXX: need to be implemented  */
11472169Sphantom		ret = "";
11572169Sphantom		break;
11672169Sphantom	case ERA_D_T_FMT:
11772706Sphantom		/* XXX: need to be implemented  */
11872169Sphantom		ret = "";
11972169Sphantom		break;
12072169Sphantom	case ERA_T_FMT:
12172706Sphantom		/* XXX: need to be implemented  */
12272169Sphantom		ret = "";
12372169Sphantom		break;
12472169Sphantom	case ALT_DIGITS:
12572706Sphantom		/* XXX: need to be implemented  */
12672169Sphantom		ret = "";
12772169Sphantom		break;
12872706Sphantom	case RADIXCHAR:
129227753Stheraven		ret = (char*) __get_current_numeric_locale(loc)->decimal_point;
13072169Sphantom		break;
13172706Sphantom	case THOUSEP:
132227753Stheraven		ret = (char*) __get_current_numeric_locale(loc)->thousands_sep;
13372169Sphantom		break;
13472169Sphantom	case YESEXPR:
135227753Stheraven		ret = (char*) __get_current_messages_locale(loc)->yesexpr;
13672169Sphantom		break;
13772169Sphantom	case NOEXPR:
138227753Stheraven		ret = (char*) __get_current_messages_locale(loc)->noexpr;
13972169Sphantom		break;
14087658Sphantom	/*
141116875Sphantom	 * YESSTR and NOSTR items marked with LEGACY are available, but not
142116875Sphantom	 * recomended by SUSv2 to be used in portable applications since
143116875Sphantom	 * they're subject to remove in future specification editions.
14472706Sphantom	 */
14572706Sphantom	case YESSTR:            /* LEGACY  */
146227753Stheraven		ret = (char*) __get_current_messages_locale(loc)->yesstr;
14772169Sphantom		break;
14872706Sphantom	case NOSTR:             /* LEGACY  */
149227753Stheraven		ret = (char*) __get_current_messages_locale(loc)->nostr;
15072169Sphantom		break;
151116875Sphantom	/*
152116875Sphantom	 * SUSv2 special formatted currency string
153116875Sphantom	 */
15472706Sphantom	case CRNCYSTR:
15572245Sache		ret = "";
156227753Stheraven		cs = (char*) __get_current_monetary_locale(loc)->currency_symbol;
15772561Sache		if (*cs != '\0') {
158227753Stheraven			char pos = localeconv_l(loc)->p_cs_precedes;
15972561Sache
160227753Stheraven			if (pos == localeconv_l(loc)->n_cs_precedes) {
16172568Sache				char psn = '\0';
16272561Sache
16372568Sache				if (pos == CHAR_MAX) {
164227753Stheraven					if (strcmp(cs, __get_current_monetary_locale(loc)->mon_decimal_point) == 0)
16572568Sache						psn = '.';
16672568Sache				} else
16772568Sache					psn = pos ? '-' : '+';
16872568Sache				if (psn != '\0') {
16972568Sache					int clen = strlen(cs);
17072568Sache
171227753Stheraven					if ((loc->csym = reallocf(loc->csym, clen + 2)) != NULL) {
172227753Stheraven						*loc->csym = psn;
173227753Stheraven						strcpy(loc->csym + 1, cs);
174227753Stheraven						ret = loc->csym;
17572568Sache					}
17672561Sache				}
17772561Sache			}
17872561Sache		}
17972243Sache		break;
180116875Sphantom	case D_MD_ORDER:        /* FreeBSD local extension */
181227753Stheraven		ret = (char *) __get_current_time_locale(loc)->md_order;
18274459Sache		break;
18372169Sphantom	default:
18472169Sphantom		ret = "";
18572169Sphantom   }
18672169Sphantom   return (ret);
18772169Sphantom}
188227753Stheraven
189227753Stheravenchar *
190227753Stheravennl_langinfo(nl_item item)
191227753Stheraven{
192227753Stheraven	return nl_langinfo_l(item, __get_locale());
193227753Stheraven}
194