Home | History | Annotate | Line # | Download | only in mkcsmapper
yacc.y revision 1.1
      1 /*	$NetBSD: yacc.y,v 1.1 2003/06/26 06:30:15 tshiozak 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 #ifdef HAVE_CONFIG_H
     31 #include "config.h"
     32 #endif
     33 
     34 #include <sys/cdefs.h>
     35 #if defined(LIBC_SCCS) && !defined(lint)
     36 __RCSID("$NetBSD: yacc.y,v 1.1 2003/06/26 06:30:15 tshiozak Exp $");
     37 #endif /* LIBC_SCCS and 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 
     49 #include "ldef.h"
     50 
     51 #ifndef __packed
     52 #define __packed
     53 #endif
     54 
     55 #include "citrus_namespace.h"
     56 #include "citrus_types.h"
     57 #include "citrus_mapper_std_file.h"
     58 #include "citrus_region.h"
     59 #include "citrus_db_factory.h"
     60 #include "citrus_db_hash.h"
     61 #include "citrus_lookup_factory.h"
     62 #include "citrus_pivot_factory.h"
     63 
     64 int			debug = 0;
     65 static char		*output = NULL;
     66 static void		*table = NULL;
     67 static size_t		table_size;
     68 static char		*map_name;
     69 static int		map_type;
     70 static zone_t		src_zone;
     71 static u_int32_t	colmask, rowmask;
     72 static u_int32_t	dst_invalid, dst_unit_bits;
     73 static void		(*putfunc)(void *, size_t, u_int32_t) = 0;
     74 
     75 static u_int32_t	src_next;
     76 static int		next_valid;
     77 
     78 static u_int32_t	done_flag = 0;
     79 #define DF_TYPE			0x00000001
     80 #define DF_NAME			0x00000002
     81 #define DF_SRC_ZONE		0x00000004
     82 #define DF_DST_INVALID		0x00000008
     83 #define DF_DST_UNIT_BITS	0x00000010
     84 
     85 static void	dump_file(void);
     86 static void	setup_map(void);
     87 static void	set_type(int);
     88 static void	set_name(char *);
     89 static void	set_src_zone(const zone_t *);
     90 static void	set_dst_invalid(u_int32_t);
     91 static void	set_dst_unit_bits(u_int32_t);
     92 static void	calc_next(void);
     93 static int	check_src(u_int32_t, u_int32_t);
     94 static void	store(const linear_zone_t *, u_int32_t, int);
     95 static void	put8(void *, size_t, u_int32_t);
     96 static void	put16(void *, size_t, u_int32_t);
     97 static void	put32(void *, size_t, u_int32_t);
     98 %}
     99 
    100 %union {
    101 	u_int32_t	i_value;
    102 	char		*s_value;
    103 	zone_t		z_value;
    104 	linear_zone_t	lz_value;
    105 }
    106 
    107 %token			R_TYPE R_NAME R_SRC_ZONE R_DST_INVALID R_DST_UNIT_BITS
    108 %token			R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL
    109 %token			R_LN
    110 %token <i_value>	L_IMM
    111 %token <s_value>	L_STRING
    112 
    113 %type <z_value>		zone
    114 %type <lz_value>	src
    115 %type <i_value>		dst types
    116 
    117 %%
    118 
    119 file		: property mapping lns
    120 		{ dump_file(); }
    121 
    122 property	: /* empty */
    123 		| property R_LN
    124 		| property name
    125 		| property type
    126 		| property src_zone
    127 		| property dst_invalid
    128 		| property dst_unit_bits
    129 
    130 name		: R_NAME L_STRING { set_name($2); $2 = NULL; }
    131 type		: R_TYPE types { set_type($2); }
    132 types		: R_ROWCOL { $$ = R_ROWCOL; }
    133 src_zone	: R_SRC_ZONE zone { set_src_zone(&$2); }
    134 zone		: L_IMM '-' L_IMM {
    135 			$$.row_begin = $$.row_end = 0;
    136 			$$.col_begin = $1; $$.col_end = $3;
    137 			$$.col_bits = 32;
    138 		}
    139 		| L_IMM '-' L_IMM '/' L_IMM '-' L_IMM '/' L_IMM {
    140 			$$.row_begin = $1; $$.row_end = $3;
    141 			$$.col_begin = $5; $$.col_end = $7;
    142 			$$.col_bits = $9;
    143 		}
    144 
    145 dst_invalid	: R_DST_INVALID L_IMM { set_dst_invalid($2); }
    146 dst_unit_bits	: R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); }
    147 
    148 
    149 mapping		: begin_map map_elems R_END_MAP
    150 begin_map	: R_BEGIN_MAP lns { setup_map(); }
    151 
    152 map_elems	: /* empty */
    153 		| map_elems map_elem lns
    154 
    155 map_elem	: src '=' dst
    156 		{ store(&$1, $3, 0); }
    157 		| src '=' L_IMM '-'
    158 		{ store(&$1, $3, 1); }
    159 dst		: L_IMM
    160 		{
    161 			$$ = $1;
    162 		}
    163 		| R_INVALID
    164 		{
    165 			$$ = dst_invalid;
    166 		}
    167 
    168 src		: /* empty */
    169 		{
    170 			if (!next_valid) {
    171 				yyerror("cannot omit src");
    172 			}
    173 			$$.begin = $$.end = src_next;
    174 			calc_next();
    175 		}
    176 		| L_IMM
    177 		{
    178 			if (check_src($1, $1)) {
    179 				yyerror("illegal zone");
    180 			}
    181 			$$.begin = $$.end = $1;
    182 			src_next = $1;
    183 			calc_next();
    184 		}
    185 		| L_IMM '-' L_IMM
    186 		{
    187 			if (check_src($1, $3)) {
    188 				yyerror("illegal zone");
    189 			}
    190 			$$.begin = $1; $$.end = $3;
    191 			src_next = $3;
    192 			calc_next();
    193 		}
    194 		| '-' L_IMM
    195 		{
    196 			if (!next_valid) {
    197 				yyerror("cannot omit src");
    198 			}
    199 			if (check_src(src_next, $2)) {
    200 				yyerror("illegal zone");
    201 			}
    202 			$$.begin = src_next; $$.end = $2;
    203 			src_next = $2;
    204 			calc_next();
    205 		}
    206 lns		: R_LN
    207 		| lns R_LN
    208 
    209 %%
    210 
    211 static void
    212 warning(const char *s)
    213 {
    214 	fprintf(stderr, "%s in %d\n", s, line_number);
    215 }
    216 
    217 int
    218 yyerror(const char *s)
    219 {
    220 	warning(s);
    221 	exit(1);
    222 }
    223 
    224 void
    225 put8(void *ptr, size_t ofs, u_int32_t val)
    226 {
    227 	*((u_int8_t *)ptr + ofs) = val;
    228 }
    229 
    230 void
    231 put16(void *ptr, size_t ofs, u_int32_t val)
    232 {
    233 	u_int16_t oval = htons(val);
    234 	memcpy((u_int16_t *)ptr + ofs, &oval, 2);
    235 }
    236 
    237 void
    238 put32(void *ptr, size_t ofs, u_int32_t val)
    239 {
    240 	u_int32_t oval = htonl(val);
    241 	memcpy((u_int32_t *)ptr + ofs, &oval, 4);
    242 }
    243 
    244 static void
    245 alloc_table(void)
    246 {
    247 	size_t i;
    248 
    249 	table_size =
    250 	    (src_zone.row_end-src_zone.row_begin+1)*
    251 	    (src_zone.col_end-src_zone.col_begin+1);
    252 	table = malloc(table_size*dst_unit_bits/8);
    253 	if (!table) {
    254 		perror("malloc");
    255 		exit(1);
    256 	}
    257 
    258 	for (i=0; i<table_size; i++)
    259 		(*putfunc)(table, i, dst_invalid);
    260 }
    261 
    262 static void
    263 setup_map(void)
    264 {
    265 
    266 	if ((done_flag & DF_SRC_ZONE)==0) {
    267 		fprintf(stderr, "SRC_ZONE is mandatory.\n");
    268 		exit(1);
    269 	}
    270 	if ((done_flag & DF_DST_UNIT_BITS)==0) {
    271 		fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
    272 		exit(1);
    273 	}
    274 
    275 	if ((done_flag & DF_DST_INVALID) == 0)
    276 		dst_invalid = 0xFFFFFFFF;
    277 
    278 	alloc_table();
    279 }
    280 
    281 static void
    282 create_rowcol_info(struct _region *r)
    283 {
    284 	void *ptr;
    285 	size_t ofs;
    286 
    287 	ofs = 0;
    288 	ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
    289 	if (ptr==NULL)
    290 		err(EXIT_FAILURE, "malloc");
    291 
    292 	put32(ptr, ofs, src_zone.col_bits); ofs++;
    293 	put32(ptr, ofs, dst_invalid); ofs++;
    294 	put32(ptr, ofs, src_zone.row_begin); ofs++;
    295 	put32(ptr, ofs, src_zone.row_end); ofs++;
    296 	put32(ptr, ofs, src_zone.col_begin); ofs++;
    297 	put32(ptr, ofs, src_zone.col_end); ofs++;
    298 	put32(ptr, ofs, dst_unit_bits); ofs++;
    299 	put32(ptr, ofs, 0); /* pad */
    300 
    301 	_region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
    302 }
    303 
    304 #define CHKERR(ret, func, a)						\
    305 do {									\
    306 	ret = func a;							\
    307 	if (ret)							\
    308 		errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret));	\
    309 } while (/*CONSTCOND*/0)
    310 
    311 static void
    312 dump_file(void)
    313 {
    314 	FILE *fp;
    315 	int ret;
    316 	struct _db_factory *df;
    317 	struct _region data;
    318 	void *serialized;
    319 	size_t size;
    320 
    321 	/*
    322 	 * build database
    323 	 */
    324 	CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
    325 
    326 	/* store type */
    327 	CHKERR(ret, _db_factory_addstr_by_s,
    328 	       (df, _CITRUS_MAPPER_STD_SYM_TYPE,
    329 		_CITRUS_MAPPER_STD_TYPE_ROWCOL));
    330 
    331 	/* store info */
    332 	create_rowcol_info(&data);
    333 	CHKERR(ret, _db_factory_add_by_s,
    334 	       (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1));
    335 
    336 	/* store table */
    337 	_region_init(&data, table, table_size*dst_unit_bits/8);
    338 	CHKERR(ret, _db_factory_add_by_s,
    339 	       (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1));
    340 
    341 	/*
    342 	 * dump database to file
    343 	 */
    344 	if (output)
    345 		fp = fopen(output, "wb");
    346 	else
    347 		fp = stdout;
    348 
    349 	if (fp == NULL) {
    350 		perror("fopen");
    351 		exit(1);
    352 	}
    353 
    354 	/* dump database body */
    355 	size = _db_factory_calc_size(df);
    356 	serialized = malloc(size);
    357 	_region_init(&data, serialized, size);
    358 	CHKERR(ret, _db_factory_serialize,
    359 	       (df, _CITRUS_MAPPER_STD_MAGIC, &data));
    360 	if (fwrite(serialized, size, 1, fp) != 1)
    361 		err(EXIT_FAILURE, "fwrite");
    362 
    363 	fclose(fp);
    364 }
    365 
    366 static void
    367 /*ARGSUSED*/
    368 set_type(int type)
    369 {
    370 
    371 	if (done_flag & DF_TYPE) {
    372 		warning("TYPE is duplicated. ignored this one");
    373 		return;
    374 	}
    375 
    376 	map_type = type;
    377 
    378 	done_flag |= DF_TYPE;
    379 }
    380 static void
    381 /*ARGSUSED*/
    382 set_name(char *str)
    383 {
    384 
    385 	if (done_flag & DF_NAME) {
    386 		warning("NAME is duplicated. ignored this one");
    387 		return;
    388 	}
    389 
    390 	map_name = str;
    391 
    392 	done_flag |= DF_NAME;
    393 }
    394 static void
    395 set_src_zone(const zone_t *zone)
    396 {
    397 
    398 	if (done_flag & DF_SRC_ZONE) {
    399 		warning("SRC_ZONE is duplicated. ignored this one");
    400 		return;
    401 	}
    402 
    403 	/* sanity check */
    404 	if (zone->col_bits<1 || zone->col_bits>32) {
    405 		goto bad;
    406 	}
    407 
    408 	if (zone->col_bits!=32)
    409 		colmask = (1 << zone->col_bits)-1;
    410 	else
    411 		colmask = ~0;
    412 	rowmask = ~colmask;
    413 	if (zone->col_begin > zone->col_end ||
    414 	    zone->row_begin > zone->row_end ||
    415 	    (zone->col_begin & rowmask)!=0 ||
    416 	    (zone->col_end & rowmask)!=0 ||
    417 	    ((zone->row_begin << zone->col_bits) & colmask)!=0 ||
    418 	    ((zone->row_end << zone->col_bits) & colmask)!=0) {
    419 bad:
    420 		yyerror("Illegal argument for SRC_ZONE");
    421 	}
    422 
    423 	src_zone = *zone;
    424 
    425 	done_flag |= DF_SRC_ZONE;
    426 
    427 	return;
    428 }
    429 static void
    430 set_dst_invalid(u_int32_t val)
    431 {
    432 
    433 	if (done_flag & DF_DST_INVALID) {
    434 		warning("DST_INVALID is duplicated. ignored this one");
    435 		return;
    436 	}
    437 
    438 	dst_invalid = val;
    439 
    440 	done_flag |= DF_DST_INVALID;
    441 }
    442 static void
    443 set_dst_unit_bits(u_int32_t val)
    444 {
    445 
    446 	if (done_flag & DF_DST_UNIT_BITS) {
    447 		warning("DST_UNIT_BITS is duplicated. ignored this one");
    448 		return;
    449 	}
    450 
    451 	switch (val) {
    452 	case 8:
    453 		putfunc = &put8;
    454 		dst_unit_bits = val;
    455 		break;
    456 	case 16:
    457 		putfunc = &put16;
    458 		dst_unit_bits = val;
    459 		break;
    460 	case 32:
    461 		putfunc = &put32;
    462 		dst_unit_bits = val;
    463 		break;
    464 	default:
    465 		yyerror("Illegal argument for DST_UNIT_BITS");
    466 	}
    467 	done_flag |= DF_DST_UNIT_BITS;
    468 }
    469 static void
    470 calc_next(void)
    471 {
    472 	src_next++;
    473 	if (check_src(src_next, src_next))
    474 		next_valid = 0;
    475 	else
    476 		next_valid = 1;
    477 }
    478 static int
    479 check_src(u_int32_t begin, u_int32_t end)
    480 {
    481 	u_int32_t b_row = 0, e_row = 0, b_col, e_col;
    482 
    483 	b_col = begin & colmask;
    484 	e_col = end & colmask;
    485 	if (src_zone.col_bits != 32) {
    486 		b_row = begin >> src_zone.col_bits;
    487 		e_row = end >> src_zone.col_bits;
    488 	}
    489 
    490 	if (b_row != e_row ||
    491 	    b_row < src_zone.row_begin ||
    492 	    b_row > src_zone.row_end ||
    493 	    e_row < src_zone.row_begin ||
    494 	    e_row > src_zone.row_end ||
    495 	    b_col < src_zone.col_begin ||
    496 	    b_col > src_zone.col_end ||
    497 	    e_col < src_zone.col_begin ||
    498 	    e_col > src_zone.col_end ||
    499 	    b_col>e_col) {
    500 		return (-1);
    501 	}
    502 	return (0);
    503 }
    504 static void
    505 store(const linear_zone_t *lz, u_int32_t dst, int inc)
    506 {
    507 	u_int32_t row=0, col, ofs, i;
    508 
    509 	if (src_zone.col_bits != 32)
    510 		row = lz->begin >> src_zone.col_bits;
    511 	col = lz->begin & colmask;
    512 	ofs =
    513 	    (row-src_zone.row_begin)*(src_zone.col_end-src_zone.col_begin+1) +
    514 	    (col-src_zone.col_begin);
    515 	for (i=lz->end-lz->begin+1; i>0; i--) {
    516 		(*putfunc)(table, ofs++, dst);
    517 		if (inc)
    518 			dst++;
    519 	}
    520 }
    521 
    522 static void
    523 do_mkdb(FILE *in)
    524 {
    525 	int ret;
    526 	FILE *out;
    527 
    528         /* dump DB to file */
    529 	if (output)
    530 		out = fopen(output, "wb");
    531 	else
    532 		out = stdout;
    533 
    534 	if (out==NULL)
    535 		err(EXIT_FAILURE, "fopen");
    536 
    537 	ret = _lookup_factory_convert(out, in);
    538 	fclose(out);
    539 	if (ret && output)
    540 		unlink(output); /* dump failure */
    541 }
    542 
    543 static void
    544 do_mkpv(FILE *in)
    545 {
    546 	int ret;
    547 	FILE *out;
    548 
    549         /* dump pivot to file */
    550 	if (output)
    551 		out = fopen(output, "wb");
    552 	else
    553 		out = stdout;
    554 
    555 	if (out==NULL)
    556 		err(EXIT_FAILURE, "fopen");
    557 
    558 	ret = _pivot_factory_convert(out, in);
    559 	fclose(out);
    560 	if (ret && output)
    561 		unlink(output); /* dump failure */
    562 	if (ret)
    563 		errx(EXIT_FAILURE, "%s\n", strerror(ret));
    564 }
    565 
    566 static void
    567 usage(void)
    568 {
    569 	warnx("usage: \n"
    570 	      "\t%s [-d] [-o outfile] [infile]\n"
    571 	      "\t%s -m [-d] [-o outfile] [infile]\n"
    572 	      "\t%s -p [-d] [-o outfile] [infile]\n",
    573 	      getprogname(), getprogname(), getprogname());
    574 	exit(1);
    575 }
    576 
    577 int
    578 main(int argc, char **argv)
    579 {
    580 	int ch;
    581 	extern char *optarg;
    582 	extern int optind;
    583 	FILE *in;
    584 	int mkdb = 0, mkpv = 0;
    585 
    586 	while ((ch=getopt(argc, argv, "do:mp")) != EOF) {
    587 		switch (ch) {
    588 		case 'd':
    589 			debug=1;
    590 			break;
    591 		case 'o':
    592 			output = strdup(optarg);
    593 			break;
    594 		case 'm':
    595 			mkdb = 1;
    596 			break;
    597 		case 'p':
    598 			mkpv = 1;
    599 			break;
    600 		default:
    601 			usage();
    602 		}
    603 	}
    604 
    605 	argc-=optind;
    606 	argv+=optind;
    607 	switch (argc) {
    608 	case 0:
    609 		in = stdin;
    610 		break;
    611 	case 1:
    612 		in = fopen(argv[0], "r");
    613 		if (!in)
    614 			err(EXIT_FAILURE, argv[0]);
    615 		break;
    616 	default:
    617 		usage();
    618 	}
    619 
    620 	if (mkdb)
    621 		do_mkdb(in);
    622 	else if (mkpv)
    623 		do_mkpv(in);
    624 	else {
    625 		yyin = in;
    626 		yyparse();
    627 	}
    628 
    629 	return (0);
    630 }
    631