1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * LC_TIME database generation routines for localedef.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <sys/types.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "localedef.h"
27 #include "parser.tab.h"
28 #include "timelocal.h"
29
30 struct lc_time_T tm;
31
32 void
33 init_time(void)
34 {
35 (void) memset(&tm, 0, sizeof (tm));
36 }
37
38 void
39 add_time_str(wchar_t *wcs)
40 {
41 char *str;
42
43 if ((str = to_mb_string(wcs)) == NULL) {
44 INTERR;
45 return;
46 }
47 free(wcs);
48
49 switch (last_kw) {
50 case T_D_T_FMT:
51 tm.c_fmt = str;
52 break;
53 case T_D_FMT:
54 tm.x_fmt = str;
55 break;
56 case T_T_FMT:
57 tm.X_fmt = str;
58 break;
59 case T_T_FMT_AMPM:
60 tm.ampm_fmt = str;
61 break;
62 case T_DATE_FMT:
63 /*
64 * This one is a Solaris extension, Too bad date just
65 * doesn't use %c, which would be simpler.
66 */
67 tm.date_fmt = str;
68 break;
69 case T_ERA_D_FMT:
70 case T_ERA_T_FMT:
71 case T_ERA_D_T_FMT:
72 /* Silently ignore it. */
73 break;
74 default:
75 free(str);
76 INTERR;
77 break;
78 }
79 }
80
81 static void
82 add_list(const char *ptr[], char *str, int limit)
83 {
84 int i;
85 for (i = 0; i < limit; i++) {
86 if (ptr[i] == NULL) {
87 ptr[i] = str;
88 return;
89 }
90 }
91 errf(_("too many list elements"));
92 }
93
94 void
95 add_time_list(wchar_t *wcs)
96 {
97 char *str;
98
99 if ((str = to_mb_string(wcs)) == NULL) {
100 INTERR;
101 return;
102 }
103 free(wcs);
104
105 switch (last_kw) {
106 case T_ABMON:
107 add_list(tm.mon, str, 12);
108 break;
109 case T_MON:
110 add_list(tm.month, str, 12);
111 break;
112 case T_ABDAY:
113 add_list(tm.wday, str, 7);
114 break;
115 case T_DAY:
116 add_list(tm.weekday, str, 7);
117 break;
118 case T_AM_PM:
119 if (tm.am == NULL) {
120 tm.am = str;
121 } else if (tm.pm == NULL) {
122 tm.pm = str;
123 } else {
124 errf(_("too many list elements"));
125 }
126 break;
127 case T_ALT_DIGITS:
128 case T_ERA:
129 free(str);
130 break;
131 default:
132 free(str);
133 INTERR;
134 break;
135 }
136 }
137
138 void
139 check_time_list(void)
140 {
141 switch (last_kw) {
142 case T_ABMON:
143 if (tm.mon[11] != NULL)
144 return;
145 break;
146 case T_MON:
147 if (tm.month[11] != NULL)
148 return;
149 break;
150 case T_ABDAY:
151 if (tm.wday[6] != NULL)
152 return;
153 break;
154 case T_DAY:
155 if (tm.weekday[6] != NULL)
156 return;
157 break;
158 case T_AM_PM:
159 if (tm.pm != NULL)
160 return;
161 break;
162 case T_ERA:
163 case T_ALT_DIGITS:
164 return;
165 default:
166 errf(_("unknown list"));
167 break;
168 }
169
170 errf(_("too few items in list (%d)"), last_kw);
171 }
172
173 void
174 reset_time_list(void)
175 {
176 int i;
177 switch (last_kw) {
178 case T_ABMON:
179 for (i = 0; i < 12; i++) {
180 free((char *)tm.mon[i]);
181 tm.mon[i] = NULL;
182 }
183 break;
184 case T_MON:
185 for (i = 0; i < 12; i++) {
186 free((char *)tm.month[i]);
187 tm.month[i] = NULL;
188 }
189 break;
190 case T_ABDAY:
191 for (i = 0; i < 7; i++) {
192 free((char *)tm.wday[i]);
193 tm.wday[i] = NULL;
194 }
195 break;
196 case T_DAY:
197 for (i = 0; i < 7; i++) {
198 free((char *)tm.weekday[i]);
199 tm.weekday[i] = NULL;
200 }
201 break;
202 case T_AM_PM:
203 free((char *)tm.am);
204 tm.am = NULL;
205 free((char *)tm.pm);
206 tm.pm = NULL;
207 break;
208 }
209 }
210
211
212 void
213 dump_time(void)
214 {
215 FILE *f;
216 int i;
217
218 if ((f = open_category()) == NULL) {
219 return;
220 }
221
222 for (i = 0; i < 12; i++) {
223 if (putl_category(tm.mon[i], f) == EOF) {
224 return;
225 }
226 }
227 for (i = 0; i < 12; i++) {
228 if (putl_category(tm.month[i], f) == EOF) {
229 return;
230 }
231 }
232 for (i = 0; i < 7; i++) {
233 if (putl_category(tm.wday[i], f) == EOF) {
234 return;
235 }
236 }
237 for (i = 0; i < 7; i++) {
238 if (putl_category(tm.weekday[i], f) == EOF) {
239 return;
240 }
241 }
242
243 /*
244 * NOTE: If date_fmt is not specified, then we'll default to
245 * using the %c for date. This is reasonable for most
246 * locales, although for reasons that I don't understand
247 * Solaris historically has had a seperate format for date.
248 */
249 if ((putl_category(tm.X_fmt, f) == EOF) ||
250 (putl_category(tm.x_fmt, f) == EOF) ||
251 (putl_category(tm.c_fmt, f) == EOF) ||
252 (putl_category(tm.am, f) == EOF) ||
253 (putl_category(tm.pm, f) == EOF) ||
254 (putl_category(tm.date_fmt ? tm.date_fmt : tm.c_fmt, f) == EOF) ||
255 (putl_category(tm.ampm_fmt, f) == EOF)) {
256 return;
257 }
258 close_category(f);
259 }