1#include <sys/types.h> 2#include <sys/time.h> 3 4#include <assert.h> 5#include <stdio.h> 6#include <stdlib.h> 7#include <string.h> 8#include <unistd.h> 9 10#include "queue.h" 11#include "shqueue.h" 12 13typedef enum { 14 FORWARD_WALK_FAILED = 1, 15 FOREACH_WALK_FAILED, 16 LIST_END_NOT_MARKED_FAILURE, 17 PREV_WALK_FAILED, 18 REVERSE_FOREACH_WALK_FAILED, 19 EXPECTED_HEAD_FAILED 20} FAILURE_REASON; 21 22const char *failure_reason_names[] = { 23 "", 24 "walking the list using the _NEXT forward failed", 25 "walking the list using the _FOREACH macro failed", 26 "what was expected to be the last element wasn't marked as such", 27 "walking the list using the _PREV macro failed", 28 "walking the list using the _REVERSE_FOREACH macro failed", 29 "expected to be at the head of the list" 30}; 31 32SH_LIST_HEAD(sh_lq); 33struct sh_le { 34 char content; 35 SH_LIST_ENTRY sh_les; 36}; 37 38/* create a string from the content of a list queue */ 39char * 40sh_l_as_string(l) 41 struct sh_lq *l; 42{ 43 static char buf[1024]; 44 struct sh_le *ele = SH_LIST_FIRST(l, sh_le); 45 int i = 1; 46 47 buf[0] = '"'; 48 while (ele != NULL) { 49 buf[i] = ele->content; 50 ele = SH_LIST_NEXT(ele, sh_les, sh_le); 51 if (ele != NULL) 52 buf[++i] = ' '; 53 i++; 54 } 55 buf[i++] = '"'; 56 buf[i] = '\0'; 57 return buf; 58} 59 60/* init a list queue */ 61struct sh_lq * 62sh_l_init(items) 63 const char *items; 64{ 65 const char *c = items; 66 struct sh_le *ele = NULL, *last_ele = (struct sh_le*)-1; 67 struct sh_lq *l = calloc(1, sizeof(struct sh_lq)); 68 69 SH_LIST_INIT(l); 70 71 while (*c != '\0') { 72 if (c[0] != ' ') { 73 last_ele = ele; 74 ele = calloc(1, sizeof(struct sh_le)); 75 ele->content = c[0]; 76 if (SH_LIST_EMPTY(l)) 77 SH_LIST_INSERT_HEAD(l, ele, sh_les, sh_le); 78 else 79 SH_LIST_INSERT_AFTER( 80 last_ele, ele, sh_les, sh_le); 81 } 82 c++; 83 } 84 return (l); 85} 86 87struct sh_lq * 88sh_l_remove_head(l) 89 struct sh_lq *l; 90{ 91 struct sh_le *ele = SH_LIST_FIRST(l, sh_le); 92 93 SH_LIST_REMOVE_HEAD(l, sh_les, sh_le); 94 if (ele != NULL) 95 free(ele); 96 97 return (l); 98} 99 100struct sh_lq * 101sh_l_remove_tail(l) 102 struct sh_lq *l; 103{ 104 struct sh_le *ele = SH_LIST_FIRST(l, sh_le); 105 106 if (SH_LIST_EMPTY(l)) 107 return (l); 108 109 while (SH_LIST_NEXT(ele, sh_les, sh_le) != NULL) 110 ele = SH_LIST_NEXT(ele, sh_les, sh_le); 111 112 if (ele) { 113 SH_LIST_REMOVE(ele, sh_les, sh_le); 114 free(ele); 115 } 116 return (l); 117} 118 119struct sh_lq * 120sh_l_remove_item(l, item) 121 struct sh_lq *l; 122 const char *item; 123{ 124 struct sh_le *ele = SH_LIST_FIRST(l, sh_le); 125 126 while (ele != NULL) { 127 if (ele->content == item[0]) 128 break; 129 ele = SH_LIST_NEXT(ele, sh_les, sh_le); 130 } 131 if (ele) 132 SH_LIST_REMOVE(ele, sh_les, sh_le); 133 return (l); 134} 135 136struct sh_lq * 137sh_l_insert_head(l, item) 138 struct sh_lq *l; 139 const char *item; 140{ 141 struct sh_le *ele = calloc(1, sizeof(struct sh_le)); 142 143 ele->content = item[0]; 144 SH_LIST_INSERT_HEAD(l, ele, sh_les, sh_le); 145 146 return (l); 147} 148 149struct sh_lq * 150sh_l_insert_tail(l, item) 151 struct sh_lq *l; 152 const char *item; 153{ 154 struct sh_le *ele = NULL; 155 struct sh_le *last_ele = SH_LIST_FIRST(l, sh_le); 156 157 if (last_ele != NULL) 158 while (SH_LIST_NEXT(last_ele, sh_les, sh_le) != NULL) 159 last_ele = SH_LIST_NEXT(last_ele, sh_les, sh_le); 160 161 if (last_ele == NULL) { 162 ele = calloc(1, sizeof(struct sh_le)); 163 ele->content = item[0]; 164 SH_LIST_INSERT_HEAD(l, ele, sh_les, sh_le); 165 } else { 166 ele = calloc(1, sizeof(struct sh_le)); 167 ele->content = item[0]; 168 SH_LIST_INSERT_AFTER(last_ele, ele, sh_les, sh_le); 169 } 170 171 return (l); 172} 173 174struct sh_lq * 175sh_l_insert_before(l, item, before_item) 176 struct sh_lq *l; 177 const char *item; 178 const char *before_item; 179{ 180 struct sh_le *ele = NULL; 181 struct sh_le *before_ele = SH_LIST_FIRST(l, sh_le); 182 183 while (before_ele != NULL) { 184 if (before_ele->content == before_item[0]) 185 break; 186 before_ele = SH_LIST_NEXT(before_ele, sh_les, sh_le); 187 } 188 if (before_ele != NULL) { 189 ele = calloc(1, sizeof(struct sh_le)); 190 ele->content = item[0]; 191 SH_LIST_INSERT_BEFORE(l, before_ele, ele, sh_les, sh_le); 192 } 193 return (l); 194} 195 196struct sh_lq * 197sh_l_insert_after(l, item, after_item) 198 struct sh_lq *l; 199 const char *item; 200 const char *after_item; 201{ 202 struct sh_le *ele = NULL; 203 struct sh_le *after_ele = SH_LIST_FIRST(l, sh_le); 204 205 while (after_ele != NULL) { 206 if (after_ele->content == after_item[0]) 207 break; 208 after_ele = SH_LIST_NEXT(after_ele, sh_les, sh_le); 209 } 210 if (after_ele != NULL) { 211 ele = calloc(1, sizeof(struct sh_le)); 212 ele->content = item[0]; 213 SH_LIST_INSERT_AFTER(after_ele, ele, sh_les, sh_le); 214 } 215 return (l); 216} 217 218void 219sh_l_discard(l) 220 struct sh_lq *l; 221{ 222 struct sh_le *ele = NULL; 223 224 while ((ele = SH_LIST_FIRST(l, sh_le)) != NULL) { 225 SH_LIST_REMOVE(ele, sh_les, sh_le); 226 free(ele); 227 } 228 229 free(l); 230} 231 232int 233sh_l_verify(l, items) 234 struct sh_lq *l; 235 const char *items; 236{ 237 const char *c = items; 238 struct sh_le *ele = NULL, *lele = NULL; 239 int i = 0, nele = 0; 240 241 while (*c != '\0') { 242 if (c[0] != ' ') 243 nele++; 244 c++; 245 } 246 247 /* use the FOREACH macro to walk the list */ 248 c = items; 249 i = 0; 250 SH_LIST_FOREACH(ele, l, sh_les, sh_le) { 251 if (ele->content != c[0]) 252 return (FOREACH_WALK_FAILED); 253 i++; 254 c +=2; 255 } 256 if (i != nele) 257 return (FOREACH_WALK_FAILED); 258 i = 0; 259 if (items[0] != '\0') { 260 /* walk the list forward */ 261 c = items; 262 ele = SH_LIST_FIRST(l, sh_le); 263 while (*c != '\0') { 264 lele = ele; 265 if (c[0] != ' ') { 266 if (ele->content != c[0]) 267 return (FORWARD_WALK_FAILED); 268 i++; 269 ele = SH_LIST_NEXT(ele, sh_les, sh_le); 270 } 271 c++; 272 } 273 ele = lele; 274 275 if (i != nele) 276 return (FOREACH_WALK_FAILED); 277 278 /* ele should be the last element in the list... */ 279 /* ... so sle_next should be -1 */ 280 if (ele->sh_les.sle_next != -1) 281 return (LIST_END_NOT_MARKED_FAILURE); 282 283 /* and NEXT needs to be NULL */ 284 if (SH_LIST_NEXT(ele, sh_les, sh_le) != NULL) 285 return (LIST_END_NOT_MARKED_FAILURE); 286 287 /* 288 * walk the list backwards using PREV macro, first move c 289 * back a bit 290 */ 291 c--; 292 i = 0; 293 while (c >= items) { 294 if (c[0] != ' ') { 295 lele = ele; 296 if (ele->content != c[0]) 297 return (PREV_WALK_FAILED); 298 ele = SH_LIST_PREV(ele, sh_les, sh_le); 299 i++; 300 } 301 c--; 302 } 303 ele = lele; 304 305 if (i != nele) 306 return (PREV_WALK_FAILED); 307 308 if (ele != SH_LIST_FIRST(l, sh_le)) 309 return (EXPECTED_HEAD_FAILED); 310 } 311 return (0); 312} 313 314SH_TAILQ_HEAD(sh_tq); 315struct sh_te { 316 char content; 317 SH_TAILQ_ENTRY sh_tes; 318}; 319 320/* create a string from the content of a list queue */ 321char * 322sh_t_as_string(l) 323 struct sh_tq *l; 324{ 325 static char buf[1024]; 326 struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te); 327 int i = 1; 328 329 buf[0] = '"'; 330 while (ele != NULL) { 331 buf[i] = ele->content; 332 ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te); 333 if (ele != NULL) 334 buf[++i] = ' '; 335 i++; 336 } 337 buf[i++] = '"'; 338 buf[i] = '\0'; 339 return (buf); 340} 341 342/* init a tail queue */ 343struct sh_tq * 344sh_t_init(items) 345 const char *items; 346{ 347 const char *c = items; 348 struct sh_te *ele = NULL, *last_ele = (struct sh_te*)-1; 349 struct sh_tq *l = calloc(1, sizeof(struct sh_tq)); 350 351 SH_TAILQ_INIT(l); 352 353 while (*c != '\0') { 354 if (c[0] != ' ') { 355 ele = calloc(1, sizeof(struct sh_te)); 356 ele->content = c[0]; 357 358 if (SH_TAILQ_EMPTY(l)) 359 SH_TAILQ_INSERT_HEAD(l, ele, sh_tes, sh_te); 360 else 361 SH_TAILQ_INSERT_AFTER( 362 l, last_ele, ele, sh_tes, sh_te); 363 last_ele = ele; 364 } 365 c++; 366 } 367 return (l); 368} 369 370struct sh_tq * 371sh_t_remove_head(l) 372 struct sh_tq *l; 373{ 374 struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te); 375 376 if (ele != NULL) 377 SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te); 378 379 free(ele); 380 381 return (l); 382} 383 384struct sh_tq * 385sh_t_remove_tail(l) 386 struct sh_tq *l; 387{ 388 struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te); 389 390 if (SH_TAILQ_EMPTY(l)) 391 return (l); 392 393 while (SH_TAILQ_NEXT(ele, sh_tes, sh_te) != NULL) 394 ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te); 395 396 if (ele != NULL) { 397 SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te); 398 free(ele); 399 } 400 401 return (l); 402} 403 404struct sh_tq * 405sh_t_remove_item(l, item) 406 struct sh_tq *l; 407 const char *item; 408{ 409 struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te); 410 411 while (ele != NULL) { 412 if (ele->content == item[0]) 413 break; 414 ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te); 415 } 416 if (ele != NULL) 417 SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te); 418 419 return (l); 420} 421 422struct sh_tq * 423sh_t_insert_head(l, item) 424 struct sh_tq *l; 425 const char *item; 426{ 427 struct sh_te *ele = calloc(1, sizeof(struct sh_te)); 428 429 ele->content = item[0]; 430 SH_TAILQ_INSERT_HEAD(l, ele, sh_tes, sh_te); 431 432 return (l); 433} 434 435struct sh_tq * 436sh_t_insert_tail(l, item) 437 struct sh_tq *l; 438 const char *item; 439{ 440 struct sh_te *ele = 0; 441 ele = calloc(1, sizeof(struct sh_te)); 442 ele->content = item[0]; 443 SH_TAILQ_INSERT_TAIL(l, ele, sh_tes); 444 return l; 445} 446 447struct sh_tq * 448sh_t_insert_before(l, item, before_item) 449 struct sh_tq *l; 450 const char *item; 451 const char *before_item; 452{ 453 struct sh_te *ele = NULL; 454 struct sh_te *before_ele = SH_TAILQ_FIRST(l, sh_te); 455 456 while (before_ele != NULL) { 457 if (before_ele->content == before_item[0]) 458 break; 459 before_ele = SH_TAILQ_NEXT(before_ele, sh_tes, sh_te); 460 } 461 462 if (before_ele != NULL) { 463 ele = calloc(1, sizeof(struct sh_te)); 464 ele->content = item[0]; 465 SH_TAILQ_INSERT_BEFORE(l, before_ele, ele, sh_tes, sh_te); 466 } 467 468 return (l); 469} 470 471struct sh_tq * 472sh_t_insert_after(l, item, after_item) 473 struct sh_tq *l; 474 const char *item; 475 const char *after_item; 476{ 477 struct sh_te *ele = NULL; 478 struct sh_te *after_ele = SH_TAILQ_FIRST(l, sh_te); 479 480 while (after_ele != NULL) { 481 if (after_ele->content == after_item[0]) 482 break; 483 after_ele = SH_TAILQ_NEXT(after_ele, sh_tes, sh_te); 484 } 485 486 if (after_ele != NULL) { 487 ele = calloc(1, sizeof(struct sh_te)); 488 ele->content = item[0]; 489 SH_TAILQ_INSERT_AFTER(l, after_ele, ele, sh_tes, sh_te); 490 } 491 492 return (l); 493} 494 495void 496sh_t_discard(l) 497 struct sh_tq *l; 498{ 499 struct sh_te *ele = NULL; 500 501 while ((ele = SH_TAILQ_FIRST(l, sh_te)) != NULL) { 502 SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te); 503 free(ele); 504 } 505 free(l); 506} 507 508int 509sh_t_verify(l, items) 510 struct sh_tq *l; 511 const char *items; 512{ 513 const char *c = items, *b = NULL; 514 struct sh_te *ele = NULL, *lele = NULL; 515 int i = 0, nele = 0; 516 517 while (*c != '\0') { 518 if (c[0] != ' ') 519 nele++; 520 c++; 521 } 522 523 /* use the FOREACH macro to walk the list */ 524 c = items; 525 i = 0; 526 SH_TAILQ_FOREACH(ele, l, sh_tes, sh_te) { 527 if (ele->content != c[0]) 528 return (FOREACH_WALK_FAILED); 529 i++; 530 c +=2; 531 } 532 if (i != nele) 533 return (FOREACH_WALK_FAILED); 534 i = 0; 535 if (items[0] != '\0') { 536 /* walk the list forward */ 537 c = items; 538 ele = SH_TAILQ_FIRST(l, sh_te); 539 while (*c != '\0') { 540 lele = ele; 541 if (c[0] != ' ') { 542 if (ele->content != c[0]) 543 return (FORWARD_WALK_FAILED); 544 i++; 545 ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te); 546 } 547 c++; 548 } 549 550 if (i != nele) 551 return (FOREACH_WALK_FAILED); 552 553 if (lele != SH_TAILQ_LAST(l, sh_tes, sh_te)) 554 return (LIST_END_NOT_MARKED_FAILURE); 555 ele = lele; 556 557 /* ele should be the last element in the list... */ 558 /* ... so sle_next should be -1 */ 559 if (ele->sh_tes.stqe_next != -1) 560 return (LIST_END_NOT_MARKED_FAILURE); 561 562 /* and NEXT needs to be NULL */ 563 if (SH_TAILQ_NEXT(ele, sh_tes, sh_te) != NULL) 564 return (LIST_END_NOT_MARKED_FAILURE); 565 566 /* walk the list backwards using SH_LIST_PREV macro */ 567 c--; 568 b = c; 569 i = 0; 570 while (c >= items) { 571 if (c[0] != ' ') { 572 lele = ele; 573 if (ele->content != c[0]) 574 return (PREV_WALK_FAILED); 575 ele = SH_TAILQ_PREV(l, ele, sh_tes, sh_te); 576 i++; 577 } 578 c--; 579 } 580 ele = lele; 581 582 if (i != nele) 583 return (PREV_WALK_FAILED); 584 585 if (ele != SH_TAILQ_FIRST(l, sh_te)) 586 return (-1); 587 588 /* c should be the last character in the array, walk backwards 589 from here using FOREACH_REVERSE and check the values again */ 590 c = b; 591 i = 0; 592 ele = SH_TAILQ_LAST(l, sh_tes, sh_te); 593 SH_TAILQ_FOREACH_REVERSE(ele, l, sh_tes, sh_te) { 594 if (ele->content != c[0]) 595 return (REVERSE_FOREACH_WALK_FAILED); 596 i++; 597 c -=2; 598 } 599 if (i != nele) 600 return (REVERSE_FOREACH_WALK_FAILED); 601 } 602 return (0); 603} 604 605int 606sh_t_verify_TAILQ_LAST(l, items) 607 struct sh_tq *l; 608 const char *items; 609{ 610 const char *c = items; 611 struct sh_te *ele = NULL; 612 613 c = items; 614 while (*c != '\0') { 615 c++; 616 } 617 if (c == items) { 618 /* items is empty, so last should be NULL */ 619 if (SH_TAILQ_LAST(l, sh_tes, sh_te) != NULL) 620 return (-1); 621 } else { 622 c--; 623 ele = SH_TAILQ_LAST(l, sh_tes, sh_te); 624 if (ele->content != c[0]) 625 return (-1); 626 } 627 return (0); 628} 629 630typedef void *qds_t; 631struct { 632 const char *name; 633 qds_t *(*f_init)(const char *); 634 qds_t *(*f_remove_head)(qds_t *); 635 qds_t *(*f_remove_tail)(qds_t *); 636 qds_t *(*f_remove_item)(qds_t *, const char *); 637 qds_t *(*f_insert_head)(qds_t *, const char *); 638 qds_t *(*f_insert_tail)(qds_t *, const char *); 639 qds_t *(*f_insert_before)(qds_t *, const char *, const char *); 640 qds_t *(*f_insert_after)(qds_t *, const char *, const char *); 641 qds_t *(*f_discard)(qds_t *); 642 char *(*f_as_string)(qds_t *); 643 int (*f_verify)(qds_t *, const char *); 644} qfns[]= { 645{ "sh_list", 646 (qds_t*(*)(const char *))sh_l_init, 647 (qds_t*(*)(qds_t *))sh_l_remove_head, 648 (qds_t*(*)(qds_t *))sh_l_remove_tail, 649 (qds_t*(*)(qds_t *, const char *))sh_l_remove_item, 650 (qds_t*(*)(qds_t *, const char *))sh_l_insert_head, 651 (qds_t*(*)(qds_t *, const char *))sh_l_insert_tail, 652 (qds_t*(*)(qds_t *, const char *, const char *))sh_l_insert_before, 653 (qds_t*(*)(qds_t *, const char *, const char *))sh_l_insert_after, 654 (qds_t*(*)(qds_t *))sh_l_discard, 655 (char *(*)(qds_t *))sh_l_as_string, 656 (int(*)(qds_t *, const char *))sh_l_verify }, 657{ "sh_tailq", 658 (qds_t*(*)(const char *))sh_t_init, 659 (qds_t*(*)(qds_t *))sh_t_remove_head, 660 (qds_t*(*)(qds_t *))sh_t_remove_tail, 661 (qds_t*(*)(qds_t *, const char *))sh_t_remove_item, 662 (qds_t*(*)(qds_t *, const char *))sh_t_insert_head, 663 (qds_t*(*)(qds_t *, const char *))sh_t_insert_tail, 664 (qds_t*(*)(qds_t *, const char *, const char *))sh_t_insert_before, 665 (qds_t*(*)(qds_t *, const char *, const char *))sh_t_insert_after, 666 (qds_t*(*)(qds_t *))sh_t_discard, 667 (char *(*)(qds_t *))sh_t_as_string, 668 (int(*)(qds_t *, const char *))sh_t_verify } 669}; 670 671typedef enum { 672 INSERT_BEFORE, 673 INSERT_AFTER, 674 INSERT_HEAD, 675 INSERT_TAIL, 676 REMOVE_HEAD, 677 REMOVE_ITEM, 678 REMOVE_TAIL, 679} OP; 680 681const char *op_names[] = { 682 "INSERT_BEFORE", 683 "INSERT_AFTER", 684 "INSERT_HEAD", 685 "INSERT_TAIL", 686 "REMOVE_HEAD", 687 "REMOVE_ITEM", 688 "REMOVE_TAIL" }; 689 690struct { 691 char *init; /* initial state. */ 692 char *final; /* final state. */ 693 char *elem; /* element to operate on */ 694 char *insert; /* element to insert */ 695 OP op; /* operation. */ 696} ops[] = { 697 698 /* most operations on a empty list */ 699 { "", "", NULL, NULL, REMOVE_HEAD }, 700 { "", "", NULL, NULL, REMOVE_TAIL }, 701 { "", "A", NULL, "A", INSERT_HEAD }, 702 { "", "A", NULL, "A", INSERT_TAIL }, 703 704 /* all operations on a one element list */ 705 { "A", "", NULL, NULL, REMOVE_HEAD }, 706 { "A", "", NULL, NULL, REMOVE_TAIL }, 707 { "A", "", "A", NULL, REMOVE_ITEM }, 708 { "B", "A B", NULL, "A", INSERT_HEAD }, 709 { "A", "A B", NULL, "B", INSERT_TAIL }, 710 { "B", "A B", "B", "A", INSERT_BEFORE }, 711 { "A", "A B", "A", "B", INSERT_AFTER }, 712 713 /* all operations on a two element list */ 714 { "A B", "B", NULL, NULL, REMOVE_HEAD }, 715 { "A B", "A", NULL, NULL, REMOVE_TAIL }, 716 { "A B", "A", "B", NULL, REMOVE_ITEM }, 717 { "A B", "B", "A", NULL, REMOVE_ITEM }, 718 { "B C", "A B C", NULL, "A", INSERT_HEAD }, 719 { "A B", "A B C", NULL, "C", INSERT_TAIL }, 720 { "B C", "A B C", "B", "A", INSERT_BEFORE }, 721 { "A C", "A B C", "C", "B", INSERT_BEFORE }, 722 { "A C", "A B C", "A", "B", INSERT_AFTER }, 723 { "A C", "A C B", "C", "B", INSERT_AFTER }, 724 725 /* all operations on a three element list */ 726 727 { "A B C", "B C", NULL, NULL, REMOVE_HEAD }, 728 { "A B C", "A B", NULL, NULL, REMOVE_TAIL }, 729 { "A B C", "A B", "C", NULL, REMOVE_ITEM }, 730 { "A B C", "A C", "B", NULL, REMOVE_ITEM }, 731 { "A B C", "B C", "A", NULL, REMOVE_ITEM }, 732 { "B C D", "A B C D", NULL, "A", INSERT_HEAD }, 733 { "A B C", "A B C D", NULL, "D", INSERT_TAIL }, 734 { "A B C", "X A B C", "A", "X", INSERT_BEFORE }, 735 { "A B C", "A X B C", "B", "X", INSERT_BEFORE }, 736 { "A B C", "A B X C", "C", "X", INSERT_BEFORE }, 737 { "A B C", "A X B C", "A", "X", INSERT_AFTER }, 738 { "A B C", "A B X C", "B", "X", INSERT_AFTER }, 739 { "A B C", "A B C X", "C", "X", INSERT_AFTER }, 740}; 741 742int 743main(argc, argv) 744 int argc; 745 char *argv[]; 746{ 747 void *list; 748 int fc, tc; /* tc is total count, fc is failed count */ 749 int eval, i, t, result; 750 751 eval = 0; 752 for (t = 0; t < sizeof(qfns) / sizeof(qfns[0]); ++t) { 753 fc = tc = 0; 754 printf("TESTING: %s\n", qfns[t].name); 755 756 for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) { 757 list = qfns[t].f_init(ops[i].init); 758 result = qfns[t].f_verify(list, ops[i].init); 759 if (result == 0) { 760 fc++; 761 putchar('.'); 762 } else { 763 putchar('+'); /* + means failed before op */ 764 printf("\nVerify failed: %s\n", 765 failure_reason_names[result]); 766 eval = 1; 767 } 768 if (!strcmp("sh_tailq", qfns[t].name)) { 769 result = 770 sh_t_verify_TAILQ_LAST(list, ops[i].init); 771 } 772#ifdef VERBOSE 773 printf("\ncase %d %s in %s init: \"%s\" desired: \"%s\" elem: \"%s\" insert: \"%s\"\n", 774 i, op_names[ops[i].op], qfns[t].name, 775 ops[i].init, ops[i].final, 776 ops[i].elem, ops[i].insert); 777 fflush(stdout); 778#endif 779 tc++; 780 switch (ops[i].op) { 781 case REMOVE_HEAD: 782 qfns[t].f_remove_head(list); 783 break; 784 case REMOVE_TAIL: 785 qfns[t].f_remove_tail(list); 786 break; 787 case REMOVE_ITEM: 788 qfns[t].f_remove_item(list, ops[i].elem); 789 break; 790 case INSERT_HEAD: 791 qfns[t].f_insert_head(list, ops[i].insert); 792 break; 793 case INSERT_TAIL: 794 qfns[t].f_insert_tail(list, ops[i].insert); 795 break; 796 case INSERT_BEFORE: 797 qfns[t].f_insert_before( 798 list, ops[i].insert, ops[i].elem); 799 break; 800 case INSERT_AFTER: 801 qfns[t].f_insert_after( 802 list, ops[i].insert, ops[i].elem); 803 break; 804 } 805 if (!strcmp("sh_tailq", op_names[ops[i].op])) { 806 result = sh_t_verify_TAILQ_LAST(list, 807 ops[i].final); 808 } 809 if (result == 0) 810 result = qfns[t].f_verify(list, ops[i].final); 811 if (result == 0) { 812 fc++; 813 putchar('.'); 814 } else { 815 putchar('*'); /* * means failed after op */ 816 printf("\ncase %d %s in %s init: \"%s\" desired: \"%s\" elem: \"%s\" insert: \"%s\" got: %s - %s\n", 817 i, op_names[ops[i].op], qfns[t].name, 818 ops[i].init, ops[i].final, 819 ops[i].elem, ops[i].insert, 820 qfns[t].f_as_string(list), 821 failure_reason_names[result]); 822 fflush(stdout); 823 eval = 1; 824 } 825 826 tc++; 827 qfns[t].f_discard(list); 828 } 829 830 printf("\t%0.2f%% passed (%d/%d).\n", 831 (((double)fc/tc) * 100), fc, tc); 832 } 833 return (eval); 834} 835