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. */
27 /* Undefine following line in production version. */
28 /* #define NDEBUG 1 */
32 #include "localeinfo.h"
33 #include "stringtrans.h"
36 void *xmalloc (size_t __n
);
37 void *xrealloc (void *__p
, size_t __n
);
40 /* The real definition of the struct for the LC_TIME locale. */
47 const char *abmon
[12];
56 const char *t_fmt_ampm
;
60 const char *era_d_t_fmt
;
61 const char *era_t_fmt
;
62 const char *era_d_fmt
;
63 const char *alt_digits
[100];
64 size_t cur_num_alt_digits
;
69 time_startup (struct linereader
*lr
, struct localedef_t
*locale
,
70 struct charset_t
*charset
)
72 struct locale_time_t
*time
;
74 /* It is important that we always use UCS1 encoding for strings now. */
75 encoding_method
= ENC_UCS1
;
77 locale
->categories
[LC_TIME
].time
= time
=
78 (struct locale_time_t
*) xmalloc (sizeof (struct locale_time_t
));
80 memset (time
, '\0', sizeof (struct locale_time_t
));
85 time_finish (struct localedef_t
*locale
)
87 struct locale_time_t
*time
= locale
->categories
[LC_TIME
].time
;
89 #define TESTARR_ELEM(cat, max) \
90 if (time->cur_num_##cat == 0) \
91 error (0, 0, _("field `%s' in category `%s' not defined"), \
93 else if (time->cur_num_##cat != max) \
94 error (0, 0, _("field `%s' in category `%s' has not enough values"), \
97 TESTARR_ELEM (abday
, 7);
98 TESTARR_ELEM (day
, 7);
99 TESTARR_ELEM (abmon
, 12);
100 TESTARR_ELEM (mon
, 12);
101 TESTARR_ELEM (am_pm
, 2);
103 #define TEST_ELEM(cat) \
104 if (time->cat == NULL) \
105 error (0, 0, _("field `%s' in category `%s' not defined"), \
111 TEST_ELEM (t_fmt_ampm
);
116 time_output (struct localedef_t
*locale
, const char *output_path
)
118 struct locale_time_t
*time
= locale
->categories
[LC_TIME
].time
;
119 struct iovec iov
[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME
)
120 + (time
->era_num
> 0 ? time
->era_num
- 1 : 0)
121 + time
->cur_num_alt_digits
];
122 struct locale_file data
;
123 u_int32_t idx
[_NL_ITEM_INDEX (_NL_NUM_LC_TIME
)];
124 size_t cnt
, last_idx
, num
;
126 if ((locale
->binary
& (1 << LC_TIME
)) != 0)
128 iov
[0].iov_base
= time
;
129 iov
[0].iov_len
= locale
->len
[LC_TIME
];
131 write_locale_data (output_path
, "LC_TIME", 1, iov
);
136 data
.magic
= LIMAGIC (LC_TIME
);
137 data
.n
= _NL_ITEM_INDEX (_NL_NUM_LC_TIME
);
138 iov
[0].iov_base
= (void *) &data
;
139 iov
[0].iov_len
= sizeof (data
);
141 iov
[1].iov_base
= (void *) idx
;
142 iov
[1].iov_len
= sizeof (idx
);
144 idx
[0] = iov
[0].iov_len
+ iov
[1].iov_len
;
147 for (cnt
= 0; cnt
<= _NL_ITEM_INDEX (ABDAY_7
); ++cnt
)
149 iov
[2 + cnt
].iov_base
=
150 (void *) (time
->abday
[cnt
- _NL_ITEM_INDEX (ABDAY_1
)] ?: "");
151 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
152 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
156 for (; cnt
<= _NL_ITEM_INDEX (DAY_7
); ++cnt
)
158 iov
[2 + cnt
].iov_base
=
159 (void *) (time
->day
[cnt
- _NL_ITEM_INDEX (DAY_1
)] ?: "");
160 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
161 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
165 for (; cnt
<= _NL_ITEM_INDEX (ABMON_12
); ++cnt
)
167 iov
[2 + cnt
].iov_base
=
168 (void *) (time
->abmon
[cnt
- _NL_ITEM_INDEX (ABMON_1
)] ?: "");
169 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
170 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
174 for (; cnt
<= _NL_ITEM_INDEX (MON_12
); ++cnt
)
176 iov
[2 + cnt
].iov_base
=
177 (void *) (time
->mon
[cnt
- _NL_ITEM_INDEX (MON_1
)] ?: "");
178 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
179 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
183 for (; cnt
<= _NL_ITEM_INDEX (PM_STR
); ++cnt
)
185 iov
[2 + cnt
].iov_base
=
186 (void *) (time
->am_pm
[cnt
- _NL_ITEM_INDEX (AM_STR
)] ?: "");
187 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
188 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
191 iov
[2 + cnt
].iov_base
= (void *) (time
->d_t_fmt
?: "");
192 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
193 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
196 iov
[2 + cnt
].iov_base
= (void *) (time
->d_fmt
?: "");
197 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
198 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
201 iov
[2 + cnt
].iov_base
= (void *) (time
->t_fmt
?: "");
202 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
203 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
206 iov
[2 + cnt
].iov_base
= (void *) (time
->t_fmt_ampm
?: "");
207 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
208 idx
[1 + cnt
] = idx
[cnt
] + iov
[2 + cnt
].iov_len
;
211 idx
[1 + last_idx
] = idx
[last_idx
];
212 for (num
= 0; num
< time
->era_num
; ++num
, ++cnt
)
214 iov
[2 + cnt
].iov_base
= (void *) time
->era
[num
];
215 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
219 iov
[2 + cnt
].iov_base
= (void *) (time
->era_year
?: "");
220 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
221 idx
[1 + last_idx
] = idx
[last_idx
] + iov
[2 + cnt
].iov_len
;
225 iov
[2 + cnt
].iov_base
= (void *) (time
->era_d_fmt
?: "");
226 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
227 idx
[1 + last_idx
] = idx
[last_idx
] + iov
[2 + cnt
].iov_len
;
231 idx
[1 + last_idx
] = idx
[last_idx
];
232 for (num
= 0; num
< time
->cur_num_alt_digits
; ++num
, ++cnt
)
234 iov
[2 + cnt
].iov_base
= (void *) (time
->alt_digits
[num
] ?: "");
235 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
236 idx
[1 + last_idx
] += iov
[2 + cnt
].iov_len
;
240 iov
[2 + cnt
].iov_base
= (void *) (time
->era_d_t_fmt
?: "");
241 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
242 idx
[1 + last_idx
] = idx
[last_idx
] + iov
[2 + cnt
].iov_len
;
245 iov
[2 + cnt
].iov_base
= (void *) (time
->era_d_fmt
?: "");
246 iov
[2 + cnt
].iov_len
= strlen (iov
[2 + cnt
].iov_base
) + 1;
249 assert (cnt
== (_NL_ITEM_INDEX (_NL_NUM_LC_TIME
) - 1
250 + time
->cur_num_alt_digits
));
252 write_locale_data (output_path
, "LC_TIME", 2 + cnt
, iov
);
257 time_add (struct linereader
*lr
, struct localedef_t
*locale
,
258 enum token_t tok
, struct token
*code
,
259 struct charset_t
*charset
)
261 struct locale_time_t
*time
= locale
->categories
[LC_TIME
].time
;
265 #define STRARR_ELEM(cat, max) \
267 if (time->cur_num_##cat >= max) \
269 too many values for field `%s' in category `LC_TIME'"), \
271 else if (code->val.str.start == NULL) \
273 lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
275 time->cat[time->cur_num_##cat++] = ""; \
278 time->cat[time->cur_num_##cat++] = code->val.str.start; \
281 STRARR_ELEM (abday
, 7);
282 STRARR_ELEM (day
, 7);
283 STRARR_ELEM (abmon
, 12);
284 STRARR_ELEM (mon
, 12);
285 STRARR_ELEM (am_pm
, 2);
286 STRARR_ELEM (alt_digits
, 100);
289 if (code
->val
.str
.start
== NULL
)
290 lr_error (lr
, _("unknown character in field `%s' of category `%s'"),
295 time
->era
= xrealloc (time
->era
, time
->era_num
* sizeof (char *));
296 time
->era
[time
->era_num
- 1] = code
->val
.str
.start
;
300 #define STR_ELEM(cat) \
302 if (time->cat != NULL) \
304 field `%s' in category `%s' declared more than once"), \
306 else if (code->val.str.start == NULL) \
308 lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
313 time->cat = code->val.str.start; \
319 STR_ELEM (t_fmt_ampm
);
321 STR_ELEM (era_d_t_fmt
);
322 STR_ELEM (era_d_fmt
);
323 STR_ELEM (era_t_fmt
);
326 assert (! "unknown token in category `LC_TIME': should not happen");