Pre-2.0 release: Sync with HAMMER 64 - NFS and cross-device link fixes.
[dragonfly.git] / usr.bin / mkesdb / yacc.y
blob8d85ab5045931e99711559724d14397b558c20c8
1 /* $NetBSD: src/usr.bin/mkesdb/yacc.y,v 1.3 2004/01/02 12:09:48 itojun Exp $ */
2 /* $DragonFly: src/usr.bin/mkesdb/yacc.y,v 1.2 2008/07/10 18:29:51 swildner Exp $ */
4 %{
5 /*-
6 * Copyright (c)2003 Citrus Project,
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
31 #include <sys/types.h>
32 #include <sys/queue.h>
33 #include <assert.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
42 #include "citrus_namespace.h"
43 #include "citrus_types.h"
44 #include "citrus_region.h"
45 #include "citrus_esdb_file.h"
46 #include "citrus_db_hash.h"
47 #include "citrus_db_factory.h"
48 #include "citrus_lookup_factory.h"
50 #include "ldef.h"
52 extern FILE *yyin;
54 static int debug = 0, num_csids = 0;
55 static char *output = NULL;
56 static char *name, *encoding, *variable;
57 static uint32_t invalid;
58 static int use_invalid = 0;
59 static struct named_csid_list named_csids;
61 static void dump_file(void);
62 static void register_named_csid(char *, uint32_t);
63 static void set_prop_string(const char *, char **, char **);
64 static void set_invalid(uint32_t);
66 %union {
67 uint32_t i_value;
68 char *s_value;
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
78 file : property
79 { dump_file(); }
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
89 name : R_NAME L_STRING
91 set_prop_string("NAME", &name, &$2);
94 encoding : R_ENCODING L_STRING
96 set_prop_string("ENCODING", &encoding, &$2);
98 variable : R_VARIABLE L_STRING
100 set_prop_string("VARIABLE", &variable, &$2);
102 defcsid : R_DEFCSID L_STRING L_IMM
104 register_named_csid($2, $3);
105 $2 = NULL;
107 invalid : R_INVALID L_IMM
109 set_invalid($2);
114 yyerror(const char *s)
116 fprintf(stderr, "%s in %d\n", s, line_number);
118 return (0);
121 #define CHKERR(ret, func, a) \
122 do { \
123 ret = func a; \
124 if (ret) \
125 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
126 } while (/*CONSTCOND*/0)
127 static void
128 dump_file(void)
130 int ret;
131 FILE *fp;
132 struct _db_factory *df;
133 struct _region data;
134 struct named_csid *csid;
135 char buf[100];
136 int i;
137 void *serialized;
138 size_t size;
140 ret = 0;
141 if (!name) {
142 fprintf(stderr, "NAME is mandatory.\n");
143 ret = 1;
145 if (!encoding) {
146 fprintf(stderr, "ENCODING is mandatory.\n");
147 ret = 1;
149 if (ret)
150 exit(1);
153 * build database
155 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
157 /* store version */
158 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION,
159 _CITRUS_ESDB_VERSION));
161 /* store encoding */
162 CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING,
163 encoding));
165 /* store variable */
166 if (variable)
167 CHKERR(ret, _db_factory_addstr_by_s,
168 (df, _CITRUS_ESDB_SYM_VARIABLE, variable));
170 /* store invalid */
171 if (use_invalid)
172 CHKERR(ret, _db_factory_add32_by_s, (df,
173 _CITRUS_ESDB_SYM_INVALID,
174 invalid));
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",
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",
187 CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
188 i++;
192 * dump database to file
194 if (output)
195 fp = fopen(output, "wb");
196 else
197 fp = stdout;
199 if (fp == NULL) {
200 perror("fopen");
201 exit(1);
204 /* dump database body */
205 size = _db_factory_calc_size(df);
206 serialized = malloc(size);
207 _region_init(&data, serialized, size);
208 CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
209 if (fwrite(serialized, size, 1, fp) != 1)
210 err(EXIT_FAILURE, "fwrite");
212 fclose(fp);
215 static void
216 set_prop_string(const char *res, char **store, char **data)
218 char buf[256];
220 if (*store) {
221 snprintf(buf, sizeof(buf),
222 "%s is duplicated. ignored the one", res);
223 yyerror(buf);
224 return;
227 *store = *data;
228 *data = NULL;
231 static void
232 set_invalid(uint32_t inv)
234 invalid = inv;
235 use_invalid = 1;
238 static void
239 register_named_csid(char *sym, uint32_t val)
241 struct named_csid *csid;
243 STAILQ_FOREACH(csid, &named_csids, ci_entry) {
244 if (strcmp(csid->ci_symbol, sym) == 0) {
245 yyerror("multiply defined CSID");
246 exit(1);
250 csid = malloc(sizeof(*csid));
251 if (csid == NULL) {
252 perror("malloc");
253 exit(1);
255 csid->ci_symbol = sym;
256 csid->ci_csid = val;
257 STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry);
258 num_csids++;
261 static void
262 do_mkdb(FILE *in)
264 int ret;
265 FILE *out;
267 /* dump DB to file */
268 if (output)
269 out = fopen(output, "wb");
270 else
271 out = stdout;
273 if (out==NULL)
274 err(EXIT_FAILURE, "fopen");
276 ret = _lookup_factory_convert(out, in);
277 fclose(out);
278 if (ret && output)
279 unlink(output); /* dump failure */
280 if (ret)
281 errx(EXIT_FAILURE, "%s\n", strerror(ret));
284 static void
285 usage(void)
287 errx(EXIT_FAILURE,
288 "usage:\n"
289 "\t%s [-o outfile] [infile]\n"
290 "\t%s -m [-o outfile] [infile]",
291 getprogname(), getprogname());
295 main(int argc, char **argv)
297 int ch;
298 FILE *in = NULL;
299 int mkdb = 0;
301 while ((ch=getopt(argc, argv, "do:m")) != -1) {
302 switch (ch) {
303 case 'd':
304 debug = 1;
305 break;
306 case 'o':
307 output = strdup(optarg);
308 break;
309 case 'm':
310 mkdb = 1;
311 break;
312 default:
313 usage();
317 argc-=optind;
318 argv+=optind;
319 switch (argc) {
320 case 0:
321 in = stdin;
322 break;
323 case 1:
324 in = fopen(argv[0], "r");
325 if (!in)
326 err(EXIT_FAILURE, argv[0]);
327 break;
328 default:
329 usage();
332 if (mkdb)
333 do_mkdb(in);
334 else {
335 STAILQ_INIT(&named_csids);
336 yyin=in;
337 yyparse();
340 return (0);