]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.bin/mkesdb/yacc.y
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.bin / mkesdb / yacc.y
1 /* $FreeBSD$ */
2 /* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $        */
3
4 %{
5 /*-
6  * Copyright (c)2003 Citrus Project,
7  * All rights reserved.
8  *
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.
17  *
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.
29  */
30
31 #include <sys/cdefs.h>
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
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
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
227 set_invalid(u_int32_t inv)
228 {
229
230         invalid = inv;
231         use_invalid = 1;
232 }
233
234 static void
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
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
277 usage(void)
278 {
279         errx(EXIT_FAILURE,
280             "usage:\n"
281             "\t%s [-o outfile] [infile]\n"
282             "\t%s -m [-o outfile] [infile]",
283             getprogname(), getprogname());
284 }
285
286 int
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 }