xref: /freebsd/usr.bin/localedef/localedef.c (revision 3141e51d2e38fa7b9e6d81477dfa860d087c514d)
1e12a957fSPedro F. Giffuni /*-
24644f9beSYuri Pankov  * Copyright 2018 Nexenta Systems, Inc.
3057ca2d4SBaptiste Daroussin  * Copyright 2015 John Marino <draco@marino.st>
4057ca2d4SBaptiste Daroussin  *
5057ca2d4SBaptiste Daroussin  * This source code is derived from the illumos localedef command, and
6057ca2d4SBaptiste Daroussin  * provided under BSD-style license terms by Nexenta Systems, Inc.
7057ca2d4SBaptiste Daroussin  *
8057ca2d4SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
9057ca2d4SBaptiste Daroussin  * modification, are permitted provided that the following conditions
10057ca2d4SBaptiste Daroussin  * are met:
11057ca2d4SBaptiste Daroussin  *
12057ca2d4SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
13057ca2d4SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
14057ca2d4SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
15057ca2d4SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
16057ca2d4SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
17057ca2d4SBaptiste Daroussin  *
18057ca2d4SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19057ca2d4SBaptiste Daroussin  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20057ca2d4SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21057ca2d4SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22057ca2d4SBaptiste Daroussin  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23057ca2d4SBaptiste Daroussin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24057ca2d4SBaptiste Daroussin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25057ca2d4SBaptiste Daroussin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26057ca2d4SBaptiste Daroussin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27057ca2d4SBaptiste Daroussin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28057ca2d4SBaptiste Daroussin  * POSSIBILITY OF SUCH DAMAGE.
29057ca2d4SBaptiste Daroussin  */
30057ca2d4SBaptiste Daroussin 
31057ca2d4SBaptiste Daroussin /*
32057ca2d4SBaptiste Daroussin  * POSIX localedef.
33057ca2d4SBaptiste Daroussin  */
34057ca2d4SBaptiste Daroussin #include <sys/cdefs.h>
354644f9beSYuri Pankov #include <sys/endian.h>
364644f9beSYuri Pankov #include <sys/stat.h>
374644f9beSYuri Pankov #include <sys/types.h>
384644f9beSYuri Pankov 
39057ca2d4SBaptiste Daroussin #include <stdio.h>
40057ca2d4SBaptiste Daroussin #include <stdlib.h>
41057ca2d4SBaptiste Daroussin #include <errno.h>
42057ca2d4SBaptiste Daroussin #include <string.h>
43057ca2d4SBaptiste Daroussin #include <libgen.h>
44057ca2d4SBaptiste Daroussin #include <stddef.h>
45057ca2d4SBaptiste Daroussin #include <unistd.h>
46057ca2d4SBaptiste Daroussin #include <limits.h>
47057ca2d4SBaptiste Daroussin #include <locale.h>
48057ca2d4SBaptiste Daroussin #include <dirent.h>
49cc7edd25SThomas Munro #include "collate.h"
50057ca2d4SBaptiste Daroussin #include "localedef.h"
51057ca2d4SBaptiste Daroussin #include "parser.h"
52057ca2d4SBaptiste Daroussin 
53057ca2d4SBaptiste Daroussin #ifndef	TEXT_DOMAIN
54057ca2d4SBaptiste Daroussin #define	TEXT_DOMAIN	"SYS_TEST"
55057ca2d4SBaptiste Daroussin #endif
56057ca2d4SBaptiste Daroussin 
57557a07f0SBaptiste Daroussin static int bsd = 0;
584644f9beSYuri Pankov static int byteorder = 0;
59057ca2d4SBaptiste Daroussin int verbose = 0;
60057ca2d4SBaptiste Daroussin int undefok = 0;
61057ca2d4SBaptiste Daroussin int warnok = 0;
62057ca2d4SBaptiste Daroussin static char *locname = NULL;
63057ca2d4SBaptiste Daroussin static char locpath[PATH_MAX];
64cc7edd25SThomas Munro char *version = NULL;
65057ca2d4SBaptiste Daroussin 
66057ca2d4SBaptiste Daroussin const char *
category_name(void)67057ca2d4SBaptiste Daroussin category_name(void)
68057ca2d4SBaptiste Daroussin {
69057ca2d4SBaptiste Daroussin 	switch (get_category()) {
70057ca2d4SBaptiste Daroussin 	case T_CHARMAP:
71057ca2d4SBaptiste Daroussin 		return ("CHARMAP");
72057ca2d4SBaptiste Daroussin 	case T_WIDTH:
73057ca2d4SBaptiste Daroussin 		return ("WIDTH");
74057ca2d4SBaptiste Daroussin 	case T_COLLATE:
75057ca2d4SBaptiste Daroussin 		return ("LC_COLLATE");
76057ca2d4SBaptiste Daroussin 	case T_CTYPE:
77057ca2d4SBaptiste Daroussin 		return ("LC_CTYPE");
78057ca2d4SBaptiste Daroussin 	case T_MESSAGES:
79057ca2d4SBaptiste Daroussin 		return ("LC_MESSAGES");
80057ca2d4SBaptiste Daroussin 	case T_MONETARY:
81057ca2d4SBaptiste Daroussin 		return ("LC_MONETARY");
82057ca2d4SBaptiste Daroussin 	case T_NUMERIC:
83057ca2d4SBaptiste Daroussin 		return ("LC_NUMERIC");
84057ca2d4SBaptiste Daroussin 	case T_TIME:
85057ca2d4SBaptiste Daroussin 		return ("LC_TIME");
86057ca2d4SBaptiste Daroussin 	default:
87057ca2d4SBaptiste Daroussin 		INTERR;
88057ca2d4SBaptiste Daroussin 		return (NULL);
89057ca2d4SBaptiste Daroussin 	}
90057ca2d4SBaptiste Daroussin }
91057ca2d4SBaptiste Daroussin 
92057ca2d4SBaptiste Daroussin static char *
category_file(void)93057ca2d4SBaptiste Daroussin category_file(void)
94057ca2d4SBaptiste Daroussin {
95057ca2d4SBaptiste Daroussin 	if (bsd)
96057ca2d4SBaptiste Daroussin 		(void) snprintf(locpath, sizeof (locpath), "%s.%s",
97057ca2d4SBaptiste Daroussin 		    locname, category_name());
98057ca2d4SBaptiste Daroussin 	else
99057ca2d4SBaptiste Daroussin 		(void) snprintf(locpath, sizeof (locpath), "%s/%s",
100057ca2d4SBaptiste Daroussin 		    locname, category_name());
101057ca2d4SBaptiste Daroussin 	return (locpath);
102057ca2d4SBaptiste Daroussin }
103057ca2d4SBaptiste Daroussin 
104057ca2d4SBaptiste Daroussin FILE *
open_category(void)105057ca2d4SBaptiste Daroussin open_category(void)
106057ca2d4SBaptiste Daroussin {
107057ca2d4SBaptiste Daroussin 	FILE *file;
108057ca2d4SBaptiste Daroussin 
109057ca2d4SBaptiste Daroussin 	if (verbose) {
110057ca2d4SBaptiste Daroussin 		(void) printf("Writing category %s: ", category_name());
111057ca2d4SBaptiste Daroussin 		(void) fflush(stdout);
112057ca2d4SBaptiste Daroussin 	}
113057ca2d4SBaptiste Daroussin 
114057ca2d4SBaptiste Daroussin 	/* make the parent directory */
115057ca2d4SBaptiste Daroussin 	if (!bsd)
116057ca2d4SBaptiste Daroussin 		(void) mkdir(dirname(category_file()), 0755);
117057ca2d4SBaptiste Daroussin 
118057ca2d4SBaptiste Daroussin 	/*
119057ca2d4SBaptiste Daroussin 	 * note that we have to regenerate the file name, as dirname
120057ca2d4SBaptiste Daroussin 	 * clobbered it.
121057ca2d4SBaptiste Daroussin 	 */
122057ca2d4SBaptiste Daroussin 	file = fopen(category_file(), "w");
123057ca2d4SBaptiste Daroussin 	if (file == NULL) {
124ead8d64aSEnji Cooper 		errf("%s", strerror(errno));
125057ca2d4SBaptiste Daroussin 		return (NULL);
126057ca2d4SBaptiste Daroussin 	}
127057ca2d4SBaptiste Daroussin 	return (file);
128057ca2d4SBaptiste Daroussin }
129057ca2d4SBaptiste Daroussin 
130057ca2d4SBaptiste Daroussin void
close_category(FILE * f)131057ca2d4SBaptiste Daroussin close_category(FILE *f)
132057ca2d4SBaptiste Daroussin {
133c48c87b7SPedro F. Giffuni 	if (fchmod(fileno(f), 0644) < 0) {
134c48c87b7SPedro F. Giffuni 		(void) fclose(f);
135c48c87b7SPedro F. Giffuni 		(void) unlink(category_file());
136ead8d64aSEnji Cooper 		errf("%s", strerror(errno));
137057ca2d4SBaptiste Daroussin 	}
138057ca2d4SBaptiste Daroussin 	if (fclose(f) < 0) {
139057ca2d4SBaptiste Daroussin 		(void) unlink(category_file());
140ead8d64aSEnji Cooper 		errf("%s", strerror(errno));
141057ca2d4SBaptiste Daroussin 	}
142057ca2d4SBaptiste Daroussin 	if (verbose) {
143057ca2d4SBaptiste Daroussin 		(void) fprintf(stdout, "done.\n");
144057ca2d4SBaptiste Daroussin 		(void) fflush(stdout);
145057ca2d4SBaptiste Daroussin 	}
146057ca2d4SBaptiste Daroussin }
147057ca2d4SBaptiste Daroussin 
148057ca2d4SBaptiste Daroussin /*
149057ca2d4SBaptiste Daroussin  * This function is used when copying the category from another
150057ca2d4SBaptiste Daroussin  * locale.  Note that the copy is actually performed using a hard
151057ca2d4SBaptiste Daroussin  * link for efficiency.
152057ca2d4SBaptiste Daroussin  */
153057ca2d4SBaptiste Daroussin void
copy_category(char * src)154057ca2d4SBaptiste Daroussin copy_category(char *src)
155057ca2d4SBaptiste Daroussin {
156057ca2d4SBaptiste Daroussin 	char	srcpath[PATH_MAX];
157057ca2d4SBaptiste Daroussin 	int	rv;
158057ca2d4SBaptiste Daroussin 
159057ca2d4SBaptiste Daroussin 	(void) snprintf(srcpath, sizeof (srcpath), "%s/%s",
160057ca2d4SBaptiste Daroussin 	    src, category_name());
161057ca2d4SBaptiste Daroussin 	rv = access(srcpath, R_OK);
162057ca2d4SBaptiste Daroussin 	if ((rv != 0) && (strchr(srcpath, '/') == NULL)) {
163057ca2d4SBaptiste Daroussin 		/* Maybe we should try the system locale */
164057ca2d4SBaptiste Daroussin 		(void) snprintf(srcpath, sizeof (srcpath),
165057ca2d4SBaptiste Daroussin 		    "/usr/lib/locale/%s/%s", src, category_name());
166057ca2d4SBaptiste Daroussin 		rv = access(srcpath, R_OK);
167057ca2d4SBaptiste Daroussin 	}
168057ca2d4SBaptiste Daroussin 
169057ca2d4SBaptiste Daroussin 	if (rv != 0) {
170*3141e51dSKyle Evans 		fprintf(stderr,"source locale data unavailable: %s\n", src);
171057ca2d4SBaptiste Daroussin 		return;
172057ca2d4SBaptiste Daroussin 	}
173057ca2d4SBaptiste Daroussin 
174057ca2d4SBaptiste Daroussin 	if (verbose > 1) {
175057ca2d4SBaptiste Daroussin 		(void) printf("Copying category %s from %s: ",
176057ca2d4SBaptiste Daroussin 		    category_name(), src);
177057ca2d4SBaptiste Daroussin 		(void) fflush(stdout);
178057ca2d4SBaptiste Daroussin 	}
179057ca2d4SBaptiste Daroussin 
180057ca2d4SBaptiste Daroussin 	/* make the parent directory */
181057ca2d4SBaptiste Daroussin 	if (!bsd)
182057ca2d4SBaptiste Daroussin 		(void) mkdir(dirname(category_file()), 0755);
183057ca2d4SBaptiste Daroussin 
184057ca2d4SBaptiste Daroussin 	if (link(srcpath, category_file()) != 0) {
185*3141e51dSKyle Evans 		fprintf(stderr,"unable to copy locale data: %s\n",
186057ca2d4SBaptiste Daroussin 			strerror(errno));
187057ca2d4SBaptiste Daroussin 		return;
188057ca2d4SBaptiste Daroussin 	}
189057ca2d4SBaptiste Daroussin 	if (verbose > 1) {
190057ca2d4SBaptiste Daroussin 		(void) printf("done.\n");
191057ca2d4SBaptiste Daroussin 	}
192057ca2d4SBaptiste Daroussin }
193057ca2d4SBaptiste Daroussin 
194057ca2d4SBaptiste Daroussin int
putl_category(const char * s,FILE * f)195057ca2d4SBaptiste Daroussin putl_category(const char *s, FILE *f)
196057ca2d4SBaptiste Daroussin {
197057ca2d4SBaptiste Daroussin 	if (s && fputs(s, f) == EOF) {
198c48c87b7SPedro F. Giffuni 		(void) fclose(f);
199c48c87b7SPedro F. Giffuni 		(void) unlink(category_file());
200ead8d64aSEnji Cooper 		errf("%s", strerror(errno));
201057ca2d4SBaptiste Daroussin 		return (EOF);
202057ca2d4SBaptiste Daroussin 	}
203057ca2d4SBaptiste Daroussin 	if (fputc('\n', f) == EOF) {
204c48c87b7SPedro F. Giffuni 		(void) fclose(f);
205c48c87b7SPedro F. Giffuni 		(void) unlink(category_file());
206ead8d64aSEnji Cooper 		errf("%s", strerror(errno));
207057ca2d4SBaptiste Daroussin 		return (EOF);
208057ca2d4SBaptiste Daroussin 	}
209057ca2d4SBaptiste Daroussin 	return (0);
210057ca2d4SBaptiste Daroussin }
211057ca2d4SBaptiste Daroussin 
212057ca2d4SBaptiste Daroussin int
wr_category(void * buf,size_t sz,FILE * f)213057ca2d4SBaptiste Daroussin wr_category(void *buf, size_t sz, FILE *f)
214057ca2d4SBaptiste Daroussin {
215057ca2d4SBaptiste Daroussin 	if (!sz) {
216057ca2d4SBaptiste Daroussin 		return (0);
217057ca2d4SBaptiste Daroussin 	}
218057ca2d4SBaptiste Daroussin 	if (fwrite(buf, sz, 1, f) < 1) {
219c48c87b7SPedro F. Giffuni 		(void) fclose(f);
220c48c87b7SPedro F. Giffuni 		(void) unlink(category_file());
221ead8d64aSEnji Cooper 		errf("%s", strerror(errno));
222057ca2d4SBaptiste Daroussin 		return (EOF);
223057ca2d4SBaptiste Daroussin 	}
224057ca2d4SBaptiste Daroussin 	return (0);
225057ca2d4SBaptiste Daroussin }
226057ca2d4SBaptiste Daroussin 
2274644f9beSYuri Pankov uint32_t
htote(uint32_t arg)2284644f9beSYuri Pankov htote(uint32_t arg)
2294644f9beSYuri Pankov {
2304644f9beSYuri Pankov 
2314644f9beSYuri Pankov 	if (byteorder == 4321)
2324644f9beSYuri Pankov 		return (htobe32(arg));
2334644f9beSYuri Pankov 	else if (byteorder == 1234)
2344644f9beSYuri Pankov 		return (htole32(arg));
2354644f9beSYuri Pankov 	else
2364644f9beSYuri Pankov 		return (arg);
2374644f9beSYuri Pankov }
2384644f9beSYuri Pankov 
239057ca2d4SBaptiste Daroussin int yyparse(void);
240057ca2d4SBaptiste Daroussin 
241057ca2d4SBaptiste Daroussin static void
usage(void)242057ca2d4SBaptiste Daroussin usage(void)
243057ca2d4SBaptiste Daroussin {
244057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "Usage: localedef [options] localename\n");
245057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "[options] are:\n");
246057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -D          : BSD-style output\n");
2474644f9beSYuri Pankov 	(void) fprintf(stderr, "  -b          : big-endian output\n");
248057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -c          : ignore warnings\n");
2494644f9beSYuri Pankov 	(void) fprintf(stderr, "  -l          : little-endian output\n");
250057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -v          : verbose output\n");
251057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -U          : ignore undefined symbols\n");
252057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -f charmap  : use given charmap file\n");
253057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -u encoding : assume encoding\n");
254057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -w widths   : use screen widths file\n");
255057ca2d4SBaptiste Daroussin 	(void) fprintf(stderr, "  -i locsrc   : source file for locale\n");
256cc7edd25SThomas Munro 	(void) fprintf(stderr, "  -V version  : version string for locale\n");
257057ca2d4SBaptiste Daroussin 	exit(4);
258057ca2d4SBaptiste Daroussin }
259057ca2d4SBaptiste Daroussin 
260057ca2d4SBaptiste Daroussin int
main(int argc,char ** argv)261057ca2d4SBaptiste Daroussin main(int argc, char **argv)
262057ca2d4SBaptiste Daroussin {
263057ca2d4SBaptiste Daroussin 	int c;
264057ca2d4SBaptiste Daroussin 	char *lfname = NULL;
265057ca2d4SBaptiste Daroussin 	char *cfname = NULL;
266057ca2d4SBaptiste Daroussin 	char *wfname = NULL;
267057ca2d4SBaptiste Daroussin 	DIR *dir;
268057ca2d4SBaptiste Daroussin 
269057ca2d4SBaptiste Daroussin 	init_charmap();
270057ca2d4SBaptiste Daroussin 	init_collate();
271057ca2d4SBaptiste Daroussin 	init_ctype();
272057ca2d4SBaptiste Daroussin 	init_messages();
273057ca2d4SBaptiste Daroussin 	init_monetary();
274057ca2d4SBaptiste Daroussin 	init_numeric();
275057ca2d4SBaptiste Daroussin 	init_time();
276057ca2d4SBaptiste Daroussin 
277d836a9dbSJung-uk Kim #if YYDEBUG
278057ca2d4SBaptiste Daroussin 	yydebug = 0;
279d836a9dbSJung-uk Kim #endif
280057ca2d4SBaptiste Daroussin 
281057ca2d4SBaptiste Daroussin 	(void) setlocale(LC_ALL, "");
282057ca2d4SBaptiste Daroussin 
283cc7edd25SThomas Munro 	while ((c = getopt(argc, argv, "blw:i:cf:u:vUDV:")) != -1) {
284057ca2d4SBaptiste Daroussin 		switch (c) {
285057ca2d4SBaptiste Daroussin 		case 'D':
286057ca2d4SBaptiste Daroussin 			bsd = 1;
287057ca2d4SBaptiste Daroussin 			break;
2884644f9beSYuri Pankov 		case 'b':
2894644f9beSYuri Pankov 		case 'l':
2904644f9beSYuri Pankov 			if (byteorder != 0)
2914644f9beSYuri Pankov 				usage();
2924644f9beSYuri Pankov 			byteorder = c == 'b' ? 4321 : 1234;
2934644f9beSYuri Pankov 			break;
294057ca2d4SBaptiste Daroussin 		case 'v':
295057ca2d4SBaptiste Daroussin 			verbose++;
296057ca2d4SBaptiste Daroussin 			break;
297057ca2d4SBaptiste Daroussin 		case 'i':
298057ca2d4SBaptiste Daroussin 			lfname = optarg;
299057ca2d4SBaptiste Daroussin 			break;
300057ca2d4SBaptiste Daroussin 		case 'u':
301057ca2d4SBaptiste Daroussin 			set_wide_encoding(optarg);
302057ca2d4SBaptiste Daroussin 			break;
303057ca2d4SBaptiste Daroussin 		case 'f':
304057ca2d4SBaptiste Daroussin 			cfname = optarg;
305057ca2d4SBaptiste Daroussin 			break;
306057ca2d4SBaptiste Daroussin 		case 'U':
307057ca2d4SBaptiste Daroussin 			undefok++;
308057ca2d4SBaptiste Daroussin 			break;
309057ca2d4SBaptiste Daroussin 		case 'c':
310057ca2d4SBaptiste Daroussin 			warnok++;
311057ca2d4SBaptiste Daroussin 			break;
312057ca2d4SBaptiste Daroussin 		case 'w':
313057ca2d4SBaptiste Daroussin 			wfname = optarg;
314057ca2d4SBaptiste Daroussin 			break;
315057ca2d4SBaptiste Daroussin 		case '?':
316057ca2d4SBaptiste Daroussin 			usage();
317057ca2d4SBaptiste Daroussin 			break;
318cc7edd25SThomas Munro 		case 'V':
319cc7edd25SThomas Munro 			version = optarg;
320cc7edd25SThomas Munro 			break;
321057ca2d4SBaptiste Daroussin 		}
322057ca2d4SBaptiste Daroussin 	}
323057ca2d4SBaptiste Daroussin 
324057ca2d4SBaptiste Daroussin 	if ((argc - 1) != (optind)) {
325057ca2d4SBaptiste Daroussin 		usage();
326057ca2d4SBaptiste Daroussin 	}
327057ca2d4SBaptiste Daroussin 	locname = argv[argc - 1];
328057ca2d4SBaptiste Daroussin 	if (verbose) {
329057ca2d4SBaptiste Daroussin 		(void) printf("Processing locale %s.\n", locname);
330057ca2d4SBaptiste Daroussin 	}
331057ca2d4SBaptiste Daroussin 
332cc7edd25SThomas Munro 	if (version && strlen(version) >= XLOCALE_DEF_VERSION_LEN) {
333cc7edd25SThomas Munro 		(void) fprintf(stderr, "Version string too long.\n");
334cc7edd25SThomas Munro 		exit(1);
335cc7edd25SThomas Munro 	}
336cc7edd25SThomas Munro 
337057ca2d4SBaptiste Daroussin 	if (cfname) {
338057ca2d4SBaptiste Daroussin 		if (verbose)
339057ca2d4SBaptiste Daroussin 			(void) printf("Loading charmap %s.\n", cfname);
340057ca2d4SBaptiste Daroussin 		reset_scanner(cfname);
341057ca2d4SBaptiste Daroussin 		(void) yyparse();
342057ca2d4SBaptiste Daroussin 	}
343057ca2d4SBaptiste Daroussin 
344057ca2d4SBaptiste Daroussin 	if (wfname) {
345057ca2d4SBaptiste Daroussin 		if (verbose)
346057ca2d4SBaptiste Daroussin 			(void) printf("Loading widths %s.\n", wfname);
347057ca2d4SBaptiste Daroussin 		reset_scanner(wfname);
348057ca2d4SBaptiste Daroussin 		(void) yyparse();
349057ca2d4SBaptiste Daroussin 	}
350057ca2d4SBaptiste Daroussin 
351057ca2d4SBaptiste Daroussin 	if (verbose) {
352057ca2d4SBaptiste Daroussin 		(void) printf("Loading POSIX portable characters.\n");
353057ca2d4SBaptiste Daroussin 	}
354057ca2d4SBaptiste Daroussin 	add_charmap_posix();
355057ca2d4SBaptiste Daroussin 
356057ca2d4SBaptiste Daroussin 	if (lfname) {
357057ca2d4SBaptiste Daroussin 		reset_scanner(lfname);
358057ca2d4SBaptiste Daroussin 	} else {
359057ca2d4SBaptiste Daroussin 		reset_scanner(NULL);
360057ca2d4SBaptiste Daroussin 	}
361057ca2d4SBaptiste Daroussin 
362057ca2d4SBaptiste Daroussin 	/* make the directory for the locale if not already present */
363057ca2d4SBaptiste Daroussin 	if (!bsd) {
364057ca2d4SBaptiste Daroussin 		while ((dir = opendir(locname)) == NULL) {
365057ca2d4SBaptiste Daroussin 			if ((errno != ENOENT) ||
366057ca2d4SBaptiste Daroussin 			    (mkdir(locname, 0755) <  0)) {
367ead8d64aSEnji Cooper 				errf("%s", strerror(errno));
368057ca2d4SBaptiste Daroussin 			}
369057ca2d4SBaptiste Daroussin 		}
370057ca2d4SBaptiste Daroussin 		(void) closedir(dir);
371057ca2d4SBaptiste Daroussin 		(void) mkdir(dirname(category_file()), 0755);
372057ca2d4SBaptiste Daroussin 	}
373057ca2d4SBaptiste Daroussin 
374057ca2d4SBaptiste Daroussin 	(void) yyparse();
375057ca2d4SBaptiste Daroussin 	if (verbose) {
376057ca2d4SBaptiste Daroussin 		(void) printf("All done.\n");
377057ca2d4SBaptiste Daroussin 	}
378057ca2d4SBaptiste Daroussin 	return (warnings ? 1 : 0);
379057ca2d4SBaptiste Daroussin }
380