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