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