#include "errmsg.h"
#include "stdio.h"
#include "string.h"
#include <locale.h>
#define DEAD 0
#define LIVE 1
#define VISITED 2
#define STR(X) #X
#define XSTR(X) STR(X)
#define FORMAT "%" XSTR(FILENAME_MAX) "s%" XSTR(FILENAME_MAX) "s"
static
struct nodelist {
struct nodelist *nextnode;
struct predlist *inedges;
char *name;
int live;
} firstnode = {NULL, NULL, NULL, DEAD};
struct predlist {
struct predlist *nextpred;
struct nodelist *pred;
};
static struct nodelist *index(char *s);
static struct nodelist *findloop(void);
static struct nodelist *mark(struct nodelist *i);
static int present(struct nodelist *i, struct nodelist *j);
static int anypred(struct nodelist *i);
int
main(int argc, char **argv)
{
struct predlist *t;
FILE *input = stdin;
struct nodelist *i, *j;
int x;
char precedes[FILENAME_MAX+1], follows[FILENAME_MAX+1];
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
errprefix("UX");
errsource(*argv);
errverb("notag,notofix");
switch (argc) {
case 1:
break;
case 2:
if (strcmp(argv[1], "-") == 0)
break;
if (strcmp(argv[1], "--") == 0)
break;
input = zfopen(EERROR, argv[1], "r");
break;
case 3:
if (strcmp(argv[1], "--") != 0)
errusage(gettext("[ file ]"));
input = zfopen(EERROR, argv[2], "r");
break;
default:
errusage("[ file ]");
}
for (;;) {
x = fscanf(input, FORMAT, precedes, follows);
if (x == EOF)
break;
if (x != 2)
errmsg(EERROR, gettext("odd data"));
i = index(precedes);
j = index(follows);
if (i == j || present(i, j))
continue;
t = (struct predlist *)
zmalloc(EERROR, sizeof (struct predlist));
t->nextpred = j->inedges;
t->pred = i;
j->inedges = t;
}
for (;;) {
x = 0;
for (i = &firstnode; i->nextnode != NULL; i = i->nextnode) {
if (i->live == LIVE) {
x = 1;
if (!anypred(i))
break;
}
}
if (x == 0)
break;
if (i->nextnode == NULL)
i = findloop();
(void) puts(i->name);
i->live = DEAD;
}
return (0);
}
static int
present(struct nodelist *i, struct nodelist *j)
{
struct predlist *t;
for (t = j->inedges; t != NULL; t = t->nextpred)
if (t->pred == i)
return (1);
return (0);
}
static int
anypred(struct nodelist *i)
{
struct predlist *t;
for (t = i->inedges; t != NULL; t = t->nextpred)
if (t->pred->live == LIVE)
return (1);
return (0);
}
static struct nodelist *
index(char *s)
{
struct nodelist *i;
char *t;
for (i = &firstnode; i->nextnode != NULL; i = i->nextnode)
if (strcmp(s, i->name) == 0)
return (i);
for (t = s; *t; t++);
t = zmalloc(EERROR, (unsigned)(t + 1 - s));
i->nextnode = (struct nodelist *)
zmalloc(EERROR, sizeof (struct nodelist));
i->name = t;
i->live = LIVE;
i->nextnode->nextnode = NULL;
i->nextnode->inedges = NULL;
i->nextnode->live = DEAD;
while (*t++ = *s++);
return (i);
}
static struct nodelist *
findloop(void)
{
struct nodelist *i, *j;
for (i = &firstnode; i->nextnode != NULL; i = i->nextnode)
if (i->live == LIVE)
break;
errmsg(EINFO, "cycle in data");
i = mark(i);
if (i == NULL)
errmsg(EHALT, gettext("program error"));
for (j = &firstnode; j->nextnode != NULL; j = j->nextnode)
if (j->live == VISITED)
j->live = LIVE;
return (i);
}
static struct nodelist *
mark(struct nodelist *i)
{
struct nodelist *j;
struct predlist *t;
if (i->live == DEAD)
return (NULL);
if (i->live == VISITED)
return (i);
i->live = VISITED;
for (t = i->inedges; t != NULL; t = t->nextpred) {
j = mark(t->pred);
if (j != NULL) {
(void) fprintf(stderr, "\t%s\n", i->name);
return (j);
}
}
return (NULL);
}