diff options
Diffstat (limited to 'locale/programs/ld-monetary.c')
-rw-r--r-- | locale/programs/ld-monetary.c | 757 |
1 files changed, 580 insertions, 177 deletions
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c index b903d630aa..61f9f8dc6c 100644 --- a/locale/programs/ld-monetary.c +++ b/locale/programs/ld-monetary.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + Contributed by Ulrich Drepper <drepper@gnu.org>, 1995. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -21,26 +21,22 @@ # include <config.h> #endif +#include <byteswap.h> #include <langinfo.h> #include <limits.h> #include <stdlib.h> #include <string.h> -#include <libintl.h> +#include <sys/uio.h> - -/* Undefine following line in production version. */ -/* #define NDEBUG 1 */ #include <assert.h> -#include "locales.h" +#include "linereader.h" +#include "localedef.h" #include "localeinfo.h" -#include "stringtrans.h" - -extern void *xmalloc (size_t __n); -extern void *xrealloc (void *__ptr, size_t __n); +#include "locfile.h" -/* The real definition of the struct for the LC_NUMERIC locale. */ +/* The real definition of the struct for the LC_MONETARY locale. */ struct locale_monetary_t { const char *int_curr_symbol; @@ -48,8 +44,7 @@ struct locale_monetary_t const char *mon_decimal_point; const char *mon_thousands_sep; char *mon_grouping; - size_t mon_grouping_max; - size_t mon_grouping_act; + size_t mon_grouping_len; const char *positive_sign; const char *negative_sign; signed char int_frac_digits; @@ -60,10 +55,38 @@ struct locale_monetary_t signed char n_sep_by_space; signed char p_sign_posn; signed char n_sign_posn; + signed char int_p_cs_precedes; + signed char int_p_sep_by_space; + signed char int_n_cs_precedes; + signed char int_n_sep_by_space; + signed char int_p_sign_posn; + signed char int_n_sign_posn; + const char *duo_int_curr_symbol; + const char *duo_currency_symbol; + signed char duo_int_frac_digits; + signed char duo_frac_digits; + signed char duo_p_cs_precedes; + signed char duo_p_sep_by_space; + signed char duo_n_cs_precedes; + signed char duo_n_sep_by_space; + signed char duo_p_sign_posn; + signed char duo_n_sign_posn; + signed char duo_int_p_cs_precedes; + signed char duo_int_p_sep_by_space; + signed char duo_int_n_cs_precedes; + signed char duo_int_n_sep_by_space; + signed char duo_int_p_sign_posn; + signed char duo_int_n_sign_posn; + uint32_t uno_valid_from; + uint32_t uno_valid_to; + uint32_t duo_valid_from; + uint32_t duo_valid_to; + uint32_t conversion_rate[2]; + uint32_t conversion_rate_ob[2]; }; -/* The contents of the field int_curr_symbol have to be taken from +/* The content iof the field int_curr_symbol has to be taken from ISO-4217. We test for correct values. */ #define DEFINE_INT_CURR(str) str, static const char *const valid_int_curr[] = @@ -76,52 +99,73 @@ static const char *const valid_int_curr[] = /* Prototypes for local functions. */ -static int curr_strcmp(const char *s1, const char **s2); +static int curr_strcmp (const char *s1, const char **s2); -void +static void monetary_startup (struct linereader *lr, struct localedef_t *locale, - struct charset_t *charset) + int ignore_content) { - struct locale_monetary_t *monetary; - - /* We have a definition for LC_MONETARY. */ - copy_posix.mask &= ~(1 << LC_MONETARY); - - /* It is important that we always use UCS1 encoding for strings now. */ - encoding_method = ENC_UCS1; - - locale->categories[LC_MONETARY].monetary = monetary = - (struct locale_monetary_t *) xmalloc (sizeof (struct locale_monetary_t)); - - memset (monetary, '\0', sizeof (struct locale_monetary_t)); - - monetary->mon_grouping_max = 80; - monetary->mon_grouping = - (char *) xmalloc (monetary->mon_grouping_max); - monetary->mon_grouping_act = 0; + if (!ignore_content) + { + struct locale_monetary_t *monetary; + + locale->categories[LC_MONETARY].monetary = monetary = + (struct locale_monetary_t *) xmalloc (sizeof (*monetary)); + + memset (monetary, '\0', sizeof (struct locale_monetary_t)); + + monetary->mon_grouping = NULL; + monetary->mon_grouping_len = 0; + + monetary->int_frac_digits = -2; + monetary->frac_digits = -2; + monetary->p_cs_precedes = -2; + monetary->p_sep_by_space = -2; + monetary->n_cs_precedes = -2; + monetary->n_sep_by_space = -2; + monetary->p_sign_posn = -2; + monetary->n_sign_posn = -2; + monetary->int_p_cs_precedes = -2; + monetary->int_p_sep_by_space = -2; + monetary->int_n_cs_precedes = -2; + monetary->int_n_sep_by_space = -2; + monetary->int_p_sign_posn = -2; + monetary->int_n_sign_posn = -2; + monetary->duo_int_frac_digits = -2; + monetary->duo_frac_digits = -2; + monetary->duo_p_cs_precedes = -2; + monetary->duo_p_sep_by_space = -2; + monetary->duo_n_cs_precedes = -2; + monetary->duo_n_sep_by_space = -2; + monetary->duo_p_sign_posn = -2; + monetary->duo_n_sign_posn = -2; + monetary->duo_int_p_cs_precedes = -2; + monetary->duo_int_p_sep_by_space = -2; + monetary->duo_int_n_cs_precedes = -2; + monetary->duo_int_n_sep_by_space = -2; + monetary->duo_int_p_sign_posn = -2; + monetary->duo_int_n_sign_posn = -2; + } - monetary->int_frac_digits = -2; - monetary->frac_digits = -2; - monetary->p_cs_precedes = -2; - monetary->p_sep_by_space = -2; - monetary->n_cs_precedes = -2; - monetary->n_sep_by_space = -2; - monetary->p_sign_posn = -2; - monetary->n_sign_posn = -2; + lr->translate_strings = 1; + lr->return_widestr = 0; } void -monetary_finish (struct localedef_t *locale) +monetary_finish (struct localedef_t *locale, struct charmap_t *charmap) { struct locale_monetary_t *monetary = locale->categories[LC_MONETARY].monetary; -#define TEST_ELEM(cat) \ +#define TEST_ELEM(cat) \ if (monetary->cat == NULL && !be_quiet) \ - error (0, 0, _("field `%s' in category `%s' undefined"), \ - #cat, "LC_MONETARY") + { \ + error (0, 0, _("%s: field `%s' not defined"), \ + "LC_MONETARY", #cat); \ + monetary->cat = ""; \ + } TEST_ELEM (int_curr_symbol); TEST_ELEM (currency_symbol); @@ -133,21 +177,21 @@ monetary_finish (struct localedef_t *locale) /* The international currency symbol must come from ISO 4217. */ if (monetary->int_curr_symbol != NULL) { - if (strlen (monetary->int_curr_symbol) != 4 - && monetary->int_curr_symbol[0] != '\0') + if (strlen (monetary->int_curr_symbol) != 4) { if (!be_quiet) error (0, 0, _("\ -value of field `int_curr_symbol' in category `LC_MONETARY' has wrong length")); +%s: value of field `int_curr_symbol' has wrong length"), + "LC_MONETARY"); } - else if (monetary->int_curr_symbol[0] != '\0' - && bsearch (monetary->int_curr_symbol, valid_int_curr, - NR_VALID_INT_CURR, sizeof (const char *), - (comparison_fn_t) curr_strcmp) == NULL + else if (bsearch (monetary->int_curr_symbol, valid_int_curr, + NR_VALID_INT_CURR, sizeof (const char *), + (comparison_fn_t) curr_strcmp) == NULL && !be_quiet) error (0, 0, _("\ -value of field `int_curr_symbol' in category `LC_MONETARY' does \ -not correspond to a valid name in ISO 4217")); +%s: value of field `int_curr_symbol' does \ +not correspond to a valid name in ISO 4217"), + "LC_MONETARY"); } /* The decimal point must not be empty. This is not said explicitly @@ -156,27 +200,27 @@ not correspond to a valid name in ISO 4217")); if (monetary->mon_decimal_point[0] == '\0' && !be_quiet) { error (0, 0, _("\ -value for field `%s' in category `%s' must not be the empty string"), - "mon_decimal_point", "LC_MONETARY"); +%s: value for field `%s' must not be the empty string"), + "LC_MONETARY", "mon_decimal_point"); } - if (monetary->mon_grouping_act == 0 && !be_quiet) - error (0, 0, _("field `%s' in category `%s' undefined"), - "mon_grouping", "LC_MONETARY"); + if (monetary->mon_grouping_len == 0 && !be_quiet) + error (0, 0, _("%s: field `%s' not defined"), + "LC_MONETARY", "mon_grouping"); #undef TEST_ELEM -#define TEST_ELEM(cat, min, max) \ +#define TEST_ELEM(cat, min, max) \ if (monetary->cat == -2 && !be_quiet) \ - error (0, 0, _("field `%s' in category `%s' undefined"), \ - #cat, "LC_MONETARY"); \ + error (0, 0, _("%s: field `%s' not defined"), \ + "LC_MONETARY", #cat); \ else if ((monetary->cat < min || monetary->cat > max) && !be_quiet) \ error (0, 0, _("\ -value for field `%s' in category `%s' must be in range %d...%d"), \ - #cat, "LC_MONETARY", min, max) +%s: value for field `%s' must be in range %d...%d"), \ + "LC_MONETARY", #cat, min, max) #if 0 - /* The following two tests are not really necessary because all values - the variable could have are valid. */ +/* The following two test are not really necessary because all values + the variable could have are valid. */ TEST_ELEM (int_frac_digits, -128, 127); /* No range check. */ TEST_ELEM (frac_digits, -128, 127); /* No range check. */ #endif @@ -186,29 +230,78 @@ value for field `%s' in category `%s' must be in range %d...%d"), \ TEST_ELEM (n_sep_by_space, -1, 2); TEST_ELEM (p_sign_posn, -1, 4); TEST_ELEM (n_sign_posn, -1, 4); + + /* The non-POSIX.2 extensions are optional. */ + if (monetary->duo_int_curr_symbol == NULL) + monetary->duo_int_curr_symbol = monetary->int_curr_symbol; + if (monetary->duo_currency_symbol == NULL) + monetary->duo_currency_symbol = monetary->currency_symbol; + + if (monetary->duo_int_frac_digits == -2) + monetary->duo_int_frac_digits = monetary->int_frac_digits; + if (monetary->duo_frac_digits == -2) + monetary->duo_frac_digits = monetary->frac_digits; + +#undef TEST_ELEM +#define TEST_ELEM(cat, alt, min, max) \ + if (monetary->cat == -2 && !be_quiet) \ + monetary->cat = monetary->alt; \ + else if ((monetary->cat < min || monetary->cat > max) && !be_quiet) \ + error (0, 0, _("\ +%s: value for field `%s' must be in range %d...%d"), \ + "LC_MONETARY", #cat, min, max) + + TEST_ELEM (int_p_cs_precedes, p_cs_precedes, -1, 1); + TEST_ELEM (int_p_sep_by_space, p_sep_by_space, -1, 2); + TEST_ELEM (int_n_cs_precedes, n_cs_precedes, -1, 1); + TEST_ELEM (int_n_sep_by_space, n_sep_by_space, -1, 2); + TEST_ELEM (int_p_sign_posn, p_sign_posn, -1, 4); + TEST_ELEM (int_n_sign_posn, n_sign_posn, -1, 4); + + TEST_ELEM (duo_p_cs_precedes, p_cs_precedes, -1, 1); + TEST_ELEM (duo_p_sep_by_space, p_sep_by_space, -1, 2); + TEST_ELEM (duo_n_cs_precedes, n_cs_precedes, -1, 1); + TEST_ELEM (duo_n_sep_by_space, n_sep_by_space, -1, 2); + TEST_ELEM (duo_int_p_cs_precedes, int_p_cs_precedes, -1, 1); + TEST_ELEM (duo_int_p_sep_by_space, int_p_sep_by_space, -1, 2); + TEST_ELEM (duo_int_n_cs_precedes, int_n_cs_precedes, -1, 1); + TEST_ELEM (duo_int_n_sep_by_space, int_n_sep_by_space, -1, 2); + TEST_ELEM (duo_p_sign_posn, p_sign_posn, -1, 4); + TEST_ELEM (duo_n_sign_posn, n_sign_posn, -1, 4); + TEST_ELEM (duo_int_p_sign_posn, int_p_sign_posn, -1, 4); + TEST_ELEM (duo_int_n_sign_posn, int_n_sign_posn, -1, 4); + + if (monetary->uno_valid_from == 0) + monetary->uno_valid_from = 10101; + if (monetary->uno_valid_to == 0) + monetary->uno_valid_to = 99991231; + if (monetary->duo_valid_from == 0) + monetary->duo_valid_from = 10101; + if (monetary->duo_valid_to == 0) + monetary->duo_valid_to = 99991231; + + if (monetary->conversion_rate[0] == 0) + { + monetary->conversion_rate[0] = 1; + monetary->conversion_rate[1] = 1; + } + + monetary->conversion_rate_ob[0] = bswap_32 (monetary->conversion_rate[0]); + monetary->conversion_rate_ob[1] = bswap_32 (monetary->conversion_rate[1]); } void -monetary_output (struct localedef_t *locale, const char *output_path) +monetary_output (struct localedef_t *locale, struct charmap_t *charmap, + const char *output_path) { struct locale_monetary_t *monetary = locale->categories[LC_MONETARY].monetary; struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)]; struct locale_file data; - u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)]; + uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)]; size_t cnt = 0; - if ((locale->binary & (1 << LC_MONETARY)) != 0) - { - iov[0].iov_base = monetary; - iov[0].iov_len = locale->len[LC_MONETARY]; - - write_locale_data (output_path, "LC_MONETARY", 1, iov); - - return; - } - data.magic = LIMAGIC (LC_MONETARY); data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY); iov[cnt].iov_base = (void *) &data; @@ -220,40 +313,37 @@ monetary_output (struct localedef_t *locale, const char *output_path) ++cnt; idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len; - iov[cnt].iov_base = (void *) (monetary->int_curr_symbol ?: ""); + iov[cnt].iov_base = (void *) monetary->int_curr_symbol; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; ++cnt; idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; - iov[cnt].iov_base = (void *) (monetary->currency_symbol ?: ""); + iov[cnt].iov_base = (void *) monetary->currency_symbol; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; ++cnt; idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; - iov[cnt].iov_base = (void *) (monetary->mon_decimal_point ?: ""); + iov[cnt].iov_base = (void *) monetary->mon_decimal_point; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; ++cnt; idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; - iov[cnt].iov_base = (void *) (monetary->mon_thousands_sep ?: ""); + iov[cnt].iov_base = (void *) monetary->mon_thousands_sep; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; ++cnt; idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; - iov[cnt].iov_base = alloca (monetary->mon_grouping_act + 1); - iov[cnt].iov_len = monetary->mon_grouping_act + 1; - memcpy (iov[cnt].iov_base, monetary->mon_grouping, - monetary->mon_grouping_act); - ((char *) iov[cnt].iov_base)[monetary->mon_grouping_act] = '\0'; + iov[cnt].iov_base = monetary->mon_grouping; + iov[cnt].iov_len = monetary->mon_grouping_len; ++cnt; idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; - iov[cnt].iov_base = (void *) (monetary->positive_sign ?: ""); + iov[cnt].iov_base = (void *) monetary->positive_sign; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; ++cnt; idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; - iov[cnt].iov_base = (void *) (monetary->negative_sign ?: ""); + iov[cnt].iov_base = (void *) monetary->negative_sign; iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; ++cnt; @@ -295,109 +385,422 @@ monetary_output (struct localedef_t *locale, const char *output_path) idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; iov[cnt].iov_base = (void *) &monetary->n_sign_posn; iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->int_p_cs_precedes; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->int_p_sep_by_space; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->int_n_cs_precedes; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->int_n_sep_by_space; + iov[cnt].iov_len = 1; + ++cnt; - assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)); + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->int_p_sign_posn; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->int_n_sign_posn; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len; + iov[cnt].iov_base = (void *) monetary->duo_int_curr_symbol; + iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) monetary->duo_currency_symbol; + iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_frac_digits; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_frac_digits; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_p_cs_precedes; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_p_sep_by_space; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_n_cs_precedes; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_n_sep_by_space; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_p_cs_precedes; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_p_sep_by_space; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_n_cs_precedes; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_n_sep_by_space; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_p_sign_posn; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_n_sign_posn; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_p_sign_posn; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_int_n_sign_posn; + iov[cnt].iov_len = 1; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->uno_valid_from; + iov[cnt].iov_len = 4; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->uno_valid_to; + iov[cnt].iov_len = 4; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_valid_from; + iov[cnt].iov_len = 4; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->duo_valid_to; + iov[cnt].iov_len = 4; + ++cnt; + +#if BYTE_ORDER == LITTLE_ENDIAN +# define conversion_rate_el conversion_rate +# define conversion_rate_eb conversion_rate_ob +#else +# define conversion_rate_el conversion_rate_ob +# define conversion_rate_eb conversion_rate +#endif + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->conversion_rate_el; + iov[cnt].iov_len = 8; + ++cnt; + + idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; + iov[cnt].iov_base = (void *) &monetary->conversion_rate_eb; + iov[cnt].iov_len = 8; + ++cnt; + + assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)); write_locale_data (output_path, "LC_MONETARY", 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY), iov); } +static int +curr_strcmp (const char *s1, const char **s2) +{ + return strcmp (s1, *s2); +} + + +/* The parser for the LC_MONETARY section of the locale definition. */ void -monetary_add (struct linereader *lr, struct localedef_t *locale, - enum token_t tok, struct token *code, - struct charset_t *charset) +monetary_read (struct linereader *ldfile, struct localedef_t *result, + struct charmap_t *charmap, const char *repertoire_name, + int ignore_content) { - struct locale_monetary_t *monetary - = locale->categories[LC_MONETARY].monetary; + struct repertoire_t *repertoire = NULL; + struct locale_monetary_t *monetary; + struct token *now; + enum token_t nowtok; + + /* Get the repertoire we have to use. */ + if (repertoire_name != NULL) + repertoire = repertoire_read (repertoire_name); + + /* The rest of the line containing `LC_MONETARY' must be free. */ + lr_ignore_rest (ldfile, 1); + + do + { + now = lr_token (ldfile, charmap, NULL); + nowtok = now->tok; + } + while (nowtok == tok_eol); + + /* If we see `copy' now we are almost done. */ + if (nowtok == tok_copy) + { + handle_copy (ldfile, charmap, repertoire, tok_lc_monetary, LC_MONETARY, + "LC_MONETARY", ignore_content); + return; + } + + /* Prepare the data structures. */ + monetary_startup (ldfile, result, ignore_content); + monetary = result->categories[LC_MONETARY].monetary; - switch (tok) + while (1) { -#define STR_ELEM(cat) \ - case tok_##cat: \ - if (monetary->cat != NULL) \ - lr_error (lr, _("\ -field `%s' in category `%s' declared more than once"), \ - #cat, "LC_MONETARY"); \ - else if (code->val.str.start == NULL) \ - { \ - lr_error (lr, _("unknown character in field `%s' of category `%s'"),\ - #cat, "LC_MONETARY"); \ - monetary->cat = ""; \ - } \ - else \ - monetary->cat = code->val.str.start; \ - break - - STR_ELEM (int_curr_symbol); - STR_ELEM (currency_symbol); - STR_ELEM (mon_decimal_point); - STR_ELEM (mon_thousands_sep); - STR_ELEM (positive_sign); - STR_ELEM (negative_sign); - -#define INT_ELEM(cat) \ - case tok_##cat: \ - if (monetary->cat != -2) \ - lr_error (lr, _("\ -field `%s' in category `%s' declared more than once"), \ - #cat, "LC_MONETARY"); \ - else if (code->tok == tok_minus1) \ - monetary->cat = -1; \ - else \ - monetary->cat = code->val.num; \ - break - - INT_ELEM (int_frac_digits); - INT_ELEM (frac_digits); - INT_ELEM (p_cs_precedes); - INT_ELEM (p_sep_by_space); - INT_ELEM (n_cs_precedes); - INT_ELEM (n_sep_by_space); - INT_ELEM (p_sign_posn); - INT_ELEM (n_sign_posn); - - case tok_mon_grouping: - if (monetary->mon_grouping_act == monetary->mon_grouping_max) + /* Of course we don't proceed beyond the end of file. */ + if (nowtok == tok_eof) + break; + + /* Ingore empty lines. */ + if (nowtok == tok_eol) { - monetary->mon_grouping_max *= 2; - monetary->mon_grouping = - (char *) xrealloc (monetary->mon_grouping, - monetary->mon_grouping_max); + now = lr_token (ldfile, charmap, NULL); + nowtok = now->tok; + continue; } - if (monetary->mon_grouping[monetary->mon_grouping_act - 1] - == '\177') - lr_error (lr, _("\ -`-1' must be last entry in `%s' field in `%s' category"), - "mon_grouping", "LC_MONETARY"); - else + + switch (nowtok) { - if (code->tok == tok_minus1) - monetary->mon_grouping[monetary->mon_grouping_act++] = '\177'; - else if (code->val.num == 0) - /* A value of 0 disables grouping from here on but we must - not store a NUL character since this terminates the - string. Use something different which must not be used - otherwise. */ - monetary->mon_grouping[monetary->mon_grouping_act++] = '\377'; - else if (code->val.num > 126) - lr_error (lr, _("\ -values for field `%s' in category `%s' must be smaller than 127"), - "mon_grouping", "LC_MONETARY"); +#define STR_ELEM(cat) \ + case tok_##cat: \ + now = lr_token (ldfile, charmap, NULL); \ + if (now->tok != tok_string) \ + goto err_label; \ + else if (monetary->cat != NULL) \ + lr_error (ldfile, _("%s: field `%s' declared more than once"), \ + "LC_MONETARY", #cat); \ + else if (!ignore_content && now->val.str.startmb == NULL) \ + { \ + lr_error (ldfile, _("\ +%s: unknown character in field `%s'"), "LC_MONETARY", #cat); \ + monetary->cat = ""; \ + } \ + else if (!ignore_content) \ + monetary->cat = now->val.str.startmb; \ + lr_ignore_rest (ldfile, 1); \ + break + + STR_ELEM (int_curr_symbol); + STR_ELEM (currency_symbol); + STR_ELEM (mon_decimal_point); + STR_ELEM (mon_thousands_sep); + STR_ELEM (positive_sign); + STR_ELEM (negative_sign); + STR_ELEM (duo_int_curr_symbol); + STR_ELEM (duo_currency_symbol); + +#define INT_ELEM(cat) \ + case tok_##cat: \ + now = lr_token (ldfile, charmap, NULL); \ + if (now->tok != tok_minus1 && now->tok != tok_number) \ + goto err_label; \ + else if (monetary->cat != -2) \ + lr_error (ldfile, _("%s: field `%s' declared more than once"), \ + "LC_MONETARY", #cat); \ + else if (!ignore_content) \ + monetary->cat = now->tok == tok_minus1 ? -1 : now->val.num; \ + break + + INT_ELEM (int_frac_digits); + INT_ELEM (frac_digits); + INT_ELEM (p_cs_precedes); + INT_ELEM (p_sep_by_space); + INT_ELEM (n_cs_precedes); + INT_ELEM (n_sep_by_space); + INT_ELEM (p_sign_posn); + INT_ELEM (n_sign_posn); + INT_ELEM (int_p_cs_precedes); + INT_ELEM (int_p_sep_by_space); + INT_ELEM (int_n_cs_precedes); + INT_ELEM (int_n_sep_by_space); + INT_ELEM (int_p_sign_posn); + INT_ELEM (int_n_sign_posn); + INT_ELEM (duo_int_frac_digits); + INT_ELEM (duo_frac_digits); + INT_ELEM (duo_p_cs_precedes); + INT_ELEM (duo_p_sep_by_space); + INT_ELEM (duo_n_cs_precedes); + INT_ELEM (duo_n_sep_by_space); + INT_ELEM (duo_p_sign_posn); + INT_ELEM (duo_n_sign_posn); + INT_ELEM (duo_int_p_cs_precedes); + INT_ELEM (duo_int_p_sep_by_space); + INT_ELEM (duo_int_n_cs_precedes); + INT_ELEM (duo_int_n_sep_by_space); + INT_ELEM (duo_int_p_sign_posn); + INT_ELEM (duo_int_n_sign_posn); + INT_ELEM (uno_valid_from); + INT_ELEM (uno_valid_to); + INT_ELEM (duo_valid_from); + INT_ELEM (duo_valid_to); + + case tok_mon_grouping: + now = lr_token (ldfile, charmap, NULL); + if (now->tok != tok_minus1 && now->tok != tok_number) + goto err_label; else - monetary->mon_grouping[monetary->mon_grouping_act++] - = code->val.num; + { + size_t act = 0; + size_t max = 10; + char *grouping = ignore_content ? NULL : xmalloc (max); + + do + { + if (act + 1 >= max) + { + max *= 2; + grouping = xrealloc (grouping, max); + } + + if (act > 0 && grouping[act - 1] == '\177') + { + lr_error (ldfile, _("\ +%s: `-1' must be last entry in `%s' field"), + "LC_MONETARY", "mon_grouping"); + lr_ignore_rest (ldfile, 0); + break; + } + + if (now->tok == tok_minus1) + { + if (!ignore_content) + grouping[act++] = '\177'; + } + else if (now->val.num == 0) + { + /* A value of 0 disables grouping from here on but + we must not store a NUL character since this + terminates the string. Use something different + which must not be used otherwise. */ + if (!ignore_content) + grouping[act++] = '\377'; + } + else if (now->val.num > 126) + lr_error (ldfile, _("\ +%s: values for field `%s' must be smaller than 127"), + "LC_MONETARY", "mon_grouping"); + else if (!ignore_content) + grouping[act++] = now->val.num; + + /* Next must be semicolon. */ + now = lr_token (ldfile, charmap, NULL); + if (now->tok != tok_semicolon) + break; + + now = lr_token (ldfile, charmap, NULL); + } + while (now->tok == tok_minus1 || now->tok == tok_number); + + if (now->tok != tok_eol) + goto err_label; + + if (!ignore_content) + { + grouping[act++] = '\0'; + + monetary->mon_grouping = xrealloc (grouping, act); + monetary->mon_grouping_len = act; + } + } + break; + + case tok_conversion_rate: + now = lr_token (ldfile, charmap, NULL); + if (now->tok != tok_number) + goto err_label; + if (now->val.num == 0) + { + invalid_conversion_rate: + lr_error (ldfile, _("conversion rate valze cannot be zero")); + if (!ignore_content) + { + monetary->conversion_rate[0] = 1; + monetary->conversion_rate[1] = 1; + } + break; + } + if (!ignore_content) + monetary->conversion_rate[0] = now->val.num; + /* Next must be a semicolon. */ + now = lr_token (ldfile, charmap, NULL); + if (now->tok != tok_semicolon) + goto err_label; + /* And another number. */ + now = lr_token (ldfile, charmap, NULL); + if (now->tok != tok_number) + goto err_label; + if (now->val.num == 0) + goto invalid_conversion_rate; + if (!ignore_content) + monetary->conversion_rate[1] = now->val.num; + /* The rest of the line must be empty. */ + lr_ignore_rest (ldfile, 1); + break; + + case tok_end: + /* Next we assume `LC_MONETARY'. */ + now = lr_token (ldfile, charmap, NULL); + if (now->tok == tok_eof) + break; + if (now->tok == tok_eol) + lr_error (ldfile, _("%s: incomplete `END' line"), "LC_MONETARY"); + else if (now->tok != tok_lc_monetary) + lr_error (ldfile, _("\ +%1$s: definition does not end with `END %1$s'"), "LC_MONETARY"); + lr_ignore_rest (ldfile, now->tok == tok_lc_monetary); + return; + + default: + err_label: + SYNTAX_ERROR (_("%s: syntax error"), "LC_MONETARY"); } - break; - default: - assert (! "unknown token in category `LC_MONETARY': should not happen"); + /* Prepare for the next round. */ + now = lr_token (ldfile, charmap, NULL); + nowtok = now->tok; } -} - -static int -curr_strcmp(const char *s1, const char **s2) -{ - return strcmp (s1, *s2); + /* When we come here we reached the end of the file. */ + lr_error (ldfile, _("%s: premature end of file"), "LC_MONETARY"); } |