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