]>
git.ipfire.org Git - thirdparty/glibc.git/blob - locale/programs/ld-monetary.c
1 /* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
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 not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
33 #include "linereader.h"
34 #include "localedef.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
;
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];
85 uint32_t conversion_rate_ob
[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
, 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
)
191 error (0, 0, _("No definition for %s category found"),
193 monetary_startup (NULL
, locale
, 0);
194 monetary
= locale
->categories
[LC_MONETARY
].monetary
;
199 #define TEST_ELEM(cat) \
200 if (monetary->cat == NULL && !be_quiet) \
203 error (0, 0, _("%s: field `%s' not defined"), \
204 "LC_MONETARY", #cat); \
205 monetary->cat = ""; \
208 TEST_ELEM (int_curr_symbol
);
209 TEST_ELEM (currency_symbol
);
210 TEST_ELEM (mon_decimal_point
);
211 TEST_ELEM (mon_thousands_sep
);
212 TEST_ELEM (positive_sign
);
213 TEST_ELEM (negative_sign
);
215 /* The international currency symbol must come from ISO 4217. */
216 if (monetary
->int_curr_symbol
!= NULL
)
218 if (strlen (monetary
->int_curr_symbol
) != 4)
222 %s: value of field `int_curr_symbol' has wrong length"),
225 else if (bsearch (monetary
->int_curr_symbol
, valid_int_curr
,
226 NR_VALID_INT_CURR
, sizeof (const char *),
227 (comparison_fn_t
) curr_strcmp
) == NULL
230 %s: value of field `int_curr_symbol' does \
231 not correspond to a valid name in ISO 4217"),
235 /* The decimal point must not be empty. This is not said explicitly
236 in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
238 if (monetary
->mon_decimal_point
[0] == '\0' && ! be_quiet
&& ! nothing
)
241 %s: value for field `%s' must not be the empty string"),
242 "LC_MONETARY", "mon_decimal_point");
245 if (monetary
->mon_grouping_len
== 0 && ! be_quiet
&& ! nothing
)
246 error (0, 0, _("%s: field `%s' not defined"),
247 "LC_MONETARY", "mon_grouping");
250 #define TEST_ELEM(cat, min, max) \
251 if (monetary->cat == -2 && ! be_quiet && ! nothing) \
252 error (0, 0, _("%s: field `%s' not defined"), \
253 "LC_MONETARY", #cat); \
254 else if ((monetary->cat < min || monetary->cat > max) && !be_quiet) \
256 %s: value for field `%s' must be in range %d...%d"), \
257 "LC_MONETARY", #cat, min, max)
260 /* The following two test are not really necessary because all values
261 the variable could have are valid. */
262 TEST_ELEM (int_frac_digits
, -128, 127); /* No range check. */
263 TEST_ELEM (frac_digits
, -128, 127); /* No range check. */
265 TEST_ELEM (p_cs_precedes
, -1, 1);
266 TEST_ELEM (p_sep_by_space
, -1, 2);
267 TEST_ELEM (n_cs_precedes
, -1, 1);
268 TEST_ELEM (n_sep_by_space
, -1, 2);
269 TEST_ELEM (p_sign_posn
, -1, 4);
270 TEST_ELEM (n_sign_posn
, -1, 4);
272 /* The non-POSIX.2 extensions are optional. */
273 if (monetary
->duo_int_curr_symbol
== NULL
)
274 monetary
->duo_int_curr_symbol
= monetary
->int_curr_symbol
;
275 if (monetary
->duo_currency_symbol
== NULL
)
276 monetary
->duo_currency_symbol
= monetary
->currency_symbol
;
278 if (monetary
->duo_int_frac_digits
== -2)
279 monetary
->duo_int_frac_digits
= monetary
->int_frac_digits
;
280 if (monetary
->duo_frac_digits
== -2)
281 monetary
->duo_frac_digits
= monetary
->frac_digits
;
284 #define TEST_ELEM(cat, alt, min, max) \
285 if (monetary->cat == -2) \
286 monetary->cat = monetary->alt; \
287 else if ((monetary->cat < min || monetary->cat > max) && !be_quiet \
290 %s: value for field `%s' must be in range %d...%d"), \
291 "LC_MONETARY", #cat, min, max)
293 TEST_ELEM (int_p_cs_precedes
, p_cs_precedes
, -1, 1);
294 TEST_ELEM (int_p_sep_by_space
, p_sep_by_space
, -1, 2);
295 TEST_ELEM (int_n_cs_precedes
, n_cs_precedes
, -1, 1);
296 TEST_ELEM (int_n_sep_by_space
, n_sep_by_space
, -1, 2);
297 TEST_ELEM (int_p_sign_posn
, p_sign_posn
, -1, 4);
298 TEST_ELEM (int_n_sign_posn
, n_sign_posn
, -1, 4);
300 TEST_ELEM (duo_p_cs_precedes
, p_cs_precedes
, -1, 1);
301 TEST_ELEM (duo_p_sep_by_space
, p_sep_by_space
, -1, 2);
302 TEST_ELEM (duo_n_cs_precedes
, n_cs_precedes
, -1, 1);
303 TEST_ELEM (duo_n_sep_by_space
, n_sep_by_space
, -1, 2);
304 TEST_ELEM (duo_int_p_cs_precedes
, int_p_cs_precedes
, -1, 1);
305 TEST_ELEM (duo_int_p_sep_by_space
, int_p_sep_by_space
, -1, 2);
306 TEST_ELEM (duo_int_n_cs_precedes
, int_n_cs_precedes
, -1, 1);
307 TEST_ELEM (duo_int_n_sep_by_space
, int_n_sep_by_space
, -1, 2);
308 TEST_ELEM (duo_p_sign_posn
, p_sign_posn
, -1, 4);
309 TEST_ELEM (duo_n_sign_posn
, n_sign_posn
, -1, 4);
310 TEST_ELEM (duo_int_p_sign_posn
, int_p_sign_posn
, -1, 4);
311 TEST_ELEM (duo_int_n_sign_posn
, int_n_sign_posn
, -1, 4);
313 if (monetary
->uno_valid_from
== 0)
314 monetary
->uno_valid_from
= 10101;
315 if (monetary
->uno_valid_to
== 0)
316 monetary
->uno_valid_to
= 99991231;
317 if (monetary
->duo_valid_from
== 0)
318 monetary
->duo_valid_from
= 10101;
319 if (monetary
->duo_valid_to
== 0)
320 monetary
->duo_valid_to
= 99991231;
322 if (monetary
->conversion_rate
[0] == 0)
324 monetary
->conversion_rate
[0] = 1;
325 monetary
->conversion_rate
[1] = 1;
328 monetary
->conversion_rate_ob
[0] = bswap_32 (monetary
->conversion_rate
[0]);
329 monetary
->conversion_rate_ob
[1] = bswap_32 (monetary
->conversion_rate
[1]);
334 monetary_output (struct localedef_t
*locale
, struct charmap_t
*charmap
,
335 const char *output_path
)
337 struct locale_monetary_t
*monetary
338 = locale
->categories
[LC_MONETARY
].monetary
;
339 struct iovec iov
[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
)];
340 struct locale_file data
;
341 uint32_t idx
[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
)];
344 data
.magic
= LIMAGIC (LC_MONETARY
);
345 data
.n
= _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
);
346 iov
[cnt
].iov_base
= (void *) &data
;
347 iov
[cnt
].iov_len
= sizeof (data
);
350 iov
[cnt
].iov_base
= (void *) idx
;
351 iov
[cnt
].iov_len
= sizeof (idx
);
354 idx
[cnt
- 2] = iov
[0].iov_len
+ iov
[1].iov_len
;
355 iov
[cnt
].iov_base
= (void *) monetary
->int_curr_symbol
;
356 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
359 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
360 iov
[cnt
].iov_base
= (void *) monetary
->currency_symbol
;
361 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
364 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
365 iov
[cnt
].iov_base
= (void *) monetary
->mon_decimal_point
;
366 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
369 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
370 iov
[cnt
].iov_base
= (void *) monetary
->mon_thousands_sep
;
371 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
374 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
375 iov
[cnt
].iov_base
= monetary
->mon_grouping
;
376 iov
[cnt
].iov_len
= monetary
->mon_grouping_len
;
379 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
380 iov
[cnt
].iov_base
= (void *) monetary
->positive_sign
;
381 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
384 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
385 iov
[cnt
].iov_base
= (void *) monetary
->negative_sign
;
386 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
389 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
390 iov
[cnt
].iov_base
= (void *) &monetary
->int_frac_digits
;
391 iov
[cnt
].iov_len
= 1;
394 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
395 iov
[cnt
].iov_base
= (void *) &monetary
->frac_digits
;
396 iov
[cnt
].iov_len
= 1;
399 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
400 iov
[cnt
].iov_base
= (void *) &monetary
->p_cs_precedes
;
401 iov
[cnt
].iov_len
= 1;
404 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
405 iov
[cnt
].iov_base
= (void *) &monetary
->p_sep_by_space
;
406 iov
[cnt
].iov_len
= 1;
409 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
410 iov
[cnt
].iov_base
= (void *) &monetary
->n_cs_precedes
;
411 iov
[cnt
].iov_len
= 1;
414 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
415 iov
[cnt
].iov_base
= (void *) &monetary
->n_sep_by_space
;
416 iov
[cnt
].iov_len
= 1;
419 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
420 iov
[cnt
].iov_base
= (void *) &monetary
->p_sign_posn
;
421 iov
[cnt
].iov_len
= 1;
424 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
425 iov
[cnt
].iov_base
= (void *) &monetary
->n_sign_posn
;
426 iov
[cnt
].iov_len
= 1;
429 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
430 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_cs_precedes
;
431 iov
[cnt
].iov_len
= 1;
434 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
435 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_sep_by_space
;
436 iov
[cnt
].iov_len
= 1;
439 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
440 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_cs_precedes
;
441 iov
[cnt
].iov_len
= 1;
444 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
445 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_sep_by_space
;
446 iov
[cnt
].iov_len
= 1;
449 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
450 iov
[cnt
].iov_base
= (void *) &monetary
->int_p_sign_posn
;
451 iov
[cnt
].iov_len
= 1;
454 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
455 iov
[cnt
].iov_base
= (void *) &monetary
->int_n_sign_posn
;
456 iov
[cnt
].iov_len
= 1;
459 idx
[cnt
- 2] = iov
[0].iov_len
+ iov
[1].iov_len
;
460 iov
[cnt
].iov_base
= (void *) monetary
->duo_int_curr_symbol
;
461 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
464 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
465 iov
[cnt
].iov_base
= (void *) monetary
->duo_currency_symbol
;
466 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
469 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
470 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_frac_digits
;
471 iov
[cnt
].iov_len
= 1;
474 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
475 iov
[cnt
].iov_base
= (void *) &monetary
->duo_frac_digits
;
476 iov
[cnt
].iov_len
= 1;
479 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
480 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_cs_precedes
;
481 iov
[cnt
].iov_len
= 1;
484 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
485 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_sep_by_space
;
486 iov
[cnt
].iov_len
= 1;
489 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
490 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_cs_precedes
;
491 iov
[cnt
].iov_len
= 1;
494 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
495 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_sep_by_space
;
496 iov
[cnt
].iov_len
= 1;
499 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
500 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_cs_precedes
;
501 iov
[cnt
].iov_len
= 1;
504 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
505 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_sep_by_space
;
506 iov
[cnt
].iov_len
= 1;
509 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
510 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_cs_precedes
;
511 iov
[cnt
].iov_len
= 1;
514 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
515 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_sep_by_space
;
516 iov
[cnt
].iov_len
= 1;
519 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
520 iov
[cnt
].iov_base
= (void *) &monetary
->duo_p_sign_posn
;
521 iov
[cnt
].iov_len
= 1;
524 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
525 iov
[cnt
].iov_base
= (void *) &monetary
->duo_n_sign_posn
;
526 iov
[cnt
].iov_len
= 1;
529 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
530 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_p_sign_posn
;
531 iov
[cnt
].iov_len
= 1;
534 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
535 iov
[cnt
].iov_base
= (void *) &monetary
->duo_int_n_sign_posn
;
536 iov
[cnt
].iov_len
= 1;
539 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
540 iov
[cnt
].iov_base
= (void *) &monetary
->uno_valid_from
;
541 iov
[cnt
].iov_len
= 4;
544 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
545 iov
[cnt
].iov_base
= (void *) &monetary
->uno_valid_to
;
546 iov
[cnt
].iov_len
= 4;
549 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
550 iov
[cnt
].iov_base
= (void *) &monetary
->duo_valid_from
;
551 iov
[cnt
].iov_len
= 4;
554 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
555 iov
[cnt
].iov_base
= (void *) &monetary
->duo_valid_to
;
556 iov
[cnt
].iov_len
= 4;
559 #if BYTE_ORDER == LITTLE_ENDIAN
560 # define conversion_rate_el conversion_rate
561 # define conversion_rate_eb conversion_rate_ob
563 # define conversion_rate_el conversion_rate_ob
564 # define conversion_rate_eb conversion_rate
567 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
568 iov
[cnt
].iov_base
= (void *) &monetary
->conversion_rate_el
;
569 iov
[cnt
].iov_len
= 8;
572 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
573 iov
[cnt
].iov_base
= (void *) &monetary
->conversion_rate_eb
;
574 iov
[cnt
].iov_len
= 8;
577 assert (cnt
== 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
));
579 write_locale_data (output_path
, "LC_MONETARY",
580 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY
), iov
);
585 curr_strcmp (const char *s1
, const char **s2
)
587 return strcmp (s1
, *s2
);
591 /* The parser for the LC_MONETARY section of the locale definition. */
593 monetary_read (struct linereader
*ldfile
, struct localedef_t
*result
,
594 struct charmap_t
*charmap
, const char *repertoire_name
,
597 struct repertoire_t
*repertoire
= NULL
;
598 struct locale_monetary_t
*monetary
;
602 /* Get the repertoire we have to use. */
603 if (repertoire_name
!= NULL
)
604 repertoire
= repertoire_read (repertoire_name
);
606 /* The rest of the line containing `LC_MONETARY' must be free. */
607 lr_ignore_rest (ldfile
, 1);
611 now
= lr_token (ldfile
, charmap
, NULL
);
614 while (nowtok
== tok_eol
);
616 /* If we see `copy' now we are almost done. */
617 if (nowtok
== tok_copy
)
619 handle_copy (ldfile
, charmap
, repertoire
, result
, tok_lc_monetary
,
620 LC_MONETARY
, "LC_MONETARY", ignore_content
);
624 /* Prepare the data structures. */
625 monetary_startup (ldfile
, result
, ignore_content
);
626 monetary
= result
->categories
[LC_MONETARY
].monetary
;
630 /* Of course we don't proceed beyond the end of file. */
631 if (nowtok
== tok_eof
)
634 /* Ingore empty lines. */
635 if (nowtok
== tok_eol
)
637 now
= lr_token (ldfile
, charmap
, NULL
);
644 #define STR_ELEM(cat) \
646 /* Ignore the rest of the line if we don't need the input of \
648 if (ignore_content) \
650 lr_ignore_rest (ldfile, 0); \
654 now = lr_token (ldfile, charmap, NULL); \
655 if (now->tok != tok_string) \
657 else if (monetary->cat != NULL) \
658 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
659 "LC_MONETARY", #cat); \
660 else if (!ignore_content && now->val.str.startmb == NULL) \
662 lr_error (ldfile, _("\
663 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
664 monetary->cat = ""; \
666 else if (!ignore_content) \
667 monetary->cat = now->val.str.startmb; \
668 lr_ignore_rest (ldfile, 1); \
671 STR_ELEM (int_curr_symbol
);
672 STR_ELEM (currency_symbol
);
673 STR_ELEM (mon_decimal_point
);
674 STR_ELEM (mon_thousands_sep
);
675 STR_ELEM (positive_sign
);
676 STR_ELEM (negative_sign
);
677 STR_ELEM (duo_int_curr_symbol
);
678 STR_ELEM (duo_currency_symbol
);
680 #define INT_ELEM(cat) \
682 /* Ignore the rest of the line if we don't need the input of \
684 if (ignore_content) \
686 lr_ignore_rest (ldfile, 0); \
690 now = lr_token (ldfile, charmap, NULL); \
691 if (now->tok != tok_minus1 && now->tok != tok_number) \
693 else if (monetary->cat != -2) \
694 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
695 "LC_MONETARY", #cat); \
696 else if (!ignore_content) \
697 monetary->cat = now->tok == tok_minus1 ? -1 : now->val.num; \
700 INT_ELEM (int_frac_digits
);
701 INT_ELEM (frac_digits
);
702 INT_ELEM (p_cs_precedes
);
703 INT_ELEM (p_sep_by_space
);
704 INT_ELEM (n_cs_precedes
);
705 INT_ELEM (n_sep_by_space
);
706 INT_ELEM (p_sign_posn
);
707 INT_ELEM (n_sign_posn
);
708 INT_ELEM (int_p_cs_precedes
);
709 INT_ELEM (int_p_sep_by_space
);
710 INT_ELEM (int_n_cs_precedes
);
711 INT_ELEM (int_n_sep_by_space
);
712 INT_ELEM (int_p_sign_posn
);
713 INT_ELEM (int_n_sign_posn
);
714 INT_ELEM (duo_int_frac_digits
);
715 INT_ELEM (duo_frac_digits
);
716 INT_ELEM (duo_p_cs_precedes
);
717 INT_ELEM (duo_p_sep_by_space
);
718 INT_ELEM (duo_n_cs_precedes
);
719 INT_ELEM (duo_n_sep_by_space
);
720 INT_ELEM (duo_p_sign_posn
);
721 INT_ELEM (duo_n_sign_posn
);
722 INT_ELEM (duo_int_p_cs_precedes
);
723 INT_ELEM (duo_int_p_sep_by_space
);
724 INT_ELEM (duo_int_n_cs_precedes
);
725 INT_ELEM (duo_int_n_sep_by_space
);
726 INT_ELEM (duo_int_p_sign_posn
);
727 INT_ELEM (duo_int_n_sign_posn
);
728 INT_ELEM (uno_valid_from
);
729 INT_ELEM (uno_valid_to
);
730 INT_ELEM (duo_valid_from
);
731 INT_ELEM (duo_valid_to
);
733 case tok_mon_grouping
:
734 /* Ignore the rest of the line if we don't need the input of
738 lr_ignore_rest (ldfile
, 0);
742 now
= lr_token (ldfile
, charmap
, NULL
);
743 if (now
->tok
!= tok_minus1
&& now
->tok
!= tok_number
)
749 char *grouping
= ignore_content
? NULL
: xmalloc (max
);
756 grouping
= xrealloc (grouping
, max
);
759 if (act
> 0 && grouping
[act
- 1] == '\177')
761 lr_error (ldfile
, _("\
762 %s: `-1' must be last entry in `%s' field"),
763 "LC_MONETARY", "mon_grouping");
764 lr_ignore_rest (ldfile
, 0);
768 if (now
->tok
== tok_minus1
)
771 grouping
[act
++] = '\177';
773 else if (now
->val
.num
== 0)
775 /* A value of 0 disables grouping from here on but
776 we must not store a NUL character since this
777 terminates the string. Use something different
778 which must not be used otherwise. */
780 grouping
[act
++] = '\377';
782 else if (now
->val
.num
> 126)
783 lr_error (ldfile
, _("\
784 %s: values for field `%s' must be smaller than 127"),
785 "LC_MONETARY", "mon_grouping");
786 else if (!ignore_content
)
787 grouping
[act
++] = now
->val
.num
;
789 /* Next must be semicolon. */
790 now
= lr_token (ldfile
, charmap
, NULL
);
791 if (now
->tok
!= tok_semicolon
)
794 now
= lr_token (ldfile
, charmap
, NULL
);
796 while (now
->tok
== tok_minus1
|| now
->tok
== tok_number
);
798 if (now
->tok
!= tok_eol
)
803 grouping
[act
++] = '\0';
805 monetary
->mon_grouping
= xrealloc (grouping
, act
);
806 monetary
->mon_grouping_len
= act
;
811 case tok_conversion_rate
:
812 /* Ignore the rest of the line if we don't need the input of
816 lr_ignore_rest (ldfile
, 0);
820 now
= lr_token (ldfile
, charmap
, NULL
);
821 if (now
->tok
!= tok_number
)
823 if (now
->val
.num
== 0)
825 invalid_conversion_rate
:
826 lr_error (ldfile
, _("conversion rate valze cannot be zero"));
829 monetary
->conversion_rate
[0] = 1;
830 monetary
->conversion_rate
[1] = 1;
835 monetary
->conversion_rate
[0] = now
->val
.num
;
836 /* Next must be a semicolon. */
837 now
= lr_token (ldfile
, charmap
, NULL
);
838 if (now
->tok
!= tok_semicolon
)
840 /* And another number. */
841 now
= lr_token (ldfile
, charmap
, NULL
);
842 if (now
->tok
!= tok_number
)
844 if (now
->val
.num
== 0)
845 goto invalid_conversion_rate
;
847 monetary
->conversion_rate
[1] = now
->val
.num
;
848 /* The rest of the line must be empty. */
849 lr_ignore_rest (ldfile
, 1);
853 /* Next we assume `LC_MONETARY'. */
854 now
= lr_token (ldfile
, charmap
, NULL
);
855 if (now
->tok
== tok_eof
)
857 if (now
->tok
== tok_eol
)
858 lr_error (ldfile
, _("%s: incomplete `END' line"), "LC_MONETARY");
859 else if (now
->tok
!= tok_lc_monetary
)
860 lr_error (ldfile
, _("\
861 %1$s: definition does not end with `END %1$s'"), "LC_MONETARY");
862 lr_ignore_rest (ldfile
, now
->tok
== tok_lc_monetary
);
867 SYNTAX_ERROR (_("%s: syntax error"), "LC_MONETARY");
870 /* Prepare for the next round. */
871 now
= lr_token (ldfile
, charmap
, NULL
);
875 /* When we come here we reached the end of the file. */
876 lr_error (ldfile
, _("%s: premature end of file"), "LC_MONETARY");