Home | History | Annotate | Line # | Download | only in mkesdb
yacc.y revision 1.2
      1 /*	$NetBSD: yacc.y,v 1.2 2003/10/27 00:12:43 lukem Exp $	*/
      2 
      3 %{
      4 /*-
      5  * Copyright (c)2003 Citrus Project,
      6  * All rights reserved.
      7  *
      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.
     16  *
     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.
     28  */
     29 
     30 #if HAVE_NBTOOL_CONFIG_H
     31 #include "nbtool_config.h"
     32 #endif
     33 
     34 #include <sys/cdefs.h>
     35 #if !defined(lint)
     36 __RCSID("$NetBSD: yacc.y,v 1.2 2003/10/27 00:12:43 lukem Exp $");
     37 #endif /* not lint */
     38 
     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>
     49 
     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"
     57 
     58 #include "ldef.h"
     59 
     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;
     66 
     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);
     71 %}
     72 %union {
     73 	u_int32_t	i_value;
     74 	char		*s_value;
     75 }
     76 
     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
     81 
     82 %%
     83 
     84 file		: property
     85 		{ dump_file(); }
     86 
     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
     94 
     95 name		: R_NAME L_STRING
     96 		{
     97 			set_prop_string("NAME", &name, &$2);
     98 		}
     99 
    100 encoding	: R_ENCODING L_STRING
    101 		{
    102 			set_prop_string("ENCODING", &encoding, &$2);
    103 		}
    104 variable	: R_VARIABLE L_STRING
    105 		{
    106 			set_prop_string("VARIABLE", &variable, &$2);
    107 		}
    108 defcsid		: R_DEFCSID L_STRING L_IMM
    109 		{
    110 			register_named_csid($2, $3);
    111 			$2 = NULL;
    112 		}
    113 invalid		: R_INVALID L_IMM
    114 		{
    115 			set_invalid($2);
    116 		}
    117 %%
    118 
    119 int
    120 yyerror(const char *s)
    121 {
    122 	fprintf(stderr, "%s in %d\n", s, line_number);
    123 
    124 	return (0);
    125 }
    126 
    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)
    135 {
    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;
    145 
    146 	ret = 0;
    147 	if (!name) {
    148 		fprintf(stderr, "NAME is mandatory.\n");
    149 		ret = 1;
    150 	}
    151 	if (!encoding) {
    152 		fprintf(stderr, "ENCODING is mandatory.\n");
    153 		ret = 1;
    154 	}
    155 	if (ret)
    156 		exit(1);
    157 
    158 	/*
    159 	 * build database
    160 	 */
    161 	CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
    162 
    163 	/* store version */
    164 	CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION,
    165 					     _CITRUS_ESDB_VERSION));
    166 
    167 	/* store encoding */
    168 	CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING,
    169 					      encoding));
    170 
    171 	/* store variable */
    172 	if (variable)
    173 		CHKERR(ret, _db_factory_addstr_by_s,
    174 		       (df, _CITRUS_ESDB_SYM_VARIABLE, variable));
    175 
    176 	/* store invalid */
    177 	if (use_invalid)
    178 		CHKERR(ret, _db_factory_add32_by_s, (df,
    179 						     _CITRUS_ESDB_SYM_INVALID,
    180 						     invalid));
    181 
    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 		sprintf(buf, _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", i);
    188 		CHKERR(ret, _db_factory_addstr_by_s,
    189 		       (df, buf, csid->ci_symbol));
    190 		sprintf(buf, _CITRUS_ESDB_SYM_CSID_PREFIX "%d", i);
    191 		CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
    192 		i++;
    193 	}
    194 
    195 	/*
    196 	 * dump database to file
    197 	 */
    198 	if (output)
    199 		fp = fopen(output, "wb");
    200 	else
    201 		fp = stdout;
    202 
    203 	if (fp == NULL) {
    204 		perror("fopen");
    205 		exit(1);
    206 	}
    207 
    208 	/* dump database body */
    209 	size = _db_factory_calc_size(df);
    210 	serialized = malloc(size);
    211 	_region_init(&data, serialized, size);
    212 	CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
    213 	if (fwrite(serialized, size, 1, fp) != 1)
    214 		err(EXIT_FAILURE, "fwrite");
    215 
    216 	fclose(fp);
    217 }
    218 
    219 static void
    220 set_prop_string(const char *res, char **store, char **data)
    221 {
    222 	char buf[256];
    223 
    224 	if (*store) {
    225 		snprintf(buf, sizeof(buf),
    226 			 "%s is duplicated. ignored the one", res);
    227 		yyerror(buf);
    228 		return;
    229 	}
    230 
    231 	*store = *data;
    232 	*data = NULL;
    233 }
    234 
    235 static void
    236 set_invalid(u_int32_t inv)
    237 {
    238 	invalid = inv;
    239 	use_invalid = 1;
    240 }
    241 
    242 static void
    243 register_named_csid(char *sym, u_int32_t val)
    244 {
    245 	struct named_csid *csid;
    246 
    247 	SIMPLEQ_FOREACH(csid, &named_csids, ci_entry) {
    248 		if (strcmp(csid->ci_symbol, sym) == 0) {
    249 			yyerror("multiply defined CSID");
    250 			exit(1);
    251 		}
    252 	}
    253 
    254 	csid = malloc(sizeof(*csid));
    255 	if (csid == NULL) {
    256 		perror("malloc");
    257 		exit(1);
    258 	}
    259 	csid->ci_symbol = sym;
    260 	csid->ci_csid = val;
    261 	SIMPLEQ_INSERT_TAIL(&named_csids, csid, ci_entry);
    262 	num_csids++;
    263 }
    264 
    265 static void
    266 do_mkdb(FILE *in)
    267 {
    268 	int ret;
    269 	FILE *out;
    270 
    271         /* dump DB to file */
    272 	if (output)
    273 		out = fopen(output, "wb");
    274 	else
    275 		out = stdout;
    276 
    277 	if (out==NULL)
    278 		err(EXIT_FAILURE, "fopen");
    279 
    280 	ret = _lookup_factory_convert(out, in);
    281 	fclose(out);
    282 	if (ret && output)
    283 		unlink(output); /* dump failure */
    284 	if (ret)
    285 		errx(EXIT_FAILURE, "%s\n", strerror(ret));
    286 }
    287 
    288 static void
    289 usage(void)
    290 {
    291 	errx(EXIT_FAILURE,
    292 	     "usage:\n"
    293 	     "\t%s [-o outfile] [infile]\n"
    294 	     "\t%s -m [-o outfile] [infile]",
    295 	     getprogname(), getprogname());
    296 }
    297 
    298 int
    299 main(int argc, char **argv)
    300 {
    301 	int ch;
    302 	extern char *optarg;
    303 	extern int optind;
    304 	FILE *in;
    305 	int mkdb = 0;
    306 
    307 	while ((ch=getopt(argc, argv, "do:m")) != EOF) {
    308 		switch (ch) {
    309 		case 'd':
    310 			debug = 1;
    311 			break;
    312 		case 'o':
    313 			output = strdup(optarg);
    314 			break;
    315 		case 'm':
    316 			mkdb = 1;
    317 			break;
    318 		default:
    319 			usage();
    320 		}
    321 	}
    322 
    323 	argc-=optind;
    324 	argv+=optind;
    325 	switch (argc) {
    326 	case 0:
    327 		in = stdin;
    328 		break;
    329 	case 1:
    330 		in = fopen(argv[0], "r");
    331 		if (!in)
    332 			err(EXIT_FAILURE, argv[0]);
    333 		break;
    334 	default:
    335 		usage();
    336 	}
    337 
    338 	if (mkdb)
    339 		do_mkdb(in);
    340 	else {
    341 		SIMPLEQ_INIT(&named_csids);
    342 		yyin=in;
    343 		yyparse();
    344 	}
    345 
    346 	return (0);
    347 }
    348