[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.27

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