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