1 /* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $ */
2
3 %{
4 /*-
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * Copyright (c)2003 Citrus Project,
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
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
54 extern FILE *yyin;
55
56 static struct named_csid_list named_csids;
57 static char *encoding, *name, *output = NULL, *variable;
58 static u_int32_t invalid;
59 static int debug = 0, num_csids = 0, use_invalid = 0;
60
61 static void dump_file(void);
62 static void register_named_csid(char *, u_int32_t);
63 static void set_invalid(u_int32_t);
64 static 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
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
117 fprintf(stderr, "%s in %d\n", s, linenumber);
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
dump_file(void)129 dump_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
210 static void
set_prop_string(const char * res,char ** store,char ** data)211 set_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
226 static void
set_invalid(u_int32_t inv)227 set_invalid(u_int32_t inv)
228 {
229
230 invalid = inv;
231 use_invalid = 1;
232 }
233
234 static void
register_named_csid(char * sym,u_int32_t val)235 register_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
257 static void
do_mkdb(FILE * in)258 do_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
276 static void
usage(void)277 usage(void)
278 {
279 errx(EXIT_FAILURE,
280 "usage:\n"
281 "\t%s [-d] [-o outfile] [infile]\n"
282 "\t%s -m [-d] [-o outfile] [infile]",
283 getprogname(), getprogname());
284 }
285
286 int
main(int argc,char ** argv)287 main(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