1 /* Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
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 #include <sys/param.h>
31 #include "localedef.h"
34 #include "locfile-kw.h"
38 locfile_read (struct localedef_t
*result
, struct charmap_t
*charmap
)
40 const char *filename
= result
->name
;
41 const char *repertoire_name
= result
->repertoire_name
;
42 int locale_mask
= result
->needed
^ result
->avail
;
43 struct linereader
*ldfile
;
44 int not_here
= ALL_LOCALES
;
46 /* If no repertoire name was specified use the global one. */
47 if (repertoire_name
== NULL
)
48 repertoire_name
= repertoire_global
;
50 /* Open the locale definition file. */
51 ldfile
= lr_open (filename
, locfile_hash
);
54 if (filename
[0] != '/')
56 char *i18npath
= getenv ("I18NPATH");
57 if (i18npath
!= NULL
&& *i18npath
!= '\0')
59 char path
[strlen (filename
) + 1 + strlen (i18npath
)
60 + sizeof ("/locales/") - 1];
62 i18npath
= strdupa (i18npath
);
66 && (next
= strsep (&i18npath
, ":")) != NULL
)
68 stpcpy (stpcpy (stpcpy (path
, next
), "/locales/"), filename
);
70 ldfile
= lr_open (path
, locfile_hash
);
74 stpcpy (stpcpy (path
, next
), filename
);
76 ldfile
= lr_open (path
, locfile_hash
);
81 /* Test in the default directory. */
84 char path
[strlen (filename
) + 1 + sizeof (LOCSRCDIR
)];
86 stpcpy (stpcpy (stpcpy (path
, LOCSRCDIR
), "/"), filename
);
87 ldfile
= lr_open (path
, locfile_hash
);
95 /* Parse locale definition file and store result in RESULT. */
98 struct token
*now
= lr_token (ldfile
, charmap
, NULL
, verbose
);
99 enum token_t nowtok
= now
->tok
;
102 if (nowtok
== tok_eof
)
105 if (nowtok
== tok_eol
)
106 /* Ignore empty lines. */
111 case tok_escape_char
:
112 case tok_comment_char
:
113 /* We need an argument. */
114 arg
= lr_token (ldfile
, charmap
, NULL
, verbose
);
116 if (arg
->tok
!= tok_ident
)
118 SYNTAX_ERROR (_("bad argument"));
122 if (arg
->val
.str
.lenmb
!= 1)
124 lr_error (ldfile
, _("\
125 argument to `%s' must be a single character"),
126 nowtok
== tok_escape_char
127 ? "escape_char" : "comment_char");
129 lr_ignore_rest (ldfile
, 0);
133 if (nowtok
== tok_escape_char
)
134 ldfile
->escape_char
= *arg
->val
.str
.startmb
;
136 ldfile
->comment_char
= *arg
->val
.str
.startmb
;
139 case tok_repertoiremap
:
140 /* We need an argument. */
141 arg
= lr_token (ldfile
, charmap
, NULL
, verbose
);
143 if (arg
->tok
!= tok_ident
)
145 SYNTAX_ERROR (_("bad argument"));
149 if (repertoire_name
== NULL
)
151 repertoire_name
= memcpy (xmalloc (arg
->val
.str
.lenmb
+ 1),
152 arg
->val
.str
.startmb
,
154 ((char *) repertoire_name
)[arg
->val
.str
.lenmb
] = '\0';
159 ctype_read (ldfile
, result
, charmap
, repertoire_name
,
160 (locale_mask
& CTYPE_LOCALE
) == 0);
161 result
->avail
|= locale_mask
& CTYPE_LOCALE
;
162 not_here
^= CTYPE_LOCALE
;
166 collate_read (ldfile
, result
, charmap
, repertoire_name
,
167 (locale_mask
& COLLATE_LOCALE
) == 0);
168 result
->avail
|= locale_mask
& COLLATE_LOCALE
;
169 not_here
^= COLLATE_LOCALE
;
172 case tok_lc_monetary
:
173 monetary_read (ldfile
, result
, charmap
, repertoire_name
,
174 (locale_mask
& MONETARY_LOCALE
) == 0);
175 result
->avail
|= locale_mask
& MONETARY_LOCALE
;
176 not_here
^= MONETARY_LOCALE
;
180 numeric_read (ldfile
, result
, charmap
, repertoire_name
,
181 (locale_mask
& NUMERIC_LOCALE
) == 0);
182 result
->avail
|= locale_mask
& NUMERIC_LOCALE
;
183 not_here
^= NUMERIC_LOCALE
;
187 time_read (ldfile
, result
, charmap
, repertoire_name
,
188 (locale_mask
& TIME_LOCALE
) == 0);
189 result
->avail
|= locale_mask
& TIME_LOCALE
;
190 not_here
^= TIME_LOCALE
;
193 case tok_lc_messages
:
194 messages_read (ldfile
, result
, charmap
, repertoire_name
,
195 (locale_mask
& MESSAGES_LOCALE
) == 0);
196 result
->avail
|= locale_mask
& MESSAGES_LOCALE
;
197 not_here
^= MESSAGES_LOCALE
;
201 paper_read (ldfile
, result
, charmap
, repertoire_name
,
202 (locale_mask
& PAPER_LOCALE
) == 0);
203 result
->avail
|= locale_mask
& PAPER_LOCALE
;
204 not_here
^= PAPER_LOCALE
;
208 name_read (ldfile
, result
, charmap
, repertoire_name
,
209 (locale_mask
& NAME_LOCALE
) == 0);
210 result
->avail
|= locale_mask
& NAME_LOCALE
;
211 not_here
^= NAME_LOCALE
;
215 address_read (ldfile
, result
, charmap
, repertoire_name
,
216 (locale_mask
& ADDRESS_LOCALE
) == 0);
217 result
->avail
|= locale_mask
& ADDRESS_LOCALE
;
218 not_here
^= ADDRESS_LOCALE
;
221 case tok_lc_telephone
:
222 telephone_read (ldfile
, result
, charmap
, repertoire_name
,
223 (locale_mask
& TELEPHONE_LOCALE
) == 0);
224 result
->avail
|= locale_mask
& TELEPHONE_LOCALE
;
225 not_here
^= TELEPHONE_LOCALE
;
228 case tok_lc_measurement
:
229 measurement_read (ldfile
, result
, charmap
, repertoire_name
,
230 (locale_mask
& MEASUREMENT_LOCALE
) == 0);
231 result
->avail
|= locale_mask
& MEASUREMENT_LOCALE
;
232 not_here
^= MEASUREMENT_LOCALE
;
235 case tok_lc_identification
:
236 identification_read (ldfile
, result
, charmap
, repertoire_name
,
237 (locale_mask
& IDENTIFICATION_LOCALE
) == 0);
238 result
->avail
|= locale_mask
& IDENTIFICATION_LOCALE
;
239 not_here
^= IDENTIFICATION_LOCALE
;
244 syntax error: not inside a locale definition section"));
248 /* The rest of the line must be empty. */
249 lr_ignore_rest (ldfile
, 1);
252 /* We read all of the file. */
255 /* Mark the categories which are not contained in the file. We assume
256 them to be available and the default data will be used. */
257 result
->avail
|= not_here
;
263 static void (*const check_funcs
[]) (struct localedef_t
*,
264 struct charmap_t
*) =
266 [LC_CTYPE
] = ctype_finish
,
267 [LC_COLLATE
] = collate_finish
,
268 [LC_MESSAGES
] = messages_finish
,
269 [LC_MONETARY
] = monetary_finish
,
270 [LC_NUMERIC
] = numeric_finish
,
271 [LC_TIME
] = time_finish
,
272 [LC_PAPER
] = paper_finish
,
273 [LC_NAME
] = name_finish
,
274 [LC_ADDRESS
] = address_finish
,
275 [LC_TELEPHONE
] = telephone_finish
,
276 [LC_MEASUREMENT
] = measurement_finish
,
277 [LC_IDENTIFICATION
] = identification_finish
282 check_all_categories (struct localedef_t
*definitions
,
283 struct charmap_t
*charmap
)
287 for (cnt
= 0; cnt
< sizeof (check_funcs
) / sizeof (check_funcs
[0]); ++cnt
)
288 if (check_funcs
[cnt
] != NULL
)
289 check_funcs
[cnt
] (definitions
, charmap
);
293 static void (*const write_funcs
[]) (struct localedef_t
*, struct charmap_t
*,
296 [LC_CTYPE
] = ctype_output
,
297 [LC_COLLATE
] = collate_output
,
298 [LC_MESSAGES
] = messages_output
,
299 [LC_MONETARY
] = monetary_output
,
300 [LC_NUMERIC
] = numeric_output
,
301 [LC_TIME
] = time_output
,
302 [LC_PAPER
] = paper_output
,
303 [LC_NAME
] = name_output
,
304 [LC_ADDRESS
] = address_output
,
305 [LC_TELEPHONE
] = telephone_output
,
306 [LC_MEASUREMENT
] = measurement_output
,
307 [LC_IDENTIFICATION
] = identification_output
312 write_all_categories (struct localedef_t
*definitions
,
313 struct charmap_t
*charmap
,
314 const char *output_path
)
318 for (cnt
= 0; cnt
< sizeof (write_funcs
) / sizeof (write_funcs
[0]); ++cnt
)
319 if (write_funcs
[cnt
] != NULL
)
320 write_funcs
[cnt
] (definitions
, charmap
, output_path
);
325 write_locale_data (const char *output_path
, const char *category
,
326 size_t n_elem
, struct iovec
*vec
)
328 size_t cnt
, step
, maxiov
;
332 fname
= malloc (strlen (output_path
) + 2 * strlen (category
) + 7);
334 error (5, errno
, _("memory exhausted"));
336 /* Normally we write to the directory pointed to by the OUTPUT_PATH.
337 But for LC_MESSAGES we have to take care for the translation
338 data. This means we need to have a directory LC_MESSAGES in
339 which we place the file under the name SYS_LC_MESSAGES. */
340 sprintf (fname
, "%s%s", output_path
, category
);
341 if (strcmp (category
, "LC_MESSAGES") == 0)
345 if (stat (fname
, &st
) < 0)
347 if (mkdir (fname
, 0777) < 0)
348 fd
= creat (fname
, 0666);
355 else if (S_ISREG (st
.st_mode
))
356 fd
= creat (fname
, 0666);
364 fd
= creat (fname
, 0666);
368 int save_err
= errno
;
372 sprintf (fname
, "%1$s/%2$s/SYS_%2$s", output_path
, category
);
373 fd
= creat (fname
, 0666);
381 error (0, save_err
, _("\
382 cannot open output file `%s' for category `%s'"),
392 maxiov
= sysconf (_SC_UIO_MAXIOV
);
395 /* Write the data using writev. But we must take care for the
396 limitation of the implementation. */
397 for (cnt
= 0; cnt
< n_elem
; cnt
+= step
)
401 step
= MIN (maxiov
, step
);
403 if (writev (fd
, &vec
[cnt
], step
) < 0)
406 error (0, errno
, _("failure while writing data for category `%s'"),