1/*	$NetBSD: yacc.y,v 1.11 2016/06/28 09:24:46 wiz 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.11 2016/06/28 09:24:46 wiz 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
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		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
221static void
222set_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
237static void
238set_invalid(u_int32_t inv)
239{
240	invalid = inv;
241	use_invalid = 1;
242}
243
244static void
245register_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
267static void
268do_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		errc(EXIT_FAILURE, ret, NULL);
288}
289
290__dead static void
291usage(void)
292{
293	fprintf(stderr, "Usage: %s [-dm] [-o outfile] [infile]\n",
294	    getprogname());
295	exit(EXIT_FAILURE);
296}
297
298int
299main(int argc, char **argv)
300{
301	int ch;
302	extern char *optarg;
303	extern int optind;
304	FILE *in = NULL;
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, "%s", 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