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