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