Annotation of 42BSD/usr.bin/tsort.c, revision 1.1

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

unix.superglobalmegacorp.com

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