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