-/* Copyright (C) 1995-1999,2000,2001,2002,2005 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#include <sys/uio.h>
#include <assert.h>
= from->categories[LC_MONETARY].monetary;
}
- /* If there is still no definition issue an warning and create an
+ /* If there is still no definition issue a warning and create an
empty one. */
if (monetary == NULL)
{
- if (! be_quiet)
- WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_MONETARY"));
+ record_warning (_("\
+No definition for %s category found"), "LC_MONETARY");
monetary_startup (NULL, locale, 0);
monetary = locale->categories[LC_MONETARY].monetary;
nothing = 1;
#define TEST_ELEM(cat, initval) \
if (monetary->cat == NULL) \
{ \
- if (! be_quiet && ! nothing) \
- WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
- "LC_MONETARY", #cat)); \
+ if (! nothing) \
+ record_error (0, 0, _("%s: field `%s' not defined"), \
+ "LC_MONETARY", #cat); \
monetary->cat = initval; \
}
/* The international currency symbol must come from ISO 4217. */
if (monetary->int_curr_symbol != NULL)
{
- if (strlen (monetary->int_curr_symbol) != 4)
+ /* POSIX says this should be a 3-character symbol from ISO 4217
+ along with a 4th character that is a divider, but the POSIX
+ locale is documented as having a special case of "", and we
+ support that also, so allow other locales to be created with
+ a blank int_curr_symbol. */
+ int ics_len = strlen (monetary->int_curr_symbol);
+ if (ics_len != 4 && ics_len != 0)
{
- if (! be_quiet && ! nothing)
- WITH_CUR_LOCALE (error (0, 0, _("\
+ if (! nothing)
+ record_error (0, 0, _("\
%s: value of field `int_curr_symbol' has wrong length"),
- "LC_MONETARY"));
+ "LC_MONETARY");
}
- else
+ else if (ics_len == 4)
{ /* Check the first three characters against ISO 4217 */
char symbol[4];
strncpy (symbol, monetary->int_curr_symbol, 3);
symbol[3] = '\0';
+ /* A user may disable this waning for testing purposes or
+ for building a locale with a 3 letter country code that
+ was not yet supported in our ISO 4217 list.
+ See the use of --no-warnings=intcurrsym. */
if (bsearch (symbol, valid_int_curr, NR_VALID_INT_CURR,
sizeof (const char *),
(comparison_fn_t) curr_strcmp) == NULL
- && !be_quiet)
- WITH_CUR_LOCALE (error (0, 0, _("\
+ && warn_int_curr_symbol)
+ record_warning (_("\
%s: value of field `int_curr_symbol' does \
-not correspond to a valid name in ISO 4217"),
- "LC_MONETARY"));
+not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
+ "LC_MONETARY");
}
}
!= "". */
if (monetary->mon_decimal_point == NULL)
{
- if (! be_quiet && ! nothing)
- WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
- "LC_MONETARY", "mon_decimal_point"));
+ if (! nothing)
+ record_error (0, 0, _("%s: field `%s' not defined"),
+ "LC_MONETARY", "mon_decimal_point");
monetary->mon_decimal_point = ".";
}
else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
{
- WITH_CUR_LOCALE (error (0, 0, _("\
+ record_error (0, 0, _("\
%s: value for field `%s' must not be an empty string"),
- "LC_MONETARY", "mon_decimal_point"));
+ "LC_MONETARY", "mon_decimal_point");
}
if (monetary->mon_decimal_point_wc == L'\0')
monetary->mon_decimal_point_wc = L'.';
if (monetary->mon_grouping_len == 0)
{
- if (! be_quiet && ! nothing)
- WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
- "LC_MONETARY", "mon_grouping"));
+ if (! nothing)
+ record_error (0, 0, _("%s: field `%s' not defined"),
+ "LC_MONETARY", "mon_grouping");
monetary->mon_grouping = (char *) "\177";
monetary->mon_grouping_len = 1;
#define TEST_ELEM(cat, min, max, initval) \
if (monetary->cat == -2) \
{ \
- if (! be_quiet && ! nothing) \
- WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
- "LC_MONETARY", #cat)); \
+ if (! nothing) \
+ record_error (0, 0, _("%s: field `%s' not defined"), \
+ "LC_MONETARY", #cat); \
monetary->cat = initval; \
} \
else if ((monetary->cat < min || monetary->cat > max) \
+ && min < max \
&& !be_quiet && !nothing) \
- WITH_CUR_LOCALE (error (0, 0, _("\
+ record_error (0, 0, _("\
%s: value for field `%s' must be in range %d...%d"), \
- "LC_MONETARY", #cat, min, max))
+ "LC_MONETARY", #cat, min, max)
- TEST_ELEM (int_frac_digits, -128, 127, -1);
- TEST_ELEM (frac_digits, -128, 127, -1);
+ TEST_ELEM (int_frac_digits, 1, 0, -1);
+ TEST_ELEM (frac_digits, 1, 0, -1);
TEST_ELEM (p_cs_precedes, -1, 1, -1);
TEST_ELEM (p_sep_by_space, -1, 2, -1);
TEST_ELEM (n_cs_precedes, -1, 1, -1);
#define TEST_ELEM(cat, alt, min, max) \
if (monetary->cat == -2) \
monetary->cat = monetary->alt; \
- else if ((monetary->cat < min || monetary->cat > max) && !be_quiet \
- && ! nothing) \
- WITH_CUR_LOCALE (error (0, 0, _("\
+ else if ((monetary->cat < min || monetary->cat > max) && ! nothing) \
+ record_error (0, 0, _("\
%s: value for field `%s' must be in range %d...%d"), \
- "LC_MONETARY", #cat, min, max))
+ "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);
{
struct locale_monetary_t *monetary
= locale->categories[LC_MONETARY].monetary;
- struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
- struct locale_file data;
- uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
- size_t cnt = 0;
-
- data.magic = LIMAGIC (LC_MONETARY);
- data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY);
- iov[cnt].iov_base = (void *) &data;
- iov[cnt].iov_len = sizeof (data);
- ++cnt;
-
- iov[cnt].iov_base = (void *) idx;
- iov[cnt].iov_len = sizeof (idx);
- ++cnt;
-
- idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
- 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_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_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_len = strlen (iov[cnt].iov_base) + 1;
- ++cnt;
-
- idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- 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_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_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->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->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->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->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->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->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->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->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->crncystr;
- 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->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;
-
- 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] = idx[cnt - 3] + iov[cnt - 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;
-
- /* Align following data */
- iov[cnt].iov_base = (void *) "\0\0";
- iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
- idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
- ++cnt;
-
- iov[cnt].iov_base = (void *) &monetary->uno_valid_from;
- iov[cnt].iov_len = sizeof(uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) &monetary->uno_valid_to;
- iov[cnt].iov_len = sizeof(uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) &monetary->duo_valid_from;
- iov[cnt].iov_len = sizeof(uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) &monetary->duo_valid_to;
- iov[cnt].iov_len = sizeof(uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) monetary->conversion_rate;
- iov[cnt].iov_len = 2 * sizeof(uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) &monetary->mon_decimal_point_wc;
- iov[cnt].iov_len = sizeof (uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) &monetary->mon_thousands_sep_wc;
- iov[cnt].iov_len = sizeof (uint32_t);
- ++cnt;
-
- idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) charmap->code_set_name;
- iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
- ++cnt;
-
- assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
-
- write_locale_data (output_path, LC_MONETARY, "LC_MONETARY",
- 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY), iov);
+ struct locale_file file;
+
+ init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
+ add_locale_string (&file, monetary->int_curr_symbol);
+ add_locale_string (&file, monetary->currency_symbol);
+ add_locale_string (&file, monetary->mon_decimal_point);
+ add_locale_string (&file, monetary->mon_thousands_sep);
+ add_locale_raw_data (&file, monetary->mon_grouping,
+ monetary->mon_grouping_len);
+ add_locale_string (&file, monetary->positive_sign);
+ add_locale_string (&file, monetary->negative_sign);
+ add_locale_char (&file, monetary->int_frac_digits);
+ add_locale_char (&file, monetary->frac_digits);
+ add_locale_char (&file, monetary->p_cs_precedes);
+ add_locale_char (&file, monetary->p_sep_by_space);
+ add_locale_char (&file, monetary->n_cs_precedes);
+ add_locale_char (&file, monetary->n_sep_by_space);
+ add_locale_char (&file, monetary->p_sign_posn);
+ add_locale_char (&file, monetary->n_sign_posn);
+ add_locale_string (&file, monetary->crncystr);
+ add_locale_char (&file, monetary->int_p_cs_precedes);
+ add_locale_char (&file, monetary->int_p_sep_by_space);
+ add_locale_char (&file, monetary->int_n_cs_precedes);
+ add_locale_char (&file, monetary->int_n_sep_by_space);
+ add_locale_char (&file, monetary->int_p_sign_posn);
+ add_locale_char (&file, monetary->int_n_sign_posn);
+ add_locale_string (&file, monetary->duo_int_curr_symbol);
+ add_locale_string (&file, monetary->duo_currency_symbol);
+ add_locale_char (&file, monetary->duo_int_frac_digits);
+ add_locale_char (&file, monetary->duo_frac_digits);
+ add_locale_char (&file, monetary->duo_p_cs_precedes);
+ add_locale_char (&file, monetary->duo_p_sep_by_space);
+ add_locale_char (&file, monetary->duo_n_cs_precedes);
+ add_locale_char (&file, monetary->duo_n_sep_by_space);
+ add_locale_char (&file, monetary->duo_int_p_cs_precedes);
+ add_locale_char (&file, monetary->duo_int_p_sep_by_space);
+ add_locale_char (&file, monetary->duo_int_n_cs_precedes);
+ add_locale_char (&file, monetary->duo_int_n_sep_by_space);
+ add_locale_char (&file, monetary->duo_p_sign_posn);
+ add_locale_char (&file, monetary->duo_n_sign_posn);
+ add_locale_char (&file, monetary->duo_int_p_sign_posn);
+ add_locale_char (&file, monetary->duo_int_n_sign_posn);
+ add_locale_uint32 (&file, monetary->uno_valid_from);
+ add_locale_uint32 (&file, monetary->uno_valid_to);
+ add_locale_uint32 (&file, monetary->duo_valid_from);
+ add_locale_uint32 (&file, monetary->duo_valid_to);
+ add_locale_uint32_array (&file, monetary->conversion_rate, 2);
+ add_locale_uint32 (&file, monetary->mon_decimal_point_wc);
+ add_locale_uint32 (&file, monetary->mon_thousands_sep_wc);
+ add_locale_string (&file, charmap->code_set_name);
+ write_locale_data (output_path, LC_MONETARY, "LC_MONETARY", &file);
}
if (!ignore_content)
{
+ /* A single -1 means no grouping. */
+ if (act == 1 && grouping[0] == '\177')
+ act--;
grouping[act++] = '\0';
monetary->mon_grouping = xrealloc (grouping, act);