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