[BACK]Return to tsort.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tsort

Annotation of src/usr.bin/tsort/tsort.c, Revision 1.17

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