Pull up CVS idents from FreeBSD to match our current version.
[dragonfly.git] / usr.bin / mkcsmapper / yacc.y
bloba4f84b200418e632e9a104ab636c788149c23b39
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 $ */
4 %{
5 /*-
6 * Copyright (c)2003 Citrus Project,
7 * All rights reserved.
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.
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.
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>
41 #include <netinet/in.h>
43 #include "ldef.h"
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"
54 extern FILE * yyin;
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;
67 static u_int32_t src_next;
68 static int next_valid;
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
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);
96 %union {
97 u_int32_t i_value;
98 char *s_value;
99 zone_t z_value;
100 linear_zone_t lz_value;
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
111 %type <z_value> zone
112 %type <lz_value> src
113 %type <i_value> dst types oob_mode_sel
117 file : property mapping lns
118 { dump_file(); }
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
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;
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;
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); }
150 oob_mode_sel : R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; }
151 | R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; }
153 mapping : begin_map map_elems R_END_MAP
154 begin_map : R_BEGIN_MAP lns { setup_map(); }
156 map_elems : /* empty */
157 | map_elems map_elem lns
159 map_elem : src '=' dst
160 { store(&$1, $3, 0); }
161 | src '=' L_IMM '-'
162 { store(&$1, $3, 1); }
163 dst : L_IMM
165 $$ = $1;
167 | R_INVALID
169 $$ = dst_invalid;
171 | R_ILSEQ
173 $$ = dst_ilseq;
176 src : /* empty */
178 if (!next_valid) {
179 yyerror("cannot omit src");
181 $$.begin = $$.end = src_next;
182 calc_next();
184 | L_IMM
186 if (check_src($1, $1)) {
187 yyerror("illegal zone");
189 $$.begin = $$.end = $1;
190 src_next = $1;
191 calc_next();
193 | L_IMM '-' L_IMM
195 if (check_src($1, $3)) {
196 yyerror("illegal zone");
198 $$.begin = $1; $$.end = $3;
199 src_next = $3;
200 calc_next();
202 | '-' L_IMM
204 if (!next_valid) {
205 yyerror("cannot omit src");
207 if (check_src(src_next, $2)) {
208 yyerror("illegal zone");
210 $$.begin = src_next; $$.end = $2;
211 src_next = $2;
212 calc_next();
214 lns : R_LN
215 | lns R_LN
219 static void
220 warning(const char *s)
222 fprintf(stderr, "%s in %d\n", s, line_number);
226 yyerror(const char *s)
228 warning(s);
229 exit(1);
232 void
233 put8(void *ptr, size_t ofs, u_int32_t val)
235 *((u_int8_t *)ptr + ofs) = val;
238 void
239 put16(void *ptr, size_t ofs, u_int32_t val)
241 u_int16_t oval = htons(val);
242 memcpy((u_int16_t *)ptr + ofs, &oval, 2);
245 void
246 put32(void *ptr, size_t ofs, u_int32_t val)
248 u_int32_t oval = htonl(val);
249 memcpy((u_int32_t *)ptr + ofs, &oval, 4);
252 static void
253 alloc_table(void)
255 size_t i;
256 u_int32_t val = 0;
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);
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:
277 for (i = 0; i < table_size; i++)
278 (*putfunc)(table, i, val);
281 static void
282 setup_map(void)
285 if ((done_flag & DF_SRC_ZONE)==0) {
286 fprintf(stderr, "SRC_ZONE is mandatory.\n");
287 exit(1);
289 if ((done_flag & DF_DST_UNIT_BITS)==0) {
290 fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
291 exit(1);
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;
301 alloc_table();
304 static void
305 create_rowcol_info(struct _region *r)
307 void *ptr;
308 size_t ofs;
310 ofs = 0;
311 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
312 if (ptr==NULL)
313 err(EXIT_FAILURE, "malloc");
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 */
324 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
327 static void
328 create_rowcol_ext_ilseq_info(struct _region *r)
330 void *ptr;
331 size_t ofs;
333 ofs = 0;
334 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
335 if (ptr==NULL)
336 err(EXIT_FAILURE, "malloc");
338 put32(ptr, ofs, oob_mode); ofs++;
339 put32(ptr, ofs, dst_ilseq); ofs++;
341 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
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)
351 static void
352 dump_file(void)
354 FILE *fp;
355 int ret;
356 struct _db_factory *df;
357 struct _region data;
358 void *serialized;
359 size_t size;
362 * build database
364 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
366 /* store type */
367 CHKERR(ret, _db_factory_addstr_by_s,
368 (df, _CITRUS_MAPPER_STD_SYM_TYPE,
369 _CITRUS_MAPPER_STD_TYPE_ROWCOL));
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));
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));
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));
387 * dump database to file
389 if (output)
390 fp = fopen(output, "wb");
391 else
392 fp = stdout;
394 if (fp == NULL) {
395 perror("fopen");
396 exit(1);
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");
408 fclose(fp);
411 static void
412 /*ARGSUSED*/
413 set_type(int type)
416 if (done_flag & DF_TYPE) {
417 warning("TYPE is duplicated. ignored this one");
418 return;
421 map_type = type;
423 done_flag |= DF_TYPE;
425 static void
426 /*ARGSUSED*/
427 set_name(char *str)
430 if (done_flag & DF_NAME) {
431 warning("NAME is duplicated. ignored this one");
432 return;
435 map_name = str;
437 done_flag |= DF_NAME;
439 static void
440 set_src_zone(const zone_t *zone)
443 if (done_flag & DF_SRC_ZONE) {
444 warning("SRC_ZONE is duplicated. ignored this one");
445 return;
448 /* sanity check */
449 if (zone->col_bits < 1 || zone->col_bits > 32) {
450 goto bad;
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");
468 src_zone = *zone;
470 done_flag |= DF_SRC_ZONE;
472 return;
474 static void
475 set_dst_invalid(u_int32_t val)
478 if (done_flag & DF_DST_INVALID) {
479 warning("DST_INVALID is duplicated. ignored this one");
480 return;
483 dst_invalid = val;
485 done_flag |= DF_DST_INVALID;
487 static void
488 set_dst_ilseq(u_int32_t val)
491 if (done_flag & DF_DST_ILSEQ) {
492 warning("DST_ILSEQ is duplicated. ignored this one");
493 return;
496 dst_ilseq = val;
498 done_flag |= DF_DST_ILSEQ;
500 static void
501 set_oob_mode(u_int32_t val)
504 if (done_flag & DF_OOB_MODE) {
505 warning("OOB_MODE is duplicated. ignored this one");
506 return;
509 oob_mode = val;
511 done_flag |= DF_OOB_MODE;
513 static void
514 set_dst_unit_bits(u_int32_t val)
517 if (done_flag & DF_DST_UNIT_BITS) {
518 warning("DST_UNIT_BITS is duplicated. ignored this one");
519 return;
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");
538 done_flag |= DF_DST_UNIT_BITS;
540 static void
541 calc_next(void)
543 src_next++;
544 if (check_src(src_next, src_next))
545 next_valid = 0;
546 else
547 next_valid = 1;
549 static int
550 check_src(u_int32_t begin, u_int32_t end)
552 u_int32_t b_row = 0, e_row = 0, b_col, e_col;
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;
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);
573 return (0);
575 static void
576 store(const linear_zone_t *lz, u_int32_t dst, int inc)
578 u_int32_t row=0, col, ofs, i;
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++;
593 static void
594 do_mkdb(FILE *in)
596 int ret;
597 FILE *out;
599 /* dump DB to file */
600 if (output)
601 out = fopen(output, "wb");
602 else
603 out = stdout;
605 if (out==NULL)
606 err(EXIT_FAILURE, "fopen");
608 ret = _lookup_factory_convert(out, in);
609 fclose(out);
610 if (ret && output)
611 unlink(output); /* dump failure */
614 static void
615 do_mkpv(FILE *in)
617 int ret;
618 FILE *out;
620 /* dump pivot to file */
621 if (output)
622 out = fopen(output, "wb");
623 else
624 out = stdout;
626 if (out==NULL)
627 err(EXIT_FAILURE, "fopen");
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));
637 static void
638 usage(void)
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);
649 main(int argc, char **argv)
651 int ch;
652 FILE *in = NULL;
653 int mkdb = 0, mkpv = 0;
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();
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();
689 if (mkdb)
690 do_mkdb(in);
691 else if (mkpv)
692 do_mkpv(in);
693 else {
694 yyin = in;
695 yyparse();
698 return (0);