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 locale_file file;
370 init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
371 add_locale_string (&file, monetary->int_curr_symbol);
372 add_locale_string (&file, monetary->currency_symbol);
373 add_locale_string (&file, monetary->mon_decimal_point);
374 add_locale_string (&file, monetary->mon_thousands_sep);
375 add_locale_raw_data (&file, monetary->mon_grouping,
376 monetary->mon_grouping_len);
377 add_locale_string (&file, monetary->positive_sign);
378 add_locale_string (&file, monetary->negative_sign);
379 add_locale_char (&file, monetary->int_frac_digits);
380 add_locale_char (&file, monetary->frac_digits);
381 add_locale_char (&file, monetary->p_cs_precedes);
382 add_locale_char (&file, monetary->p_sep_by_space);
383 add_locale_char (&file, monetary->n_cs_precedes);
384 add_locale_char (&file, monetary->n_sep_by_space);
385 add_locale_char (&file, monetary->p_sign_posn);
386 add_locale_char (&file, monetary->n_sign_posn);
387 add_locale_string (&file, monetary->crncystr);
388 add_locale_char (&file, monetary->int_p_cs_precedes);
389 add_locale_char (&file, monetary->int_p_sep_by_space);
390 add_locale_char (&file, monetary->int_n_cs_precedes);
391 add_locale_char (&file, monetary->int_n_sep_by_space);
392 add_locale_char (&file, monetary->int_p_sign_posn);
393 add_locale_char (&file, monetary->int_n_sign_posn);
394 add_locale_string (&file, monetary->duo_int_curr_symbol);
395 add_locale_string (&file, monetary->duo_currency_symbol);
396 add_locale_char (&file, monetary->duo_int_frac_digits);
397 add_locale_char (&file, monetary->duo_frac_digits);
398 add_locale_char (&file, monetary->duo_p_cs_precedes);
399 add_locale_char (&file, monetary->duo_p_sep_by_space);
400 add_locale_char (&file, monetary->duo_n_cs_precedes);
401 add_locale_char (&file, monetary->duo_n_sep_by_space);
402 add_locale_char (&file, monetary->duo_int_p_cs_precedes);
403 add_locale_char (&file, monetary->duo_int_p_sep_by_space);
404 add_locale_char (&file, monetary->duo_int_n_cs_precedes);
405 add_locale_char (&file, monetary->duo_int_n_sep_by_space);
406 add_locale_char (&file, monetary->duo_p_sign_posn);
407 add_locale_char (&file, monetary->duo_n_sign_posn);
408 add_locale_char (&file, monetary->duo_int_p_sign_posn);
409 add_locale_char (&file, monetary->duo_int_n_sign_posn);
410 add_locale_uint32 (&file, monetary->uno_valid_from);
411 add_locale_uint32 (&file, monetary->uno_valid_to);
412 add_locale_uint32 (&file, monetary->duo_valid_from);
413 add_locale_uint32 (&file, monetary->duo_valid_to);
414 add_locale_uint32_array (&file, monetary->conversion_rate, 2);
415 add_locale_uint32 (&file, monetary->mon_decimal_point_wc);
416 add_locale_uint32 (&file, monetary->mon_thousands_sep_wc);
417 add_locale_string (&file, charmap->code_set_name);
418 write_locale_data (output_path, LC_MONETARY, "LC_MONETARY", &file);
423 curr_strcmp (const char *s1, const char **s2)
425 return strcmp (s1, *s2);
429 /* The parser for the LC_MONETARY section of the locale definition. */
431 monetary_read (struct linereader *ldfile, struct localedef_t *result,
432 const struct charmap_t *charmap, const char *repertoire_name,
435 struct repertoire_t *repertoire = NULL;
436 struct locale_monetary_t *monetary;
440 /* Get the repertoire we have to use. */
441 if (repertoire_name != NULL)
442 repertoire = repertoire_read (repertoire_name);
444 /* The rest of the line containing `LC_MONETARY' must be free. */
445 lr_ignore_rest (ldfile, 1);
449 now = lr_token (ldfile, charmap, result, NULL, verbose);
452 while (nowtok == tok_eol);
454 /* If we see `copy' now we are almost done. */
455 if (nowtok == tok_copy)
457 handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_monetary,
458 LC_MONETARY, "LC_MONETARY", ignore_content);
462 /* Prepare the data structures. */
463 monetary_startup (ldfile, result, ignore_content);
464 monetary = result->categories[LC_MONETARY].monetary;
468 /* Of course we don't proceed beyond the end of file. */
469 if (nowtok == tok_eof)
472 /* Ignore empty lines. */
473 if (nowtok == tok_eol)
475 now = lr_token (ldfile, charmap, result, NULL, verbose);
482 #define STR_ELEM(cat) \
484 /* Ignore the rest of the line if we don't need the input of \
486 if (ignore_content) \
488 lr_ignore_rest (ldfile, 0); \
492 now = lr_token (ldfile, charmap, result, NULL, verbose); \
493 if (now->tok != tok_string) \
495 else if (monetary->cat != NULL) \
496 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
497 "LC_MONETARY", #cat); \
498 else if (!ignore_content && now->val.str.startmb == NULL) \
500 lr_error (ldfile, _("\
501 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
502 monetary->cat = ""; \
504 else if (!ignore_content) \
505 monetary->cat = now->val.str.startmb; \
506 lr_ignore_rest (ldfile, 1); \
509 STR_ELEM (int_curr_symbol);
510 STR_ELEM (currency_symbol);
511 STR_ELEM (positive_sign);
512 STR_ELEM (negative_sign);
513 STR_ELEM (duo_int_curr_symbol);
514 STR_ELEM (duo_currency_symbol);
516 #define STR_ELEM_WC(cat) \
518 /* Ignore the rest of the line if we don't need the input of \
520 if (ignore_content) \
522 lr_ignore_rest (ldfile, 0); \
526 ldfile->return_widestr = 1; \
527 now = lr_token (ldfile, charmap, result, repertoire, verbose); \
528 if (now->tok != tok_string) \
530 if (monetary->cat != NULL) \
531 lr_error (ldfile, _("\
532 %s: field `%s' declared more than once"), "LC_MONETARY", #cat); \
533 else if (!ignore_content && now->val.str.startmb == NULL) \
535 lr_error (ldfile, _("\
536 %s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
537 monetary->cat = ""; \
538 monetary->cat##_wc = L'\0'; \
540 else if (now->val.str.startwc != NULL && now->val.str.lenwc > 2) \
542 lr_error (ldfile, _("\
543 %s: value for field `%s' must be a single character"), "LC_MONETARY", #cat); \
545 else if (!ignore_content) \
547 monetary->cat = now->val.str.startmb; \
549 if (now->val.str.startwc != NULL) \
550 monetary->cat##_wc = *now->val.str.startwc; \
552 ldfile->return_widestr = 0; \
555 STR_ELEM_WC (mon_decimal_point);
556 STR_ELEM_WC (mon_thousands_sep);
558 #define INT_ELEM(cat) \
560 /* Ignore the rest of the line if we don't need the input of \
562 if (ignore_content) \
564 lr_ignore_rest (ldfile, 0); \
568 now = lr_token (ldfile, charmap, result, NULL, verbose); \
569 if (now->tok != tok_minus1 && now->tok != tok_number) \
571 else if (monetary->cat != -2) \
572 lr_error (ldfile, _("%s: field `%s' declared more than once"), \
573 "LC_MONETARY", #cat); \
574 else if (!ignore_content) \
575 monetary->cat = now->tok == tok_minus1 ? -1 : now->val.num; \
578 INT_ELEM (int_frac_digits);
579 INT_ELEM (frac_digits);
580 INT_ELEM (p_cs_precedes);
581 INT_ELEM (p_sep_by_space);
582 INT_ELEM (n_cs_precedes);
583 INT_ELEM (n_sep_by_space);
584 INT_ELEM (p_sign_posn);
585 INT_ELEM (n_sign_posn);
586 INT_ELEM (int_p_cs_precedes);
587 INT_ELEM (int_p_sep_by_space);
588 INT_ELEM (int_n_cs_precedes);
589 INT_ELEM (int_n_sep_by_space);
590 INT_ELEM (int_p_sign_posn);
591 INT_ELEM (int_n_sign_posn);
592 INT_ELEM (duo_int_frac_digits);
593 INT_ELEM (duo_frac_digits);
594 INT_ELEM (duo_p_cs_precedes);
595 INT_ELEM (duo_p_sep_by_space);
596 INT_ELEM (duo_n_cs_precedes);
597 INT_ELEM (duo_n_sep_by_space);
598 INT_ELEM (duo_p_sign_posn);
599 INT_ELEM (duo_n_sign_posn);
600 INT_ELEM (duo_int_p_cs_precedes);
601 INT_ELEM (duo_int_p_sep_by_space);
602 INT_ELEM (duo_int_n_cs_precedes);
603 INT_ELEM (duo_int_n_sep_by_space);
604 INT_ELEM (duo_int_p_sign_posn);
605 INT_ELEM (duo_int_n_sign_posn);
606 INT_ELEM (uno_valid_from);
607 INT_ELEM (uno_valid_to);
608 INT_ELEM (duo_valid_from);
609 INT_ELEM (duo_valid_to);
611 case tok_mon_grouping:
612 /* Ignore the rest of the line if we don't need the input of
616 lr_ignore_rest (ldfile, 0);
620 now = lr_token (ldfile, charmap, result, NULL, verbose);
621 if (now->tok != tok_minus1 && now->tok != tok_number)
627 char *grouping = ignore_content ? NULL : xmalloc (max);
634 grouping = xrealloc (grouping, max);
637 if (act > 0 && grouping[act - 1] == '\177')
639 lr_error (ldfile, _("\
640 %s: `-1' must be last entry in `%s' field"),
641 "LC_MONETARY", "mon_grouping");
642 lr_ignore_rest (ldfile, 0);
646 if (now->tok == tok_minus1)
649 grouping[act++] = '\177';
651 else if (now->val.num == 0)
653 /* A value of 0 disables grouping from here on but
654 we must not store a NUL character since this
655 terminates the string. Use something different
656 which must not be used otherwise. */
658 grouping[act++] = '\377';
660 else if (now->val.num > 126)
661 lr_error (ldfile, _("\
662 %s: values for field `%s' must be smaller than 127"),
663 "LC_MONETARY", "mon_grouping");
664 else if (!ignore_content)
665 grouping[act++] = now->val.num;
667 /* Next must be semicolon. */
668 now = lr_token (ldfile, charmap, result, NULL, verbose);
669 if (now->tok != tok_semicolon)
672 now = lr_token (ldfile, charmap, result, NULL, verbose);
674 while (now->tok == tok_minus1 || now->tok == tok_number);
676 if (now->tok != tok_eol)
681 grouping[act++] = '\0';
683 monetary->mon_grouping = xrealloc (grouping, act);
684 monetary->mon_grouping_len = act;
689 case tok_conversion_rate:
690 /* Ignore the rest of the line if we don't need the input of
694 lr_ignore_rest (ldfile, 0);
698 now = lr_token (ldfile, charmap, result, NULL, verbose);
699 if (now->tok != tok_number)
701 if (now->val.num == 0)
703 invalid_conversion_rate:
704 lr_error (ldfile, _("conversion rate value cannot be zero"));
707 monetary->conversion_rate[0] = 1;
708 monetary->conversion_rate[1] = 1;
713 monetary->conversion_rate[0] = now->val.num;
714 /* Next must be a semicolon. */
715 now = lr_token (ldfile, charmap, result, NULL, verbose);
716 if (now->tok != tok_semicolon)
718 /* And another number. */
719 now = lr_token (ldfile, charmap, result, NULL, verbose);
720 if (now->tok != tok_number)
722 if (now->val.num == 0)
723 goto invalid_conversion_rate;
725 monetary->conversion_rate[1] = now->val.num;
726 /* The rest of the line must be empty. */
727 lr_ignore_rest (ldfile, 1);
731 /* Next we assume `LC_MONETARY'. */
732 now = lr_token (ldfile, charmap, result, NULL, verbose);
733 if (now->tok == tok_eof)
735 if (now->tok == tok_eol)
736 lr_error (ldfile, _("%s: incomplete `END' line"), "LC_MONETARY");
737 else if (now->tok != tok_lc_monetary)
738 lr_error (ldfile, _("\
739 %1$s: definition does not end with `END %1$s'"), "LC_MONETARY");
740 lr_ignore_rest (ldfile, now->tok == tok_lc_monetary);
745 SYNTAX_ERROR (_("%s: syntax error"), "LC_MONETARY");
748 /* Prepare for the next round. */
749 now = lr_token (ldfile, charmap, result, NULL, verbose);
753 /* When we come here we reached the end of the file. */
754 lr_error (ldfile, _("%s: premature end of file"), "LC_MONETARY");