xref: /netbsd-src/lib/libc/locale/nl_langinfo.c (revision 46629f8e5f9d71484de0fc0e7aa176f3fe373bd8)
1 /* $NetBSD: nl_langinfo.c,v 1.18 2017/01/10 17:50:24 christos Exp $ */
2 
3 /*-
4  * Copyright (c)2008 Citrus Project,
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 <sys/cdefs.h>
30 __RCSID("$NetBSD: nl_langinfo.c,v 1.18 2017/01/10 17:50:24 christos Exp $");
31 
32 #include "namespace.h"
33 #include <sys/types.h>
34 #include <sys/localedef.h>
35 #include <langinfo.h>
36 #include <stddef.h>
37 #define __SETLOCALE_SOURCE__
38 #include <locale.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "runetype_local.h"
43 #include "setlocale_local.h"
44 
45 static const char langinfo_category[] = {
46     [ D_T_FMT ] = LC_TIME,
47     [ D_FMT ] = LC_TIME,
48     [ T_FMT ] = LC_TIME,
49     [ T_FMT_AMPM ] = LC_TIME,
50     [ AM_STR ] = LC_TIME,
51     [ PM_STR ] = LC_TIME,
52     [ DAY_1 ] = LC_TIME,
53     [ DAY_2 ] = LC_TIME,
54     [ DAY_3 ] = LC_TIME,
55     [ DAY_4 ] = LC_TIME,
56     [ DAY_5 ] = LC_TIME,
57     [ DAY_6 ] = LC_TIME,
58     [ DAY_7 ] = LC_TIME,
59     [ ABDAY_1 ] = LC_TIME,
60     [ ABDAY_2 ] = LC_TIME,
61     [ ABDAY_3 ] = LC_TIME,
62     [ ABDAY_4 ] = LC_TIME,
63     [ ABDAY_5 ] = LC_TIME,
64     [ ABDAY_6 ] = LC_TIME,
65     [ ABDAY_7 ] = LC_TIME,
66     [ MON_1 ] = LC_TIME,
67     [ MON_2 ] = LC_TIME,
68     [ MON_3 ] = LC_TIME,
69     [ MON_4 ] = LC_TIME,
70     [ MON_5 ] = LC_TIME,
71     [ MON_6 ] = LC_TIME,
72     [ MON_7 ] = LC_TIME,
73     [ MON_8 ] = LC_TIME,
74     [ MON_9 ] = LC_TIME,
75     [ MON_10 ] = LC_TIME,
76     [ MON_11 ] = LC_TIME,
77     [ MON_12 ] = LC_TIME,
78     [ ABMON_1 ] = LC_TIME,
79     [ ABMON_2 ] = LC_TIME,
80     [ ABMON_3 ] = LC_TIME,
81     [ ABMON_4 ] = LC_TIME,
82     [ ABMON_5 ] = LC_TIME,
83     [ ABMON_6 ] = LC_TIME,
84     [ ABMON_7 ] = LC_TIME,
85     [ ABMON_8 ] = LC_TIME,
86     [ ABMON_9 ] = LC_TIME,
87     [ ABMON_10 ] = LC_TIME,
88     [ ABMON_11 ] = LC_TIME,
89     [ ABMON_12 ] = LC_TIME,
90     [ RADIXCHAR ] = LC_NUMERIC,
91     [ THOUSEP ] = LC_NUMERIC,
92     [ YESSTR ] = LC_MESSAGES,
93     [ YESEXPR ] = LC_MESSAGES,
94     [ NOSTR ] = LC_MESSAGES,
95     [ NOEXPR ] = LC_MESSAGES,
96     [ CRNCYSTR ] = 0,
97     [ CODESET ] = LC_CTYPE,
98     [ ERA ] = 0,
99     [ ERA_D_FMT ] = 0,
100     [ ERA_D_T_FMT ] = 0,
101     [ ERA_T_FMT ] = 0,
102     [ ALT_DIGITS ] = 0,
103 };
104 
105 #define offsetofu16(a, b) ((uint16_t)offsetof(a, b))
106 
107 static const uint16_t langinfo_offset[] = {
108     [ D_T_FMT ] = offsetofu16(_TimeLocale, d_t_fmt),
109     [ D_FMT ] = offsetofu16(_TimeLocale, d_fmt),
110     [ T_FMT ] = offsetofu16(_TimeLocale, t_fmt),
111     [ T_FMT_AMPM ] = offsetofu16(_TimeLocale, t_fmt_ampm),
112     [ AM_STR ] = offsetofu16(_TimeLocale, am_pm[0]),
113     [ PM_STR ] = offsetofu16(_TimeLocale, am_pm[1]),
114     [ DAY_1 ] = offsetofu16(_TimeLocale, day[0]),
115     [ DAY_2 ] = offsetofu16(_TimeLocale, day[1]),
116     [ DAY_3 ] = offsetofu16(_TimeLocale, day[2]),
117     [ DAY_4 ] = offsetofu16(_TimeLocale, day[3]),
118     [ DAY_5 ] = offsetofu16(_TimeLocale, day[4]),
119     [ DAY_6 ] = offsetofu16(_TimeLocale, day[5]),
120     [ DAY_7 ] = offsetofu16(_TimeLocale, day[6]),
121     [ ABDAY_1 ] = offsetofu16(_TimeLocale, abday[0]),
122     [ ABDAY_2 ] = offsetofu16(_TimeLocale, abday[1]),
123     [ ABDAY_3 ] = offsetofu16(_TimeLocale, abday[2]),
124     [ ABDAY_4 ] = offsetofu16(_TimeLocale, abday[3]),
125     [ ABDAY_5 ] = offsetofu16(_TimeLocale, abday[4]),
126     [ ABDAY_6 ] = offsetofu16(_TimeLocale, abday[5]),
127     [ ABDAY_7 ] = offsetofu16(_TimeLocale, abday[6]),
128     [ MON_1 ] = offsetofu16(_TimeLocale, mon[0]),
129     [ MON_2 ] = offsetofu16(_TimeLocale, mon[1]),
130     [ MON_3 ] = offsetofu16(_TimeLocale, mon[2]),
131     [ MON_4 ] = offsetofu16(_TimeLocale, mon[3]),
132     [ MON_5 ] = offsetofu16(_TimeLocale, mon[4]),
133     [ MON_6 ] = offsetofu16(_TimeLocale, mon[5]),
134     [ MON_7 ] = offsetofu16(_TimeLocale, mon[6]),
135     [ MON_8 ] = offsetofu16(_TimeLocale, mon[7]),
136     [ MON_9 ] = offsetofu16(_TimeLocale, mon[8]),
137     [ MON_10 ] = offsetofu16(_TimeLocale, mon[9]),
138     [ MON_11 ] = offsetofu16(_TimeLocale, mon[10]),
139     [ MON_12 ] = offsetofu16(_TimeLocale, mon[11]),
140     [ ABMON_1 ] = offsetofu16(_TimeLocale, abmon[0]),
141     [ ABMON_2 ] = offsetofu16(_TimeLocale, abmon[1]),
142     [ ABMON_3 ] = offsetofu16(_TimeLocale, abmon[2]),
143     [ ABMON_4 ] = offsetofu16(_TimeLocale, abmon[3]),
144     [ ABMON_5 ] = offsetofu16(_TimeLocale, abmon[4]),
145     [ ABMON_6 ] = offsetofu16(_TimeLocale, abmon[5]),
146     [ ABMON_7 ] = offsetofu16(_TimeLocale, abmon[6]),
147     [ ABMON_8 ] = offsetofu16(_TimeLocale, abmon[7]),
148     [ ABMON_9 ] = offsetofu16(_TimeLocale, abmon[8]),
149     [ ABMON_10 ] = offsetofu16(_TimeLocale, abmon[9]),
150     [ ABMON_11 ] = offsetofu16(_TimeLocale, abmon[10]),
151     [ ABMON_12 ] = offsetofu16(_TimeLocale, abmon[11]),
152     [ RADIXCHAR ] = offsetofu16(_NumericLocale, decimal_point),
153     [ THOUSEP ] = offsetofu16(_NumericLocale, thousands_sep),
154     [ YESSTR ] = offsetofu16(_MessagesLocale, yesstr),
155     [ YESEXPR ] = offsetofu16(_MessagesLocale, yesexpr),
156     [ NOSTR ] = offsetofu16(_MessagesLocale, nostr),
157     [ NOEXPR ] = offsetofu16(_MessagesLocale, noexpr),
158     [ CRNCYSTR ] = 0,
159     [ CODESET ] = offsetofu16(_RuneLocale, rl_codeset),
160     [ ERA ] = 0,
161     [ ERA_D_FMT ] = 0,
162     [ ERA_D_T_FMT ] = 0,
163     [ ERA_T_FMT ] = 0,
164     [ ALT_DIGITS ] = 0,
165 };
166 
__weak_alias(nl_langinfo_l,_nl_langinfo_l)167 __weak_alias(nl_langinfo_l, _nl_langinfo_l)
168 
169 char *
170 nl_langinfo(nl_item item)
171 {
172 
173 	return nl_langinfo_l(item, _current_locale());
174 }
175 
176 char *
nl_langinfo_l(nl_item item,locale_t loc)177 nl_langinfo_l(nl_item item, locale_t loc)
178 {
179 	char *s;
180 	int category;
181 	size_t offset;
182 
183 	if (item < 0 || item >= (long)__arraycount(langinfo_category))
184 		return __UNCONST(""); /* Outside the defined range */
185 
186 	category = langinfo_category[item];
187 	if (category == 0)
188 		return __UNCONST(""); /* Not in use */
189 	offset = langinfo_offset[item];
190 
191 	memcpy(&s, (char *)loc->part_impl[category] + offset, sizeof(s));
192 	if (s == NULL)
193 		return __UNCONST("");
194 	else
195 		return s;
196 }
197