xref: /dragonfly/usr.bin/mkesdb/yacc.y (revision f746689a)
1 /*	$NetBSD: src/usr.bin/mkesdb/yacc.y,v 1.3 2004/01/02 12:09:48 itojun Exp $	*/
2 /*	$DragonFly: src/usr.bin/mkesdb/yacc.y,v 1.2 2008/07/10 18:29:51 swildner 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/types.h>
32 #include <sys/queue.h>
33 #include <assert.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 
42 #include "citrus_namespace.h"
43 #include "citrus_types.h"
44 #include "citrus_region.h"
45 #include "citrus_esdb_file.h"
46 #include "citrus_db_hash.h"
47 #include "citrus_db_factory.h"
48 #include "citrus_lookup_factory.h"
49 
50 #include "ldef.h"
51 
52 extern FILE	*yyin;
53 
54 static int			debug = 0, num_csids = 0;
55 static char			*output = NULL;
56 static char			*name, *encoding, *variable;
57 static uint32_t			invalid;
58 static int			use_invalid = 0;
59 static struct named_csid_list	named_csids;
60 
61 static void	dump_file(void);
62 static void	register_named_csid(char *, uint32_t);
63 static void	set_prop_string(const char *, char **, char **);
64 static void	set_invalid(uint32_t);
65 %}
66 %union {
67 	uint32_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 	fprintf(stderr, "%s in %d\n", s, line_number);
117 
118 	return (0);
119 }
120 
121 #define CHKERR(ret, func, a)						\
122 do {									\
123 	ret = func a;							\
124 	if (ret)							\
125 		errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret));	\
126 } while (/*CONSTCOND*/0)
127 static void
128 dump_file(void)
129 {
130 	int ret;
131 	FILE *fp;
132 	struct _db_factory *df;
133 	struct _region data;
134 	struct named_csid *csid;
135 	char buf[100];
136 	int i;
137 	void *serialized;
138 	size_t size;
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,
174 						     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 	if (output)
195 		fp = fopen(output, "wb");
196 	else
197 		fp = stdout;
198 
199 	if (fp == NULL) {
200 		perror("fopen");
201 		exit(1);
202 	}
203 
204 	/* dump database body */
205 	size = _db_factory_calc_size(df);
206 	serialized = malloc(size);
207 	_region_init(&data, serialized, size);
208 	CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
209 	if (fwrite(serialized, size, 1, fp) != 1)
210 		err(EXIT_FAILURE, "fwrite");
211 
212 	fclose(fp);
213 }
214 
215 static void
216 set_prop_string(const char *res, char **store, char **data)
217 {
218 	char buf[256];
219 
220 	if (*store) {
221 		snprintf(buf, sizeof(buf),
222 			 "%s is duplicated. ignored the one", res);
223 		yyerror(buf);
224 		return;
225 	}
226 
227 	*store = *data;
228 	*data = NULL;
229 }
230 
231 static void
232 set_invalid(uint32_t inv)
233 {
234 	invalid = inv;
235 	use_invalid = 1;
236 }
237 
238 static void
239 register_named_csid(char *sym, uint32_t val)
240 {
241 	struct named_csid *csid;
242 
243 	STAILQ_FOREACH(csid, &named_csids, ci_entry) {
244 		if (strcmp(csid->ci_symbol, sym) == 0) {
245 			yyerror("multiply defined CSID");
246 			exit(1);
247 		}
248 	}
249 
250 	csid = malloc(sizeof(*csid));
251 	if (csid == NULL) {
252 		perror("malloc");
253 		exit(1);
254 	}
255 	csid->ci_symbol = sym;
256 	csid->ci_csid = val;
257 	STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry);
258 	num_csids++;
259 }
260 
261 static void
262 do_mkdb(FILE *in)
263 {
264 	int ret;
265 	FILE *out;
266 
267         /* dump DB to file */
268 	if (output)
269 		out = fopen(output, "wb");
270 	else
271 		out = stdout;
272 
273 	if (out==NULL)
274 		err(EXIT_FAILURE, "fopen");
275 
276 	ret = _lookup_factory_convert(out, in);
277 	fclose(out);
278 	if (ret && output)
279 		unlink(output); /* dump failure */
280 	if (ret)
281 		errx(EXIT_FAILURE, "%s\n", strerror(ret));
282 }
283 
284 static void
285 usage(void)
286 {
287 	errx(EXIT_FAILURE,
288 	     "usage:\n"
289 	     "\t%s [-o outfile] [infile]\n"
290 	     "\t%s -m [-o outfile] [infile]",
291 	     getprogname(), getprogname());
292 }
293 
294 int
295 main(int argc, char **argv)
296 {
297 	int ch;
298 	FILE *in = NULL;
299 	int mkdb = 0;
300 
301 	while ((ch=getopt(argc, argv, "do:m")) != -1) {
302 		switch (ch) {
303 		case 'd':
304 			debug = 1;
305 			break;
306 		case 'o':
307 			output = strdup(optarg);
308 			break;
309 		case 'm':
310 			mkdb = 1;
311 			break;
312 		default:
313 			usage();
314 		}
315 	}
316 
317 	argc-=optind;
318 	argv+=optind;
319 	switch (argc) {
320 	case 0:
321 		in = stdin;
322 		break;
323 	case 1:
324 		in = fopen(argv[0], "r");
325 		if (!in)
326 			err(EXIT_FAILURE, argv[0]);
327 		break;
328 	default:
329 		usage();
330 	}
331 
332 	if (mkdb)
333 		do_mkdb(in);
334 	else {
335 		STAILQ_INIT(&named_csids);
336 		yyin=in;
337 		yyparse();
338 	}
339 
340 	return (0);
341 }
342