]>
Commit | Line | Data |
---|---|---|
93693c4d | 1 | /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
4b10dd6c UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
4b10dd6c UD |
9 | |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
4b10dd6c | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
4b10dd6c UD |
19 | |
20 | #ifdef HAVE_CONFIG_H | |
21 | # include <config.h> | |
22 | #endif | |
23 | ||
24 | #include <error.h> | |
25 | #include <langinfo.h> | |
26 | #include <string.h> | |
27 | #include <sys/uio.h> | |
28 | ||
29 | #include <assert.h> | |
30 | ||
31 | #include "localeinfo.h" | |
32 | #include "locfile.h" | |
33 | ||
34 | ||
35 | /* The real definition of the struct for the LC_TELEPHONE locale. */ | |
36 | struct locale_telephone_t | |
37 | { | |
38 | const char *tel_int_fmt; | |
39 | const char *tel_dom_fmt; | |
40 | const char *int_select; | |
41 | const char *int_prefix; | |
42 | }; | |
43 | ||
44 | ||
45 | static void | |
46 | telephone_startup (struct linereader *lr, struct localedef_t *locale, | |
47 | int ignore_content) | |
48 | { | |
49 | if (!ignore_content) | |
50 | locale->categories[LC_TELEPHONE].telephone = (struct locale_telephone_t *) | |
51 | xcalloc (1, sizeof (struct locale_telephone_t)); | |
52 | ||
b9eb05d6 UD |
53 | if (lr != NULL) |
54 | { | |
55 | lr->translate_strings = 1; | |
56 | lr->return_widestr = 0; | |
57 | } | |
4b10dd6c UD |
58 | } |
59 | ||
60 | ||
61 | void | |
62 | telephone_finish (struct localedef_t *locale, struct charmap_t *charmap) | |
63 | { | |
64 | struct locale_telephone_t *telephone = | |
65 | locale->categories[LC_TELEPHONE].telephone; | |
b9eb05d6 UD |
66 | int nothing = 0; |
67 | ||
68 | /* Now resolve copying and also handle completely missing definitions. */ | |
69 | if (telephone == NULL) | |
70 | { | |
71 | /* First see whether we were supposed to copy. If yes, find the | |
72 | actual definition. */ | |
73 | if (locale->copy_name[LC_TELEPHONE] != NULL) | |
74 | { | |
75 | /* Find the copying locale. This has to happen transitively since | |
76 | the locale we are copying from might also copying another one. */ | |
77 | struct localedef_t *from = locale; | |
78 | ||
79 | do | |
80 | from = find_locale (LC_TELEPHONE, from->copy_name[LC_TELEPHONE], | |
81 | from->repertoire_name, charmap); | |
82 | while (from->categories[LC_TELEPHONE].telephone == NULL | |
83 | && from->copy_name[LC_TELEPHONE] != NULL); | |
84 | ||
85 | telephone = locale->categories[LC_TELEPHONE].telephone | |
86 | = from->categories[LC_TELEPHONE].telephone; | |
87 | } | |
88 | ||
89 | /* If there is still no definition issue an warning and create an | |
90 | empty one. */ | |
91 | if (telephone == NULL) | |
92 | { | |
f6ada7ad UD |
93 | if (! be_quiet) |
94 | error (0, 0, _("No definition for %s category found"), | |
95 | "LC_TELEPHONE"); | |
b9eb05d6 UD |
96 | telephone_startup (NULL, locale, 0); |
97 | telephone = locale->categories[LC_TELEPHONE].telephone; | |
98 | nothing = 1; | |
99 | } | |
100 | } | |
4b10dd6c UD |
101 | |
102 | if (telephone->tel_int_fmt == NULL) | |
103 | { | |
b9eb05d6 UD |
104 | if (! nothing) |
105 | error (0, 0, _("%s: field `%s' not defined"), | |
106 | "LC_TELEPHONE", "tel_int_fmt"); | |
4b10dd6c UD |
107 | /* Use as the default value the value of the i18n locale. */ |
108 | telephone->tel_int_fmt = "+%c %a %l"; | |
109 | } | |
110 | else | |
111 | { | |
112 | /* We must check whether the format string contains only the | |
113 | allowed escape sequences. */ | |
114 | const char *cp = telephone->tel_int_fmt; | |
115 | ||
116 | if (*cp == '\0') | |
117 | error (0, 0, _("%s: field `%s' must not be empty"), | |
118 | "LC_TELEPHONE", "tel_int_fmt"); | |
119 | else | |
120 | while (*cp != '\0') | |
121 | { | |
122 | if (*cp == '%') | |
123 | { | |
124 | if (strchr ("aAlc", *++cp) == NULL) | |
125 | { | |
126 | error (0, 0, _("\ | |
127 | %s: invalid escape sequence in field `%s'"), | |
128 | "LC_TELEPHONE", "tel_int_fmt"); | |
129 | break; | |
130 | } | |
131 | } | |
132 | ++cp; | |
133 | } | |
134 | } | |
135 | ||
136 | if (telephone->tel_dom_fmt == NULL) | |
137 | telephone->tel_dom_fmt = ""; | |
138 | else if (telephone->tel_dom_fmt[0] != '\0') | |
139 | { | |
140 | /* We must check whether the format string contains only the | |
141 | allowed escape sequences. */ | |
142 | const char *cp = telephone->tel_dom_fmt; | |
143 | ||
144 | while (*cp != '\0') | |
145 | { | |
146 | if (*cp == '%') | |
147 | { | |
148 | if (strchr ("aAlc", *++cp) == NULL) | |
149 | { | |
150 | error (0, 0, _("%s: invalid escape sequence in field `%s'"), | |
151 | "LC_TELEPHONE", "tel_dom_fmt"); | |
152 | break; | |
153 | } | |
154 | } | |
155 | ++cp; | |
156 | } | |
157 | } | |
158 | ||
159 | #define TEST_ELEM(cat) \ | |
160 | if (telephone->cat == NULL) \ | |
161 | { \ | |
b9eb05d6 | 162 | if (verbose && ! nothing) \ |
4b10dd6c UD |
163 | error (0, 0, _("%s: field `%s' not defined"), "LC_TELEPHONE", #cat); \ |
164 | telephone->cat = ""; \ | |
165 | } | |
166 | ||
167 | TEST_ELEM (int_select); | |
168 | TEST_ELEM (int_prefix); | |
169 | } | |
170 | ||
171 | ||
172 | void | |
173 | telephone_output (struct localedef_t *locale, struct charmap_t *charmap, | |
174 | const char *output_path) | |
175 | { | |
176 | struct locale_telephone_t *telephone = | |
177 | locale->categories[LC_TELEPHONE].telephone; | |
178 | struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)]; | |
179 | struct locale_file data; | |
180 | uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)]; | |
181 | size_t cnt = 0; | |
182 | ||
183 | data.magic = LIMAGIC (LC_TELEPHONE); | |
184 | data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE); | |
185 | iov[cnt].iov_base = (void *) &data; | |
186 | iov[cnt].iov_len = sizeof (data); | |
187 | ++cnt; | |
188 | ||
189 | iov[cnt].iov_base = (void *) idx; | |
190 | iov[cnt].iov_len = sizeof (idx); | |
191 | ++cnt; | |
192 | ||
193 | idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len; | |
194 | iov[cnt].iov_base = (void *) telephone->tel_int_fmt; | |
195 | iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; | |
196 | ++cnt; | |
197 | ||
198 | idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; | |
199 | iov[cnt].iov_base = (void *) telephone->tel_dom_fmt; | |
200 | iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; | |
201 | ++cnt; | |
202 | ||
203 | idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; | |
204 | iov[cnt].iov_base = (void *) telephone->int_select; | |
205 | iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; | |
206 | ++cnt; | |
207 | ||
208 | idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; | |
209 | iov[cnt].iov_base = (void *) telephone->int_prefix; | |
210 | iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; | |
211 | ++cnt; | |
212 | ||
e7f21fa6 UD |
213 | idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len; |
214 | iov[cnt].iov_base = (void *) charmap->code_set_name;; | |
215 | iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1; | |
216 | ++cnt; | |
217 | ||
4b10dd6c UD |
218 | assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)); |
219 | ||
220 | write_locale_data (output_path, "LC_TELEPHONE", | |
221 | 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE), iov); | |
222 | } | |
223 | ||
224 | ||
225 | /* The parser for the LC_TELEPHONE section of the locale definition. */ | |
226 | void | |
227 | telephone_read (struct linereader *ldfile, struct localedef_t *result, | |
228 | struct charmap_t *charmap, const char *repertoire_name, | |
229 | int ignore_content) | |
230 | { | |
4b10dd6c UD |
231 | struct locale_telephone_t *telephone; |
232 | struct token *now; | |
233 | struct token *arg; | |
234 | enum token_t nowtok; | |
235 | ||
4b10dd6c UD |
236 | /* The rest of the line containing `LC_TELEPHONE' must be free. */ |
237 | lr_ignore_rest (ldfile, 1); | |
238 | ||
239 | do | |
240 | { | |
93693c4d | 241 | now = lr_token (ldfile, charmap, NULL, verbose); |
4b10dd6c UD |
242 | nowtok = now->tok; |
243 | } | |
244 | while (nowtok == tok_eol); | |
245 | ||
246 | /* If we see `copy' now we are almost done. */ | |
247 | if (nowtok == tok_copy) | |
248 | { | |
01ff9d0b | 249 | handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_telephone, |
b9eb05d6 | 250 | LC_TELEPHONE, "LC_TELEPHONE", ignore_content); |
4b10dd6c UD |
251 | return; |
252 | } | |
253 | ||
254 | /* Prepare the data structures. */ | |
255 | telephone_startup (ldfile, result, ignore_content); | |
256 | telephone = result->categories[LC_TELEPHONE].telephone; | |
257 | ||
258 | while (1) | |
259 | { | |
260 | /* Of course we don't proceed beyond the end of file. */ | |
261 | if (nowtok == tok_eof) | |
262 | break; | |
263 | ||
264 | /* Ingore empty lines. */ | |
265 | if (nowtok == tok_eol) | |
266 | { | |
93693c4d | 267 | now = lr_token (ldfile, charmap, NULL, verbose); |
4b10dd6c UD |
268 | nowtok = now->tok; |
269 | continue; | |
270 | } | |
271 | ||
272 | switch (nowtok) | |
273 | { | |
274 | #define STR_ELEM(cat) \ | |
275 | case tok_##cat: \ | |
b9eb05d6 UD |
276 | /* Ignore the rest of the line if we don't need the input of \ |
277 | this line. */ \ | |
278 | if (ignore_content) \ | |
279 | { \ | |
280 | lr_ignore_rest (ldfile, 0); \ | |
281 | break; \ | |
282 | } \ | |
283 | \ | |
93693c4d | 284 | arg = lr_token (ldfile, charmap, NULL, verbose); \ |
4b10dd6c UD |
285 | if (arg->tok != tok_string) \ |
286 | goto err_label; \ | |
287 | if (telephone->cat != NULL) \ | |
288 | lr_error (ldfile, _("%s: field `%s' declared more than once"), \ | |
289 | "LC_TELEPHONE", #cat); \ | |
290 | else if (!ignore_content && arg->val.str.startmb == NULL) \ | |
291 | { \ | |
292 | lr_error (ldfile, _("%s: unknown character in field `%s'"), \ | |
293 | "LC_TELEPHONE", #cat); \ | |
294 | telephone->cat = ""; \ | |
295 | } \ | |
296 | else if (!ignore_content) \ | |
297 | telephone->cat = arg->val.str.startmb; \ | |
298 | break | |
299 | ||
300 | STR_ELEM (tel_int_fmt); | |
301 | STR_ELEM (tel_dom_fmt); | |
302 | STR_ELEM (int_select); | |
303 | STR_ELEM (int_prefix); | |
304 | ||
305 | case tok_end: | |
306 | /* Next we assume `LC_TELEPHONE'. */ | |
93693c4d | 307 | arg = lr_token (ldfile, charmap, NULL, verbose); |
4b10dd6c UD |
308 | if (arg->tok == tok_eof) |
309 | break; | |
310 | if (arg->tok == tok_eol) | |
311 | lr_error (ldfile, _("%s: incomplete `END' line"), "LC_TELEPHONE"); | |
312 | else if (arg->tok != tok_lc_telephone) | |
313 | lr_error (ldfile, _("\ | |
314 | %1$s: definition does not end with `END %1$s'"), "LC_TELEPHONE"); | |
315 | lr_ignore_rest (ldfile, arg->tok == tok_lc_telephone); | |
316 | return; | |
317 | ||
318 | default: | |
319 | err_label: | |
320 | SYNTAX_ERROR (_("%s: syntax error"), "LC_TELEPHONE"); | |
321 | } | |
322 | ||
323 | /* Prepare for the next round. */ | |
93693c4d | 324 | now = lr_token (ldfile, charmap, NULL, verbose); |
4b10dd6c UD |
325 | nowtok = now->tok; |
326 | } | |
327 | ||
328 | /* When we come here we reached the end of the file. */ | |
329 | lr_error (ldfile, _("%s: premature end of file"), "LC_TELEPHONE"); | |
330 | } |