Last minute change.
[glibc.git] / locale / programs / ld-time.c
blob00f288f69bcfdc3fb7e8592eb45ffd46636d81ff
1 /* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #include <langinfo.h>
25 #include <string.h>
27 /* Undefine following line in production version. */
28 /* #define NDEBUG 1 */
29 #include <assert.h>
31 #include "locales.h"
32 #include "localeinfo.h"
33 #include "stringtrans.h"
36 void *xmalloc (size_t __n);
39 /* The real definition of the struct for the LC_TIME locale. */
40 struct locale_time_t
42 const char *abday[7];
43 size_t cur_num_abday;
44 const char *day[7];
45 size_t cur_num_day;
46 const char *abmon[12];
47 size_t cur_num_abmon;
48 const char *mon[12];
49 size_t cur_num_mon;
50 const char *am_pm[2];
51 size_t cur_num_am_pm;
52 const char *d_t_fmt;
53 const char *d_fmt;
54 const char *t_fmt;
55 const char *t_fmt_ampm;
56 const char *era;
57 const char *era_year;
58 const char *era_d_t_fmt;
59 const char *era_t_fmt;
60 const char *era_d_fmt;
61 const char *alt_digits[100];
62 size_t cur_num_alt_digits;
66 void
67 time_startup (struct linereader *lr, struct localedef_t *locale,
68 struct charset_t *charset)
70 struct locale_time_t *time;
72 /* It is important that we always use UCS1 encoding for strings now. */
73 encoding_method = ENC_UCS1;
75 locale->categories[LC_TIME].time = time =
76 (struct locale_time_t *) xmalloc (sizeof (struct locale_time_t));
78 memset (time, '\0', sizeof (struct locale_time_t));
82 void
83 time_finish (struct localedef_t *locale)
85 struct locale_time_t *time = locale->categories[LC_TIME].time;
87 #define TESTARR_ELEM(cat, max) \
88 if (time->cur_num_##cat == 0) \
89 error (0, 0, _("field `%s' in category `%s' not defined"), \
90 #cat, "LC_TIME"); \
91 else if (time->cur_num_##cat != max) \
92 error (0, 0, _("field `%s' in category `%s' has not enough values"), \
93 #cat, "LC_TIME")
95 TESTARR_ELEM (abday, 7);
96 TESTARR_ELEM (day, 7);
97 TESTARR_ELEM (abmon, 12);
98 TESTARR_ELEM (mon, 12);
99 TESTARR_ELEM (am_pm, 2);
101 #define TEST_ELEM(cat) \
102 if (time->cat == NULL) \
103 error (0, 0, _("field `%s' in category `%s' not defined"), \
104 #cat, "LC_TIME")
106 TEST_ELEM (d_t_fmt);
107 TEST_ELEM (d_fmt);
108 TEST_ELEM (t_fmt);
109 TEST_ELEM (t_fmt_ampm);
113 void
114 time_output (struct localedef_t *locale, const char *output_path)
116 struct locale_time_t *time = locale->categories[LC_TIME].time;
117 struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
118 + time->cur_num_alt_digits];
119 struct locale_file data;
120 u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
121 size_t cnt, last_idx, num;
123 if ((locale->binary & (1 << LC_TIME)) != 0)
125 iov[0].iov_base = time;
126 iov[0].iov_len = locale->len[LC_TIME];
128 write_locale_data (output_path, "LC_TIME", 1, iov);
130 return;
133 data.magic = LIMAGIC (LC_TIME);
134 data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TIME);
135 iov[0].iov_base = (void *) &data;
136 iov[0].iov_len = sizeof (data);
138 iov[1].iov_base = (void *) idx;
139 iov[1].iov_len = sizeof (idx);
141 idx[0] = iov[0].iov_len + iov[1].iov_len;
143 /* The ab'days. */
144 for (cnt = 0; cnt <= _NL_ITEM_INDEX (ABDAY_7); ++cnt)
146 iov[2 + cnt].iov_base =
147 (void *) (time->abday[cnt - _NL_ITEM_INDEX (ABDAY_1)] ?: "");
148 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
149 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
152 /* The days. */
153 for (; cnt <= _NL_ITEM_INDEX (DAY_7); ++cnt)
155 iov[2 + cnt].iov_base =
156 (void *) (time->day[cnt - _NL_ITEM_INDEX (DAY_1)] ?: "");
157 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
158 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
161 /* The ab'mons. */
162 for (; cnt <= _NL_ITEM_INDEX (ABMON_12); ++cnt)
164 iov[2 + cnt].iov_base =
165 (void *) (time->abmon[cnt - _NL_ITEM_INDEX (ABMON_1)] ?: "");
166 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
167 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
170 /* The mons. */
171 for (; cnt <= _NL_ITEM_INDEX (MON_12); ++cnt)
173 iov[2 + cnt].iov_base =
174 (void *) (time->mon[cnt - _NL_ITEM_INDEX (MON_1)] ?: "");
175 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
176 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
179 /* AM/PM. */
180 for (; cnt <= _NL_ITEM_INDEX (PM_STR); ++cnt)
182 iov[2 + cnt].iov_base =
183 (void *) (time->am_pm[cnt - _NL_ITEM_INDEX (AM_STR)] ?: "");
184 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
185 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
188 iov[2 + cnt].iov_base = (void *) (time->d_t_fmt ?: "");
189 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
190 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
191 ++cnt;
193 iov[2 + cnt].iov_base = (void *) (time->d_fmt ?: "");
194 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
195 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
196 ++cnt;
198 iov[2 + cnt].iov_base = (void *) (time->t_fmt ?: "");
199 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
200 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
201 ++cnt;
203 iov[2 + cnt].iov_base = (void *) (time->t_fmt_ampm ?: "");
204 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
205 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
206 ++cnt;
208 iov[2 + cnt].iov_base = (void *) (time->era ?: "");
209 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
210 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
211 ++cnt;
213 iov[2 + cnt].iov_base = (void *) (time->era_year ?: "");
214 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
215 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
216 ++cnt;
218 iov[2 + cnt].iov_base = (void *) (time->era_d_fmt ?: "");
219 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
220 idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
221 last_idx = ++cnt;
223 idx[1 + last_idx] = idx[last_idx];
224 for (num = 0; num < time->cur_num_alt_digits; ++num, ++cnt)
226 iov[2 + cnt].iov_base = (void *) (time->alt_digits[num] ?: "");
227 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
228 idx[1 + last_idx] += iov[2 + cnt].iov_len;
230 ++last_idx;
232 iov[2 + cnt].iov_base = (void *) (time->era_d_t_fmt ?: "");
233 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
234 idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
235 ++cnt;
237 iov[2 + cnt].iov_base = (void *) (time->era_d_fmt ?: "");
238 iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
239 ++cnt;
241 assert (cnt == (_NL_ITEM_INDEX (_NL_NUM_LC_TIME) - 1
242 + time->cur_num_alt_digits));
244 write_locale_data (output_path, "LC_TIME", 2 + cnt, iov);
248 void
249 time_add (struct linereader *lr, struct localedef_t *locale,
250 enum token_t tok, struct token *code,
251 struct charset_t *charset)
253 struct locale_time_t *time = locale->categories[LC_TIME].time;
255 switch (tok)
257 #define STRARR_ELEM(cat, max) \
258 case tok_##cat: \
259 if (time->cur_num_##cat >= max) \
260 lr_error (lr, _("\
261 too many values for field `%s' in category `LC_TIME'"), \
262 #cat, "LC_TIME"); \
263 else if (code->val.str.start == NULL) \
265 lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
266 #cat, "LC_TIME"); \
267 time->cat[time->cur_num_##cat++] = ""; \
269 else \
270 time->cat[time->cur_num_##cat++] \
271 = code->val.str.start; \
272 break
274 STRARR_ELEM (abday, 7);
275 STRARR_ELEM (day, 7);
276 STRARR_ELEM (abmon, 12);
277 STRARR_ELEM (mon, 12);
278 STRARR_ELEM (am_pm, 2);
279 STRARR_ELEM (alt_digits, 100);
281 #define STR_ELEM(cat) \
282 case tok_##cat: \
283 if (time->cat != NULL) \
284 lr_error (lr, _("\
285 field `%s' in category `%s' declared more than once"), \
286 #cat, "LC_TIME"); \
287 else if (code->val.str.start == NULL) \
289 lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
290 #cat, "LC_TIME"); \
291 time->cat = ""; \
293 else \
294 time->cat = code->val.str.start; \
295 break
297 STR_ELEM (d_t_fmt);
298 STR_ELEM (d_fmt);
299 STR_ELEM (t_fmt);
300 STR_ELEM (t_fmt_ampm);
301 STR_ELEM (era);
302 STR_ELEM (era_year);
303 STR_ELEM (era_d_t_fmt);
304 STR_ELEM (era_d_fmt);
305 STR_ELEM (era_t_fmt);
307 default:
308 assert (! "unknown token in category `LC_TIME': should not happen");