1 /* $FreeBSD$ */ 2 /* $NetBSD: yacc.y,v 1.7 2006/09/09 14:35:17 tnozaki Exp $ */ 3 4 %{ 5 /*- 6 * Copyright (c)2003, 2006 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/cdefs.h> 32 #include <sys/types.h> 33 34 #include <assert.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <limits.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <arpa/inet.h> 43 44 #include "ldef.h" 45 46 #ifndef __packed 47 #define __packed 48 #endif 49 50 #include "citrus_namespace.h" 51 #include "citrus_types.h" 52 #include "citrus_mapper_std_file.h" 53 #include "citrus_region.h" 54 #include "citrus_db_factory.h" 55 #include "citrus_db_hash.h" 56 #include "citrus_lookup_factory.h" 57 #include "citrus_pivot_factory.h" 58 59 extern FILE *yyin; 60 61 int debug = 0; 62 63 static linear_zone_t rowcol[_CITRUS_MAPPER_STD_ROWCOL_MAX]; 64 static char *map_name; 65 static char *output = NULL; 66 static void *table = NULL; 67 static size_t rowcol_len = 0; 68 static size_t table_size; 69 static u_int32_t done_flag = 0; 70 static u_int32_t dst_ilseq, dst_invalid, dst_unit_bits, oob_mode; 71 static u_int32_t rowcol_bits = 0, rowcol_mask = 0; 72 static u_int32_t src_next; 73 static int map_type; 74 static void (*putfunc)(void *, size_t, u_int32_t) = NULL; 75 76 #define DF_TYPE 0x00000001 77 #define DF_NAME 0x00000002 78 #define DF_SRC_ZONE 0x00000004 79 #define DF_DST_INVALID 0x00000008 80 #define DF_DST_ILSEQ 0x00000010 81 #define DF_DST_UNIT_BITS 0x00000020 82 #define DF_OOB_MODE 0x00000040 83 84 static void dump_file(void); 85 static void setup_map(void); 86 static void set_type(int); 87 static void set_name(char *); 88 static void set_src_zone(u_int32_t); 89 static void set_dst_invalid(u_int32_t); 90 static void set_dst_ilseq(u_int32_t); 91 static void set_dst_unit_bits(u_int32_t); 92 static void set_oob_mode(u_int32_t); 93 static int check_src(u_int32_t, u_int32_t); 94 static void store(const linear_zone_t *, u_int32_t, int); 95 static void put8(void *, size_t, u_int32_t); 96 static void put16(void *, size_t, u_int32_t); 97 static void put32(void *, size_t, u_int32_t); 98 static void set_range(u_int32_t, u_int32_t); 99 static void set_src(linear_zone_t *, u_int32_t, u_int32_t); 100 %} 101 102 %union { 103 u_int32_t i_value; 104 char *s_value; 105 linear_zone_t lz_value; 106 } 107 108 %token R_TYPE R_NAME R_SRC_ZONE R_DST_UNIT_BITS 109 %token R_DST_INVALID R_DST_ILSEQ 110 %token R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL 111 %token R_ILSEQ R_OOB_MODE 112 %token R_LN 113 %token <i_value> L_IMM 114 %token <s_value> L_STRING 115 116 %type <lz_value> src 117 %type <i_value> dst types oob_mode_sel zone 118 119 %% 120 121 file : property mapping lns 122 { dump_file(); } 123 124 property : /* empty */ 125 | property R_LN 126 | property name 127 | property type 128 | property src_zone 129 | property dst_invalid 130 | property dst_ilseq 131 | property dst_unit_bits 132 | property oob_mode 133 134 name : R_NAME L_STRING { set_name($2); $2 = NULL; } 135 type : R_TYPE types { set_type($2); } 136 types : R_ROWCOL { $$ = R_ROWCOL; } 137 range : L_IMM '-' L_IMM { set_range($1, $3); } 138 139 ranges : /* empty */ 140 | ranges range '/' 141 142 src_zone : R_SRC_ZONE zone { set_src_zone($2); } 143 zone : range { 144 $$ = 32; 145 } 146 | range '/' range '/' ranges L_IMM { 147 $$ = $6; 148 } 149 150 dst_invalid : R_DST_INVALID L_IMM { set_dst_invalid($2); } 151 dst_ilseq : R_DST_ILSEQ L_IMM { set_dst_ilseq($2); } 152 dst_unit_bits : R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); } 153 oob_mode : R_OOB_MODE oob_mode_sel { set_oob_mode($2); } 154 155 oob_mode_sel : R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; } 156 | R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; } 157 158 mapping : begin_map map_elems R_END_MAP 159 begin_map : R_BEGIN_MAP lns { setup_map(); } 160 161 map_elems : /* empty */ 162 | map_elems map_elem lns 163 164 map_elem : src '=' dst 165 { store(&$1, $3, 0); } 166 | src '=' L_IMM '-' 167 { store(&$1, $3, 1); } 168 dst : L_IMM 169 { 170 $$ = $1; 171 } 172 | R_INVALID 173 { 174 $$ = dst_invalid; 175 } 176 | R_ILSEQ 177 { 178 $$ = dst_ilseq; 179 } 180 181 src : /* empty */ 182 { 183 set_src(&$$, src_next, src_next); 184 } 185 | L_IMM 186 { 187 set_src(&$$, $1, $1); 188 } 189 | L_IMM '-' L_IMM 190 { 191 set_src(&$$, $1, $3); 192 } 193 | '-' L_IMM 194 { 195 set_src(&$$, src_next, $2); 196 } 197 lns : R_LN 198 | lns R_LN 199 200 %% 201 202 static void 203 warning(const char *s) 204 { 205 206 fprintf(stderr, "%s in %d\n", s, linenumber); 207 } 208 209 int 210 yyerror(const char *s) 211 { 212 213 warning(s); 214 exit(1); 215 } 216 217 void 218 put8(void *ptr, size_t ofs, u_int32_t val) 219 { 220 221 *((u_int8_t *)ptr + ofs) = val; 222 } 223 224 void 225 put16(void *ptr, size_t ofs, u_int32_t val) 226 { 227 228 u_int16_t oval = htons(val); 229 memcpy((u_int16_t *)ptr + ofs, &oval, 2); 230 } 231 232 void 233 put32(void *ptr, size_t ofs, u_int32_t val) 234 { 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 linear_zone_t *p; 244 size_t i; 245 uint32_t val = 0; 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 break; 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 i, len, ofs; 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 struct _db_factory *df; 361 struct _region data; 362 void *serialized; 363 FILE *fp; 364 size_t size; 365 int ret; 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, _CITRUS_MAPPER_STD_TYPE_ROWCOL)); 375 376 /* store info */ 377 create_rowcol_info(&data); 378 CHKERR(ret, _db_factory_add_by_s, 379 (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1)); 380 381 /* ilseq extension */ 382 create_rowcol_ext_ilseq_info(&data); 383 CHKERR(ret, _db_factory_add_by_s, 384 (df, _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &data, 1)); 385 386 /* store table */ 387 _region_init(&data, table, table_size*dst_unit_bits/8); 388 CHKERR(ret, _db_factory_add_by_s, 389 (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1)); 390 391 /* 392 * dump database to file 393 */ 394 fp = output ? fopen(output, "wb") : stdout; 395 396 if (fp == NULL) { 397 perror("fopen"); 398 exit(1); 399 } 400 401 /* dump database body */ 402 size = _db_factory_calc_size(df); 403 serialized = malloc(size); 404 _region_init(&data, serialized, size); 405 CHKERR(ret, _db_factory_serialize, 406 (df, _CITRUS_MAPPER_STD_MAGIC, &data)); 407 if (fwrite(serialized, size, 1, fp) != 1) 408 err(EXIT_FAILURE, "fwrite"); 409 410 fclose(fp); 411 } 412 413 static void 414 /*ARGSUSED*/ 415 set_type(int type) 416 { 417 418 if (done_flag & DF_TYPE) { 419 warning("TYPE is duplicated. ignored this one"); 420 return; 421 } 422 423 map_type = type; 424 425 done_flag |= DF_TYPE; 426 } 427 428 static void 429 /*ARGSUSED*/ 430 set_name(char *str) 431 { 432 433 if (done_flag & DF_NAME) { 434 warning("NAME is duplicated. ignored this one"); 435 return; 436 } 437 438 map_name = str; 439 440 done_flag |= DF_NAME; 441 } 442 443 static void 444 set_src_zone(u_int32_t val) 445 { 446 linear_zone_t *p; 447 size_t i; 448 449 if (done_flag & DF_SRC_ZONE) { 450 warning("SRC_ZONE is duplicated. ignored this one"); 451 return; 452 } 453 rowcol_bits = val; 454 455 /* sanity check */ 456 switch (rowcol_bits) { 457 case 8: case 16: case 32: 458 if (rowcol_len <= 32 / rowcol_bits) 459 break; 460 /*FALLTHROUGH*/ 461 default: 462 goto bad; 463 } 464 rowcol_mask = 1 << (rowcol_bits - 1); 465 rowcol_mask |= rowcol_mask - 1; 466 for (i = 0; i < rowcol_len; ++i) { 467 p = &rowcol[i]; 468 if (p->end > rowcol_mask) 469 goto bad; 470 } 471 done_flag |= DF_SRC_ZONE; 472 return; 473 474 bad: 475 yyerror("Illegal argument for SRC_ZONE"); 476 } 477 478 static void 479 set_dst_invalid(u_int32_t val) 480 { 481 482 if (done_flag & DF_DST_INVALID) { 483 warning("DST_INVALID is duplicated. ignored this one"); 484 return; 485 } 486 487 dst_invalid = val; 488 489 done_flag |= DF_DST_INVALID; 490 } 491 492 static void 493 set_dst_ilseq(u_int32_t val) 494 { 495 496 if (done_flag & DF_DST_ILSEQ) { 497 warning("DST_ILSEQ is duplicated. ignored this one"); 498 return; 499 } 500 501 dst_ilseq = val; 502 503 done_flag |= DF_DST_ILSEQ; 504 } 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 520 static void 521 set_dst_unit_bits(u_int32_t val) 522 { 523 524 if (done_flag & DF_DST_UNIT_BITS) { 525 warning("DST_UNIT_BITS is duplicated. ignored this one"); 526 return; 527 } 528 529 switch (val) { 530 case 8: 531 putfunc = &put8; 532 dst_unit_bits = val; 533 break; 534 case 16: 535 putfunc = &put16; 536 dst_unit_bits = val; 537 break; 538 case 32: 539 putfunc = &put32; 540 dst_unit_bits = val; 541 break; 542 default: 543 yyerror("Illegal argument for DST_UNIT_BITS"); 544 } 545 done_flag |= DF_DST_UNIT_BITS; 546 } 547 548 static int 549 check_src(u_int32_t begin, u_int32_t end) 550 { 551 linear_zone_t *p; 552 size_t i; 553 u_int32_t m, n; 554 555 if (begin > end) 556 return (1); 557 if (begin < end) { 558 m = begin & ~rowcol_mask; 559 n = end & ~rowcol_mask; 560 if (m != n) 561 return (1); 562 } 563 for (i = rowcol_len * rowcol_bits, p = &rowcol[0]; i > 0; ++p) { 564 i -= rowcol_bits; 565 m = (begin >> i) & rowcol_mask; 566 if (m < p->begin || m > p->end) 567 return (1); 568 } 569 if (begin < end) { 570 n = end & rowcol_mask; 571 --p; 572 if (n < p->begin || n > p->end) 573 return (1); 574 } 575 return (0); 576 } 577 578 static void 579 store(const linear_zone_t *lz, u_int32_t dst, int inc) 580 { 581 linear_zone_t *p; 582 size_t i, ofs; 583 u_int32_t n; 584 585 ofs = 0; 586 for (i = rowcol_len * rowcol_bits, p = &rowcol[0]; i > 0; ++p) { 587 i -= rowcol_bits; 588 n = ((lz->begin >> i) & rowcol_mask) - p->begin; 589 ofs = (ofs * p->width) + n; 590 } 591 n = lz->width; 592 while (n-- > 0) { 593 (*putfunc)(table, ofs++, dst); 594 if (inc) 595 dst++; 596 } 597 } 598 599 static void 600 set_range(u_int32_t begin, u_int32_t end) 601 { 602 linear_zone_t *p; 603 604 if (rowcol_len >= _CITRUS_MAPPER_STD_ROWCOL_MAX) 605 goto bad; 606 p = &rowcol[rowcol_len++]; 607 608 if (begin > end) 609 goto bad; 610 p->begin = begin, p->end = end; 611 p->width = end - begin + 1; 612 613 return; 614 615 bad: 616 yyerror("Illegal argument for SRC_ZONE"); 617 } 618 619 static void 620 set_src(linear_zone_t *lz, u_int32_t begin, u_int32_t end) 621 { 622 623 if (check_src(begin, end) != 0) 624 yyerror("illegal zone"); 625 626 lz->begin = begin, lz->end = end; 627 lz->width = end - begin + 1; 628 629 src_next = end + 1; 630 } 631 632 static void 633 do_mkdb(FILE *in) 634 { 635 FILE *out; 636 int ret; 637 638 /* dump DB to file */ 639 out = output ? fopen(output, "wb") : 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 FILE *out; 654 int ret; 655 656 /* dump pivot to file */ 657 out = output ? fopen(output, "wb") : stdout; 658 659 if (out == NULL) 660 err(EXIT_FAILURE, "fopen"); 661 662 ret = _pivot_factory_convert(out, in); 663 fclose(out); 664 if (ret && output) 665 unlink(output); /* dump failure */ 666 if (ret) 667 errx(EXIT_FAILURE, "%s\n", strerror(ret)); 668 } 669 670 static void 671 usage(void) 672 { 673 warnx("usage: \n" 674 "\t%s [-d] [-o outfile] [infile]\n" 675 "\t%s -m [-d] [-o outfile] [infile]\n" 676 "\t%s -p [-d] [-o outfile] [infile]\n", 677 getprogname(), getprogname(), getprogname()); 678 exit(1); 679 } 680 681 int 682 main(int argc, char **argv) 683 { 684 FILE *in = NULL; 685 int ch, mkdb = 0, mkpv = 0; 686 687 while ((ch = getopt(argc, argv, "do:mp")) != EOF) { 688 switch (ch) { 689 case 'd': 690 debug = 1; 691 break; 692 case 'o': 693 output = strdup(optarg); 694 break; 695 case 'm': 696 mkdb = 1; 697 break; 698 case 'p': 699 mkpv = 1; 700 break; 701 default: 702 usage(); 703 } 704 } 705 706 argc -= optind; 707 argv += optind; 708 switch (argc) { 709 case 0: 710 in = stdin; 711 break; 712 case 1: 713 in = fopen(argv[0], "r"); 714 if (!in) 715 err(EXIT_FAILURE, "%s", argv[0]); 716 break; 717 default: 718 usage(); 719 } 720 721 if (mkdb) 722 do_mkdb(in); 723 else if (mkpv) 724 do_mkpv(in); 725 else { 726 yyin = in; 727 yyparse(); 728 } 729 730 return (0); 731 } 732