1 /* $OpenBSD: tsort.c,v 1.22 2013/11/27 00:13:24 deraadt Exp $ */ 2 /* ex:ts=8 sw=4: 3 * 4 * Copyright (c) 1999-2004 Marc Espie <espie@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <assert.h> 20 #include <ctype.h> 21 #include <err.h> 22 #include <limits.h> 23 #include <stddef.h> 24 #include <stdio.h> 25 #include <stdint.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <sysexits.h> 29 #include <unistd.h> 30 #include <ohash.h> 31 32 /* The complexity of topological sorting is O(e), where e is the 33 * size of input. While reading input, vertices have to be identified, 34 * thus add the complexity of e keys retrieval among v keys using 35 * an appropriate data structure. This program uses open double hashing 36 * for that purpose. See Knuth for the expected complexity of double 37 * hashing (Brent variation should probably be used if v << e, as a user 38 * option). 39 * 40 * The algorithm used for longest cycle reporting is accurate, but somewhat 41 * expensive. It may need to build all free paths of the graph (a free 42 * path is a path that never goes twice through the same node), whose 43 * number can be as high as O(2^e). Usually, the number of free paths is 44 * much smaller though. This program's author does not believe that a 45 * significantly better worst-case complexity algorithm exists. 46 * 47 * In case of a hints file, the set of minimal nodes is maintained as a 48 * heap. The resulting complexity is O(e+v log v) for the worst case. 49 * The average should actually be near O(e). 50 * 51 * If the hints file is incomplete, there is some extra complexity incurred 52 * by make_transparent, which does propagate order values to unmarked 53 * nodes. In the worst case, make_transparent is O(e u), 54 * where u is the number of originally unmarked nodes. 55 * In practice, it is much faster. 56 * 57 * The simple topological sort algorithm detects cycles. This program 58 * goes further, breaking cycles through the use of simple heuristics. 59 * Each cycle break checks the whole set of nodes, hence if c cycles break 60 * are needed, this is an extra cost of O(c v). 61 * 62 * Possible heuristics are as follows: 63 * - break cycle at node with lowest number of predecessors (default case), 64 * - break longest cycle at node with lowest number of predecessors, 65 * - break cycle at next node from the hints file. 66 * 67 * Except for the hints file case, which sets an explicit constraint on 68 * which cycle to break, those heuristics locally result in the smallest 69 * number of broken edges. 70 * 71 * Those are admittedly greedy strategies, as is the selection of the next 72 * node from the hints file amongst equivalent candidates that is used for 73 * `stable' topological sorting. 74 */ 75 76 #ifdef __GNUC__ 77 #define UNUSED __attribute__((unused)) 78 #else 79 #define UNUSED 80 #endif 81 82 struct node; 83 84 /* The set of arcs from a given node is stored as a linked list. */ 85 struct link { 86 struct link *next; 87 struct node *node; 88 }; 89 90 #define NO_ORDER UINT_MAX 91 92 struct node { 93 unsigned int refs; /* Number of arcs left, coming into this node. 94 * Note that nodes with a null count can't 95 * be part of cycles. */ 96 struct link *arcs; /* List of forward arcs. */ 97 98 unsigned int order; /* Order of nodes according to a hint file. */ 99 100 /* Cycle detection algorithms build a free path of nodes. */ 101 struct node *from; /* Previous node in the current path. */ 102 103 unsigned int mark; /* Mark processed nodes in cycle discovery. */ 104 struct link *traverse; /* Next link to traverse when backtracking. */ 105 char k[1]; /* Name of this node. */ 106 }; 107 108 #define HASH_START 9 109 110 struct array { 111 unsigned int entries; 112 struct node **t; 113 }; 114 115 static void nodes_init(struct ohash *); 116 static struct node *node_lookup(struct ohash *, const char *, const char *); 117 static void usage(void); 118 static struct node *new_node(const char *, const char *); 119 120 static unsigned int read_pairs(FILE *, struct ohash *, int, 121 const char *, unsigned int, int); 122 static void split_nodes(struct ohash *, struct array *, struct array *); 123 static void make_transparent(struct ohash *); 124 static void insert_arc(struct node *, struct node *); 125 126 #ifdef DEBUG 127 static void dump_node(struct node *); 128 static void dump_array(struct array *); 129 static void dump_hash(struct ohash *); 130 #endif 131 static unsigned int read_hints(FILE *, struct ohash *, int, 132 const char *, unsigned int); 133 static struct node *find_smallest_node(struct array *); 134 static struct node *find_good_cycle_break(struct array *); 135 static void print_cycle(struct array *); 136 static struct node *find_cycle_from(struct node *, struct array *); 137 static struct node *find_predecessor(struct array *, struct node *); 138 static unsigned int traverse_node(struct node *, unsigned int, struct array *); 139 static struct node *find_longest_cycle(struct array *, struct array *); 140 141 static void heap_down(struct array *, unsigned int); 142 static void heapify(struct array *, int); 143 static struct node *dequeue(struct array *); 144 static void enqueue(struct array *, struct node *); 145 146 147 148 #define erealloc(n, s) emem(realloc(n, s)) 149 static void *hash_alloc(size_t, void *); 150 static void hash_free(void *, size_t, void *); 151 static void* entry_alloc(size_t, void *); 152 static void *emalloc(size_t); 153 static void *emem(void *); 154 #define DEBUG_TRAVERSE 0 155 static struct ohash_info node_info = { 156 offsetof(struct node, k), NULL, hash_alloc, hash_free, entry_alloc }; 157 158 159 int main(int, char *[]); 160 161 162 /*** 163 *** Memory handling. 164 ***/ 165 166 static void * 167 emem(void *p) 168 { 169 if (p) 170 return p; 171 else 172 errx(EX_SOFTWARE, "Memory exhausted"); 173 } 174 175 static void * 176 hash_alloc(size_t s, void *u UNUSED) 177 { 178 return emem(calloc(s, 1)); 179 } 180 181 static void 182 hash_free(void *p, size_t s UNUSED, void *u UNUSED) 183 { 184 free(p); 185 } 186 187 static void * 188 entry_alloc(size_t s, void *u UNUSED) 189 { 190 return emalloc(s); 191 } 192 193 static void * 194 emalloc(size_t s) 195 { 196 return emem(malloc(s)); 197 } 198 199 200 /*** 201 *** Hash table. 202 ***/ 203 204 /* Inserting and finding nodes in the hash structure. 205 * We handle interval strings for efficiency wrt fgetln. */ 206 static struct node * 207 new_node(const char *start, const char *end) 208 { 209 struct node *n; 210 211 n = ohash_create_entry(&node_info, start, &end); 212 n->from = NULL; 213 n->arcs = NULL; 214 n->refs = 0; 215 n->mark = 0; 216 n->order = NO_ORDER; 217 n->traverse = NULL; 218 return n; 219 } 220 221 222 static void 223 nodes_init(struct ohash *h) 224 { 225 ohash_init(h, HASH_START, &node_info); 226 } 227 228 static struct node * 229 node_lookup(struct ohash *h, const char *start, const char *end) 230 { 231 unsigned int i; 232 struct node * n; 233 234 i = ohash_qlookupi(h, start, &end); 235 236 n = ohash_find(h, i); 237 if (n == NULL) 238 n = ohash_insert(h, i, new_node(start, end)); 239 return n; 240 } 241 242 #ifdef DEBUG 243 static void 244 dump_node(struct node *n) 245 { 246 struct link *l; 247 248 if (n->refs == 0) 249 return; 250 printf("%s (%u/%u): ", n->k, n->order, n->refs); 251 for (l = n->arcs; l != NULL; l = l->next) 252 if (n->refs != 0) 253 printf("%s(%u/%u) ", l->node->k, l->node->order, l->node->refs); 254 putchar('\n'); 255 } 256 257 static void 258 dump_array(struct array *a) 259 { 260 unsigned int i; 261 262 for (i = 0; i < a->entries; i++) 263 dump_node(a->t[i]); 264 } 265 266 static void 267 dump_hash(struct ohash *h) 268 { 269 unsigned int i; 270 struct node *n; 271 272 for (n = ohash_first(h, &i); n != NULL; n = ohash_next(h, &i)) 273 dump_node(n); 274 } 275 #endif 276 277 278 /*** 279 *** Reading data. 280 ***/ 281 282 static void 283 insert_arc(struct node *a, struct node *b) 284 { 285 struct link *l; 286 287 /* Check that this arc is not already present. */ 288 for (l = a->arcs; l != NULL; l = l->next) { 289 if (l->node == b) 290 return; 291 } 292 b->refs++; 293 l = emalloc(sizeof(struct link)); 294 l->node = b; 295 l->next = a->arcs; 296 a->arcs = l; 297 } 298 299 static unsigned int 300 read_pairs(FILE *f, struct ohash *h, int reverse, const char *name, 301 unsigned int order, int hint) 302 { 303 int toggle; 304 struct node *a; 305 size_t size; 306 char *str; 307 308 toggle = 1; 309 a = NULL; 310 311 while ((str = fgetln(f, &size)) != NULL) { 312 char *sentinel; 313 314 sentinel = str + size; 315 for (;;) { 316 char *e; 317 318 while (str < sentinel && 319 isspace((unsigned char)*str)) 320 str++; 321 if (str == sentinel) 322 break; 323 for (e = str; 324 e < sentinel && !isspace((unsigned char)*e); e++) 325 continue; 326 if (toggle) { 327 a = node_lookup(h, str, e); 328 if (a->order == NO_ORDER && hint) 329 a->order = order++; 330 } else { 331 struct node *b; 332 333 b = node_lookup(h, str, e); 334 assert(a != NULL); 335 if (b != a) { 336 if (reverse) 337 insert_arc(b, a); 338 else 339 insert_arc(a, b); 340 } 341 } 342 toggle = !toggle; 343 str = e; 344 } 345 } 346 if (toggle == 0) 347 errx(EX_DATAERR, "odd number of node names in %s", name); 348 if (!feof(f)) 349 err(EX_IOERR, "error reading %s", name); 350 return order; 351 } 352 353 static unsigned int 354 read_hints(FILE *f, struct ohash *h, int quiet, const char *name, 355 unsigned int order) 356 { 357 char *str; 358 size_t size; 359 360 while ((str = fgetln(f, &size)) != NULL) { 361 char *sentinel; 362 363 sentinel = str + size; 364 for (;;) { 365 char *e; 366 struct node *a; 367 368 while (str < sentinel && isspace((unsigned char)*str)) 369 str++; 370 if (str == sentinel) 371 break; 372 for (e = str; 373 e < sentinel && !isspace((unsigned char)*e); e++) 374 continue; 375 a = node_lookup(h, str, e); 376 if (a->order != NO_ORDER) { 377 if (!quiet) 378 warnx( 379 "duplicate node %s in hints file %s", 380 a->k, name); 381 } else 382 a->order = order++; 383 str = e; 384 } 385 } 386 return order; 387 } 388 389 390 /*** 391 *** Standard heap handling routines. 392 ***/ 393 394 static void 395 heap_down(struct array *h, unsigned int i) 396 { 397 unsigned int j; 398 struct node *swap; 399 400 for (; (j=2*i+1) < h->entries; i = j) { 401 if (j+1 < h->entries && h->t[j+1]->order < h->t[j]->order) 402 j++; 403 if (h->t[i]->order <= h->t[j]->order) 404 break; 405 swap = h->t[i]; 406 h->t[i] = h->t[j]; 407 h->t[j] = swap; 408 } 409 } 410 411 static void 412 heapify(struct array *h, int verbose) 413 { 414 unsigned int i; 415 416 for (i = h->entries; i != 0;) { 417 if (h->t[--i]->order == NO_ORDER && verbose) 418 warnx("node %s absent from hints file", h->t[i]->k); 419 heap_down(h, i); 420 } 421 } 422 423 #define DEQUEUE(h) ( hints_flag ? dequeue(h) : (h)->t[--(h)->entries] ) 424 425 static struct node * 426 dequeue(struct array *h) 427 { 428 struct node *n; 429 430 if (h->entries == 0) 431 n = NULL; 432 else { 433 n = h->t[0]; 434 if (--h->entries != 0) { 435 h->t[0] = h->t[h->entries]; 436 heap_down(h, 0); 437 } 438 } 439 return n; 440 } 441 442 #define ENQUEUE(h, n) do { \ 443 if (hints_flag) \ 444 enqueue((h), (n)); \ 445 else \ 446 (h)->t[(h)->entries++] = (n); \ 447 } while(0); 448 449 static void 450 enqueue(struct array *h, struct node *n) 451 { 452 unsigned int i, j; 453 struct node *swap; 454 455 h->t[h->entries++] = n; 456 for (i = h->entries-1; i > 0; i = j) { 457 j = (i-1)/2; 458 if (h->t[j]->order < h->t[i]->order) 459 break; 460 swap = h->t[j]; 461 h->t[j] = h->t[i]; 462 h->t[i] = swap; 463 } 464 } 465 466 /* Nodes without order should not hinder direct dependencies. 467 * Iterate until no nodes are left. 468 */ 469 static void 470 make_transparent(struct ohash *hash) 471 { 472 struct node *n; 473 unsigned int i; 474 struct link *l; 475 int adjusted; 476 int bad; 477 unsigned int min; 478 479 /* first try to solve complete nodes */ 480 do { 481 adjusted = 0; 482 bad = 0; 483 for (n = ohash_first(hash, &i); n != NULL; 484 n = ohash_next(hash, &i)) { 485 if (n->order == NO_ORDER) { 486 min = NO_ORDER; 487 488 for (l = n->arcs; l != NULL; l = l->next) { 489 /* unsolved node -> delay resolution */ 490 if (l->node->order == NO_ORDER) { 491 bad = 1; 492 break; 493 } else if (l->node->order < min) 494 min = l->node->order; 495 } 496 if (min < NO_ORDER && l == NULL) { 497 n->order = min; 498 adjusted = 1; 499 } 500 } 501 } 502 503 } while (adjusted); 504 505 /* then, if incomplete nodes are left, do them */ 506 if (bad) do { 507 adjusted = 0; 508 for (n = ohash_first(hash, &i); n != NULL; 509 n = ohash_next(hash, &i)) 510 if (n->order == NO_ORDER) 511 for (l = n->arcs; l != NULL; l = l->next) 512 if (l->node->order < n->order) { 513 n->order = l->node->order; 514 adjusted = 1; 515 } 516 } while (adjusted); 517 } 518 519 520 /*** 521 *** Search through hash array for nodes. 522 ***/ 523 524 /* Split nodes into unrefed nodes/live nodes. */ 525 static void 526 split_nodes(struct ohash *hash, struct array *heap, struct array *remaining) 527 { 528 529 struct node *n; 530 unsigned int i; 531 532 heap->t = emalloc(sizeof(struct node *) * ohash_entries(hash)); 533 remaining->t = emalloc(sizeof(struct node *) * ohash_entries(hash)); 534 heap->entries = 0; 535 remaining->entries = 0; 536 537 for (n = ohash_first(hash, &i); n != NULL; n = ohash_next(hash, &i)) { 538 if (n->refs == 0) 539 heap->t[heap->entries++] = n; 540 else 541 remaining->t[remaining->entries++] = n; 542 } 543 } 544 545 /* Good point to break a cycle: live node with as few refs as possible. */ 546 static struct node * 547 find_good_cycle_break(struct array *h) 548 { 549 unsigned int i; 550 unsigned int best; 551 struct node *u; 552 553 best = UINT_MAX; 554 u = NULL; 555 556 assert(h->entries != 0); 557 for (i = 0; i < h->entries; i++) { 558 struct node *n = h->t[i]; 559 /* No need to look further. */ 560 if (n->refs == 1) 561 return n; 562 if (n->refs != 0 && n->refs < best) { 563 best = n->refs; 564 u = n; 565 } 566 } 567 assert(u != NULL); 568 return u; 569 } 570 571 /* Retrieve the node with the smallest order. */ 572 static struct node * 573 find_smallest_node(struct array *h) 574 { 575 unsigned int i; 576 unsigned int best; 577 struct node *u; 578 579 best = UINT_MAX; 580 u = NULL; 581 582 assert(h->entries != 0); 583 for (i = 0; i < h->entries; i++) { 584 struct node *n = h->t[i]; 585 if (n->refs != 0 && n->order < best) { 586 best = n->order; 587 u = n; 588 } 589 } 590 assert(u != NULL); 591 return u; 592 } 593 594 595 /*** 596 *** Graph algorithms. 597 ***/ 598 599 /* Explore the nodes reachable from i to find a cycle, store it in c. 600 * This may fail. */ 601 static struct node * 602 find_cycle_from(struct node *i, struct array *c) 603 { 604 struct node *n; 605 606 n = i; 607 /* XXX Previous cycle findings may have left this pointer non-null. */ 608 i->from = NULL; 609 610 for (;;) { 611 /* Note that all marks are reversed before this code exits. */ 612 n->mark = 1; 613 if (n->traverse) 614 n->traverse = n->traverse->next; 615 else 616 n->traverse = n->arcs; 617 /* Skip over dead nodes. */ 618 while (n->traverse && n->traverse->node->refs == 0) 619 n->traverse = n->traverse->next; 620 if (n->traverse) { 621 struct node *go = n->traverse->node; 622 623 if (go->mark) { 624 c->entries = 0; 625 for (; n != NULL && n != go; n = n->from) { 626 c->t[c->entries++] = n; 627 n->mark = 0; 628 } 629 for (; n != NULL; n = n->from) 630 n->mark = 0; 631 c->t[c->entries++] = go; 632 return go; 633 } else { 634 go->from = n; 635 n = go; 636 } 637 } else { 638 n->mark = 0; 639 n = n->from; 640 if (n == NULL) 641 return NULL; 642 } 643 } 644 } 645 646 /* Find a live predecessor of node n. This is a slow routine, as it needs 647 * to go through the whole array, but it is not needed often. 648 */ 649 static struct node * 650 find_predecessor(struct array *a, struct node *n) 651 { 652 unsigned int i; 653 654 for (i = 0; i < a->entries; i++) { 655 struct node *m; 656 657 m = a->t[i]; 658 if (m->refs != 0) { 659 struct link *l; 660 661 for (l = m->arcs; l != NULL; l = l->next) 662 if (l->node == n) 663 return m; 664 } 665 } 666 assert(1 == 0); 667 return NULL; 668 } 669 670 /* Traverse all strongly connected components reachable from node n. 671 Start numbering them at o. Return the maximum order reached. 672 Update the largest cycle found so far. 673 */ 674 static unsigned int 675 traverse_node(struct node *n, unsigned int o, struct array *c) 676 { 677 unsigned int min, max; 678 679 n->from = NULL; 680 min = o; 681 max = ++o; 682 683 for (;;) { 684 n->mark = o; 685 if (DEBUG_TRAVERSE) 686 printf("%s(%u) ", n->k, n->mark); 687 /* Find next arc to explore. */ 688 if (n->traverse) 689 n->traverse = n->traverse->next; 690 else 691 n->traverse = n->arcs; 692 /* Skip over dead nodes. */ 693 while (n->traverse && n->traverse->node->refs == 0) 694 n->traverse = n->traverse->next; 695 /* If arc left. */ 696 if (n->traverse) { 697 struct node *go; 698 699 go = n->traverse->node; 700 /* Optimisation: if go->mark < min, we already 701 * visited this strongly-connected component in 702 * a previous pass. Hence, this can yield no new 703 * cycle. */ 704 705 /* Not part of the current path: go for it. */ 706 if (go->mark == 0 || go->mark == min) { 707 go->from = n; 708 n = go; 709 o++; 710 if (o > max) 711 max = o; 712 /* Part of the current path: check cycle length. */ 713 } else if (go->mark > min) { 714 if (DEBUG_TRAVERSE) 715 printf("%d\n", o - go->mark + 1); 716 if (o - go->mark + 1 > c->entries) { 717 struct node *t; 718 unsigned int i; 719 720 c->entries = o - go->mark + 1; 721 i = 0; 722 c->t[i++] = go; 723 for (t = n; t != go; t = t->from) 724 c->t[i++] = t; 725 } 726 } 727 728 /* No arc left: backtrack. */ 729 } else { 730 n->mark = min; 731 n = n->from; 732 if (!n) 733 return max; 734 o--; 735 } 736 } 737 } 738 739 static void 740 print_cycle(struct array *c) 741 { 742 unsigned int i; 743 744 /* Printing in reverse order, since cycle discoveries finds reverse 745 * edges. */ 746 for (i = c->entries; i != 0;) { 747 i--; 748 warnx("%s", c->t[i]->k); 749 } 750 } 751 752 static struct node * 753 find_longest_cycle(struct array *h, struct array *c) 754 { 755 unsigned int i; 756 unsigned int o; 757 unsigned int best; 758 struct node *n; 759 static int notfirst = 0; 760 761 assert(h->entries != 0); 762 763 /* No cycle found yet. */ 764 c->entries = 0; 765 766 /* Reset the set of marks, except the first time around. */ 767 if (notfirst) { 768 for (i = 0; i < h->entries; i++) 769 h->t[i]->mark = 0; 770 } else 771 notfirst = 1; 772 773 o = 0; 774 775 /* Traverse the array. Each unmarked, live node heralds a 776 * new set of strongly connected components. */ 777 for (i = 0; i < h->entries; i++) { 778 n = h->t[i]; 779 if (n->refs != 0 && n->mark == 0) { 780 /* Each call to traverse_node uses a separate 781 * interval of numbers to mark nodes. */ 782 o++; 783 o = traverse_node(n, o, c); 784 } 785 } 786 787 assert(c->entries != 0); 788 n = c->t[0]; 789 best = n->refs; 790 for (i = 0; i < c->entries; i++) { 791 if (c->t[i]->refs < best) { 792 n = c->t[i]; 793 best = n->refs; 794 } 795 } 796 return n; 797 } 798 799 800 #define plural(n) ((n) > 1 ? "s" : "") 801 802 int 803 main(int argc, char *argv[]) 804 { 805 struct ohash pairs; 806 int reverse_flag, quiet_flag, long_flag, 807 warn_flag, hints_flag, verbose_flag; 808 unsigned int order; 809 810 order = 0; 811 812 reverse_flag = quiet_flag = long_flag = 813 warn_flag = hints_flag = verbose_flag = 0; 814 nodes_init(&pairs); 815 816 { 817 int c; 818 819 while ((c = getopt(argc, argv, "h:flqrvw")) != -1) { 820 switch(c) { 821 case 'h': { 822 FILE *f; 823 824 f = fopen(optarg, "r"); 825 if (f == NULL) 826 err(EX_NOINPUT, "Can't open hint file %s", 827 optarg); 828 order = read_hints(f, &pairs, quiet_flag, 829 optarg, order); 830 fclose(f); 831 } 832 hints_flag = 1; 833 break; 834 /*FALLTHRU*/ 835 case 'f': 836 hints_flag = 2; 837 break; 838 case 'l': 839 long_flag = 1; 840 break; 841 case 'q': 842 quiet_flag = 1; 843 break; 844 case 'r': 845 reverse_flag = 1; 846 break; 847 case 'v': 848 verbose_flag = 1; 849 break; 850 case 'w': 851 warn_flag = 1; 852 break; 853 default: 854 usage(); 855 } 856 } 857 858 argc -= optind; 859 argv += optind; 860 } 861 862 switch(argc) { 863 case 1: { 864 FILE *f; 865 866 f = fopen(argv[0], "r"); 867 if (f == NULL) 868 err(EX_NOINPUT, "Can't open file %s", argv[1]); 869 order = read_pairs(f, &pairs, reverse_flag, argv[1], order, 870 hints_flag == 2); 871 fclose(f); 872 break; 873 } 874 case 0: 875 order = read_pairs(stdin, &pairs, reverse_flag, "stdin", 876 order, hints_flag == 2); 877 break; 878 default: 879 usage(); 880 } 881 882 { 883 struct array aux; /* Unrefed nodes/cycle reporting. */ 884 struct array remaining; 885 unsigned int broken_arcs, broken_cycles; 886 unsigned int left; 887 888 broken_arcs = 0; 889 broken_cycles = 0; 890 891 if (hints_flag) 892 make_transparent(&pairs); 893 split_nodes(&pairs, &aux, &remaining); 894 ohash_delete(&pairs); 895 896 if (hints_flag) 897 heapify(&aux, verbose_flag); 898 899 left = remaining.entries + aux.entries; 900 while (left != 0) { 901 902 /* Standard topological sort. */ 903 while (aux.entries) { 904 struct link *l; 905 struct node *n; 906 907 n = DEQUEUE(&aux); 908 printf("%s\n", n->k); 909 left--; 910 /* We can't free nodes, as we don't know which 911 * entry we can remove in the hash table. We 912 * rely on refs == 0 to recognize live nodes. 913 * Decrease ref count of live nodes, enter new 914 * candidates into the unrefed list. */ 915 for (l = n->arcs; l != NULL; l = l->next) 916 if (l->node->refs != 0 && 917 --l->node->refs == 0) { 918 ENQUEUE(&aux, l->node); 919 } 920 } 921 /* There are still cycles to break. */ 922 if (left != 0) { 923 struct node *n; 924 925 broken_cycles++; 926 /* XXX Simple cycle detection and long cycle 927 * detection are mutually exclusive. */ 928 929 if (long_flag) { 930 n = find_longest_cycle(&remaining, &aux); 931 } else { 932 struct node *b; 933 934 if (hints_flag) 935 n = find_smallest_node(&remaining); 936 else 937 n = find_good_cycle_break(&remaining); 938 while ((b = find_cycle_from(n, &aux)) == NULL) 939 n = find_predecessor(&remaining, n); 940 n = b; 941 } 942 943 if (!quiet_flag) { 944 warnx("cycle in data"); 945 print_cycle(&aux); 946 } 947 948 if (verbose_flag) 949 warnx("%u edge%s broken", n->refs, 950 plural(n->refs)); 951 broken_arcs += n->refs; 952 n->refs = 0; 953 /* Reinitialization, cycle reporting uses aux. */ 954 aux.t[0] = n; 955 aux.entries = 1; 956 } 957 } 958 if (verbose_flag && broken_cycles != 0) 959 warnx("%u cycle%s broken, for a total of %u edge%s", 960 broken_cycles, plural(broken_cycles), 961 broken_arcs, plural(broken_arcs)); 962 if (warn_flag) 963 exit(broken_cycles < 256 ? broken_cycles : 255); 964 else 965 exit(EX_OK); 966 } 967 } 968 969 970 extern char *__progname; 971 972 static void 973 usage(void) 974 { 975 fprintf(stderr, "Usage: %s [-flqrvw] [-h file] [file]\n", __progname); 976 exit(EX_USAGE); 977 } 978