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