1 /* Copyright (C) 1995-1999,2000,2001,2002,2005,2007
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 #include "localedef.h"
34 #include "linereader.h"
35 #include "localeinfo.h"
39 /* The real definition of the struct for the LC_MONETARY locale. */
40 struct locale_monetary_t
42 const char *int_curr_symbol
;
43 const char *currency_symbol
;
44 const char *mon_decimal_point
;
45 const char *mon_thousands_sep
;
46 uint32_t mon_decimal_point_wc
;
47 uint32_t mon_thousands_sep_wc
;
49 size_t mon_grouping_len
;
50 const char *positive_sign
;
51 const char *negative_sign
;
52 signed char int_frac_digits
;
53 signed char frac_digits
;
54 signed char p_cs_precedes
;
55 signed char p_sep_by_space
;
56 signed char n_cs_precedes
;
57 signed char n_sep_by_space
;
58 signed char p_sign_posn
;
59 signed char n_sign_posn
;
60 signed char int_p_cs_precedes
;
61 signed char int_p_sep_by_space
;
62 signed char int_n_cs_precedes
;
63 signed char int_n_sep_by_space
;
64 signed char int_p_sign_posn
;
65 signed char int_n_sign_posn
;
66 const char *duo_int_curr_symbol
;
67 const char *duo_currency_symbol
;
68 signed char duo_int_frac_digits
;
69 signed char duo_frac_digits
;
70 signed char duo_p_cs_precedes
;
71 signed char duo_p_sep_by_space
;
72 signed char duo_n_cs_precedes
;
73 signed char duo_n_sep_by_space
;
74 signed char duo_p_sign_posn
;
75 signed char duo_n_sign_posn
;
76 signed char duo_int_p_cs_precedes
;
77 signed char duo_int_p_sep_by_space
;
78 signed char duo_int_n_cs_precedes
;
79 signed char duo_int_n_sep_by_space
;
80 signed char duo_int_p_sign_posn
;
81 signed char duo_int_n_sign_posn
;
82 uint32_t uno_valid_from
;
83 uint32_t uno_valid_to
;
84 uint32_t duo_valid_from
;
85 uint32_t duo_valid_to
;
86 uint32_t conversion_rate
[2];
91 /* The content iof the field int_curr_symbol has to be taken from
92 ISO-4217. We test for correct values. */
93 #define DEFINE_INT_CURR(str) str,
94 static const char *const valid_int_curr
[] =
96 # include "../iso-4217.def"
98 #define NR_VALID_INT_CURR ((sizeof (valid_int_curr) \
99 / sizeof (valid_int_curr[0])))
100 #undef DEFINE_INT_CURR
103 /* Prototypes for local functions. */
104 static int curr_strcmp (const char *s1
, const char **s2
);
108 monetary_startup (struct linereader
*lr
, struct localedef_t
*locale
,
113 struct locale_monetary_t
*monetary
;
115 locale
->categories
[LC_MONETARY
].monetary
= monetary
=
116 (struct locale_monetary_t
*) xmalloc (sizeof (*monetary
));
118 memset (monetary
, '\0', sizeof (struct locale_monetary_t
));
120 monetary
->mon_grouping
= NULL
;
121 monetary
->mon_grouping_len
= 0;
123 monetary
->int_frac_digits
= -2;
124 monetary
->frac_digits
= -2;
125 monetary
->p_cs_precedes
= -2;
126 monetary
->p_sep_by_space
= -2;
127 monetary
->n_cs_precedes
= -2;
128 monetary
->n_sep_by_space
= -2;
129 monetary
->p_sign_posn
= -2;
130 monetary
->n_sign_posn
= -2;
131 monetary
->int_p_cs_precedes
= -2;
132 monetary
->int_p_sep_by_space
= -2;
133 monetary
->int_n_cs_precedes
= -2;
134 monetary
->int_n_sep_by_space
= -2;
135 monetary
->int_p_sign_posn
= -2;
136 monetary
->int_n_sign_posn
= -2;
137 monetary
->duo_int_frac_digits
= -2;
138 monetary
->duo_frac_digits
= -2;
139 monetary
->duo_p_cs_precedes
= -2;
140 monetary
->duo_p_sep_by_space
= -2;
141 monetary
->duo_n_cs_precedes
= -2;
142 monetary
->duo_n_sep_by_space
= -2;
143 monetary
->duo_p_sign_posn
= -2;
144 monetary
->duo_n_sign_posn
= -2;
145 monetary
->duo_int_p_cs_precedes
= -2;
146 monetary
->duo_int_p_sep_by_space
= -2;
147 monetary
->duo_int_n_cs_precedes
= -2;
148 monetary
->duo_int_n_sep_by_space
= -2;
149 monetary
->duo_int_p_sign_posn
= -2;
150 monetary
->duo_int_n_sign_posn
= -2;
155 lr
->translate_strings
= 1;
156 lr
->return_widestr
= 0;
162 monetary_finish (struct localedef_t
*locale
, const struct charmap_t
*charmap
)
164 struct locale_monetary_t
*monetary
165 = locale
->categories
[LC_MONETARY
].monetary
;
168 /* Now resolve copying and also handle completely missing definitions. */
169 if (monetary
== NULL
)
171 /* First see whether we were supposed to copy. If yes, find the
172 actual definition. */
173 if (locale
->copy_name
[LC_MONETARY
] != NULL
)
175 /* Find the copying locale. This has to happen transitively since
176 the locale we are copying from might also copying another one. */
177 struct localedef_t
*from
= locale
;
180 from
= find_locale (LC_MONETARY
, from
->copy_name
[LC_MONETARY
],
181 from
->repertoire_name
, charmap
);
182 while (from
->categories
[LC_MONETARY
].monetary
== NULL
183 && from
->copy_name
[LC_MONETARY
] != NULL
);
185 monetary
= locale
->categories
[LC_MONETARY
].monetary
186 = from
->categories
[LC_MONETARY
].monetary
;
189 /* If there is still no definition issue an warning and create an
191 if (monetary
== NULL
)
194 WITH_CUR_LOCALE (error (0, 0, _("\
195 No definition for %s category found"), "LC_MONETARY"));
196 monetary_startup (NULL
, locale
, 0);
197 monetary
= locale
->categories
[LC_MONETARY
].monetary
;
202 #define TEST_ELEM(cat, initval) \
203 if (monetary->cat == NULL) \
205 if (! be_quiet && ! nothing) \
206 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
207 "LC_MONETARY", #cat)); \
208 monetary->cat = initval; \
211 TEST_ELEM (int_curr_symbol
, "");
212 TEST_ELEM (currency_symbol
, "");
213 TEST_ELEM (mon_decimal_point
, ".");
214 TEST_ELEM (mon_thousands_sep
, "");
215 TEST_ELEM (positive_sign
, "");
216 TEST_ELEM (negative_sign
, "");
218 /* The international currency symbol must come from ISO 4217. */
219 if (monetary
->int_curr_symbol
!= NULL
)
221 if (strlen (monetary
->int_curr_symbol
) != 4)
223 if (! be_quiet
&& ! nothing
)
224 WITH_CUR_LOCALE (error (0, 0, _("\
225 %s: value of field `int_curr_symbol' has wrong length"),
229 { /* Check the first three characters against ISO 4217 */
231 strncpy (symbol
, monetary
->int_curr_symbol
, 3);
233 if (bsearch (symbol
, valid_int_curr
, NR_VALID_INT_CURR
,
234 sizeof (const char *),
235 (comparison_fn_t
) curr_strcmp
) == NULL
237 WITH_CUR_LOCALE (error (0, 0, _("\
238 %s: value of field `int_curr_symbol' does \
239 not correspond to a valid name in ISO 4217"),
244 /* The decimal point must not be empty. This is not said explicitly
245 in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
247 if (monetary
->mon_decimal_point
== NULL
)
249 if (! be_quiet
&& ! nothing
)
250 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
251 "LC_MONETARY", "mon_decimal_point"));
252 monetary
->mon_decimal_point
= ".";
254 else if (monetary
->mon_decimal_point
[0] == '\0' && ! be_quiet
&& ! nothing
)
256 WITH_CUR_LOCALE (error (0, 0, _("\
257 %s: value for field `%s' must not be an empty string"),
258 "LC_MONETARY", "mon_decimal_point"));
260 if (monetary
->mon_decimal_point_wc
== L
'\0')
261 monetary
->mon_decimal_point_wc
= L
'.';
263 if (monetary
->mon_grouping_len
== 0)
265 if (! be_quiet
&& ! nothing
)
266 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
267 "LC_MONETARY", "mon_grouping"));
269 monetary
->mon_grouping
= (char *) "\177";
270 monetary
->mon_grouping_len
= 1;
274 #define TEST_ELEM(cat, min, max, initval) \
275 if (monetary->cat == -2) \
277 if (! be_quiet && ! nothing) \
278 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
279 "LC_MONETARY", #cat)); \
280 monetary->cat = initval; \
282 else if ((monetary->cat < min || monetary->cat > max) \
284 && !be_quiet && !nothing) \
285 WITH_CUR_LOCALE (error (0, 0, _("\
286 %s: value for field `%s' must be in range %d...%d"), \
287 "LC_MONETARY", #cat, min, max))
289 TEST_ELEM (int_frac_digits
, 1, 0, -1);
290 TEST_ELEM (frac_digits
, 1, 0, -1);
291 TEST_ELEM (p_cs_precedes
, -1, 1, -1);
292 TEST_ELEM (p_sep_by_space
, -1, 2, -1);
293 TEST_ELEM (n_cs_precedes
, -1, 1, -1);
294 TEST_ELEM (n_sep_by_space
, -1, 2, -1);
295 TEST_ELEM (p_sign_posn
, -1, 4, -1);
296 TEST_ELEM (n_sign_posn
, -1, 4, -1);
298 /* The non-POSIX.2 extensions are optional. */
299 if (monetary
->duo_int_curr_symbol
== NULL
)
300 monetary
->duo_int_curr_symbol
= monetary
->int_curr_symbol
;
301 if (monetary
->duo_currency_symbol
== NULL
)
302 monetary
->duo_currency_symbol
= monetary
->currency_symbol
;
304 if (monetary
->duo_int_frac_digits
== -2)
305 monetary
->duo_int_frac_digits
= monetary
->int_frac_digits
;
306 if (monetary
->duo_frac_digits
== -2)
307 monetary
->duo_frac_digits
= monetary
->frac_digits
;
310 #define TEST_ELEM(cat, alt, min, max) \
311 if (monetary->cat == -2) \
312 monetary->cat = monetary->alt; \
313 else if ((monetary->cat < min || monetary->cat > max) && !be_quiet \
315 WITH_CUR_LOCALE (error (0, 0, _("\
316 %s: value for field `%s' must be in range %d...%d"), \
317 "LC_MONETARY", #cat, min, max))
319 TEST_ELEM (int_p_cs_precedes
, p_cs_precedes
, -1, 1);
320 TEST_ELEM (int_p_sep_by_space
, p_sep_by_space
, -1, 2);
321 TEST_ELEM (int_n_cs_precedes
, n_cs_precedes
, -1, 1);
322 TEST_ELEM (int_n_sep_by_space
, n_sep_by_space
, -1, 2);
323 TEST_ELEM (int_p_sign_posn
, p_sign_posn
, -1, 4);
324 TEST_ELEM (int_n_sign_posn
, n_sign_posn
, -1, 4);
326 TEST_ELEM (duo_p_cs_precedes
, p_cs_precedes
, -1, 1);
327 TEST_ELEM (duo_p_sep_by_space
, p_sep_by_space
, -1, 2);
328 TEST_ELEM (duo_n_cs_precedes
, n_cs_precedes
, -1, 1);
329 TEST_ELEM (duo_n_sep_by_space
, n_sep_by_space
, -1, 2);
330 TEST_ELEM (duo_int_p_cs_precedes
, int_p_cs_precedes
, -1, 1);
331 TEST_ELEM (duo_int_p_sep_by_space
, int_p_sep_by_space
, -1, 2);
332 TEST_ELEM (duo_int_n_cs_precedes
, int_n_cs_precedes
, -1, 1);
333 TEST_ELEM (duo_int_n_sep_by_space
, int_n_sep_by_space
, -1, 2);
334 TEST_ELEM (duo_p_sign_posn
, p_sign_posn
, -1, 4);
335 TEST_ELEM (duo_n_sign_posn
, n_sign_posn
, -1, 4);
336 TEST_ELEM (duo_int_p_sign_posn
, int_p_sign_posn
, -1, 4);
337 TEST_ELEM (duo_int_n_sign_posn
, int_n_sign_posn
, -1, 4);
339 if (monetary
->uno_valid_from
== 0)
340 monetary
->uno_valid_from
= 10101;
341 if (monetary
->uno_valid_to
== 0)
342 monetary
->uno_valid_to
= 99991231;
343 if (monetary
->duo_valid_from
== 0)
344 monetary
->duo_valid_from
= 10101;
345 if (monetary
->duo_valid_to
== 0)
346 monetary
->duo_valid_to
= 99991231;
348 if (monetary
->conversion_rate
[0] == 0)
350 monetary
->conversion_rate
[0] = 1;
351 monetary
->conversion_rate
[1] = 1;
354 /* Create the crncystr entry. */
355 monetary
->crncystr
= (char *) xmalloc (strlen (monetary
->currency_symbol
)
357 monetary
->crncystr
[0] = monetary
->p_cs_precedes
? '-' : '+';
358 strcpy (&monetary
->crncystr
[1], monetary
->currency_symbol
);
363 monetary_output (struct localedef_t
*locale
, const struct charmap_t
*charmap
,
364 const char *output_path
)
366 struct locale_monetary_t
*monetary
367 = locale
->categories
[LC_MONETARY
].monetary
;
368 struct iovec iov
[3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
)];
369 struct locale_file data
;
370 uint32_t idx
[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
)];
373 data
.magic
= LIMAGIC (LC_MONETARY
);
374 data
.n
= _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
);
375 iov
[cnt
].iov_base
= (void *) &data
;
376 iov
[cnt
].iov_len
= sizeof (data
);
379 iov
[cnt
].iov_base
= (void *) idx
;
380 iov
[cnt
].iov_len
= sizeof (idx
);
383 idx
[cnt
- 2] = iov
[0].iov_len
+ iov
[1].iov_len
;
384 iov
[cnt
].iov_base
= (void *) monetary
->int_curr_symbol
;
385 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
388 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
389 iov
[cnt
].iov_base
= (void *) monetary
->currency_symbol
;
390 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
393 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
394 iov
[cnt
].iov_base
= (void *) monetary
->mon_decimal_point
;
395 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
398 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
399 iov
[cnt
].iov_base
= (void *) monetary
->mon_thousands_sep
;
400 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
403 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
404 iov
[cnt
].iov_base
= monetary
->mon_grouping
;
405 iov
[cnt
].iov_len
= monetary
->mon_grouping_len
;
408 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
409 iov
[cnt
].iov_base
= (void *) monetary
->positive_sign
;
410 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
413 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
414 iov
[cnt
].iov_base
= (void *) monetary
->negative_sign
;
415 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
418 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
419 iov
[cnt
].iov_base
= (void *) &monetary
->int_frac_digits
;
420 iov
[cnt
].iov_len
= 1;
423 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
424 iov
[cnt
].iov_base
= (void *) &monetary
->frac_digits
;
425 iov
[cnt
].iov_len
= 1;
428 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
429 iov
[cnt
].iov_base
= (void *) &monetary
->p_cs_precedes
;
430 iov
[cnt
].iov_len
= 1;
433 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
434 iov
[cnt
].iov_base
= (void *) &monetary
->p_sep_by_space
;
435 iov
[cnt
].iov_len
= 1;
438 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
439 iov
[cnt
].iov_base
= (void *) &monetary
->n_cs_precedes
;
440 iov
[cnt
].iov_len
= 1;
443 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
444 iov
[cnt
].iov_base
= (void *) &monetary
->n_sep_by_space
;
445 iov
[cnt
].iov_len
= 1;
448 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
449 iov
[cnt
].iov_base
= (void *) &monetary
->p_sign_posn
;
450 iov
[cnt
].iov_len
= 1;
453 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
454 iov
[cnt
].iov_base
= (void *) &monetary
->n_sign_posn
;
455 iov
[cnt
].iov_len
= 1;
458 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
459 iov
[cnt
].iov_base
= (void *) monetary
->crncystr
;
460 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
463 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
464 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_cs_precedes
;
465 iov
[cnt
].iov_len
= 1;
468 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
469 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_sep_by_space
;
470 iov
[cnt
].iov_len
= 1;
473 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
474 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_cs_precedes
;
475 iov
[cnt
].iov_len
= 1;
478 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
479 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_sep_by_space
;
480 iov
[cnt
].iov_len
= 1;
483 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
484 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_sign_posn
;
485 iov
[cnt
].iov_len
= 1;
488 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
489 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_sign_posn
;
490 iov
[cnt
].iov_len
= 1;
493 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
494 iov
[cnt
].iov_base
= (void *) monetary
->duo_int_curr_symbol
;
495 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
498 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
499 iov
[cnt
].iov_base
= (void *) monetary
->duo_currency_symbol
;
500 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
503 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
504 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_frac_digits
;
505 iov
[cnt
].iov_len
= 1;
508 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
509 iov
[cnt
].iov_base
= (void *) &monetary
->duo_frac_digits
;
510 iov
[cnt
].iov_len
= 1;
513 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
514 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_cs_precedes
;
515 iov
[cnt
].iov_len
= 1;
518 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
519 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_sep_by_space
;
520 iov
[cnt
].iov_len
= 1;
523 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
524 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_cs_precedes
;
525 iov
[cnt
].iov_len
= 1;
528 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
529 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_sep_by_space
;
530 iov
[cnt
].iov_len
= 1;
533 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
534 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_cs_precedes
;
535 iov
[cnt
].iov_len
= 1;
538 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
539 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_sep_by_space
;
540 iov
[cnt
].iov_len
= 1;
543 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
544 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_cs_precedes
;
545 iov
[cnt
].iov_len
= 1;
548 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
549 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_sep_by_space
;
550 iov
[cnt
].iov_len
= 1;
553 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
554 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_sign_posn
;
555 iov
[cnt
].iov_len
= 1;
558 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
559 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_sign_posn
;
560 iov
[cnt
].iov_len
= 1;
563 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
564 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_sign_posn
;
565 iov
[cnt
].iov_len
= 1;
568 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
569 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_sign_posn
;
570 iov
[cnt
].iov_len
= 1;
573 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
575 /* Align following data */
576 iov
[cnt
].iov_base
= (void *) "\0\0";
577 iov
[cnt
].iov_len
= ((idx
[cnt
- 2] + 3) & ~3) - idx
[cnt
- 2];
578 idx
[cnt
- 2] = (idx
[cnt
- 2] + 3) & ~3;
581 iov
[cnt
].iov_base
= (void *) &monetary
->uno_valid_from
;
582 iov
[cnt
].iov_len
= sizeof(uint32_t);
585 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
586 iov
[cnt
].iov_base
= (void *) &monetary
->uno_valid_to
;
587 iov
[cnt
].iov_len
= sizeof(uint32_t);
590 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
591 iov
[cnt
].iov_base
= (void *) &monetary
->duo_valid_from
;
592 iov
[cnt
].iov_len
= sizeof(uint32_t);
595 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
596 iov
[cnt
].iov_base
= (void *) &monetary
->duo_valid_to
;
597 iov
[cnt
].iov_len
= sizeof(uint32_t);
600 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
601 iov
[cnt
].iov_base
= (void *) monetary
->conversion_rate
;
602 iov
[cnt
].iov_len
= 2 * sizeof(uint32_t);
605 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
606 iov
[cnt
].iov_base
= (void *) &monetary
->mon_decimal_point_wc
;
607 iov
[cnt
].iov_len
= sizeof (uint32_t);
610 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
611 iov
[cnt
].iov_base
= (void *) &monetary
->mon_thousands_sep_wc
;
612 iov
[cnt
].iov_len
= sizeof (uint32_t);
615 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
616 iov
[cnt
].iov_base
= (void *) charmap
->code_set_name
;
617 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
620 assert (cnt
== 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
));
622 write_locale_data (output_path
, LC_MONETARY
, "LC_MONETARY",
623 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
), iov
);
628 curr_strcmp (const char *s1
, const char **s2
)
630 return strcmp (s1
, *s2
);
634 /* The parser for the LC_MONETARY section of the locale definition. */
636 monetary_read (struct linereader
*ldfile
, struct localedef_t
*result
,
637 const struct charmap_t
*charmap
, const char *repertoire_name
,
640 struct repertoire_t
*repertoire
= NULL
;
641 struct locale_monetary_t
*monetary
;
645 /* Get the repertoire we have to use. */
646 if (repertoire_name
!= NULL
)
647 repertoire
= repertoire_read (repertoire_name
);
649 /* The rest of the line containing `LC_MONETARY' must be free. */
650 lr_ignore_rest (ldfile
, 1);
654 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
657 while (nowtok
== tok_eol
);
659 /* If we see `copy' now we are almost done. */
660 if (nowtok
== tok_copy
)
662 handle_copy (ldfile
, charmap
, repertoire_name
, result
, tok_lc_monetary
,
663 LC_MONETARY
, "LC_MONETARY", ignore_content
);
667 /* Prepare the data structures. */
668 monetary_startup (ldfile
, result
, ignore_content
);
669 monetary
= result
->categories
[LC_MONETARY
].monetary
;
673 /* Of course we don't proceed beyond the end of file. */
674 if (nowtok
== tok_eof
)
677 /* Ignore empty lines. */
678 if (nowtok
== tok_eol
)
680 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
687 #define STR_ELEM(cat) \
689 /* Ignore the rest of the line if we don't need the input of \
691 if (ignore_content) \
693 lr_ignore_rest (ldfile, 0); \
697 now = lr_token (ldfile, charmap, result, NULL, verbose); \
698 if (now->tok != tok_string) \
700 else if (monetary->cat != NULL) \
701 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
702 "LC_MONETARY", #cat); \
703 else if (!ignore_content && now->val.str.startmb == NULL) \
705 lr_error (ldfile, _("\
706 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
707 monetary->cat = ""; \
709 else if (!ignore_content) \
710 monetary->cat = now->val.str.startmb; \
711 lr_ignore_rest (ldfile, 1); \
714 STR_ELEM (int_curr_symbol
);
715 STR_ELEM (currency_symbol
);
716 STR_ELEM (positive_sign
);
717 STR_ELEM (negative_sign
);
718 STR_ELEM (duo_int_curr_symbol
);
719 STR_ELEM (duo_currency_symbol
);
721 #define STR_ELEM_WC(cat) \
723 /* Ignore the rest of the line if we don't need the input of \
725 if (ignore_content) \
727 lr_ignore_rest (ldfile, 0); \
731 ldfile->return_widestr = 1; \
732 now = lr_token (ldfile, charmap, result, repertoire, verbose); \
733 if (now->tok != tok_string) \
735 if (monetary->cat != NULL) \
736 lr_error (ldfile, _("\
737 %s: field `%s' declared more than once"), "LC_MONETARY", #cat); \
738 else if (!ignore_content && now->val.str.startmb == NULL) \
740 lr_error (ldfile, _("\
741 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
742 monetary->cat = ""; \
743 monetary->cat##_wc = L'\0'; \
745 else if (now->val.str.startwc != NULL && now->val.str.lenwc > 2) \
747 lr_error (ldfile, _("\
748 %s: value for field `%s' must be a single character"), "LC_MONETARY", #cat); \
750 else if (!ignore_content) \
752 monetary->cat = now->val.str.startmb; \
754 if (now->val.str.startwc != NULL) \
755 monetary->cat##_wc = *now->val.str.startwc; \
757 ldfile->return_widestr = 0; \
760 STR_ELEM_WC (mon_decimal_point
);
761 STR_ELEM_WC (mon_thousands_sep
);
763 #define INT_ELEM(cat) \
765 /* Ignore the rest of the line if we don't need the input of \
767 if (ignore_content) \
769 lr_ignore_rest (ldfile, 0); \
773 now = lr_token (ldfile, charmap, result, NULL, verbose); \
774 if (now->tok != tok_minus1 && now->tok != tok_number) \
776 else if (monetary->cat != -2) \
777 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
778 "LC_MONETARY", #cat); \
779 else if (!ignore_content) \
780 monetary->cat = now->tok == tok_minus1 ? -1 : now->val.num; \
783 INT_ELEM (int_frac_digits
);
784 INT_ELEM (frac_digits
);
785 INT_ELEM (p_cs_precedes
);
786 INT_ELEM (p_sep_by_space
);
787 INT_ELEM (n_cs_precedes
);
788 INT_ELEM (n_sep_by_space
);
789 INT_ELEM (p_sign_posn
);
790 INT_ELEM (n_sign_posn
);
791 INT_ELEM (int_p_cs_precedes
);
792 INT_ELEM (int_p_sep_by_space
);
793 INT_ELEM (int_n_cs_precedes
);
794 INT_ELEM (int_n_sep_by_space
);
795 INT_ELEM (int_p_sign_posn
);
796 INT_ELEM (int_n_sign_posn
);
797 INT_ELEM (duo_int_frac_digits
);
798 INT_ELEM (duo_frac_digits
);
799 INT_ELEM (duo_p_cs_precedes
);
800 INT_ELEM (duo_p_sep_by_space
);
801 INT_ELEM (duo_n_cs_precedes
);
802 INT_ELEM (duo_n_sep_by_space
);
803 INT_ELEM (duo_p_sign_posn
);
804 INT_ELEM (duo_n_sign_posn
);
805 INT_ELEM (duo_int_p_cs_precedes
);
806 INT_ELEM (duo_int_p_sep_by_space
);
807 INT_ELEM (duo_int_n_cs_precedes
);
808 INT_ELEM (duo_int_n_sep_by_space
);
809 INT_ELEM (duo_int_p_sign_posn
);
810 INT_ELEM (duo_int_n_sign_posn
);
811 INT_ELEM (uno_valid_from
);
812 INT_ELEM (uno_valid_to
);
813 INT_ELEM (duo_valid_from
);
814 INT_ELEM (duo_valid_to
);
816 case tok_mon_grouping
:
817 /* Ignore the rest of the line if we don't need the input of
821 lr_ignore_rest (ldfile
, 0);
825 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
826 if (now
->tok
!= tok_minus1
&& now
->tok
!= tok_number
)
832 char *grouping
= ignore_content
? NULL
: xmalloc (max
);
839 grouping
= xrealloc (grouping
, max
);
842 if (act
> 0 && grouping
[act
- 1] == '\177')
844 lr_error (ldfile
, _("\
845 %s: `-1' must be last entry in `%s' field"),
846 "LC_MONETARY", "mon_grouping");
847 lr_ignore_rest (ldfile
, 0);
851 if (now
->tok
== tok_minus1
)
854 grouping
[act
++] = '\177';
856 else if (now
->val
.num
== 0)
858 /* A value of 0 disables grouping from here on but
859 we must not store a NUL character since this
860 terminates the string. Use something different
861 which must not be used otherwise. */
863 grouping
[act
++] = '\377';
865 else if (now
->val
.num
> 126)
866 lr_error (ldfile
, _("\
867 %s: values for field `%s' must be smaller than 127"),
868 "LC_MONETARY", "mon_grouping");
869 else if (!ignore_content
)
870 grouping
[act
++] = now
->val
.num
;
872 /* Next must be semicolon. */
873 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
874 if (now
->tok
!= tok_semicolon
)
877 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
879 while (now
->tok
== tok_minus1
|| now
->tok
== tok_number
);
881 if (now
->tok
!= tok_eol
)
886 grouping
[act
++] = '\0';
888 monetary
->mon_grouping
= xrealloc (grouping
, act
);
889 monetary
->mon_grouping_len
= act
;
894 case tok_conversion_rate
:
895 /* Ignore the rest of the line if we don't need the input of
899 lr_ignore_rest (ldfile
, 0);
903 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
904 if (now
->tok
!= tok_number
)
906 if (now
->val
.num
== 0)
908 invalid_conversion_rate
:
909 lr_error (ldfile
, _("conversion rate value cannot be zero"));
912 monetary
->conversion_rate
[0] = 1;
913 monetary
->conversion_rate
[1] = 1;
918 monetary
->conversion_rate
[0] = now
->val
.num
;
919 /* Next must be a semicolon. */
920 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
921 if (now
->tok
!= tok_semicolon
)
923 /* And another number. */
924 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
925 if (now
->tok
!= tok_number
)
927 if (now
->val
.num
== 0)
928 goto invalid_conversion_rate
;
930 monetary
->conversion_rate
[1] = now
->val
.num
;
931 /* The rest of the line must be empty. */
932 lr_ignore_rest (ldfile
, 1);
936 /* Next we assume `LC_MONETARY'. */
937 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
938 if (now
->tok
== tok_eof
)
940 if (now
->tok
== tok_eol
)
941 lr_error (ldfile
, _("%s: incomplete `END' line"), "LC_MONETARY");
942 else if (now
->tok
!= tok_lc_monetary
)
943 lr_error (ldfile
, _("\
944 %1$s: definition does not end with `END %1$s'"), "LC_MONETARY");
945 lr_ignore_rest (ldfile
, now
->tok
== tok_lc_monetary
);
950 SYNTAX_ERROR (_("%s: syntax error"), "LC_MONETARY");
953 /* Prepare for the next round. */
954 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
958 /* When we come here we reached the end of the file. */
959 lr_error (ldfile
, _("%s: premature end of file"), "LC_MONETARY");