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