xref: /freebsd/usr.bin/mkesdb/yacc.y (revision c697fb7f)
1 /* $FreeBSD$ */
2 /* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $	*/
3 
4 %{
5 /*-
6  * SPDX-License-Identifier: BSD-2-Clause
7  *
8  * Copyright (c)2003 Citrus Project,
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 #include <sys/types.h>
35 #include <sys/queue.h>
36 
37 #include <assert.h>
38 #include <err.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include "citrus_namespace.h"
47 #include "citrus_types.h"
48 #include "citrus_region.h"
49 #include "citrus_esdb_file.h"
50 #include "citrus_db_hash.h"
51 #include "citrus_db_factory.h"
52 #include "citrus_lookup_factory.h"
53 
54 #include "ldef.h"
55 
56 extern FILE			*yyin;
57 
58 static struct named_csid_list	 named_csids;
59 static char			*encoding, *name, *output = NULL, *variable;
60 static u_int32_t		 invalid;
61 static int			 debug = 0, num_csids = 0, use_invalid = 0;
62 
63 static void	 dump_file(void);
64 static void	 register_named_csid(char *, u_int32_t);
65 static void	 set_invalid(u_int32_t);
66 static void	 set_prop_string(const char *, char **, char **);
67 %}
68 %union {
69 	u_int32_t	i_value;
70 	char		*s_value;
71 }
72 
73 %token			R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID
74 %token			R_LN
75 %token <i_value>	L_IMM
76 %token <s_value>	L_STRING
77 
78 %%
79 
80 file		: property
81 		{ dump_file(); }
82 
83 property	: /* empty */
84 		| property R_LN
85 		| property name R_LN
86 		| property encoding R_LN
87 		| property variable R_LN
88 		| property defcsid R_LN
89 		| property invalid R_LN
90 
91 name		: R_NAME L_STRING
92 		{
93 			set_prop_string("NAME", &name, &$2);
94 		}
95 
96 encoding	: R_ENCODING L_STRING
97 		{
98 			set_prop_string("ENCODING", &encoding, &$2);
99 		}
100 variable	: R_VARIABLE L_STRING
101 		{
102 			set_prop_string("VARIABLE", &variable, &$2);
103 		}
104 defcsid		: R_DEFCSID L_STRING L_IMM
105 		{
106 			register_named_csid($2, $3);
107 			$2 = NULL;
108 		}
109 invalid		: R_INVALID L_IMM
110 		{
111 			set_invalid($2);
112 		}
113 %%
114 
115 int
116 yyerror(const char *s)
117 {
118 
119 	fprintf(stderr, "%s in %d\n", s, linenumber);
120 
121 	return (0);
122 }
123 
124 #define CHKERR(ret, func, a)						\
125 do {									\
126 	ret = func a;							\
127 	if (ret)							\
128 		errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret));	\
129 } while (/*CONSTCOND*/0)
130 static void
131 dump_file(void)
132 {
133 	struct _db_factory *df;
134 	struct _region data;
135 	struct named_csid *csid;
136 	FILE *fp;
137 	char buf[100];
138 	void *serialized;
139 	size_t size;
140 	int i, ret;
141 
142 	ret = 0;
143 	if (!name) {
144 		fprintf(stderr, "NAME is mandatory.\n");
145 		ret = 1;
146 	}
147 	if (!encoding) {
148 		fprintf(stderr, "ENCODING is mandatory.\n");
149 		ret = 1;
150 	}
151 	if (ret)
152 		exit(1);
153 
154 	/*
155 	 * build database
156 	 */
157 	CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
158 
159 	/* store version */
160 	CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION,
161 	    _CITRUS_ESDB_VERSION));
162 
163 	/* store encoding */
164 	CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING,
165 	    encoding));
166 
167 	/* store variable */
168 	if (variable)
169 		CHKERR(ret, _db_factory_addstr_by_s,
170 		    (df, _CITRUS_ESDB_SYM_VARIABLE, variable));
171 
172 	/* store invalid */
173 	if (use_invalid)
174 		CHKERR(ret, _db_factory_add32_by_s, (df,
175 		    _CITRUS_ESDB_SYM_INVALID, invalid));
176 
177 	/* store num of charsets */
178 	CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS,
179 	    num_csids));
180 	i = 0;
181 	STAILQ_FOREACH(csid, &named_csids, ci_entry) {
182 		snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d",
183 		    i);
184 		CHKERR(ret, _db_factory_addstr_by_s,
185 		    (df, buf, csid->ci_symbol));
186 		snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d",
187 		    i);
188 		CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
189 		i++;
190 	}
191 
192 	/*
193 	 * dump database to file
194 	 */
195 	fp = output ? fopen(output, "wb") : stdout;
196 	if (fp == NULL) {
197 		perror("fopen");
198 		exit(1);
199 	}
200 
201 	/* dump database body */
202 	size = _db_factory_calc_size(df);
203 	serialized = malloc(size);
204 	_region_init(&data, serialized, size);
205 	CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
206 	if (fwrite(serialized, size, 1, fp) != 1)
207 		err(EXIT_FAILURE, "fwrite");
208 
209 	fclose(fp);
210 }
211 
212 static void
213 set_prop_string(const char *res, char **store, char **data)
214 {
215 	char buf[256];
216 
217 	if (*store) {
218 		snprintf(buf, sizeof(buf),
219 		    "%s is duplicated. ignored the one", res);
220 		yyerror(buf);
221 		return;
222 	}
223 
224 	*store = *data;
225 	*data = NULL;
226 }
227 
228 static void
229 set_invalid(u_int32_t inv)
230 {
231 
232 	invalid = inv;
233 	use_invalid = 1;
234 }
235 
236 static void
237 register_named_csid(char *sym, u_int32_t val)
238 {
239 	struct named_csid *csid;
240 
241 	STAILQ_FOREACH(csid, &named_csids, ci_entry) {
242 		if (strcmp(csid->ci_symbol, sym) == 0) {
243 			yyerror("multiply defined CSID");
244 			exit(1);
245 		}
246 	}
247 
248 	csid = malloc(sizeof(*csid));
249 	if (csid == NULL) {
250 		perror("malloc");
251 		exit(1);
252 	}
253 	csid->ci_symbol = sym;
254 	csid->ci_csid = val;
255 	STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry);
256 	num_csids++;
257 }
258 
259 static void
260 do_mkdb(FILE *in)
261 {
262 	FILE *out;
263 	int ret;
264 
265         /* dump DB to file */
266 	out = output ? fopen(output, "wb") : stdout;
267 	if (out == NULL)
268 		err(EXIT_FAILURE, "fopen");
269 
270 	ret = _lookup_factory_convert(out, in);
271 	fclose(out);
272 	if (ret && output)
273 		unlink(output); /* dump failure */
274 	if (ret)
275 		errx(EXIT_FAILURE, "%s\n", strerror(ret));
276 }
277 
278 static void
279 usage(void)
280 {
281 	errx(EXIT_FAILURE,
282 	    "usage:\n"
283 	    "\t%s [-d] [-o outfile] [infile]\n"
284 	    "\t%s -m [-d] [-o outfile] [infile]",
285 	    getprogname(), getprogname());
286 }
287 
288 int
289 main(int argc, char **argv)
290 {
291 	FILE *in = NULL;
292 	int ch, mkdb = 0;
293 
294 	while ((ch = getopt(argc, argv, "do:m")) != EOF) {
295 		switch (ch) {
296 		case 'd':
297 			debug = 1;
298 			break;
299 		case 'o':
300 			output = strdup(optarg);
301 			break;
302 		case 'm':
303 			mkdb = 1;
304 			break;
305 		default:
306 			usage();
307 		}
308 	}
309 
310 	argc -= optind;
311 	argv += optind;
312 	switch (argc) {
313 	case 0:
314 		in = stdin;
315 		break;
316 	case 1:
317 		in = fopen(argv[0], "r");
318 		if (!in)
319 			err(EXIT_FAILURE, "%s", argv[0]);
320 		break;
321 	default:
322 		usage();
323 	}
324 
325 	if (mkdb)
326 		do_mkdb(in);
327 	else {
328 		STAILQ_INIT(&named_csids);
329 		yyin = in;
330 		yyparse();
331 	}
332 
333 	return (0);
334 }
335