xref: /netbsd-src/usr.bin/mkcsmapper/yacc.y (revision 8aeff4f5aef31e364aadc985cef6e0b7cd91deca)
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
yyerror(const char * s)214 yyerror(const char *s)
215 {
216 	warning(s);
217 	exit(1);
218 }
219 
220 void
put8(void * ptr,size_t ofs,u_int32_t val)221 put8(void *ptr, size_t ofs, u_int32_t val)
222 {
223 	*((u_int8_t *)ptr + ofs) = val;
224 }
225 
226 void
put16(void * ptr,size_t ofs,u_int32_t val)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
put32(void * ptr,size_t ofs,u_int32_t val)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
alloc_table(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
setup_map(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
create_rowcol_info(struct _region * r)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
create_rowcol_ext_ilseq_info(struct _region * r)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
dump_file(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*/
set_type(int type)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*/
set_name(char * str)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
set_src_zone(u_int32_t val)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
set_dst_invalid(u_int32_t val)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
set_dst_ilseq(u_int32_t val)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
set_oob_mode(u_int32_t val)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
set_dst_unit_bits(u_int32_t val)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
check_src(u_int32_t begin,u_int32_t end)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
store(const linear_zone_t * lz,u_int32_t dst,int inc)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
set_range(u_int32_t begin,u_int32_t end)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
set_src(linear_zone_t * lz,u_int32_t begin,u_int32_t end)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
do_mkdb(FILE * in)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
do_mkpv(FILE * in)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
usage(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
main(int argc,char ** argv)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