1 /* $FreeBSD$ */
2 /* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $ */
3
4 %{
5 /*-
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * Copyright (c)2003 Citrus Project,
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 #include <sys/types.h>
35 #include <sys/queue.h>
36
37 #include <assert.h>
38 #include <err.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #include "citrus_namespace.h"
47 #include "citrus_types.h"
48 #include "citrus_region.h"
49 #include "citrus_esdb_file.h"
50 #include "citrus_db_hash.h"
51 #include "citrus_db_factory.h"
52 #include "citrus_lookup_factory.h"
53
54 #include "ldef.h"
55
56 extern FILE *yyin;
57
58 static struct named_csid_list named_csids;
59 static char *encoding, *name, *output = NULL, *variable;
60 static u_int32_t invalid;
61 static int debug = 0, num_csids = 0, use_invalid = 0;
62
63 static void dump_file(void);
64 static void register_named_csid(char *, u_int32_t);
65 static void set_invalid(u_int32_t);
66 static void set_prop_string(const char *, char **, char **);
67 %}
68 %union {
69 u_int32_t i_value;
70 char *s_value;
71 }
72
73 %token R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID
74 %token R_LN
75 %token <i_value> L_IMM
76 %token <s_value> L_STRING
77
78 %%
79
80 file : property
81 { dump_file(); }
82
83 property : /* empty */
84 | property R_LN
85 | property name R_LN
86 | property encoding R_LN
87 | property variable R_LN
88 | property defcsid R_LN
89 | property invalid R_LN
90
91 name : R_NAME L_STRING
92 {
93 set_prop_string("NAME", &name, &$2);
94 }
95
96 encoding : R_ENCODING L_STRING
97 {
98 set_prop_string("ENCODING", &encoding, &$2);
99 }
100 variable : R_VARIABLE L_STRING
101 {
102 set_prop_string("VARIABLE", &variable, &$2);
103 }
104 defcsid : R_DEFCSID L_STRING L_IMM
105 {
106 register_named_csid($2, $3);
107 $2 = NULL;
108 }
109 invalid : R_INVALID L_IMM
110 {
111 set_invalid($2);
112 }
113 %%
114
115 int
116 yyerror(const char *s)
117 {
118
119 fprintf(stderr, "%s in %d\n", s, linenumber);
120
121 return (0);
122 }
123
124 #define CHKERR(ret, func, a) \
125 do { \
126 ret = func a; \
127 if (ret) \
128 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
129 } while (/*CONSTCOND*/0)
130 static void
dump_file(void)131 dump_file(void)
132 {
133 struct _db_factory *df;
134 struct _region data;
135 struct named_csid *csid;
136 FILE *fp;
137 char buf[100];
138 void *serialized;
139 size_t size;
140 int i, ret;
141
142 ret = 0;
143 if (!name) {
144 fprintf(stderr, "NAME is mandatory.\n");
145 ret = 1;
146 }
147 if (!encoding) {
148 fprintf(stderr, "ENCODING is mandatory.\n");
149 ret = 1;
150 }
151 if (ret)
152 exit(1);
153
154 /*
155 * build database
156 */
157 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
158
159 /* store version */
160 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION,
161 _CITRUS_ESDB_VERSION));
162
163 /* store encoding */
164 CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING,
165 encoding));
166
167 /* store variable */
168 if (variable)
169 CHKERR(ret, _db_factory_addstr_by_s,
170 (df, _CITRUS_ESDB_SYM_VARIABLE, variable));
171
172 /* store invalid */
173 if (use_invalid)
174 CHKERR(ret, _db_factory_add32_by_s, (df,
175 _CITRUS_ESDB_SYM_INVALID, invalid));
176
177 /* store num of charsets */
178 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS,
179 num_csids));
180 i = 0;
181 STAILQ_FOREACH(csid, &named_csids, ci_entry) {
182 snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d",
183 i);
184 CHKERR(ret, _db_factory_addstr_by_s,
185 (df, buf, csid->ci_symbol));
186 snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d",
187 i);
188 CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
189 i++;
190 }
191
192 /*
193 * dump database to file
194 */
195 fp = output ? fopen(output, "wb") : stdout;
196 if (fp == NULL) {
197 perror("fopen");
198 exit(1);
199 }
200
201 /* dump database body */
202 size = _db_factory_calc_size(df);
203 serialized = malloc(size);
204 _region_init(&data, serialized, size);
205 CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
206 if (fwrite(serialized, size, 1, fp) != 1)
207 err(EXIT_FAILURE, "fwrite");
208
209 fclose(fp);
210 }
211
212 static void
set_prop_string(const char * res,char ** store,char ** data)213 set_prop_string(const char *res, char **store, char **data)
214 {
215 char buf[256];
216
217 if (*store) {
218 snprintf(buf, sizeof(buf),
219 "%s is duplicated. ignored the one", res);
220 yyerror(buf);
221 return;
222 }
223
224 *store = *data;
225 *data = NULL;
226 }
227
228 static void
set_invalid(u_int32_t inv)229 set_invalid(u_int32_t inv)
230 {
231
232 invalid = inv;
233 use_invalid = 1;
234 }
235
236 static void
register_named_csid(char * sym,u_int32_t val)237 register_named_csid(char *sym, u_int32_t val)
238 {
239 struct named_csid *csid;
240
241 STAILQ_FOREACH(csid, &named_csids, ci_entry) {
242 if (strcmp(csid->ci_symbol, sym) == 0) {
243 yyerror("multiply defined CSID");
244 exit(1);
245 }
246 }
247
248 csid = malloc(sizeof(*csid));
249 if (csid == NULL) {
250 perror("malloc");
251 exit(1);
252 }
253 csid->ci_symbol = sym;
254 csid->ci_csid = val;
255 STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry);
256 num_csids++;
257 }
258
259 static void
do_mkdb(FILE * in)260 do_mkdb(FILE *in)
261 {
262 FILE *out;
263 int ret;
264
265 /* dump DB to file */
266 out = output ? fopen(output, "wb") : stdout;
267 if (out == NULL)
268 err(EXIT_FAILURE, "fopen");
269
270 ret = _lookup_factory_convert(out, in);
271 fclose(out);
272 if (ret && output)
273 unlink(output); /* dump failure */
274 if (ret)
275 errx(EXIT_FAILURE, "%s\n", strerror(ret));
276 }
277
278 static void
usage(void)279 usage(void)
280 {
281 errx(EXIT_FAILURE,
282 "usage:\n"
283 "\t%s [-d] [-o outfile] [infile]\n"
284 "\t%s -m [-d] [-o outfile] [infile]",
285 getprogname(), getprogname());
286 }
287
288 int
main(int argc,char ** argv)289 main(int argc, char **argv)
290 {
291 FILE *in = NULL;
292 int ch, mkdb = 0;
293
294 while ((ch = getopt(argc, argv, "do:m")) != EOF) {
295 switch (ch) {
296 case 'd':
297 debug = 1;
298 break;
299 case 'o':
300 output = strdup(optarg);
301 break;
302 case 'm':
303 mkdb = 1;
304 break;
305 default:
306 usage();
307 }
308 }
309
310 argc -= optind;
311 argv += optind;
312 switch (argc) {
313 case 0:
314 in = stdin;
315 break;
316 case 1:
317 in = fopen(argv[0], "r");
318 if (!in)
319 err(EXIT_FAILURE, "%s", argv[0]);
320 break;
321 default:
322 usage();
323 }
324
325 if (mkdb)
326 do_mkdb(in);
327 else {
328 STAILQ_INIT(&named_csids);
329 yyin = in;
330 yyparse();
331 }
332
333 return (0);
334 }
335