1 /* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 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. */
28 /* Undefine following line in production version. */
29 /* #define NDEBUG 1 */
33 #include "localeinfo.h"
34 #include "stringtrans.h"
36 void *xmalloc (size_t __n
);
37 void *xrealloc (void *__ptr
, size_t __n
);
40 /* The real definition of the struct for the LC_NUMERIC locale. */
41 struct locale_numeric_t
43 const char *decimal_point
;
44 const char *thousands_sep
;
52 numeric_startup (struct linereader
*lr
, struct localedef_t
*locale
,
53 struct charset_t
*charset
)
55 struct locale_numeric_t
*numeric
;
57 /* It is important that we always use UCS1 encoding for strings now. */
58 encoding_method
= ENC_UCS1
;
60 locale
->categories
[LC_NUMERIC
].numeric
= numeric
=
61 (struct locale_numeric_t
*) xmalloc (sizeof (struct locale_numeric_t
));
63 memset (numeric
, '\0', sizeof (struct locale_numeric_t
));
65 numeric
->grouping_max
= 80;
66 numeric
->grouping
= (char *) xmalloc (numeric
->grouping_max
);
67 numeric
->grouping_act
= 0;
72 numeric_finish (struct localedef_t
*locale
)
74 struct locale_numeric_t
*numeric
= locale
->categories
[LC_NUMERIC
].numeric
;
76 #define TEST_ELEM(cat) \
77 if (numeric->cat == NULL && !be_quiet) \
78 error (0, 0, _("field `%s' in category `%s' not defined"), \
81 TEST_ELEM (decimal_point
);
82 TEST_ELEM (thousands_sep
);
84 /* The decimal point must not be empty. This is not said explicitly
85 in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
87 if (numeric
->decimal_point
[0] == '\0' && !be_quiet
)
90 value for field `%s' in category `%s' must not be the empty string"),
91 "decimal_point", "LC_NUMERIC");
94 if (numeric
->grouping_act
== 0 && !be_quiet
)
95 error (0, 0, _("field `%s' in category `%s' not defined"),
96 "grouping", "LC_NUMERIC");
101 numeric_output (struct localedef_t
*locale
, const char *output_path
)
103 struct locale_numeric_t
*numeric
= locale
->categories
[LC_NUMERIC
].numeric
;
104 struct iovec iov
[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
)];
105 struct locale_file data
;
106 u_int32_t idx
[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
)];
109 if ((locale
->binary
& (1 << LC_NUMERIC
)) != 0)
111 iov
[0].iov_base
= numeric
;
112 iov
[0].iov_len
= locale
->len
[LC_NUMERIC
];
114 write_locale_data (output_path
, "LC_NUMERIC", 1, iov
);
119 data
.magic
= LIMAGIC (LC_NUMERIC
);
120 data
.n
= _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
);
121 iov
[cnt
].iov_base
= (void *) &data
;
122 iov
[cnt
].iov_len
= sizeof (data
);
125 iov
[cnt
].iov_base
= (void *) idx
;
126 iov
[cnt
].iov_len
= sizeof (idx
);
129 idx
[cnt
- 2] = iov
[0].iov_len
+ iov
[1].iov_len
;
130 iov
[cnt
].iov_base
= (void *) (numeric
->decimal_point
?: "");
131 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
134 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
135 iov
[cnt
].iov_base
= (void *) (numeric
->thousands_sep
?: "");
136 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
139 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
140 iov
[cnt
].iov_base
= alloca (numeric
->grouping_act
+ 1);
141 iov
[cnt
].iov_len
= numeric
->grouping_act
+ 1;
142 memcpy (iov
[cnt
].iov_base
, numeric
->grouping
, numeric
->grouping_act
);
143 ((char *) iov
[cnt
].iov_base
)[numeric
->grouping_act
] = '\0';
145 assert (cnt
+ 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
));
147 write_locale_data (output_path
, "LC_NUMERIC",
148 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
), iov
);
153 numeric_add (struct linereader
*lr
, struct localedef_t
*locale
,
154 enum token_t tok
, struct token
*code
,
155 struct charset_t
*charset
)
157 struct locale_numeric_t
*numeric
= locale
->categories
[LC_NUMERIC
].numeric
;
161 #define STR_ELEM(cat) \
163 if (numeric->cat != NULL) \
165 field `%s' in category `%s' declared more than once"), \
166 #cat, "LC_NUMERIC"); \
167 else if (code->val.str.start == NULL) \
169 lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
170 #cat, "LC_NUMERIC"); \
174 numeric->cat = code->val.str.start; \
177 STR_ELEM (decimal_point
);
178 STR_ELEM (thousands_sep
);
181 if (numeric
->grouping_act
== numeric
->grouping_max
)
183 numeric
->grouping_max
*= 2;
184 numeric
->grouping
= (char *) xrealloc (numeric
->grouping
,
185 numeric
->grouping_max
);
187 if (numeric
->grouping_act
> 0
188 && (numeric
->grouping
[numeric
->grouping_act
- 1] == '\177'))
191 `-1' must be last entry in `%s' field in `%s' category"),
192 "grouping", "LC_NUMERIC");
193 --numeric
->grouping_act
;
196 if (code
->tok
== tok_minus1
)
197 numeric
->grouping
[numeric
->grouping_act
++] = '\177';
198 else if (code
->val
.num
> 126)
200 values for field `%s' in category `%s' must be smaller than 127"),
201 "grouping", "LC_NUMERIC");
203 numeric
->grouping
[numeric
->grouping_act
++] = code
->val
.num
;
207 assert (! "unknown token in category `LC_NUMERIC': should not happen");