yacc.y revision 219019
1/* $FreeBSD: head/usr.bin/mkesdb/yacc.y 219019 2011-02-25 00:04:39Z gabor $ */
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
54extern FILE			*yyin;
55
56static struct named_csid_list	 named_csids;
57static char			*encoding, *name, *output = NULL, *variable;
58static u_int32_t		 invalid;
59static int			 debug = 0, num_csids = 0, use_invalid = 0;
60
61static void	 dump_file(void);
62static void	 register_named_csid(char *, u_int32_t);
63static void	 set_invalid(u_int32_t);
64static 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
78file		: property
79		{ dump_file(); }
80
81property	: /* 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
89name		: R_NAME L_STRING
90		{
91			set_prop_string("NAME", &name, &$2);
92		}
93
94encoding	: R_ENCODING L_STRING
95		{
96			set_prop_string("ENCODING", &encoding, &$2);
97		}
98variable	: R_VARIABLE L_STRING
99		{
100			set_prop_string("VARIABLE", &variable, &$2);
101		}
102defcsid		: R_DEFCSID L_STRING L_IMM
103		{
104			register_named_csid($2, $3);
105			$2 = NULL;
106		}
107invalid		: R_INVALID L_IMM
108		{
109			set_invalid($2);
110		}
111%%
112
113int
114yyerror(const char *s)
115{
116
117	fprintf(stderr, "%s in %d\n", s, line_number);
118
119	return (0);
120}
121
122#define CHKERR(ret, func, a)						\
123do {									\
124	ret = func a;							\
125	if (ret)							\
126		errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret));	\
127} while (/*CONSTCOND*/0)
128static void
129dump_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
210static void
211set_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
226static void
227set_invalid(u_int32_t inv)
228{
229
230	invalid = inv;
231	use_invalid = 1;
232}
233
234static void
235register_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
257static void
258do_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
276static void
277usage(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
286int
287main(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