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