yacc.y revision 1.1
1/*	$NetBSD: yacc.y,v 1.1 2003/06/26 06:30:18 tshiozak 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#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint)
36__RCSID("$NetBSD: yacc.y,v 1.1 2003/06/26 06:30:18 tshiozak Exp $");
37#endif /* LIBC_SCCS and 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
60static int			debug = 0, num_csids = 0;
61static char			*output = NULL;
62static char			*name, *encoding, *variable;
63static u_int32_t		invalid;
64static int			use_invalid = 0;
65static struct named_csid_list	named_csids;
66
67static void	dump_file(void);
68static void	register_named_csid(char *, u_int32_t);
69static void	set_prop_string(const char *, char **, char **);
70static 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
84file		: property
85		{ dump_file(); }
86
87property	: /* 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
95name		: R_NAME L_STRING
96		{
97			set_prop_string("NAME", &name, &$2);
98		}
99
100encoding	: R_ENCODING L_STRING
101		{
102			set_prop_string("ENCODING", &encoding, &$2);
103		}
104variable	: R_VARIABLE L_STRING
105		{
106			set_prop_string("VARIABLE", &variable, &$2);
107		}
108defcsid		: R_DEFCSID L_STRING L_IMM
109		{
110			register_named_csid($2, $3);
111			$2 = NULL;
112		}
113invalid		: R_INVALID L_IMM
114		{
115			set_invalid($2);
116		}
117%%
118
119int
120yyerror(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)						\
128do {									\
129	ret = func a;							\
130	if (ret)							\
131		errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret));	\
132} while (/*CONSTCOND*/0)
133static void
134dump_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		sprintf(buf, _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", i);
188		CHKERR(ret, _db_factory_addstr_by_s,
189		       (df, buf, csid->ci_symbol));
190		sprintf(buf, _CITRUS_ESDB_SYM_CSID_PREFIX "%d", i);
191		CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
192		i++;
193	}
194
195	/*
196	 * dump database to file
197	 */
198	if (output)
199		fp = fopen(output, "wb");
200	else
201		fp = stdout;
202
203	if (fp == NULL) {
204		perror("fopen");
205		exit(1);
206	}
207
208	/* dump database body */
209	size = _db_factory_calc_size(df);
210	serialized = malloc(size);
211	_region_init(&data, serialized, size);
212	CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
213	if (fwrite(serialized, size, 1, fp) != 1)
214		err(EXIT_FAILURE, "fwrite");
215
216	fclose(fp);
217}
218
219static void
220set_prop_string(const char *res, char **store, char **data)
221{
222	char buf[256];
223
224	if (*store) {
225		snprintf(buf, sizeof(buf),
226			 "%s is duplicated. ignored the one", res);
227		yyerror(buf);
228		return;
229	}
230
231	*store = *data;
232	*data = NULL;
233}
234
235static void
236set_invalid(u_int32_t inv)
237{
238	invalid = inv;
239	use_invalid = 1;
240}
241
242static void
243register_named_csid(char *sym, u_int32_t val)
244{
245	struct named_csid *csid;
246
247	SIMPLEQ_FOREACH(csid, &named_csids, ci_entry) {
248		if (strcmp(csid->ci_symbol, sym) == 0) {
249			yyerror("multiply defined CSID");
250			exit(1);
251		}
252	}
253
254	csid = malloc(sizeof(*csid));
255	if (csid == NULL) {
256		perror("malloc");
257		exit(1);
258	}
259	csid->ci_symbol = sym;
260	csid->ci_csid = val;
261	SIMPLEQ_INSERT_TAIL(&named_csids, csid, ci_entry);
262	num_csids++;
263}
264
265static void
266do_mkdb(FILE *in)
267{
268	int ret;
269	FILE *out;
270
271        /* dump DB to file */
272	if (output)
273		out = fopen(output, "wb");
274	else
275		out = stdout;
276
277	if (out==NULL)
278		err(EXIT_FAILURE, "fopen");
279
280	ret = _lookup_factory_convert(out, in);
281	fclose(out);
282	if (ret && output)
283		unlink(output); /* dump failure */
284	if (ret)
285		errx(EXIT_FAILURE, "%s\n", strerror(ret));
286}
287
288static void
289usage(void)
290{
291	errx(EXIT_FAILURE,
292	     "usage:\n"
293	     "\t%s [-o outfile] [infile]\n"
294	     "\t%s -m [-o outfile] [infile]",
295	     getprogname(), getprogname());
296}
297
298int
299main(int argc, char **argv)
300{
301	int ch;
302	extern char *optarg;
303	extern int optind;
304	FILE *in;
305	int mkdb = 0;
306
307	while ((ch=getopt(argc, argv, "do:m")) != EOF) {
308		switch (ch) {
309		case 'd':
310			debug = 1;
311			break;
312		case 'o':
313			output = strdup(optarg);
314			break;
315		case 'm':
316			mkdb = 1;
317			break;
318		default:
319			usage();
320		}
321	}
322
323	argc-=optind;
324	argv+=optind;
325	switch (argc) {
326	case 0:
327		in = stdin;
328		break;
329	case 1:
330		in = fopen(argv[0], "r");
331		if (!in)
332			err(EXIT_FAILURE, argv[0]);
333		break;
334	default:
335		usage();
336	}
337
338	if (mkdb)
339		do_mkdb(in);
340	else {
341		SIMPLEQ_INIT(&named_csids);
342		yyin=in;
343		yyparse();
344	}
345
346	return (0);
347}
348