Annotation of 3BSD/cmd/tsort.c, revision 1.1.1.1

1.1       root        1: /*     topological sort
                      2:  *     input is sequence of pairs of items (blank-free strings)
                      3:  *     nonidentical pair is a directed edge in graph
                      4:  *     identical pair merely indicates presence of node
                      5:  *     output is ordered list of items consistent with
                      6:  *     the partial ordering specified by the graph
                      7: */
                      8: #include "stdio.h"
                      9: 
                     10: /*     the nodelist always has an empty element at the end to
                     11:  *     make it easy to grow in natural order
                     12:  *     states of the "live" field:*/
                     13: #define DEAD 0 /* already printed*/
                     14: #define LIVE 1 /* not yet printed*/
                     15: #define VISITED 2      /*used only in findloop()*/
                     16: 
                     17: struct nodelist {
                     18:        struct nodelist *nextnode;
                     19:        struct predlist *inedges;
                     20:        char *name;
                     21:        int live;
                     22: } firstnode = {NULL, NULL, NULL, DEAD};
                     23: 
                     24: /*     a predecessor list tells all the immediate
                     25:  *     predecessors of a given node
                     26: */
                     27: struct predlist {
                     28:        struct predlist *nextpred;
                     29:        struct nodelist *pred;
                     30: };
                     31: 
                     32: struct nodelist *index();
                     33: struct nodelist *findloop();
                     34: struct nodelist *mark();
                     35: char *malloc();
                     36: char *empty = "";
                     37: 
                     38: /*     the first for loop reads in the graph,
                     39:  *     the second prints out the ordering
                     40: */
                     41: main(argc,argv)
                     42: char **argv;
                     43: {
                     44:        register struct predlist *t;
                     45:        FILE *input = stdin;
                     46:        register struct nodelist *i, *j;
                     47:        int x;
                     48:        char precedes[50], follows[50];
                     49:        if(argc>1) {
                     50:                input = fopen(argv[1],"r");
                     51:                if(input==NULL)
                     52:                        error("cannot open ", argv[1]);
                     53:        }
                     54:        for(;;) {
                     55:                x = fscanf(input,"%s%s",precedes, follows);
                     56:                if(x==EOF)
                     57:                        break;
                     58:                if(x!=2)
                     59:                        error("odd data",empty);
                     60:                i = index(precedes);
                     61:                j = index(follows);
                     62:                if(i==j||present(i,j)) 
                     63:                        continue;
                     64:                t = (struct predlist *)malloc(sizeof(struct predlist));
                     65:                t->nextpred = j->inedges;
                     66:                t->pred = i;
                     67:                j->inedges = t;
                     68:        }
                     69:        for(;;) {
                     70:                x = 0;  /*anything LIVE on this sweep?*/
                     71:                for(i= &firstnode; i->nextnode!=NULL; i=i->nextnode) {
                     72:                        if(i->live==LIVE) {
                     73:                                x = 1;
                     74:                                if(!anypred(i))
                     75:                                        break;
                     76:                        }
                     77:                }
                     78:                if(x==0)
                     79:                        break;
                     80:                if(i->nextnode==NULL)
                     81:                        i = findloop();
                     82:                printf("%s\n",i->name);
                     83:                i->live = DEAD;
                     84:        }
                     85: }
                     86: 
                     87: /*     is i present on j's predecessor list?
                     88: */
                     89: present(i,j)
                     90: struct nodelist *i, *j;
                     91: {
                     92:        register struct predlist *t;
                     93:        for(t=j->inedges; t!=NULL; t=t->nextpred)
                     94:                if(t->pred==i)
                     95:                        return(1);
                     96:        return(0);
                     97: }
                     98: 
                     99: /*     is there any live predecessor for i?
                    100: */
                    101: anypred(i)
                    102: struct nodelist *i;
                    103: {
                    104:        register struct predlist *t;
                    105:        for(t=i->inedges; t!=NULL; t=t->nextpred)
                    106:                if(t->pred->live==LIVE)
                    107:                        return(1);
                    108:        return(0);
                    109: }
                    110: 
                    111: /*     turn a string into a node pointer
                    112: */
                    113: struct nodelist *
                    114: index(s)
                    115: register char *s;
                    116: {
                    117:        register struct nodelist *i;
                    118:        register char *t;
                    119:        for(i= &firstnode; i->nextnode!=NULL; i=i->nextnode)
                    120:                if(cmp(s,i->name))
                    121:                        return(i);
                    122:        for(t=s; *t; t++) ;
                    123:        t = malloc((unsigned)(t+1-s));
                    124:        i->nextnode = (struct nodelist *)malloc(sizeof(struct nodelist));
                    125:        if(i->nextnode==NULL||t==NULL)
                    126:                error("too many items",empty);
                    127:        i->name = t;
                    128:        i->live = LIVE;
                    129:        i->nextnode->nextnode = NULL;
                    130:        i->nextnode->inedges = NULL;
                    131:        i->nextnode->live = DEAD;
                    132:        while(*t++ = *s++);
                    133:        return(i);
                    134: }
                    135: 
                    136: cmp(s,t)
                    137: register char *s, *t;
                    138: {
                    139:        while(*s==*t) {
                    140:                if(*s==0)
                    141:                        return(1);
                    142:                s++;
                    143:                t++;
                    144:        }
                    145:        return(0);
                    146: }
                    147: 
                    148: error(s,t)
                    149: char *s, *t;
                    150: {
                    151:        note(s,t);
                    152:        exit(1);
                    153: }
                    154: 
                    155: note(s,t)
                    156: char *s,*t;
                    157: {
                    158:        fprintf(stderr,"tsort: %s%s\n",s,t);
                    159: }
                    160: 
                    161: /*     given that there is a cycle, find some
                    162:  *     node in it
                    163: */
                    164: struct nodelist *
                    165: findloop()
                    166: {
                    167:        register struct nodelist *i, *j;
                    168:        for(i= &firstnode; i->nextnode!=NULL; i=i->nextnode)
                    169:                if(i->live==LIVE)
                    170:                        break;
                    171:        note("cycle in data",empty);
                    172:        i = mark(i);
                    173:        if(i==NULL)
                    174:                error("program error",empty);
                    175:        for(j= &firstnode; j->nextnode!=NULL; j=j->nextnode)
                    176:                if(j->live==VISITED)
                    177:                        j->live = LIVE;
                    178:        return(i);
                    179: }
                    180: 
                    181: /*     depth-first search of LIVE predecessors
                    182:  *     to find some element of a cycle;
                    183:  *     VISITED is a temporary state recording the
                    184:  *     visits of the search
                    185: */
                    186: struct nodelist *
                    187: mark(i)
                    188: register struct nodelist *i;
                    189: {
                    190:        register struct nodelist *j;
                    191:        register struct predlist *t;
                    192:        if(i->live==DEAD)
                    193:                return(NULL);
                    194:        if(i->live==VISITED)
                    195:                return(i);
                    196:        i->live = VISITED;
                    197:        for(t=i->inedges; t!=NULL; t=t->nextpred) {
                    198:                j = mark(t->pred);
                    199:                if(j!=NULL) {
                    200:                        note(i->name,empty);
                    201:                        return(j);
                    202:                }
                    203:        }
                    204:        return(NULL);
                    205: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.