]>
git.ipfire.org Git - thirdparty/glibc.git/blob - locale/programs/ld-numeric.c
1 /* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
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
17 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
27 /* Undefine following line in production version. */
28 /* #define NDEBUG 1 */
32 #include "localeinfo.h"
33 #include "stringtrans.h"
35 void *xmalloc (size_t __n
);
36 void *xrealloc (void *__ptr
, size_t __n
);
39 /* The real definition of the struct for the LC_NUMERIC locale. */
40 struct locale_numeric_t
42 const char *decimal_point
;
43 const char *thousands_sep
;
51 numeric_startup (struct linereader
*lr
, struct localedef_t
*locale
,
52 struct charset_t
*charset
)
54 struct locale_numeric_t
*numeric
;
56 /* It is important that we always use UCS1 encoding for strings now. */
57 encoding_method
= ENC_UCS1
;
59 locale
->categories
[LC_NUMERIC
].numeric
= numeric
=
60 (struct locale_numeric_t
*) xmalloc (sizeof (struct locale_numeric_t
));
62 memset (numeric
, '\0', sizeof (struct locale_numeric_t
));
64 numeric
->grouping_max
= 80;
65 numeric
->grouping
= (char *) xmalloc (numeric
->grouping_max
);
66 numeric
->grouping_act
= 0;
71 numeric_finish (struct localedef_t
*locale
)
73 struct locale_numeric_t
*numeric
= locale
->categories
[LC_NUMERIC
].numeric
;
75 #define TEST_ELEM(cat) \
76 if (numeric->cat == NULL) \
77 error (0, 0, _("field `%s' in category `%s' not defined"), \
80 TEST_ELEM (decimal_point
);
81 TEST_ELEM (thousands_sep
);
83 /* The decimal point must not be empty. This is not said explicitly
84 in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
86 if (numeric
->decimal_point
[0] == '\0')
89 value for field `%s' in category `%s' must not be the empty string"),
90 "decimal_point", "LC_NUMERIC");
93 if (numeric
->grouping_act
== 0)
94 error (0, 0, _("field `%s' in category `%s' not defined"),
95 "grouping", "LC_NUMERIC");
100 numeric_output (struct localedef_t
*locale
, const char *output_path
)
102 struct locale_numeric_t
*numeric
= locale
->categories
[LC_NUMERIC
].numeric
;
103 struct iovec iov
[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
)];
104 struct locale_file data
;
105 u32_t idx
[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
)];
108 if ((locale
->binary
& (1 << LC_NUMERIC
)) != 0)
110 iov
[0].iov_base
= numeric
;
111 iov
[0].iov_len
= locale
->len
[LC_NUMERIC
];
113 write_locale_data (output_path
, "LC_NUMERIC", 1, iov
);
118 data
.magic
= LIMAGIC (LC_NUMERIC
);
119 data
.n
= _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
);
120 iov
[cnt
].iov_base
= (void *) &data
;
121 iov
[cnt
].iov_len
= sizeof (data
);
124 iov
[cnt
].iov_base
= (void *) idx
;
125 iov
[cnt
].iov_len
= sizeof (idx
);
128 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
129 iov
[cnt
].iov_base
= (void *) (numeric
->decimal_point
?: "");
130 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
133 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
134 iov
[cnt
].iov_base
= (void *) (numeric
->thousands_sep
?: "");
135 iov
[cnt
].iov_len
= strlen (iov
[cnt
].iov_base
) + 1;
138 idx
[cnt
- 2] = idx
[cnt
- 3] + iov
[cnt
- 1].iov_len
;
139 iov
[cnt
].iov_base
= alloca (numeric
->grouping_act
+ 1);
140 iov
[cnt
].iov_len
= numeric
->grouping_act
+ 1;
141 memcpy (iov
[cnt
].iov_base
, numeric
->grouping
, numeric
->grouping_act
);
142 ((char *) iov
[cnt
].iov_base
)[numeric
->grouping_act
] = '\0';
144 assert (cnt
+ 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
));
146 write_locale_data (output_path
, "LC_NUMERIC",
147 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC
), iov
);
152 numeric_add (struct linereader
*lr
, struct localedef_t
*locale
,
153 enum token_t tok
, struct token
*code
,
154 struct charset_t
*charset
)
156 struct locale_numeric_t
*numeric
= locale
->categories
[LC_NUMERIC
].numeric
;
160 #define STR_ELEM(cat) \
162 if (numeric->cat != NULL) \
164 field `%s' in category `%s' declared more than once"), \
165 #cat, "LC_NUMERIC"); \
166 else if (code->val.str.start == NULL) \
168 lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
169 #cat, "LC_NUMERIC"); \
173 numeric->cat = code->val.str.start; \
176 STR_ELEM (decimal_point
);
177 STR_ELEM (thousands_sep
);
180 if (numeric
->grouping_act
== numeric
->grouping_max
)
182 numeric
->grouping_max
*= 2;
183 numeric
->grouping
= (char *) xrealloc (numeric
->grouping
,
184 numeric
->grouping_max
);
186 if (numeric
->grouping_act
> 0
187 && (numeric
->grouping
[numeric
->grouping_act
- 1] == '\177'))
190 `-1' must be last entry in `%s' field in `%s' category"),
191 "grouping", "LC_NUMERIC");
192 --numeric
->grouping_act
;
195 if (code
->tok
== tok_minus1
)
196 numeric
->grouping
[numeric
->grouping_act
++] = '\177';
197 else if (code
->val
.num
> 126)
199 values for field `%s' in category `%s' must be smaller than 127"),
200 "grouping", "LC_NUMERIC");
202 numeric
->grouping
[numeric
->grouping_act
++] = code
->val
.num
;
206 assert (! "unknown token in category `LC_NUMERIC': should not happen");