Note that fcntl(2) returns EINVAL for invalid command.
[netbsd-mini2440.git] / usr.bin / mkesdb / yacc.y
blob055173c87e6ffb12bffcfab6e2755184717fff93
1 /* $NetBSD: yacc.y,v 1.3 2004/01/02 12:09:48 itojun Exp $ */
3 %{
4 /*-
5 * Copyright (c)2003 Citrus Project,
6 * All rights reserved.
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.
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.
30 #if HAVE_NBTOOL_CONFIG_H
31 #include "nbtool_config.h"
32 #endif
34 #include <sys/cdefs.h>
35 #if !defined(lint)
36 __RCSID("$NetBSD: yacc.y,v 1.3 2004/01/02 12:09:48 itojun Exp $");
37 #endif /* not lint */
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>
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"
58 #include "ldef.h"
60 static int debug = 0, num_csids = 0;
61 static char *output = NULL;
62 static char *name, *encoding, *variable;
63 static u_int32_t invalid;
64 static int use_invalid = 0;
65 static struct named_csid_list named_csids;
67 static void dump_file(void);
68 static void register_named_csid(char *, u_int32_t);
69 static void set_prop_string(const char *, char **, char **);
70 static void set_invalid(u_int32_t);
72 %union {
73 u_int32_t i_value;
74 char *s_value;
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
84 file : property
85 { dump_file(); }
87 property : /* 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
95 name : R_NAME L_STRING
97 set_prop_string("NAME", &name, &$2);
100 encoding : R_ENCODING L_STRING
102 set_prop_string("ENCODING", &encoding, &$2);
104 variable : R_VARIABLE L_STRING
106 set_prop_string("VARIABLE", &variable, &$2);
108 defcsid : R_DEFCSID L_STRING L_IMM
110 register_named_csid($2, $3);
111 $2 = NULL;
113 invalid : R_INVALID L_IMM
115 set_invalid($2);
120 yyerror(const char *s)
122 fprintf(stderr, "%s in %d\n", s, line_number);
124 return (0);
127 #define CHKERR(ret, func, a) \
128 do { \
129 ret = func a; \
130 if (ret) \
131 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
132 } while (/*CONSTCOND*/0)
133 static void
134 dump_file(void)
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;
146 ret = 0;
147 if (!name) {
148 fprintf(stderr, "NAME is mandatory.\n");
149 ret = 1;
151 if (!encoding) {
152 fprintf(stderr, "ENCODING is mandatory.\n");
153 ret = 1;
155 if (ret)
156 exit(1);
159 * build database
161 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
163 /* store version */
164 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION,
165 _CITRUS_ESDB_VERSION));
167 /* store encoding */
168 CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING,
169 encoding));
171 /* store variable */
172 if (variable)
173 CHKERR(ret, _db_factory_addstr_by_s,
174 (df, _CITRUS_ESDB_SYM_VARIABLE, variable));
176 /* store invalid */
177 if (use_invalid)
178 CHKERR(ret, _db_factory_add32_by_s, (df,
179 _CITRUS_ESDB_SYM_INVALID,
180 invalid));
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",
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",
193 CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
194 i++;
198 * dump database to file
200 if (output)
201 fp = fopen(output, "wb");
202 else
203 fp = stdout;
205 if (fp == NULL) {
206 perror("fopen");
207 exit(1);
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");
218 fclose(fp);
221 static void
222 set_prop_string(const char *res, char **store, char **data)
224 char buf[256];
226 if (*store) {
227 snprintf(buf, sizeof(buf),
228 "%s is duplicated. ignored the one", res);
229 yyerror(buf);
230 return;
233 *store = *data;
234 *data = NULL;
237 static void
238 set_invalid(u_int32_t inv)
240 invalid = inv;
241 use_invalid = 1;
244 static void
245 register_named_csid(char *sym, u_int32_t val)
247 struct named_csid *csid;
249 SIMPLEQ_FOREACH(csid, &named_csids, ci_entry) {
250 if (strcmp(csid->ci_symbol, sym) == 0) {
251 yyerror("multiply defined CSID");
252 exit(1);
256 csid = malloc(sizeof(*csid));
257 if (csid == NULL) {
258 perror("malloc");
259 exit(1);
261 csid->ci_symbol = sym;
262 csid->ci_csid = val;
263 SIMPLEQ_INSERT_TAIL(&named_csids, csid, ci_entry);
264 num_csids++;
267 static void
268 do_mkdb(FILE *in)
270 int ret;
271 FILE *out;
273 /* dump DB to file */
274 if (output)
275 out = fopen(output, "wb");
276 else
277 out = stdout;
279 if (out==NULL)
280 err(EXIT_FAILURE, "fopen");
282 ret = _lookup_factory_convert(out, in);
283 fclose(out);
284 if (ret && output)
285 unlink(output); /* dump failure */
286 if (ret)
287 errx(EXIT_FAILURE, "%s\n", strerror(ret));
290 static void
291 usage(void)
293 errx(EXIT_FAILURE,
294 "usage:\n"
295 "\t%s [-o outfile] [infile]\n"
296 "\t%s -m [-o outfile] [infile]",
297 getprogname(), getprogname());
301 main(int argc, char **argv)
303 int ch;
304 extern char *optarg;
305 extern int optind;
306 FILE *in = NULL;
307 int mkdb = 0;
309 while ((ch=getopt(argc, argv, "do:m")) != EOF) {
310 switch (ch) {
311 case 'd':
312 debug = 1;
313 break;
314 case 'o':
315 output = strdup(optarg);
316 break;
317 case 'm':
318 mkdb = 1;
319 break;
320 default:
321 usage();
325 argc-=optind;
326 argv+=optind;
327 switch (argc) {
328 case 0:
329 in = stdin;
330 break;
331 case 1:
332 in = fopen(argv[0], "r");
333 if (!in)
334 err(EXIT_FAILURE, argv[0]);
335 break;
336 default:
337 usage();
340 if (mkdb)
341 do_mkdb(in);
342 else {
343 SIMPLEQ_INIT(&named_csids);
344 yyin=in;
345 yyparse();
348 return (0);