1 /* Copyright (C) 1995-1999,2000,2001,2002,2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
31 #include "localedef.h"
32 #include "linereader.h"
33 #include "localeinfo.h"
37 /* The real definition of the struct for the LC_MONETARY locale. */
38 struct locale_monetary_t
40 const char *int_curr_symbol
;
41 const char *currency_symbol
;
42 const char *mon_decimal_point
;
43 const char *mon_thousands_sep
;
44 uint32_t mon_decimal_point_wc
;
45 uint32_t mon_thousands_sep_wc
;
47 size_t mon_grouping_len
;
48 const char *positive_sign
;
49 const char *negative_sign
;
50 signed char int_frac_digits
;
51 signed char frac_digits
;
52 signed char p_cs_precedes
;
53 signed char p_sep_by_space
;
54 signed char n_cs_precedes
;
55 signed char n_sep_by_space
;
56 signed char p_sign_posn
;
57 signed char n_sign_posn
;
58 signed char int_p_cs_precedes
;
59 signed char int_p_sep_by_space
;
60 signed char int_n_cs_precedes
;
61 signed char int_n_sep_by_space
;
62 signed char int_p_sign_posn
;
63 signed char int_n_sign_posn
;
64 const char *duo_int_curr_symbol
;
65 const char *duo_currency_symbol
;
66 signed char duo_int_frac_digits
;
67 signed char duo_frac_digits
;
68 signed char duo_p_cs_precedes
;
69 signed char duo_p_sep_by_space
;
70 signed char duo_n_cs_precedes
;
71 signed char duo_n_sep_by_space
;
72 signed char duo_p_sign_posn
;
73 signed char duo_n_sign_posn
;
74 signed char duo_int_p_cs_precedes
;
75 signed char duo_int_p_sep_by_space
;
76 signed char duo_int_n_cs_precedes
;
77 signed char duo_int_n_sep_by_space
;
78 signed char duo_int_p_sign_posn
;
79 signed char duo_int_n_sign_posn
;
80 uint32_t uno_valid_from
;
81 uint32_t uno_valid_to
;
82 uint32_t duo_valid_from
;
83 uint32_t duo_valid_to
;
84 uint32_t conversion_rate
[2];
89 /* The content iof the field int_curr_symbol has to be taken from
90 ISO-4217. We test for correct values. */
91 #define DEFINE_INT_CURR(str) str,
92 static const char *const valid_int_curr
[] =
94 # include "../iso-4217.def"
96 #define NR_VALID_INT_CURR ((sizeof (valid_int_curr) \
97 / sizeof (valid_int_curr[0])))
98 #undef DEFINE_INT_CURR
101 /* Prototypes for local functions. */
102 static int curr_strcmp (const char *s1
, const char **s2
);
106 monetary_startup (struct linereader
*lr
, struct localedef_t
*locale
,
111 struct locale_monetary_t
*monetary
;
113 locale
->categories
[LC_MONETARY
].monetary
= monetary
=
114 (struct locale_monetary_t
*) xmalloc (sizeof (*monetary
));
116 memset (monetary
, '\0', sizeof (struct locale_monetary_t
));
118 monetary
->mon_grouping
= NULL
;
119 monetary
->mon_grouping_len
= 0;
121 monetary
->int_frac_digits
= -2;
122 monetary
->frac_digits
= -2;
123 monetary
->p_cs_precedes
= -2;
124 monetary
->p_sep_by_space
= -2;
125 monetary
->n_cs_precedes
= -2;
126 monetary
->n_sep_by_space
= -2;
127 monetary
->p_sign_posn
= -2;
128 monetary
->n_sign_posn
= -2;
129 monetary
->int_p_cs_precedes
= -2;
130 monetary
->int_p_sep_by_space
= -2;
131 monetary
->int_n_cs_precedes
= -2;
132 monetary
->int_n_sep_by_space
= -2;
133 monetary
->int_p_sign_posn
= -2;
134 monetary
->int_n_sign_posn
= -2;
135 monetary
->duo_int_frac_digits
= -2;
136 monetary
->duo_frac_digits
= -2;
137 monetary
->duo_p_cs_precedes
= -2;
138 monetary
->duo_p_sep_by_space
= -2;
139 monetary
->duo_n_cs_precedes
= -2;
140 monetary
->duo_n_sep_by_space
= -2;
141 monetary
->duo_p_sign_posn
= -2;
142 monetary
->duo_n_sign_posn
= -2;
143 monetary
->duo_int_p_cs_precedes
= -2;
144 monetary
->duo_int_p_sep_by_space
= -2;
145 monetary
->duo_int_n_cs_precedes
= -2;
146 monetary
->duo_int_n_sep_by_space
= -2;
147 monetary
->duo_int_p_sign_posn
= -2;
148 monetary
->duo_int_n_sign_posn
= -2;
153 lr
->translate_strings
= 1;
154 lr
->return_widestr
= 0;
160 monetary_finish (struct localedef_t
*locale
, const struct charmap_t
*charmap
)
162 struct locale_monetary_t
*monetary
163 = locale
->categories
[LC_MONETARY
].monetary
;
166 /* Now resolve copying and also handle completely missing definitions. */
167 if (monetary
== NULL
)
169 /* First see whether we were supposed to copy. If yes, find the
170 actual definition. */
171 if (locale
->copy_name
[LC_MONETARY
] != NULL
)
173 /* Find the copying locale. This has to happen transitively since
174 the locale we are copying from might also copying another one. */
175 struct localedef_t
*from
= locale
;
178 from
= find_locale (LC_MONETARY
, from
->copy_name
[LC_MONETARY
],
179 from
->repertoire_name
, charmap
);
180 while (from
->categories
[LC_MONETARY
].monetary
== NULL
181 && from
->copy_name
[LC_MONETARY
] != NULL
);
183 monetary
= locale
->categories
[LC_MONETARY
].monetary
184 = from
->categories
[LC_MONETARY
].monetary
;
187 /* If there is still no definition issue an warning and create an
189 if (monetary
== NULL
)
192 WITH_CUR_LOCALE (error (0, 0, _("\
193 No definition for %s category found"), "LC_MONETARY"));
194 monetary_startup (NULL
, locale
, 0);
195 monetary
= locale
->categories
[LC_MONETARY
].monetary
;
200 #define TEST_ELEM(cat, initval) \
201 if (monetary->cat == NULL) \
203 if (! be_quiet && ! nothing) \
204 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
205 "LC_MONETARY", #cat)); \
206 monetary->cat = initval; \
209 TEST_ELEM (int_curr_symbol
, "");
210 TEST_ELEM (currency_symbol
, "");
211 TEST_ELEM (mon_decimal_point
, ".");
212 TEST_ELEM (mon_thousands_sep
, "");
213 TEST_ELEM (positive_sign
, "");
214 TEST_ELEM (negative_sign
, "");
216 /* The international currency symbol must come from ISO 4217. */
217 if (monetary
->int_curr_symbol
!= NULL
)
219 if (strlen (monetary
->int_curr_symbol
) != 4)
221 if (! be_quiet
&& ! nothing
)
222 WITH_CUR_LOCALE (error (0, 0, _("\
223 %s: value of field `int_curr_symbol' has wrong length"),
227 { /* Check the first three characters against ISO 4217 */
229 strncpy (symbol
, monetary
->int_curr_symbol
, 3);
231 if (bsearch (symbol
, valid_int_curr
, NR_VALID_INT_CURR
,
232 sizeof (const char *),
233 (comparison_fn_t
) curr_strcmp
) == NULL
235 WITH_CUR_LOCALE (error (0, 0, _("\
236 %s: value of field `int_curr_symbol' does \
237 not correspond to a valid name in ISO 4217"),
242 /* The decimal point must not be empty. This is not said explicitly
243 in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
245 if (monetary
->mon_decimal_point
== NULL
)
247 if (! be_quiet
&& ! nothing
)
248 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
249 "LC_MONETARY", "mon_decimal_point"));
250 monetary
->mon_decimal_point
= ".";
252 else if (monetary
->mon_decimal_point
[0] == '\0' && ! be_quiet
&& ! nothing
)
254 WITH_CUR_LOCALE (error (0, 0, _("\
255 %s: value for field `%s' must not be the empty string"),
256 "LC_MONETARY", "mon_decimal_point"));
258 if (monetary
->mon_decimal_point_wc
== L
'\0')
259 monetary
->mon_decimal_point_wc
= L
'.';
261 if (monetary
->mon_grouping_len
== 0)
263 if (! be_quiet
&& ! nothing
)
264 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
265 "LC_MONETARY", "mon_grouping"));
267 monetary
->mon_grouping
= (char *) "\177";
268 monetary
->mon_grouping_len
= 1;
272 #define TEST_ELEM(cat, min, max, initval) \
273 if (monetary->cat == -2) \
275 if (! be_quiet && ! nothing) \
276 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
277 "LC_MONETARY", #cat)); \
278 monetary->cat = initval; \
280 else if ((monetary->cat < min || monetary->cat > max) \
281 && !be_quiet && !nothing) \
282 WITH_CUR_LOCALE (error (0, 0, _("\
283 %s: value for field `%s' must be in range %d...%d"), \
284 "LC_MONETARY", #cat, min, max))
286 TEST_ELEM (int_frac_digits
, -128, 127, -1);
287 TEST_ELEM (frac_digits
, -128, 127, -1);
288 TEST_ELEM (p_cs_precedes
, -1, 1, -1);
289 TEST_ELEM (p_sep_by_space
, -1, 2, -1);
290 TEST_ELEM (n_cs_precedes
, -1, 1, -1);
291 TEST_ELEM (n_sep_by_space
, -1, 2, -1);
292 TEST_ELEM (p_sign_posn
, -1, 4, -1);
293 TEST_ELEM (n_sign_posn
, -1, 4, -1);
295 /* The non-POSIX.2 extensions are optional. */
296 if (monetary
->duo_int_curr_symbol
== NULL
)
297 monetary
->duo_int_curr_symbol
= monetary
->int_curr_symbol
;
298 if (monetary
->duo_currency_symbol
== NULL
)
299 monetary
->duo_currency_symbol
= monetary
->currency_symbol
;
301 if (monetary
->duo_int_frac_digits
== -2)
302 monetary
->duo_int_frac_digits
= monetary
->int_frac_digits
;
303 if (monetary
->duo_frac_digits
== -2)
304 monetary
->duo_frac_digits
= monetary
->frac_digits
;
307 #define TEST_ELEM(cat, alt, min, max) \
308 if (monetary->cat == -2) \
309 monetary->cat = monetary->alt; \
310 else if ((monetary->cat < min || monetary->cat > max) && !be_quiet \
312 WITH_CUR_LOCALE (error (0, 0, _("\
313 %s: value for field `%s' must be in range %d...%d"), \
314 "LC_MONETARY", #cat, min, max))
316 TEST_ELEM (int_p_cs_precedes
, p_cs_precedes
, -1, 1);
317 TEST_ELEM (int_p_sep_by_space
, p_sep_by_space
, -1, 2);
318 TEST_ELEM (int_n_cs_precedes
, n_cs_precedes
, -1, 1);
319 TEST_ELEM (int_n_sep_by_space
, n_sep_by_space
, -1, 2);
320 TEST_ELEM (int_p_sign_posn
, p_sign_posn
, -1, 4);
321 TEST_ELEM (int_n_sign_posn
, n_sign_posn
, -1, 4);
323 TEST_ELEM (duo_p_cs_precedes
, p_cs_precedes
, -1, 1);
324 TEST_ELEM (duo_p_sep_by_space
, p_sep_by_space
, -1, 2);
325 TEST_ELEM (duo_n_cs_precedes
, n_cs_precedes
, -1, 1);
326 TEST_ELEM (duo_n_sep_by_space
, n_sep_by_space
, -1, 2);
327 TEST_ELEM (duo_int_p_cs_precedes
, int_p_cs_precedes
, -1, 1);
328 TEST_ELEM (duo_int_p_sep_by_space
, int_p_sep_by_space
, -1, 2);
329 TEST_ELEM (duo_int_n_cs_precedes
, int_n_cs_precedes
, -1, 1);
330 TEST_ELEM (duo_int_n_sep_by_space
, int_n_sep_by_space
, -1, 2);
331 TEST_ELEM (duo_p_sign_posn
, p_sign_posn
, -1, 4);
332 TEST_ELEM (duo_n_sign_posn
, n_sign_posn
, -1, 4);
333 TEST_ELEM (duo_int_p_sign_posn
, int_p_sign_posn
, -1, 4);
334 TEST_ELEM (duo_int_n_sign_posn
, int_n_sign_posn
, -1, 4);
336 if (monetary
->uno_valid_from
== 0)
337 monetary
->uno_valid_from
= 10101;
338 if (monetary
->uno_valid_to
== 0)
339 monetary
->uno_valid_to
= 99991231;
340 if (monetary
->duo_valid_from
== 0)
341 monetary
->duo_valid_from
= 10101;
342 if (monetary
->duo_valid_to
== 0)
343 monetary
->duo_valid_to
= 99991231;
345 if (monetary
->conversion_rate
[0] == 0)
347 monetary
->conversion_rate
[0] = 1;
348 monetary
->conversion_rate
[1] = 1;
351 /* Create the crncystr entry. */
352 monetary
->crncystr
= (char *) xmalloc (strlen (monetary
->currency_symbol
)
354 monetary
->crncystr
[0] = monetary
->p_cs_precedes
? '-' : '+';
355 strcpy (&monetary
->crncystr
[1], monetary
->currency_symbol
);
360 monetary_output (struct localedef_t
*locale
, const struct charmap_t
*charmap
,
361 const char *output_path
)
363 struct locale_monetary_t
*monetary
364 = locale
->categories
[LC_MONETARY
].monetary
;
365 struct iovec iov
[3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
)];
366 struct locale_file data
;
367 uint32_t idx
[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
)];
370 data
.magic
= LIMAGIC (LC_MONETARY
);
371 data
.n
= _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
);
372 iov
[cnt
].iov_base
= (void *) &data
;
373 iov
[cnt
].iov_len
= sizeof (data
);
376 iov
[cnt
].iov_base
= (void *) idx
;
377 iov
[cnt
].iov_len
= sizeof (idx
);
380 idx
[cnt
- 2] = iov
[0].iov_len
+ iov
[1].iov_len
;
381 iov
[cnt
].iov_base
= (void *) monetary
->int_curr_symbol
;
382 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
385 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
386 iov
[cnt
].iov_base
= (void *) monetary
->currency_symbol
;
387 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
390 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
391 iov
[cnt
].iov_base
= (void *) monetary
->mon_decimal_point
;
392 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
395 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
396 iov
[cnt
].iov_base
= (void *) monetary
->mon_thousands_sep
;
397 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
400 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
401 iov
[cnt
].iov_base
= monetary
->mon_grouping
;
402 iov
[cnt
].iov_len
= monetary
->mon_grouping_len
;
405 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
406 iov
[cnt
].iov_base
= (void *) monetary
->positive_sign
;
407 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
410 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
411 iov
[cnt
].iov_base
= (void *) monetary
->negative_sign
;
412 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
415 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
416 iov
[cnt
].iov_base
= (void *) &monetary
->int_frac_digits
;
417 iov
[cnt
].iov_len
= 1;
420 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
421 iov
[cnt
].iov_base
= (void *) &monetary
->frac_digits
;
422 iov
[cnt
].iov_len
= 1;
425 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
426 iov
[cnt
].iov_base
= (void *) &monetary
->p_cs_precedes
;
427 iov
[cnt
].iov_len
= 1;
430 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
431 iov
[cnt
].iov_base
= (void *) &monetary
->p_sep_by_space
;
432 iov
[cnt
].iov_len
= 1;
435 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
436 iov
[cnt
].iov_base
= (void *) &monetary
->n_cs_precedes
;
437 iov
[cnt
].iov_len
= 1;
440 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
441 iov
[cnt
].iov_base
= (void *) &monetary
->n_sep_by_space
;
442 iov
[cnt
].iov_len
= 1;
445 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
446 iov
[cnt
].iov_base
= (void *) &monetary
->p_sign_posn
;
447 iov
[cnt
].iov_len
= 1;
450 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
451 iov
[cnt
].iov_base
= (void *) &monetary
->n_sign_posn
;
452 iov
[cnt
].iov_len
= 1;
455 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
456 iov
[cnt
].iov_base
= (void *) monetary
->crncystr
;
457 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
460 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
461 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_cs_precedes
;
462 iov
[cnt
].iov_len
= 1;
465 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
466 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_sep_by_space
;
467 iov
[cnt
].iov_len
= 1;
470 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
471 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_cs_precedes
;
472 iov
[cnt
].iov_len
= 1;
475 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
476 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_sep_by_space
;
477 iov
[cnt
].iov_len
= 1;
480 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
481 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_sign_posn
;
482 iov
[cnt
].iov_len
= 1;
485 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
486 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_sign_posn
;
487 iov
[cnt
].iov_len
= 1;
490 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
491 iov
[cnt
].iov_base
= (void *) monetary
->duo_int_curr_symbol
;
492 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
495 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
496 iov
[cnt
].iov_base
= (void *) monetary
->duo_currency_symbol
;
497 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
500 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
501 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_frac_digits
;
502 iov
[cnt
].iov_len
= 1;
505 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
506 iov
[cnt
].iov_base
= (void *) &monetary
->duo_frac_digits
;
507 iov
[cnt
].iov_len
= 1;
510 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
511 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_cs_precedes
;
512 iov
[cnt
].iov_len
= 1;
515 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
516 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_sep_by_space
;
517 iov
[cnt
].iov_len
= 1;
520 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
521 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_cs_precedes
;
522 iov
[cnt
].iov_len
= 1;
525 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
526 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_sep_by_space
;
527 iov
[cnt
].iov_len
= 1;
530 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
531 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_cs_precedes
;
532 iov
[cnt
].iov_len
= 1;
535 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
536 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_sep_by_space
;
537 iov
[cnt
].iov_len
= 1;
540 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
541 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_cs_precedes
;
542 iov
[cnt
].iov_len
= 1;
545 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
546 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_sep_by_space
;
547 iov
[cnt
].iov_len
= 1;
550 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
551 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_sign_posn
;
552 iov
[cnt
].iov_len
= 1;
555 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
556 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_sign_posn
;
557 iov
[cnt
].iov_len
= 1;
560 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
561 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_sign_posn
;
562 iov
[cnt
].iov_len
= 1;
565 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
566 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_sign_posn
;
567 iov
[cnt
].iov_len
= 1;
570 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
572 /* Align following data */
573 iov
[cnt
].iov_base
= (void *) "\0\0";
574 iov
[cnt
].iov_len
= ((idx
[cnt
- 2] + 3) & ~3) - idx
[cnt
- 2];
575 idx
[cnt
- 2] = (idx
[cnt
- 2] + 3) & ~3;
578 iov
[cnt
].iov_base
= (void *) &monetary
->uno_valid_from
;
579 iov
[cnt
].iov_len
= sizeof(uint32_t);
582 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
583 iov
[cnt
].iov_base
= (void *) &monetary
->uno_valid_to
;
584 iov
[cnt
].iov_len
= sizeof(uint32_t);
587 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
588 iov
[cnt
].iov_base
= (void *) &monetary
->duo_valid_from
;
589 iov
[cnt
].iov_len
= sizeof(uint32_t);
592 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
593 iov
[cnt
].iov_base
= (void *) &monetary
->duo_valid_to
;
594 iov
[cnt
].iov_len
= sizeof(uint32_t);
597 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
598 iov
[cnt
].iov_base
= (void *) monetary
->conversion_rate
;
599 iov
[cnt
].iov_len
= 2 * sizeof(uint32_t);
602 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
603 iov
[cnt
].iov_base
= (void *) &monetary
->mon_decimal_point_wc
;
604 iov
[cnt
].iov_len
= sizeof (uint32_t);
607 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
608 iov
[cnt
].iov_base
= (void *) &monetary
->mon_thousands_sep_wc
;
609 iov
[cnt
].iov_len
= sizeof (uint32_t);
612 idx
[cnt
- 3] = idx
[cnt
- 4] + iov
[cnt
- 1].iov_len
;
613 iov
[cnt
].iov_base
= (void *) charmap
->code_set_name
;
614 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
617 assert (cnt
== 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
));
619 write_locale_data (output_path
, LC_MONETARY
, "LC_MONETARY",
620 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
), iov
);
625 curr_strcmp (const char *s1
, const char **s2
)
627 return strcmp (s1
, *s2
);
631 /* The parser for the LC_MONETARY section of the locale definition. */
633 monetary_read (struct linereader
*ldfile
, struct localedef_t
*result
,
634 const struct charmap_t
*charmap
, const char *repertoire_name
,
637 struct repertoire_t
*repertoire
= NULL
;
638 struct locale_monetary_t
*monetary
;
642 /* Get the repertoire we have to use. */
643 if (repertoire_name
!= NULL
)
644 repertoire
= repertoire_read (repertoire_name
);
646 /* The rest of the line containing `LC_MONETARY' must be free. */
647 lr_ignore_rest (ldfile
, 1);
651 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
654 while (nowtok
== tok_eol
);
656 /* If we see `copy' now we are almost done. */
657 if (nowtok
== tok_copy
)
659 handle_copy (ldfile
, charmap
, repertoire_name
, result
, tok_lc_monetary
,
660 LC_MONETARY
, "LC_MONETARY", ignore_content
);
664 /* Prepare the data structures. */
665 monetary_startup (ldfile
, result
, ignore_content
);
666 monetary
= result
->categories
[LC_MONETARY
].monetary
;
670 /* Of course we don't proceed beyond the end of file. */
671 if (nowtok
== tok_eof
)
674 /* Ignore empty lines. */
675 if (nowtok
== tok_eol
)
677 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
684 #define STR_ELEM(cat) \
686 /* Ignore the rest of the line if we don't need the input of \
688 if (ignore_content) \
690 lr_ignore_rest (ldfile, 0); \
694 now = lr_token (ldfile, charmap, result, NULL, verbose); \
695 if (now->tok != tok_string) \
697 else if (monetary->cat != NULL) \
698 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
699 "LC_MONETARY", #cat); \
700 else if (!ignore_content && now->val.str.startmb == NULL) \
702 lr_error (ldfile, _("\
703 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
704 monetary->cat = ""; \
706 else if (!ignore_content) \
707 monetary->cat = now->val.str.startmb; \
708 lr_ignore_rest (ldfile, 1); \
711 STR_ELEM (int_curr_symbol
);
712 STR_ELEM (currency_symbol
);
713 STR_ELEM (positive_sign
);
714 STR_ELEM (negative_sign
);
715 STR_ELEM (duo_int_curr_symbol
);
716 STR_ELEM (duo_currency_symbol
);
718 #define STR_ELEM_WC(cat) \
720 /* Ignore the rest of the line if we don't need the input of \
722 if (ignore_content) \
724 lr_ignore_rest (ldfile, 0); \
728 ldfile->return_widestr = 1; \
729 now = lr_token (ldfile, charmap, result, repertoire, verbose); \
730 if (now->tok != tok_string) \
732 if (monetary->cat != NULL) \
733 lr_error (ldfile, _("\
734 %s: field `%s' declared more than once"), "LC_MONETARY", #cat); \
735 else if (!ignore_content && now->val.str.startmb == NULL) \
737 lr_error (ldfile, _("\
738 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
739 monetary->cat = ""; \
740 monetary->cat##_wc = L'\0'; \
742 else if (now->val.str.startwc != NULL && now->val.str.lenwc > 2) \
744 lr_error (ldfile, _("\
745 %s: value for field `%s' must be a single character"), "LC_MONETARY", #cat); \
747 else if (!ignore_content) \
749 monetary->cat = now->val.str.startmb; \
751 if (now->val.str.startwc != NULL) \
752 monetary->cat##_wc = *now->val.str.startwc; \
754 ldfile->return_widestr = 0; \
757 STR_ELEM_WC (mon_decimal_point
);
758 STR_ELEM_WC (mon_thousands_sep
);
760 #define INT_ELEM(cat) \
762 /* Ignore the rest of the line if we don't need the input of \
764 if (ignore_content) \
766 lr_ignore_rest (ldfile, 0); \
770 now = lr_token (ldfile, charmap, result, NULL, verbose); \
771 if (now->tok != tok_minus1 && now->tok != tok_number) \
773 else if (monetary->cat != -2) \
774 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
775 "LC_MONETARY", #cat); \
776 else if (!ignore_content) \
777 monetary->cat = now->tok == tok_minus1 ? -1 : now->val.num; \
780 INT_ELEM (int_frac_digits
);
781 INT_ELEM (frac_digits
);
782 INT_ELEM (p_cs_precedes
);
783 INT_ELEM (p_sep_by_space
);
784 INT_ELEM (n_cs_precedes
);
785 INT_ELEM (n_sep_by_space
);
786 INT_ELEM (p_sign_posn
);
787 INT_ELEM (n_sign_posn
);
788 INT_ELEM (int_p_cs_precedes
);
789 INT_ELEM (int_p_sep_by_space
);
790 INT_ELEM (int_n_cs_precedes
);
791 INT_ELEM (int_n_sep_by_space
);
792 INT_ELEM (int_p_sign_posn
);
793 INT_ELEM (int_n_sign_posn
);
794 INT_ELEM (duo_int_frac_digits
);
795 INT_ELEM (duo_frac_digits
);
796 INT_ELEM (duo_p_cs_precedes
);
797 INT_ELEM (duo_p_sep_by_space
);
798 INT_ELEM (duo_n_cs_precedes
);
799 INT_ELEM (duo_n_sep_by_space
);
800 INT_ELEM (duo_p_sign_posn
);
801 INT_ELEM (duo_n_sign_posn
);
802 INT_ELEM (duo_int_p_cs_precedes
);
803 INT_ELEM (duo_int_p_sep_by_space
);
804 INT_ELEM (duo_int_n_cs_precedes
);
805 INT_ELEM (duo_int_n_sep_by_space
);
806 INT_ELEM (duo_int_p_sign_posn
);
807 INT_ELEM (duo_int_n_sign_posn
);
808 INT_ELEM (uno_valid_from
);
809 INT_ELEM (uno_valid_to
);
810 INT_ELEM (duo_valid_from
);
811 INT_ELEM (duo_valid_to
);
813 case tok_mon_grouping
:
814 /* Ignore the rest of the line if we don't need the input of
818 lr_ignore_rest (ldfile
, 0);
822 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
823 if (now
->tok
!= tok_minus1
&& now
->tok
!= tok_number
)
829 char *grouping
= ignore_content
? NULL
: xmalloc (max
);
836 grouping
= xrealloc (grouping
, max
);
839 if (act
> 0 && grouping
[act
- 1] == '\177')
841 lr_error (ldfile
, _("\
842 %s: `-1' must be last entry in `%s' field"),
843 "LC_MONETARY", "mon_grouping");
844 lr_ignore_rest (ldfile
, 0);
848 if (now
->tok
== tok_minus1
)
851 grouping
[act
++] = '\177';
853 else if (now
->val
.num
== 0)
855 /* A value of 0 disables grouping from here on but
856 we must not store a NUL character since this
857 terminates the string. Use something different
858 which must not be used otherwise. */
860 grouping
[act
++] = '\377';
862 else if (now
->val
.num
> 126)
863 lr_error (ldfile
, _("\
864 %s: values for field `%s' must be smaller than 127"),
865 "LC_MONETARY", "mon_grouping");
866 else if (!ignore_content
)
867 grouping
[act
++] = now
->val
.num
;
869 /* Next must be semicolon. */
870 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
871 if (now
->tok
!= tok_semicolon
)
874 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
876 while (now
->tok
== tok_minus1
|| now
->tok
== tok_number
);
878 if (now
->tok
!= tok_eol
)
883 grouping
[act
++] = '\0';
885 monetary
->mon_grouping
= xrealloc (grouping
, act
);
886 monetary
->mon_grouping_len
= act
;
891 case tok_conversion_rate
:
892 /* Ignore the rest of the line if we don't need the input of
896 lr_ignore_rest (ldfile
, 0);
900 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
901 if (now
->tok
!= tok_number
)
903 if (now
->val
.num
== 0)
905 invalid_conversion_rate
:
906 lr_error (ldfile
, _("conversion rate value cannot be zero"));
909 monetary
->conversion_rate
[0] = 1;
910 monetary
->conversion_rate
[1] = 1;
915 monetary
->conversion_rate
[0] = now
->val
.num
;
916 /* Next must be a semicolon. */
917 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
918 if (now
->tok
!= tok_semicolon
)
920 /* And another number. */
921 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
922 if (now
->tok
!= tok_number
)
924 if (now
->val
.num
== 0)
925 goto invalid_conversion_rate
;
927 monetary
->conversion_rate
[1] = now
->val
.num
;
928 /* The rest of the line must be empty. */
929 lr_ignore_rest (ldfile
, 1);
933 /* Next we assume `LC_MONETARY'. */
934 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
935 if (now
->tok
== tok_eof
)
937 if (now
->tok
== tok_eol
)
938 lr_error (ldfile
, _("%s: incomplete `END' line"), "LC_MONETARY");
939 else if (now
->tok
!= tok_lc_monetary
)
940 lr_error (ldfile
, _("\
941 %1$s: definition does not end with `END %1$s'"), "LC_MONETARY");
942 lr_ignore_rest (ldfile
, now
->tok
== tok_lc_monetary
);
947 SYNTAX_ERROR (_("%s: syntax error"), "LC_MONETARY");
950 /* Prepare for the next round. */
951 now
= lr_token (ldfile
, charmap
, result
, NULL
, verbose
);
955 /* When we come here we reached the end of the file. */
956 lr_error (ldfile
, _("%s: premature end of file"), "LC_MONETARY");