1 /* $NetBSD: yacc.y,v 1.6 2005/06/02 02:07:54 lukem Exp $ */ 2 3 %{ 4 /*- 5 * Copyright (c)2003 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.6 2005/06/02 02:07:54 lukem 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 zone_t src_zone; 72 static u_int32_t colmask, rowmask; 73 static u_int32_t dst_invalid, dst_ilseq, oob_mode, dst_unit_bits; 74 static void (*putfunc)(void *, size_t, u_int32_t) = 0; 75 76 static u_int32_t src_next; 77 static int next_valid; 78 79 static u_int32_t done_flag = 0; 80 #define DF_TYPE 0x00000001 81 #define DF_NAME 0x00000002 82 #define DF_SRC_ZONE 0x00000004 83 #define DF_DST_INVALID 0x00000008 84 #define DF_DST_ILSEQ 0x00000010 85 #define DF_DST_UNIT_BITS 0x00000020 86 #define DF_OOB_MODE 0x00000040 87 88 static void dump_file(void); 89 static void setup_map(void); 90 static void set_type(int); 91 static void set_name(char *); 92 static void set_src_zone(const zone_t *); 93 static void set_dst_invalid(u_int32_t); 94 static void set_dst_ilseq(u_int32_t); 95 static void set_dst_unit_bits(u_int32_t); 96 static void set_oob_mode(u_int32_t); 97 static void calc_next(void); 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 %} 104 105 %union { 106 u_int32_t i_value; 107 char *s_value; 108 zone_t z_value; 109 linear_zone_t lz_value; 110 } 111 112 %token R_TYPE R_NAME R_SRC_ZONE R_DST_UNIT_BITS 113 %token R_DST_INVALID R_DST_ILSEQ 114 %token R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL 115 %token R_ILSEQ R_OOB_MODE 116 %token R_LN 117 %token <i_value> L_IMM 118 %token <s_value> L_STRING 119 120 %type <z_value> zone 121 %type <lz_value> src 122 %type <i_value> dst types oob_mode_sel 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 src_zone : R_SRC_ZONE zone { set_src_zone(&$2); } 143 zone : L_IMM '-' L_IMM { 144 $$.row_begin = $$.row_end = 0; 145 $$.col_begin = $1; $$.col_end = $3; 146 $$.col_bits = 32; 147 } 148 | L_IMM '-' L_IMM '/' L_IMM '-' L_IMM '/' L_IMM { 149 $$.row_begin = $1; $$.row_end = $3; 150 $$.col_begin = $5; $$.col_end = $7; 151 $$.col_bits = $9; 152 } 153 154 dst_invalid : R_DST_INVALID L_IMM { set_dst_invalid($2); } 155 dst_ilseq : R_DST_ILSEQ L_IMM { set_dst_ilseq($2); } 156 dst_unit_bits : R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); } 157 oob_mode : R_OOB_MODE oob_mode_sel { set_oob_mode($2); } 158 159 oob_mode_sel : R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; } 160 | R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; } 161 162 mapping : begin_map map_elems R_END_MAP 163 begin_map : R_BEGIN_MAP lns { setup_map(); } 164 165 map_elems : /* empty */ 166 | map_elems map_elem lns 167 168 map_elem : src '=' dst 169 { store(&$1, $3, 0); } 170 | src '=' L_IMM '-' 171 { store(&$1, $3, 1); } 172 dst : L_IMM 173 { 174 $$ = $1; 175 } 176 | R_INVALID 177 { 178 $$ = dst_invalid; 179 } 180 | R_ILSEQ 181 { 182 $$ = dst_ilseq; 183 } 184 185 src : /* empty */ 186 { 187 if (!next_valid) { 188 yyerror("cannot omit src"); 189 } 190 $$.begin = $$.end = src_next; 191 calc_next(); 192 } 193 | L_IMM 194 { 195 if (check_src($1, $1)) { 196 yyerror("illegal zone"); 197 } 198 $$.begin = $$.end = $1; 199 src_next = $1; 200 calc_next(); 201 } 202 | L_IMM '-' L_IMM 203 { 204 if (check_src($1, $3)) { 205 yyerror("illegal zone"); 206 } 207 $$.begin = $1; $$.end = $3; 208 src_next = $3; 209 calc_next(); 210 } 211 | '-' L_IMM 212 { 213 if (!next_valid) { 214 yyerror("cannot omit src"); 215 } 216 if (check_src(src_next, $2)) { 217 yyerror("illegal zone"); 218 } 219 $$.begin = src_next; $$.end = $2; 220 src_next = $2; 221 calc_next(); 222 } 223 lns : R_LN 224 | lns R_LN 225 226 %% 227 228 static void 229 warning(const char *s) 230 { 231 fprintf(stderr, "%s in %d\n", s, line_number); 232 } 233 234 int 235 yyerror(const char *s) 236 { 237 warning(s); 238 exit(1); 239 } 240 241 void 242 put8(void *ptr, size_t ofs, u_int32_t val) 243 { 244 *((u_int8_t *)ptr + ofs) = val; 245 } 246 247 void 248 put16(void *ptr, size_t ofs, u_int32_t val) 249 { 250 u_int16_t oval = htons(val); 251 memcpy((u_int16_t *)ptr + ofs, &oval, 2); 252 } 253 254 void 255 put32(void *ptr, size_t ofs, u_int32_t val) 256 { 257 u_int32_t oval = htonl(val); 258 memcpy((u_int32_t *)ptr + ofs, &oval, 4); 259 } 260 261 static void 262 alloc_table(void) 263 { 264 size_t i; 265 u_int32_t val = 0; 266 267 table_size = 268 (src_zone.row_end-src_zone.row_begin + 1) * 269 (src_zone.col_end-src_zone.col_begin + 1); 270 table = malloc(table_size*dst_unit_bits / 8); 271 if (!table) { 272 perror("malloc"); 273 exit(1); 274 } 275 276 switch (oob_mode) { 277 case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL: 278 val = dst_invalid; 279 break; 280 case _CITRUS_MAPPER_STD_OOB_ILSEQ: 281 val = dst_ilseq; 282 break; 283 default: 284 _DIAGASSERT(0); 285 } 286 for (i = 0; i < table_size; i++) 287 (*putfunc)(table, i, val); 288 } 289 290 static void 291 setup_map(void) 292 { 293 294 if ((done_flag & DF_SRC_ZONE)==0) { 295 fprintf(stderr, "SRC_ZONE is mandatory.\n"); 296 exit(1); 297 } 298 if ((done_flag & DF_DST_UNIT_BITS)==0) { 299 fprintf(stderr, "DST_UNIT_BITS is mandatory.\n"); 300 exit(1); 301 } 302 303 if ((done_flag & DF_DST_INVALID) == 0) 304 dst_invalid = 0xFFFFFFFF; 305 if ((done_flag & DF_DST_ILSEQ) == 0) 306 dst_ilseq = 0xFFFFFFFE; 307 if ((done_flag & DF_OOB_MODE) == 0) 308 oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; 309 310 alloc_table(); 311 } 312 313 static void 314 create_rowcol_info(struct _region *r) 315 { 316 void *ptr; 317 size_t ofs; 318 319 ofs = 0; 320 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE); 321 if (ptr==NULL) 322 err(EXIT_FAILURE, "malloc"); 323 324 put32(ptr, ofs, src_zone.col_bits); ofs++; 325 put32(ptr, ofs, dst_invalid); ofs++; 326 put32(ptr, ofs, src_zone.row_begin); ofs++; 327 put32(ptr, ofs, src_zone.row_end); ofs++; 328 put32(ptr, ofs, src_zone.col_begin); ofs++; 329 put32(ptr, ofs, src_zone.col_end); ofs++; 330 put32(ptr, ofs, dst_unit_bits); ofs++; 331 put32(ptr, ofs, 0); /* pad */ 332 333 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE); 334 } 335 336 static void 337 create_rowcol_ext_ilseq_info(struct _region *r) 338 { 339 void *ptr; 340 size_t ofs; 341 342 ofs = 0; 343 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE); 344 if (ptr==NULL) 345 err(EXIT_FAILURE, "malloc"); 346 347 put32(ptr, ofs, oob_mode); ofs++; 348 put32(ptr, ofs, dst_ilseq); ofs++; 349 350 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE); 351 } 352 353 #define CHKERR(ret, func, a) \ 354 do { \ 355 ret = func a; \ 356 if (ret) \ 357 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \ 358 } while (/*CONSTCOND*/0) 359 360 static void 361 dump_file(void) 362 { 363 FILE *fp; 364 int ret; 365 struct _db_factory *df; 366 struct _region data; 367 void *serialized; 368 size_t size; 369 370 /* 371 * build database 372 */ 373 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL)); 374 375 /* store type */ 376 CHKERR(ret, _db_factory_addstr_by_s, 377 (df, _CITRUS_MAPPER_STD_SYM_TYPE, 378 _CITRUS_MAPPER_STD_TYPE_ROWCOL)); 379 380 /* store info */ 381 create_rowcol_info(&data); 382 CHKERR(ret, _db_factory_add_by_s, 383 (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1)); 384 385 /* ilseq extension */ 386 create_rowcol_ext_ilseq_info(&data); 387 CHKERR(ret, _db_factory_add_by_s, 388 (df, _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &data, 1)); 389 390 /* store table */ 391 _region_init(&data, table, table_size*dst_unit_bits/8); 392 CHKERR(ret, _db_factory_add_by_s, 393 (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1)); 394 395 /* 396 * dump database to file 397 */ 398 if (output) 399 fp = fopen(output, "wb"); 400 else 401 fp = stdout; 402 403 if (fp == NULL) { 404 perror("fopen"); 405 exit(1); 406 } 407 408 /* dump database body */ 409 size = _db_factory_calc_size(df); 410 serialized = malloc(size); 411 _region_init(&data, serialized, size); 412 CHKERR(ret, _db_factory_serialize, 413 (df, _CITRUS_MAPPER_STD_MAGIC, &data)); 414 if (fwrite(serialized, size, 1, fp) != 1) 415 err(EXIT_FAILURE, "fwrite"); 416 417 fclose(fp); 418 } 419 420 static void 421 /*ARGSUSED*/ 422 set_type(int type) 423 { 424 425 if (done_flag & DF_TYPE) { 426 warning("TYPE is duplicated. ignored this one"); 427 return; 428 } 429 430 map_type = type; 431 432 done_flag |= DF_TYPE; 433 } 434 static void 435 /*ARGSUSED*/ 436 set_name(char *str) 437 { 438 439 if (done_flag & DF_NAME) { 440 warning("NAME is duplicated. ignored this one"); 441 return; 442 } 443 444 map_name = str; 445 446 done_flag |= DF_NAME; 447 } 448 static void 449 set_src_zone(const zone_t *zone) 450 { 451 452 if (done_flag & DF_SRC_ZONE) { 453 warning("SRC_ZONE is duplicated. ignored this one"); 454 return; 455 } 456 457 /* sanity check */ 458 if (zone->col_bits < 1 || zone->col_bits > 32) { 459 goto bad; 460 } 461 462 if (zone->col_bits != 32) 463 colmask = (1 << zone->col_bits )- 1; 464 else 465 colmask = ~0; 466 rowmask = ~colmask; 467 if (zone->col_begin > zone->col_end || 468 zone->row_begin > zone->row_end || 469 (zone->col_begin & rowmask) != 0 || 470 (zone->col_end & rowmask) != 0 || 471 ((zone->row_begin << zone->col_bits) & colmask) != 0 || 472 ((zone->row_end << zone->col_bits) & colmask) != 0) { 473 bad: 474 yyerror("Illegal argument for SRC_ZONE"); 475 } 476 477 src_zone = *zone; 478 479 done_flag |= DF_SRC_ZONE; 480 481 return; 482 } 483 static void 484 set_dst_invalid(u_int32_t val) 485 { 486 487 if (done_flag & DF_DST_INVALID) { 488 warning("DST_INVALID is duplicated. ignored this one"); 489 return; 490 } 491 492 dst_invalid = val; 493 494 done_flag |= DF_DST_INVALID; 495 } 496 static void 497 set_dst_ilseq(u_int32_t val) 498 { 499 500 if (done_flag & DF_DST_ILSEQ) { 501 warning("DST_ILSEQ is duplicated. ignored this one"); 502 return; 503 } 504 505 dst_ilseq = val; 506 507 done_flag |= DF_DST_ILSEQ; 508 } 509 static void 510 set_oob_mode(u_int32_t val) 511 { 512 513 if (done_flag & DF_OOB_MODE) { 514 warning("OOB_MODE is duplicated. ignored this one"); 515 return; 516 } 517 518 oob_mode = val; 519 520 done_flag |= DF_OOB_MODE; 521 } 522 static void 523 set_dst_unit_bits(u_int32_t val) 524 { 525 526 if (done_flag & DF_DST_UNIT_BITS) { 527 warning("DST_UNIT_BITS is duplicated. ignored this one"); 528 return; 529 } 530 531 switch (val) { 532 case 8: 533 putfunc = &put8; 534 dst_unit_bits = val; 535 break; 536 case 16: 537 putfunc = &put16; 538 dst_unit_bits = val; 539 break; 540 case 32: 541 putfunc = &put32; 542 dst_unit_bits = val; 543 break; 544 default: 545 yyerror("Illegal argument for DST_UNIT_BITS"); 546 } 547 done_flag |= DF_DST_UNIT_BITS; 548 } 549 static void 550 calc_next(void) 551 { 552 src_next++; 553 if (check_src(src_next, src_next)) 554 next_valid = 0; 555 else 556 next_valid = 1; 557 } 558 static int 559 check_src(u_int32_t begin, u_int32_t end) 560 { 561 u_int32_t b_row = 0, e_row = 0, b_col, e_col; 562 563 b_col = begin & colmask; 564 e_col = end & colmask; 565 if (src_zone.col_bits != 32) { 566 b_row = begin >> src_zone.col_bits; 567 e_row = end >> src_zone.col_bits; 568 } 569 570 if (b_row != e_row || 571 b_row < src_zone.row_begin || 572 b_row > src_zone.row_end || 573 e_row < src_zone.row_begin || 574 e_row > src_zone.row_end || 575 b_col < src_zone.col_begin || 576 b_col > src_zone.col_end || 577 e_col < src_zone.col_begin || 578 e_col > src_zone.col_end || 579 b_col>e_col) { 580 return (-1); 581 } 582 return (0); 583 } 584 static void 585 store(const linear_zone_t *lz, u_int32_t dst, int inc) 586 { 587 u_int32_t row=0, col, ofs, i; 588 589 if (src_zone.col_bits != 32) 590 row = lz->begin >> src_zone.col_bits; 591 col = lz->begin & colmask; 592 ofs = (row-src_zone.row_begin) * 593 (src_zone.col_end-src_zone.col_begin + 1) + 594 (col-src_zone.col_begin); 595 for (i = lz->end - lz->begin + 1; i > 0; i--) { 596 (*putfunc)(table, ofs++, dst); 597 if (inc) 598 dst++; 599 } 600 } 601 602 static void 603 do_mkdb(FILE *in) 604 { 605 int ret; 606 FILE *out; 607 608 /* dump DB to file */ 609 if (output) 610 out = fopen(output, "wb"); 611 else 612 out = stdout; 613 614 if (out==NULL) 615 err(EXIT_FAILURE, "fopen"); 616 617 ret = _lookup_factory_convert(out, in); 618 fclose(out); 619 if (ret && output) 620 unlink(output); /* dump failure */ 621 } 622 623 static void 624 do_mkpv(FILE *in) 625 { 626 int ret; 627 FILE *out; 628 629 /* dump pivot to file */ 630 if (output) 631 out = fopen(output, "wb"); 632 else 633 out = stdout; 634 635 if (out==NULL) 636 err(EXIT_FAILURE, "fopen"); 637 638 ret = _pivot_factory_convert(out, in); 639 fclose(out); 640 if (ret && output) 641 unlink(output); /* dump failure */ 642 if (ret) 643 errx(EXIT_FAILURE, "%s\n", strerror(ret)); 644 } 645 646 static void 647 usage(void) 648 { 649 warnx("usage: \n" 650 "\t%s [-d] [-o outfile] [infile]\n" 651 "\t%s -m [-d] [-o outfile] [infile]\n" 652 "\t%s -p [-d] [-o outfile] [infile]\n", 653 getprogname(), getprogname(), getprogname()); 654 exit(1); 655 } 656 657 int 658 main(int argc, char **argv) 659 { 660 int ch; 661 extern char *optarg; 662 extern int optind; 663 FILE *in = NULL; 664 int mkdb = 0, mkpv = 0; 665 666 while ((ch=getopt(argc, argv, "do:mp")) != EOF) { 667 switch (ch) { 668 case 'd': 669 debug=1; 670 break; 671 case 'o': 672 output = strdup(optarg); 673 break; 674 case 'm': 675 mkdb = 1; 676 break; 677 case 'p': 678 mkpv = 1; 679 break; 680 default: 681 usage(); 682 } 683 } 684 685 argc-=optind; 686 argv+=optind; 687 switch (argc) { 688 case 0: 689 in = stdin; 690 break; 691 case 1: 692 in = fopen(argv[0], "r"); 693 if (!in) 694 err(EXIT_FAILURE, argv[0]); 695 break; 696 default: 697 usage(); 698 } 699 700 if (mkdb) 701 do_mkdb(in); 702 else if (mkpv) 703 do_mkpv(in); 704 else { 705 yyin = in; 706 yyparse(); 707 } 708 709 return (0); 710 } 711